/*
    Olli's MemWatch
    ---------------
    (C) 1990 by AmigaDOS

    Überwacht Speicherseite 0 (Adressen 0 bis 1023)
    und meldet, falls Änderungen auftreten
*/

#include <proto/intuition.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <string.h>
#include <exec/interrupts.h>
#include <hardware/intbits.h>
void _exit(int);

#define print(s) if(_Backstdout) Write(_Backstdout,s,strlen(s))

/* Interrupt-Routine aus dem Assemblerteil */
extern void NewInt(void),RestorePage(void),SavePage(void);
/* Daten für den Interrupt */
long sigmask;
struct Process *mytask;
long pos,val,oldval;
long page[128];
/* Die Interrupt-Struktur */
struct Interrupt irq={0,0,NT_INTERRUPT,0,"OMW's Interrupt",0,NewInt};
char intrunning;

/* Definitionen für "cback.o" */
char *_procname="OMW";
long _priority=5;
long _stacksize=3200;
long _BackGroundIO='Yup!';
extern BPTR _Backstdout;

/* Globale Daten */
struct Message remmsg;
struct MsgPort *omwport;
struct IntuitionBase *IntuitionBase;

/* Cleanup */
void cleanup(void)
{
    if(intrunning) RemIntServer(INTB_VERTB,&irq);
    if(_Backstdout) Close(_Backstdout);
    if(omwport) DeletePort(omwport);
    _exit(0);
}

/* Jemand hat im Speicher gepfuscht - Anzeigen */
char aldata[]={
0,110,20,"Olli's MemWatch - © 1990 AmigaDOS/DMV-Verlag",1,
0,122,31,"Speicherveränderung an Position $00000000",1,
0,110,42,"Alter Wert: $00000000  Neuer Wert: $00000000",1,
0,60,60,"Linke Maustaste: KORRIGIEREN    Rechte Maustaste: WEITER",0};
char *aldb;

/* Fügt eine Hexzahl nach $ ein */
void inserthex(int hex)
{
    int c;
    while(*aldb++!='$'); aldb+=7;
    for(c=0; c<8; c++) {
	*aldb="0123456789ABCDEF"[hex&15];
	aldb--;
	hex>>=4;
    }
    aldb+=8;
}

/* Gibt die Meldung aus */
void showerror(void)
{
    /* Interrupts sperren, damit wir uns nicht
       selbst in die Quere kommen - und für den
       Fall einer $6C-Modifikation */
    Disable();
    aldb=aldata;
    /* Hexzahlen erzeugen */
    inserthex(pos);
    inserthex(oldval);
    inserthex(val);
    /* Anzeigen */
    if(DisplayAlert(0,aldata,77)) RestorePage();
    else SavePage();
    /* Signals löschen, zur Vermeidung einer
       Mehrfachmoserung */
    SetSignal(0,sigmask);
    Enable();
}

/* Die Hauptroutine */
void _main(void)
{
    struct MsgPort *p;
    struct Message *m;

    /* Das Übliche... */
    print("\x9b33;3mOlli's MemWatch\x9b0m © 1990 AmigaDOS/DMV-Verlag\n");
    mytask=FindTask(0);
    IntuitionBase=OldOpenLibrary("intuition.library");

    /* Läuft OMW schon? */
    if(p=FindPort("OMW's Port")) {
	print("OMW wird entfernt...");
	remmsg.mn_ReplyPort=CreatePort(0,0);
	PutMsg(p,&remmsg);
	WaitPort(remmsg.mn_ReplyPort);
	GetMsg(remmsg.mn_ReplyPort);
	DeletePort(remmsg.mn_ReplyPort);
	print("ok.\n");
	cleanup();
    }

    /* Installieren */
    print("OMW wird installiert...");
    SavePage();
    omwport=CreatePort("OMW's Port",0);
    if(!omwport) {
	print("Fehler beim Anlegen des MsgPorts!\x07\n");
	cleanup();
    }
    sigmask=1<<AllocSignal(-1);
    if(!sigmask) {
	print("Kein Signal mehr frei!\x07\n");
	cleanup();
    }
    AddIntServer(INTB_VERTB,&irq);
    intrunning=1;
    print("ok.\n");
    Close(_Backstdout);
    _Backstdout=0;

    /* Warten auf Signale */
    for(;;) {
	/* Hat jemand im Speicher gepfuscht? */
	if(Wait(sigmask|(1<<omwport->mp_SigBit))&sigmask) showerror();
	/* Wir werden entfernt */
	else {
	    if(m=GetMsg(omwport)) {
		ReplyMsg(m);
		cleanup();
	    }
	}
    }
}
