jac@paul.rutgers.edu (Jonathan A. Chandross) (11/19/90)
Submitted-by: None Posting-number: Volume 1, Source:6 Archive-name: unix/simulator/koning/part03 Architecture: UNIX Version-number: 1.00 =debug.c -#include "apple.h" -#include <curses.h> - -int DebugSingle; -int DebugTrace; -ADDR DebugBreak; -FILE *DebugFile; - -void htob (out, byte) -FILE *out; -BYTE byte; -{ - register int i; - - for (i = 7; i >= 0; i--) - (void)fputc (byte & (1 << i) ? '1' : '0', out); -} - -void DebugDisasm (out) -FILE *out; -{ - int opcode = MegaGetMem (PPC); - int n; - char * mne; - - switch (opcode) - { - case 0x69: /* ADC #dd */ - mne = "ADC #$%2X"; n = 1; - break; - case 0x65: /* ADC aa */ - mne = "ADC $%2X"; n = 1; - break; - case 0x75: /* ADC aa,X */ - mne = "ADC $%2X,X"; n = 1; - break; - case 0x6d: /* ADC aaaa */ - mne = "ADC $%4X"; n = 2; - break; - case 0x7d: /* ADC aaaa,X */ - mne = "ADC $%4X,X"; n = 2; - break; - case 0x79: /* ADC aaaa,Y */ - mne = "ADC $%4X,Y"; n = 2; - break; - case 0x61: /* ADC (aa,X) */ - mne = "ADC $(%2X,X)"; n = 1; - break; - case 0x71: /* ADC (aa),Y */ - mne = "ADC $(%2X),Y"; n = 1; - break; - case 0x29: /* AND #dd */ - mne = "AND #$%2X"; n = 1; - break; - case 0x25: /* AND aa */ - mne = "AND $%2X"; n = 1; - break; - case 0x35: /* AND aa,X */ - mne = "AND $%2X,X"; n = 1; - break; - case 0x2d: /* AND aaaa */ - mne = "AND $%4X"; n = 2; - break; - case 0x3d: /* AND aaaa,X */ - mne = "AND $%4X,X"; n = 2; - break; - case 0x39: /* AND aaaa,Y */ - mne = "AND $%4X,Y"; n = 2; - break; - case 0x21: /* AND (aa,X) */ - mne = "AND $(%2X,X)"; n = 1; - break; - case 0x31: /* AND (aa),Y */ - mne = "AND ($%2X),Y"; n = 1; - break; - case 0x0a: /* ASL A */ - mne = "ASL A"; n = 0; - break; - case 0x06: /* ASL aa */ - mne = "ASL $%2X"; n = 1; - break; - case 0x16: /* ASL aa,X */ - mne = "ASL $%2X,X"; n = 1; - break; - case 0x0e: /* ASL aaaa */ - mne = "ASL $%4X"; n = 2; - break; - case 0x1e: /* ASL aaaa,X */ - mne = "ASL $%4X,X"; n = 2; - break; - case 0x90: /* BCC rr */ - mne = "BCC $%2X"; n = -1; - break; - case 0xb0: /* BCS rr */ - mne = "BCS $%2X"; n = -1; - break; - case 0xf0: /* BEQ rr */ - mne = "BEQ $%2X"; n = -1; - break; - case 0x24: /* BIT aa */ - mne = "BIT $%2X"; n = 1; - break; - case 0x2c: /* BIT aaaa */ - mne = "BIT $%4X"; n = 2; - break; - case 0x30: /* BMI rr */ - mne = "BMI $%2X"; n = -1; - break; - case 0xd0: /* BNE rr */ - mne = "BNE $%2X"; n = -1; - break; - case 0x10: /* BPL rr */ - mne = "BPL $%2X"; n = -1; - break; - case 0x00: /* BRK */ - mne = "BRK"; n = 0; - break; - case 0x50: /* BVC rr */ - mne = "BVC $%2X"; n = -1; - break; - case 0x70: /* BVS rr */ - mne = "BVS $%2X"; n = -1; - break; - case 0x18: /* CLC */ - mne = "CLC"; n = 0; - break; - case 0xd8: /* CLD */ - mne = "CLD"; n = 0; - break; - case 0x58: /* CLI */ - mne = "CLI"; n = 0; - break; - case 0xb8: /* CLV */ - mne = "CLV"; n = 0; - break; - case 0xc9: /* CMP #dd */ - mne = "CMP #$%2X"; n = 1; - break; - case 0xc5: /* CMP aa */ - mne = "CMP $%2X"; n = 1; - break; - case 0xd5: /* CMP aa,X */ - mne = "CMP $%2X,X"; n = 1; - break; - case 0xcd: /* CMP aaaa */ - mne = "CMP $%4X"; n = 2; - break; - case 0xdd: /* CMP aaaa,X */ - mne = "CMP $%4X,X"; n = 2; - break; - case 0xd9: /* CMP aaaa,Y */ - mne = "CMP $%4X,Y"; n = 2; - break; - case 0xc1: /* CMP (aa,X) */ - mne = "CMP $(%2X,X)"; n = 1; - break; - case 0xd1: /* CMP (aa),y */ - mne = "CMP $(%2X),y"; n = 1; - break; - case 0xe0: /* CPX #dd */ - mne = "CPX #$%2X"; n = 1; - break; - case 0xe4: /* CPX aa */ - mne = "CPX $%2X"; n = 1; - break; - case 0xec: /* CPX aaaa */ - mne = "CPX $%4X"; n = 2; - break; - case 0xc0: /* CPY #dd */ - mne = "CPY #$%2X"; n = 1; - break; - case 0xc4: /* CPY aa */ - mne = "CPY $%2X"; n = 1; - break; - case 0xcc: /* CPY aaaa */ - mne = "CPY $%4X"; n = 2; - break; - case 0xc6: /* DEC aa */ - mne = "DEC $%2X"; n = 1; - break; - case 0xd6: /* DEC aa,X */ - mne = "DEC $%2X,X"; n = 1; - break; - case 0xce: /* DEC aaaa */ - mne = "DEC $%4X"; n = 2; - break; - case 0xde: /* DEC aaaa,X */ - mne = "DEC $%4X,X"; n = 2; - break; - case 0xca: /* DEX */ - mne = "DEX"; n = 0; - break; - case 0x88: /* DEY */ - mne = "DEY"; n = 0; - break; - case 0x49: /* EOR #dd */ - mne = "EOR #$%2X"; n = 1; - break; - case 0x45: /* EOR aa */ - mne = "EOR $%2X"; n = 1; - break; - case 0x55: /* EOR aa,X */ - mne = "EOR $%2X,X"; n = 1; - break; - case 0x4d: /* EOR aaaa */ - mne = "EOR $%4X"; n = 2; - break; - case 0x5d: /* EOR aaaa,X */ - mne = "EOR $%4X,X"; n = 2; - break; - case 0x59: /* EOR aaaa,Y */ - mne = "EOR $%4X,Y"; n = 2; - break; - case 0x41: /* EOR (aa,X) */ - mne = "EOR ($%2X,X)"; n = 1; - break; - case 0x51: /* EOR (aa),Y */ - mne = "EOR ($%2X),Y"; n = 1; - break; - case 0xe6: /* INC aa */ - mne = "INC $%2X"; n = 1; - break; - case 0xf6: /* INC aa,X */ - mne = "INC $%2X,X"; n = 1; - break; - case 0xee: /* INC aaaa */ - mne = "INC $%4X"; n = 2; - break; - case 0xfe: /* INC aaaa,X */ - mne = "INC $%4X,X"; n = 2; - break; - case 0xe8: /* INX */ - mne = "INX"; n = 0; - break; - case 0xc8: /* INY */ - mne = "INY"; n = 0; - break; - case 0x4c: /* JMP aaaa */ - mne = "JMP $%4X"; n = 2; - break; - case 0x6c: /* JMP (aaaa) */ - mne = "JMP ($%4X)"; n = 2; - break; - case 0x20: /* JSR aaaa */ - mne = "JSR $%4X"; n = 2; - break; - case 0xa9: /* LDA #dd */ - mne = "LDA #$%2X"; n = 1; - break; - case 0xa5: /* LDA aa */ - mne = "LDA $%2X"; n = 1; - break; - case 0xb5: /* LDA aa,X */ - mne = "LDA $%2X,X"; n = 1; - break; - case 0xad: /* LDA aaaa */ - mne = "LDA $%4X"; n = 2; - break; - case 0xbd: /* LDA aaaa,X */ - mne = "LDA $%4X,X"; n = 2; - break; - case 0xb9: /* LDA aaaa,Y */ - mne = "LDA $%4X,Y"; n = 2; - break; - case 0xa1: /* LDA (aa,X) */ - mne = "LDA ($%2X,X)"; n = 1; - break; - case 0xb1: /* LDA (aa),Y */ - mne = "LDA ($%2X),Y"; n = 1; - break; - case 0xa2: /* LDX #dd */ - mne = "LDX #$%2X"; n = 1; - break; - case 0xa6: /* LDX aa */ - mne = "LDX $%2X"; n = 1; - break; - case 0xb6: /* LDX aa,Y */ - mne = "LDX $%2X,Y"; n = 1; - break; - case 0xae: /* LDX aaaa */ - mne = "LDX $%4X"; n = 2; - break; - case 0xbe: /* LDX aaaa,Y */ - mne = "LDX $%4X,Y"; n = 2; - break; - case 0xa0: /* LDY #dd */ - mne = "LDY #$%2X"; n = 1; - break; - case 0xa4: /* LDY aa */ - mne = "LDY $%2X"; n = 1; - break; - case 0xb4: /* LDY aa,X */ - mne = "LDY $%2X,X"; n = 1; - break; - case 0xac: /* LDY aaaa */ - mne = "LDY $%4X"; n = 2; - break; - case 0xbc: /* LDY aaaa,X */ - mne = "LDY $%4X,X"; n = 2; - break; - case 0x4a: /* LSR A */ - mne = "LSR"; n = 0; - break; - case 0x46: /* LSR aa */ - mne = "LSR $%2X"; n = 1; - break; - case 0x56: /* LSR aa,X */ - mne = "LSR $%2X,X"; n = 1; - break; - case 0x4e: /* LSR aaaa */ - mne = "LSR $%4X"; n = 2; - break; - case 0x5e: /* LSR aaaa,X */ - mne = "LSR $%4X,X"; n = 2; - break; - case 0xea: /* NOP */ - mne = "NOP"; n = 0; - break; - case 0x09: /* ORA #dd */ - mne = "ORA #$%2X"; n = 1; - break; - case 0x05: /* ORA aa */ - mne = "ORA $%2X"; n = 1; - break; - case 0x15: /* ORA aa,X */ - mne = "ORA $%2X,X"; n = 1; - break; - case 0x0d: /* ORA aaaa */ - mne = "ORA $%4X"; n = 2; - break; - case 0x1d: /* ORA aaaa,X */ - mne = "ORA $%4X,X"; n = 2; - break; - case 0x19: /* ORA aaaa,Y */ - mne = "ORA $%4X,Y"; n = 2; - break; - case 0x01: /* ORA (aa,X) */ - mne = "ORA ($%2X,X)"; n = 1; - break; - case 0x11: /* ORA (aa),Y */ - mne = "ORA ($%2X),Y"; n = 1; - break; - case 0x48: /* PHA */ - mne = "PHA"; n = 0; - break; - case 0x08: /* PHP */ - mne = "PHP"; n = 0; - break; - case 0x68: /* PLA */ - mne = "PLA"; n = 0; - break; - case 0x28: /* PLP */ - mne = "PLP"; n = 0; - break; - case 0x2a: /* ROL A */ - mne = "ROL A"; n = 0; - break; - case 0x26: /* ROL aa */ - mne = "ROL $%2X"; n = 1; - break; - case 0x36: /* ROL aa,X */ - mne = "ROL $%2X,X"; n = 1; - break; - case 0x2e: /* ROL aaaa */ - mne = "ROL $%4X"; n = 2; - break; - case 0x3e: /* ROL aaaa,X */ - mne = "ROL $%4X,X"; n = 2; - break; - case 0x6a: /* ROR A */ - mne = "ROR A"; n = 0; - break; - case 0x66: /* ROR aa */ - mne = "ROR $%2X"; n = 1; - break; - case 0x76: /* ROR aa,X */ - mne = "ROR $%2X,X"; n = 1; - break; - case 0x6e: /* ROR aaaa */ - mne = "ROR $%4X"; n = 2; - break; - case 0x7e: /* ROR aaaa,X */ - mne = "ROR $%4X,X"; n = 2; - break; - case 0x40: /* RTI */ - mne = "RTI"; n = 0; - break; - case 0x60: /* RTS */ - mne = "RTS"; n = 0; - break; - case 0xe9: /* SBC #dd */ - mne = "SBC #$%2X"; n = 1; - break; - case 0xe5: /* SBC aa */ - mne = "SBC $%2X"; n = 1; - break; - case 0xf5: /* SBC aa,x */ - mne = "SBC $%2X,X"; n = 1; - break; - case 0xed: /* SBC aaaa */ - mne = "SBC $%4X"; n = 2; - break; - case 0xfd: /* SBC aaaa,X */ - mne = "SBC $%4X,X"; n = 2; - break; - case 0xf9: /* SBC aaaa,Y */ - mne = "SBC $%4X,Y"; n = 2; - break; - case 0xe1: /* SBC (aa,X) */ - mne = "SBC ($%2X,X)"; n = 1; - break; - case 0xf1: /* SBC (aa),Y */ - mne = "SBC ($%2X),Y"; n = 1; - break; - case 0x38: /* SEC */ - mne = "SEC"; n = 0; - break; - case 0xf8: /* SED */ - mne = "SED"; n = 0; - break; - case 0x78: /* SEI */ - mne = "SEI"; n = 0; - break; - case 0x85: /* STA aa */ - mne = "STA $%2X"; n = 1; - break; - case 0x95: /* STA aa,X */ - mne = "STA $%2X,X"; n = 1; - break; - case 0x8d: /* STA aaaa */ - mne = "STA $%4X"; n = 2; - break; - case 0x9d: /* STA aaaa,X */ - mne = "STA $%4X,X"; n = 2; - break; - case 0x99: /* STA aaaa,Y */ - mne = "STA $%4X,Y"; n = 2; - break; - case 0x81: /* STA (aa,X) */ - mne = "STA ($%2X,X)"; n = 1; - break; - case 0x91: /* STA (aa),Y */ - mne = "STA ($%2X),Y"; n = 1; - break; - case 0x86: /* STX aa */ - mne = "STX $%2X"; n = 1; - break; - case 0x96: /* STX aa,Y */ - mne = "STX $%2X,Y"; n = 1; - break; - case 0x8e: /* STX aaaa */ - mne = "STX $%4X"; n = 2; - break; - case 0x84: /* STY aa */ - mne = "STY $%2X"; n = 1; - break; - case 0x94: /* STY aa,X */ - mne = "STY $%2X,X"; n = 1; - break; - case 0x8c: /* STY aaaa */ - mne = "STY $%4X"; n = 2; - break; - case 0xaa: /* TAX */ - mne = "TAX"; n = 0; - break; - case 0xa8: /* TAY */ - mne = "TAY"; n = 0; - break; - case 0xba: /* TSX */ - mne = "TSX"; n = 0; - break; - case 0x8a: /* TXA */ - mne = "TXA"; n = 0; - break; - case 0x9a: /* TXS */ - mne = "TXS"; n = 0; - break; - case 0x98: /* TYA */ - mne = "TYA"; n = 0; - break; - default: /* Undefined opcode */ - mne = "UNDEFINED"; n = 0; - break; - } - (void)fprintf (out, "%4X: ", PPC); - switch (n) - { - case -1: - (void)fprintf (out, mne, PPC + (char)MegaGetMem (PPC + 1) + 2); - break; - case 0: - (void)fprintf (out, mne); - break; - case 1: - (void)fprintf (out, mne, MegaGetMem (PPC + 1)); - break; - case 2: - (void)fprintf (out, mne, MegaGetMem (PPC + 1) + 256 * MegaGetMem (PPC + 2)); - break; - } - (void)fputc ('\n', out); -} - - - - -void Debugger() -{ - int done = 0; - FILE *out = stdout; - char buffer[255]; - - echo(); - noraw(); - standend(); - refresh(); - - if (DebugTrace) - out = DebugFile; - - (void)fprintf (out, " A=%2X, Y=%2X, X=%2X, S=%2X, P=%%",A,Y,X,S); - htob (out, (BYTE)P); - (void)fprintf (out, " | "); - DebugDisasm (out); - if (!DebugTrace && !DebugSingle) - { - (void)printf ("\nApple ][+ Emulator Debugger\n"); - } - - if (DebugTrace) goto traceout; - - while (!done) - { - (void)printf ("DBG> "); - (void)fflush (stdout); - (void)gets (buffer); - - switch (buffer[0]) - { - case 'q': - DebugSingle = 0; - DebugTrace = 0; - MegaQuitDetect = 1; - done = 1; - break; - case 'l': /* load */ - { - ADDR addr = 0x2000; - FILE *fp; - int ch; - - (void)printf ("Filename: "); - (void)fflush (stdout); - (void)gets (buffer); - fp = fopen (buffer, "r"); - while ((ch = fgetc (fp)) != EOF) - MegaPutMem (addr++, (BYTE)ch); - - (void)printf ("%s: loaded at ,a$2000, l$%x\n", buffer, addr - 0x2000 - 1); - MegaQuitDetect = 0; - done = 0; - break; - } - case 't': - (void)printf ("Filename: "); - (void)fflush (stdout); - (void)gets (buffer); - DebugFile = fopen (buffer, "w"); - DebugTrace = 1; - MegaQuitDetect = 0; - done = 0; - break; - case 'c': - DebugSingle = 0; - MegaQuitDetect = 0; - done = 1; - break; - case 's': - case '\0': - DebugSingle = 1; - DebugTrace = 0; - MegaQuitDetect = 0; - done = 1; - break; - default: - MegaQuitDetect = 0; - } - } -traceout: - raw(); - noecho(); -} - - =main.c - -/* - *main.c -- Globals and emulation setup for Apple ][ Emulator - *(C) 1989 Ben Koning [556498717 408/738-1763 ben@apple.com] - */ - -#include "apple.h" -#include <curses.h> -#define REF_DELAY 2000 - -main (argc,argv) - -int argc; -char *argv []; - -{ - short int byte; - int i, addr; /* Loop iterators */ - int refdelay = REF_DELAY; - FILE *fp; - char *D0FILE = "APPLESOFT.ROM", - *F8FILE = "AUTOSTART.ROM" ; - - /* Interpret args: 'invokename [-t] [-m] [-i]' */ - for (i = 1; i <= argc-1; i++) - { - if (!strcmp (argv [i],"-t")) - DebugSingle = 1; - else - if (!strcmp (argv [i],"-m")) - F8FILE = "MONITOR.ROM"; - else - if (!strcmp (argv [i],"-i")) - D0FILE = "INTEGER.ROM"; - else - { - (void)fprintf (stderr,"Usage: %s [-t] [-m] [-i]\n", - argv [0]); - exit (1); - } - } - - /* Print banner message: */ - (void)fprintf (stderr,"%s: Apple ][ Emulation - Ben Koning - v1.0\n", - argv [0]); - - (void)initscr(); - - /*--------------------------------------------------*\ - Load the 'ROM' with the appropriate 6502 code: - \*--------------------------------------------------*/ - fp = fopen (D0FILE, "r"); - for (addr = 0xd000; addr <= 0xf7ff; addr++) - Rom [addr - 0xd000] = fgetc (fp); - (void)fclose (fp); - - fp = fopen (F8FILE, "r"); - for (addr = 0xf800; addr <= 0xffff; addr++) - Rom [addr - 0xd000] = fgetc (fp); - (void)fclose (fp); - - /*--------------------------------------------------*\ - load prodos as $2000 - \*--------------------------------------------------*/ - fp = fopen ("PRODOS", "r"); - addr = 0x2000; - while ((byte = fgetc (fp)) != EOF) - MMemory [addr++] = byte; - (void)fclose (fp); - - /* Make sure banner message is seen: */ - sleep (2); - - /* Initialize the emulation: */ - MegaStartUp (); - CPUReset (); - - /*--------------------------------------------------*\ - Run it until user wants to quit: - \*--------------------------------------------------*/ - while (!MegaQuitDetect) - { - CPUExecute (); - if (!(--refdelay)) - { - refresh(); - refdelay = REF_DELAY; - } - if (MegaQuitDetect || DebugSingle || DebugTrace) - Debugger(); - } - - /* Exit cleanly: */ - MegaShutDown (); - exit (0); -} - - - =mega2.c -/* - *mega2.c -- Apple ][ soft switches->UNIX emulation for Apple ][ Emulator - *(C) 1989 Ben Koning [556498717 408/738-1763 ben@apple.com] - */ - -#include "apple.h" -#include <curses.h> - - -/* - * Termcap globals: - */ - - -/* - * Emulation globals: - */ - -BYTE MMemory [49152]; /* Main memory */ -BYTE Rom [12288]; /* 12K ROM bank of Main memory */ -BYTE MRam [12288]; /* 12K RAM bank of Main memory */ -BYTE MRam1 [4096]; /* Main bank 1 $D000-$DFFF */ -BYTE MRam2 [4096]; /* Main bank 2 $D000-$DFFF */ -BYTE RamRead = 0; /* set if 16K RAM readable */ -BYTE RamWrite = 0; /* set if 16K RAM writeable */ -BYTE Bank2Enable = 0; /* set if bank 2 Ram enabled */ - -BYTE MegaRand = 0; /* Always contains 8-bit random number */ -BYTE MegaLastKey = 0; /* $C00X keyboard latch value */ -BYTE MegaQuitDetect = 0; /* Set if user requests to quit */ - -void PutC010(); -void Put0400(); -void GetC080(); -BYTE GetC000(); -BYTE GetC010(); -BYTE GetC030(); - -void ProInit(); -void ProFormat(); -void ProRead(); -void ProWrite(); -void ProStatus(); - -/* - * Base address table for 24 lines of text/lores page 1 ($400..$7F8); - * 40 bytes for each line. Note that screen "holes" exist: - */ - -int LBasCalc [24] = - -{ -1024, -1152, -1280, -1408, -1536, -1664, -1792, -1920, -1064, -1192, -1320, -1448, -1576, -1704, -1832, -1960, -1104, -1232, -1360, -1488, -1616, -1744, -1872, -2000 -}; - -#define MegaPutChar(c) addch(c) - -/**************************************************************************/ -/* Dispatch routines: The MegaPutMem and MegaGetMem, below, have default */ -/* behavior for I/O space. They may also contain calls to other routines */ -/* in this file which handle Apple II behavior. If these latter routines */ -/* need initialization/shutdown, that code should be placed in the two */ -/* MegaStartUp and MegaShutDown routines, below. */ -/**************************************************************************/ - -#ifdef NEVER -void MegaPutChar (c) -char c; /* This makes a function out of the "putchar" macro */ - -{ - addch (c); -} -#endif - -/* This routine is called at emulation startup time. All initialization - stuff, like setting terminal modes, opening files, etc. goes here. */ -void MegaStartUp () -{ - register int i; /* Iterator */ - - /* init the pseudo disk */ - ProInit(); - - /* Set input modes on terminal: */ - noecho(); - raw(); - - /* Fill 40-column screen with simulated initial memory pattern: */ - clear(); - for (i = 0; i <= 23; i++) - mvaddstr (i, 0, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - - refresh(); - - /* Initialize some variables: */ - MegaQuitDetect = 0; - MegaLastKey = 0; - MegaRand = 0; -} - - - -/* This routine is called at emulation shutdown time. All things - started in MegaStartUp, above, should be cleaned up here. */ -void MegaShutDown () -{ - /* Clear screen: */ - clear(); - refresh(); - - /* Reset sane modes on terminal: */ - echo(); - noraw(); - endwin(); -} - -/* This routine handles ALL stores to the 64K address space, in order to - faciliate special Apple ][ - specific effects. Not all behaviors may - be implemented; to install a new one, install the call in this routine. - Returns: Nothing. */ -void MegaPutMem (addr, byte) -register ADDR addr; -register BYTE byte; -{ - /* Make sure these are in range: */ - addr &= 0xffff; - byte &= 0xff; - - /* Do random number generation: */ - MegaRand = (MegaRand + addr + byte) & 0xff; - - /* If in ROM, we are done here: */ - if (addr >= 0xd000 && !RamWrite) - { -/* Rom[addr - 0xd000] = byte; */ - return; - } - - if (addr < 0xc000) /* Main memory */ - MMemory [addr] = byte; - else if (addr >= 0xd000 && addr < 0xe000) /* 4K RAM Banks */ - { - BYTE *bank = Bank2Enable ? MRam2 : MRam1; - - bank [addr - 0xd000] = byte; - } - else if (addr >= 0xe000) /* 8K RAM Bank */ - MRam [addr - 0xe000] = byte; - else if ((addr >= 0xc010) && (addr <= 0xc01f)) /* soft switches */ - PutC010 (0); - else if (addr >= 0xc080 && addr < 0xc090) - GetC080 (addr); - - /* Now do the appropriate memory-mapped OUTPUT functions, if any: */ - if ((addr >= 0x0400) && (addr < 0x0800)) - Put0400 (addr, byte); -} - - -/* This routine handles ALL fetches from the 64K address space, in order to - facilitate special Apple ][ - specific effects. Not all behaviors may - be implemented; to install a new one, install the call in this routine. - Returns: Value at location (could be random if I/O, etc.). */ -BYTE MegaGetMem (addr) -register ADDR addr; -{ - register BYTE data; /* Data from memory space to be returned */ - - /* Make sure we're in range: */ - addr &= 0xffff; - - /* If we're just in ROM or RAM, it's easy: */ - if (addr < 0xc000) - return (MMemory [addr]); - else if (addr >= 0xd000 && !RamRead) /* rom read enabled */ - return (Rom[addr - 0xd000]); - else if (addr >= 0xe000) /* 8K RAM read */ - return (MRam[addr - 0xe000]); - else if (addr >= 0xd000 && addr < 0xe000) /* 4K Bank RAM */ - return (Bank2Enable ? MRam2[addr - 0xd000] : MRam1[addr - 0xd000]); - - - /* We must be in C000 space. Default to random value: */ - data = MegaRand & 0xff; - MegaRand = (MegaRand + addr * 25 + data) & 0xff; - - /* Now do the appropriate memory-mapped INPUT functions, if any: */ - if ((addr >= 0xc000) && (addr <= 0xc00f)) - data = GetC000 (); - else if ((addr >= 0xc010) && (addr <= 0xc01f)) - data = GetC010 (); - else if ((addr >= 0xc030) && (addr <= 0xc03f)) - data = GetC030 (); - else if ((addr >= 0xc080) && (addr <= 0xc08f)) - GetC080 (addr); - else if (addr == 0xc011) - data = 0xFF * Bank2Enable; - else if (addr == 0xc012) - data = 0xFF * RamRead; - else if (addr == 0xc701) - data = 0x20; - else if (addr == 0xc703) - data = 0x00; - else if (addr == 0xc705) - data = 0x03; - else if (addr == 0xc7ff) - data = 0x80; - else if (addr == 0xc7fe) - data = 0x1f; - else if (addr == 0xc7fc) - data = 0x00; - else if (addr == 0xc7fd) - data = 0x00; - else if (addr == 0xc780) - data = 0x60; - - /* Return the data we came up with to the user: */ - return (BYTE) (data & 0xff); -} - - - - - -/**************************************************************************/ -/* Memory-Mapped I/O routines: These routines actually perform the spe- */ -/* cific UNIX operations for get/put to certain addresses. Not all Get */ -/* or Put routines must necessarily have a companion Put or Get routine: */ -/* */ -/* * GetXXXXXX: Return a byte of data from an I/O address */ -/* * PutXXXXXX: Receive a byte of data for an I/O address */ -/* */ -/**************************************************************************/ - - - - - -/* Get keyboard data in low 7 bits. Msb indicates if hit since last C010: */ -BYTE GetC000 () -{ - register int fflags; - char data = '*'; - - /* Set nonblocking input: */ - fflags = fcntl (0, F_GETFL, 0); - (void)fcntl (0, F_SETFL, fflags | O_NDELAY); - - /* See if a key was pressed. If yes, update and set hi bit; */ - /* else, leave keyboard latch with last value: */ - if (read (0, &data, 1) > 0) - MegaLastKey = (int) data | 0x80; - - /* Reset nonblocking input: */ - (void)fcntl (0, F_SETFL, fflags); - - /* See if user wants to quit: */ - MegaQuitDetect = (data == MEGAQUITKEY); - - return (BYTE)MegaLastKey; -} - - - - - -/* Clear keyboard strobe for C000 msb: */ -BYTE GetC010 () -{ - MegaLastKey &= 0x7f; /* Clear strobe bit */ - return (BYTE)(MegaRand & 0xff); -} - -void GetC080 (addr) -ADDR addr; -{ - switch (addr & 0x000F) - { - case 0x00: - RamRead = 1; - RamWrite = 0; - Bank2Enable = 1; - break; - case 0x01: - RamRead = 0; - RamWrite = 1; - Bank2Enable = 1; - break; - case 0x02: - RamRead = 0; - RamWrite = 0; - Bank2Enable = 1; - break; - case 0x03: - RamRead = 1; - RamWrite = 1; - Bank2Enable = 1; - break; - case 0x08: - RamRead = 1; - RamWrite = 0; - Bank2Enable = 0; - break; - case 0x09: - RamRead = 0; - RamWrite = 1; - Bank2Enable = 0; - break; - case 0x0a: - RamRead = 0; - RamWrite = 0; - Bank2Enable = 0; - break; - case 0x0b: - RamRead = 1; - RamWrite = 1; - Bank2Enable = 0; - break; - } -} - -/*ARGSUSED*/ -void PutC010 (data) -BYTE data; -{ - (void)GetC010 (); /* Same thing; either one works */ -} - - - -/* Beeps speaker if accessed a lot: */ -BYTE GetC030 () -{ - static int count = 0; - - if (count++ >= 100) - { - count = 0; - /* tputs (TcapBeep,1,MegaPutChar); */ - /* putchar (7); */ - /* fflush (stdout); */ - } - return (BYTE)(MegaRand & 0xff); -} - - -/* Handles stores to text/lowres page 1 memory */ -void Put0400 (addr,data) -register ADDR addr; - BYTE data; -{ - register int linenum; /* Searching for Y-coordinate */ - register int columnnum; /* Searching for X-coordinate */ - int screenhole = 1; /* Are we in screen hole? */ - - /* Find which line the given address is in: */ - for (linenum = 0; linenum <= 23; linenum++) - if ( (addr >= LBasCalc [linenum]) && - (addr <= (LBasCalc [linenum] + 39)) ) - { - columnnum = addr - LBasCalc [linenum]; - screenhole = 0; - break; - } - - /* If not on screen, don't draw anything: */ - if (screenhole) - return; - - /* Put the terminal cursor at the right location on the screen: */ - /* We assume 80x24 terminal; no need to avoid drawing on last char. */ - move (linenum, columnnum); - - /* - Set terminal into appropriate output mode and do it: - tputs (TcapInverse,1,MegaPutChar); - */ - if (data < 64) - { - /* attron (A_STANDOUT); */ - standout(); - if (data < 32) - data += 64; - } - else if ((data < 128) && (data > 63)) - { - standout(); - if (data > 95) - data -= 64; - } - else - data = data & 127; - if (!iscntrl ((char) data)) - MegaPutChar ((char) data); - else - MegaPutChar ((char) (data - 64)); - standend(); -} - -#define _setN_(b) if ((b)!=0) P |= 128; else P &= 0x7f -#define _setV_(b) if ((b)!=0) P |= 64; else P &= 0xbf - /* This bit not implemented */ -#define _setB_(b) if ((b)!=0) P |= 16; else P &= 0xef -#define _setD_(b) if ((b)!=0) P |= 8; else P &= 0xf7 -#define _setI_(b) if ((b)!=0) P |= 4; else P &= 0xfb -#define _setZ_(b) if ((b)!=0) P |= 2; else P &= 0xfd -#define _setC_(b) if ((b)!=0) P |= 1; else P &= 0xfe - -static unsigned char buffer[512]; -FILE *disk1, /* slot 7, drive 1 280 block 5.25 floppy */ - *disk2; /* slot 7, drive 2 1024 blocks "hard disk" */ - -#define NBLOCKSD1 280 -#define NBLOCKSD2 1024 - -void ProInit () -{ - MegaPutMem (0x0043, (BYTE)0x70); /* boot disk */ - disk1 = fopen ("PRODOS.IMAGE.D1", "r+"); - disk2 = fopen ("PRODOS.IMAGE.D2", "r+"); -} - -void ProFormat (drive) -int drive; -{ - int numblocks = drive ? NBLOCKSD2 : NBLOCKSD1; - FILE *disk = drive ? disk2 : disk1; - - (void)fseek (disk, (long)(512 * numblocks), 0); - (void)fwrite (" ", 1, 1, disk); -} - -void ProRead (drive) -int drive; -{ - register int i; - int block = MegaGetMem (0x46) + MegaGetMem (0x47) * 0x0100; - int buf = MegaGetMem (0x44) + MegaGetMem (0x45) * 0x0100; - FILE *disk = drive ? disk2 : disk1; - - (void)fseek (disk, (long)(block * 512), 0); - - (void)fread ((char *)buffer, 1, 512, disk); - for (i = 0; i < 512; i++) - MegaPutMem (buf + i, (BYTE)buffer[i]); - _setC_(0); /* CLC */ - A = 0; -} - -void ProWrite (drive) -int drive; -{ - register int i; - int block = MegaGetMem (0x46) + MegaGetMem (0x47) * 0x0100; - int buf = MegaGetMem (0x44) + MegaGetMem (0x45) * 0x0100; - FILE *disk = drive ? disk2 : disk1; - - (void)fseek (disk, (long)(block * 512), 0); - - for (i = 0; i < 512; i++) - buffer[i] = MegaGetMem (buf + i); - - (void)fwrite ((char *)buffer, 1, 512, disk); - _setC_(0); /* CLC */ - A = 0; -} - -void ProStatus (drive) -int drive; -{ - int numblocks = drive ? NBLOCKSD2 : NBLOCKSD1; - - _setC_(0); /* CLC */ - A = 0; /* LDA #0 */ - Y = numblocks / 256; - X = numblocks % 256; -} - -void prodos() -{ - int drive = ((MegaGetMem (0x43) >= 128) ? 1 : 0); - - switch (MegaGetMem (0x42)) - { - case 0: - ProStatus (drive); break; - case 1: - ProRead (drive); break; - case 2: - ProWrite (drive); break; - case 3: - ProFormat (drive); break; - } -} - - + END OF ARCHIVE