X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fstargem2.cpp;h=db2f65abb7e3061e04f7d6c6277dd0c9a34b2e49;hb=e3ad811139308bfe8a818cf5e42e7553785fea82;hp=edad8fdf8c2697a5b55e5d79ed8a0c3404bfbcf7;hpb=b4e8ef6c5282d8763d7559370c007fa4c1219a54;p=stargem2 diff --git a/src/stargem2.cpp b/src/stargem2.cpp index edad8fd..db2f65a 100755 --- a/src/stargem2.cpp +++ b/src/stargem2.cpp @@ -10,9 +10,11 @@ // --- ---------- ------------------------------------------------------------ // JLH 06/15/2006 Added changelog ;-) // JLH 06/15/2006 Switched over to timeslice execution code +// JLH 07/15/2009 Solved problem with DEMO mode (IRQ handling) (No, didn't) // -#include "SDL.h" + +#include #include #include #include @@ -20,7 +22,7 @@ #include #include #include -#include "types.h" +#include #include "log.h" #include "v6808.h" #include "v6809.h" @@ -31,7 +33,9 @@ #include "dis6809.h" #include "dis6808.h" -#define __DEBUG__ + +//#define __DEBUG__ +//#define LOG_PIA1_IO using namespace std; @@ -39,19 +43,41 @@ using namespace std; #define CMOS "cmos.ram" #define SAVESTATE "sg2.state" +#define FRAME_DURATION_IN_CYCLES (M6809_CLOCK_SPEED_IN_HZ / 60.0) +#define SCANLINE_DURATION_IN_CYCLES (FRAME_DURATION_IN_CYCLES / 256.0) +// Interesting... This (1/16) causes the machine to crash in the demo (if run from clean start, otherwise it FUs demo)! +// (1/32) fucks up the demo... +// (1/64) works. Weird! +//1/64 no more... but 1/128, 1/32 and 1/16 don't work either! +//#define SG2_PIA_CALLBACK_DURATION ((FRAME_DURATION_IN_CYCLES * M6809_CYCLE_IN_USEC) / 16.0) +#define SG2_PIA_CALLBACK_DURATION ((FRAME_DURATION_IN_CYCLES * M6809_CYCLE_IN_USEC) / 64.0) + // Global variables -uint8 gram[0x10000], grom[0x10000], sram[0x10000], srom[0x10000]; // RAM & ROM spaces +uint8_t gram[0x10000], grom[0x10000], sram[0x10000], srom[0x10000]; // RAM & ROM spaces V6809REGS mainCPU; V6808REGS soundCPU; -uint8 color[16]; -uint32 palette[256]; +uint8_t color[16]; +uint32_t palette[256]; +bool paletteDirty = false; // Local variables static bool running = true; // Machine running state flag... -static uint32 startTicks; -static uint8 * keys; // SDL raw keyboard matrix +static uint32_t startTicks; +static const uint8_t * keys; // SDL raw keyboard matrix +static uint64_t clockFrameStart; // V6809 clock at the start of the frame + +// Function prototypes + +uint8_t RdMem6809(uint16_t addr); +void WrMem6809(uint16_t addr, uint8_t b); +uint8_t RdMem6808(uint16_t addr); +void WrMem6808(uint16_t addr, uint8_t b); +bool LoadImg(const char * filename, uint8_t * ram, int size); +void SaveCMOS(void); +bool LoadMachineState(void); +void SaveMachineState(void); // Local timer callback functions @@ -60,130 +86,155 @@ static void ScanlineCallback(void); // -// 6809 memory functions +// Main loop // - -uint8 RdMem6809(uint16 addr) +int main(int /*argc*/, char * /*argv*/[]) { - uint8 b; + InitLog("stargem2.log"); + WriteLog("StarGem2 - A portable Stargate emulator by James L. Hammons\n"); + WriteLog("(C) 2013 Underground Software\n\n"); - if (addr >= 0x9000 && addr <= 0xCFFF) // No ROM between $9000 - $CFFF... - b = gram[addr]; - else - { - if (!gram[0xC900] && addr <= 0x8FFF) // Check RAM $C900 bank switch - b = gram[addr]; - else - b = grom[addr]; - } + LoadSettings(); -//Is $C80E COUNT240? Hmm... No. + // Initialize Williams' palette (RGB coded as: 3 bits red, 3 bits green, 2 bits blue) + for(uint32_t i=0; i<256; i++) + palette[i] = +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + (((i & 0x01) * 33 + ((i & 0x02) >> 1) * 71 + ((i & 0x04) >> 2) * 151) << 24) + | ((((i & 0x08) >> 3) * 33 + ((i & 0x10) >> 4) * 71 + ((i & 0x20) >> 5) * 151) << 16) + | ((((i & 0x40) >> 6) * 71 + ((i & 0x80) >> 7) * 151) << 8) | 0xFF; +#else + ((i & 0x01) * 33 + ((i & 0x02) >> 1) * 71 + ((i & 0x04) >> 2) * 151) + | ((((i & 0x08) >> 3) * 33 + ((i & 0x10) >> 4) * 71 + ((i & 0x20) >> 5) * 151) << 8) + | ((((i & 0x40) >> 6) * 71 + ((i & 0x80) >> 7) * 151) << 16) | 0xFF000000; +#endif -//temp... -/*extern uint16 pcr; -//if (addr >= 0xC000 && addr <= 0xCBFF) -if (addr == 0x9C59) - WriteLog("RdMem: Reading address %04X [=%02X, PC=%04X]\n", addr, b, pcr);//*/ -/*if (addr >= 0xC80D && addr <= 0xC80F) - WriteLog("V6809 RdMem: Reading address %04X [=%02X, PC=%04X]\n", addr, b, mainCPU.pc);//*/ + // Zero out memory + memset(gram, 0, 0x10000); + memset(grom, 0, 0x10000); + memset(sram, 0, 0x10000); + memset(srom, 0, 0x10000); - return b; -} + // Set up V6809 & V6808 execution contexts -void WrMem6809(uint16 addr, uint8 b) -{ -//temp... -//extern V6809REGS regs; -//if (addr >= 0xC800 && addr <= 0xCBFE) -//if (addr == 0xC80F || addr == 0xC80D) -// WriteLog("WrMem: Writing address %04X with %02X [PC=%04X, $CB00=%02X]\n", addr, b, regs.pc, gram[0xCB00]);//*/ -//if (addr == 0xC80E) -/*if (addr >= 0xC800 && addr <= 0xC80F) - WriteLog("V6809 WrMem: Writing address %04X with %02X [PC=%04X, $CB00=%02X]\n", addr, b, mainCPU.pc, gram[0xCB00]);//*/ + memset(&mainCPU, 0, sizeof(V6809REGS)); + mainCPU.RdMem = RdMem6809; + mainCPU.WrMem = WrMem6809; + mainCPU.cpuFlags |= V6809_ASSERT_LINE_RESET; - gram[addr] = b; + memset(&soundCPU, 0, sizeof(V6808REGS)); + soundCPU.RdMem = RdMem6808; + soundCPU.WrMem = WrMem6808; + soundCPU.cpuFlags |= V6808_ASSERT_LINE_RESET; - if (addr > 0x0006 && addr < 0x97F7) // 304 pixels 152-128=24-16=8 + char ROMs[12][8] = { + "ROMs/01", "ROMs/02", "ROMs/03", "ROMs/04", "ROMs/05", "ROMs/06", + "ROMs/07", "ROMs/08", "ROMs/09", "ROMs/10", "ROMs/11", "ROMs/12" + }; + + for(int i=0; i<12; i++) { - // NOTE: Screen was 304 x 256, but we truncate the vertical dimension here... - uint16 sx = (addr >> 7) & 0x01FE, sy = addr & 0x00FF; + uint32_t baseAddress = i * 0x1000; - if (sy > 5 && sy < 246) + if (i > 8) + baseAddress += 0x4000; + + if (!LoadImg(ROMs[i], grom + baseAddress, 0x1000)) { - uint32 saddr = 8 + sx + ((sy - 6) * 320); // Calc screen address -//Hmm. This approach won't work with palette color cycling... -#if 0 - scrBuffer[saddr + 0] = b >> 4; - scrBuffer[saddr + 1] = b & 0x0F; -#else - scrBuffer[saddr + 0] = palette[color[b >> 4]]; - scrBuffer[saddr + 1] = palette[color[b & 0x0F]]; -#endif + WriteLog("Could not open file '%s'!\n", ROMs[i]); + return -1; } } - else if (addr >= 0xC000 && addr <= 0xC00F) -//Let's see if we can fix the color cycling here... [DONE] -#if 0 - color[addr - 0xC000] = b; // color[] from VIDEO.CPP (not any more!) -#else - { -// A better strategy here would probably be to set a flag when the color register changes, -// then change it before doing the render. -// ALSO: This approach doesn't take the color to the edges of the screen - color[addr - 0xC000] = b; - for(uint32 addr=0x0007; addr<0x97F7; addr++) - { - uint16 sx = (addr >> 7) & 0x01FE, sy = addr & 0x00FF; + if (!LoadImg(SOUNDROM, srom + 0xF800, 0x800)) + { + WriteLog("Could not open file '%s'!\n", SOUNDROM); + return -1; + } - if (sy > 5 && sy < 246) - { - uint32 saddr = 8 + sx + ((sy - 6) * 320); // Calc screen address - uint8 sb = gram[addr]; + WriteLog("Stargate ROM images loaded...\n"); + WriteLog("About to initialize video...\n"); - scrBuffer[saddr + 0] = palette[color[sb >> 4]]; - scrBuffer[saddr + 1] = palette[color[sb & 0x0F]]; - } - } + if (!InitVideo()) + { + cout << "Aborting!" << endl; + return -1; } -#endif - else if (addr == 0xC80E) + + // Have to do this *after* video init but *before* sound init...! + WriteLog("About to load machine state..."); + + if (!LoadMachineState()) + WriteLog("Machine state file not found!\n"); + else + WriteLog("done!\n"); + + if (!LoadImg(CMOS, gram + 0xCC00, 0x400)) + WriteLog("CMOS RAM not found!\n"); + + WriteLog("About to intialize audio...\n"); + SoundInit(); + keys = SDL_GetKeyboardState(NULL); + srom[0xF800] = 0x37; // Fix checksum so ST works... + running = true; // Set running status... + + InitializeEventList(); // Clear the event list before we use it... + SetCallbackTime(FrameCallback, FRAME_DURATION_IN_CYCLES * M6809_CYCLE_IN_USEC); + SetCallbackTime(ScanlineCallback, SG2_PIA_CALLBACK_DURATION); + clockFrameStart = mainCPU.clock; + startTicks = SDL_GetTicks(); + + WriteLog("Entering main loop...\n"); + + while (running) { - sram[0x0402] = b; // Connect PIAs in 6809 & 6808 - soundCPU.cpuFlags |= V6808_ASSERT_LINE_IRQ; // Start sound IRQ + double timeToNextEvent = GetTimeToNextEvent(); + Execute6809(&mainCPU, USEC_TO_M6809_CYCLES(timeToNextEvent)); + HandleNextEvent(); } -} -// -// 6808 memory functions -// +#ifdef __DEBUG__ +WriteLog("\n"); +WriteLog("$C900 = $%02X (0=RAM)\n", gram[0xC900]); +WriteLog("PC: %04X, X: %04X, Y: %04X, S: %04X, U: %04X, A: %02X, B: %02X, DP: %02X, CC: %02X\n", mainCPU.pc, mainCPU.x, mainCPU.y, mainCPU.s, mainCPU.u, mainCPU.a, mainCPU.b, mainCPU.dp, mainCPU.cc); +WriteLog("\n"); -uint8 RdMem6808(uint16 addr) +/*uint16_t pc = mainCPU.pc;//0x15BA; +for(int i=0; i<200; i++) +//while (pc < 0x9000) { - return (addr < 0xF000 ? sram[addr] : srom[addr]); -} + pc += Decode6809(pc); + WriteLog("\n"); +}//*/ -void WrMem6808(uint16 addr, uint8 b) +/*uint32_t pc = 0; +while (pc < 0xFFFF) { - sram[addr] = b; + pc += Decode6809(pc); + WriteLog("\n"); +}//*/ +#endif - // A total guess, but let's try it... -//It probably depends on how the PIA is configured, so this is most likely wrong. -// if (addr == 0x0401) -// soundCPU.cpuFlags &= ~V6808_ASSERT_LINE_IRQ; + SoundDone(); + VideoDone(); + SaveCMOS(); + SaveMachineState(); + LogDone(); + + return 0; } // // Load a file into RAM/ROM image space // -bool LoadImg(char * filename, uint8 * ram, int size) +bool LoadImg(const char * filename, uint8_t * ram, int size) { FILE * fp = fopen(filename, "rb"); if (fp == NULL) return false; - fread(ram, 1, size, fp); + size_t ignoredResult = fread(ram, 1, size, fp); fclose(fp); return true; @@ -198,7 +249,7 @@ void SaveCMOS(void) if (fp != NULL) { - fwrite(gram + 0xCC00, 1, 1024, fp); + size_t ignoredResult = fwrite(gram + 0xCC00, 1, 1024, fp); fclose(fp); } else @@ -216,19 +267,29 @@ bool LoadMachineState(void) return false; // This is kinda crappy--we don't do any sanity checking here!!! - fread(gram, 1, 0x10000, fp); - fread(sram, 1, 0x10000, fp); - fread(&mainCPU, 1, sizeof(V6809REGS), fp); - fread(&soundCPU, 1, sizeof(V6808REGS), fp); + size_t ignoredResult = fread(gram, 1, 0x10000, fp); + ignoredResult = fread(sram, 1, 0x10000, fp); + ignoredResult = fread(&mainCPU, 1, sizeof(V6809REGS), fp); + ignoredResult = fread(&soundCPU, 1, sizeof(V6808REGS), fp); fclose(fp); - for(int i=0x0006; i<0x97F8; i++) // Set up backbuffer... ;-) + // Set up backbuffer... ;-) + for(uint16_t i=0x0006; i<0x97F8; i++) // Screen memory WrMem6809(i, gram[i]); + for(uint16_t i=0xC000; i<=0xC00F; i++) // Palette memory + WrMem6809(i, gram[i]); + + paletteDirty = true; + mainCPU.RdMem = RdMem6809; // Make sure our function pointers are mainCPU.WrMem = WrMem6809; // pointing to the right places! soundCPU.RdMem = RdMem6808; soundCPU.WrMem = WrMem6808; + mainCPU.clock = 0; // Zero out our clocks... + soundCPU.clock = 0; + mainCPU.clockOverrun = 0; // And overrun values... +//notyet soundCPU.clockOverrun = 0; return true; } @@ -242,10 +303,10 @@ void SaveMachineState(void) if (fp != NULL) { - fwrite(gram, 1, 0x10000, fp); - fwrite(sram, 1, 0x10000, fp); - fwrite(&mainCPU, 1, sizeof(V6809REGS), fp); - fwrite(&soundCPU, 1, sizeof(V6808REGS), fp); + size_t ignoredResult = fwrite(gram, 1, 0x10000, fp); + ignoredResult = fwrite(sram, 1, 0x10000, fp); + ignoredResult = fwrite(&mainCPU, 1, sizeof(V6809REGS), fp); + ignoredResult = fwrite(&soundCPU, 1, sizeof(V6808REGS), fp); fclose(fp); } else @@ -253,311 +314,132 @@ void SaveMachineState(void) } // -// Main loop +// 6809 memory functions // -int main(int /*argc*/, char * /*argv*/[]) -{ - InitLog("stargem2.log"); - WriteLog("StarGem2 - A portable Stargate emulator by James L. Hammons\n"); - - LoadSettings(); - // Initialize Williams' palette (RGB coded as: 3 bits red, 3 bits green, 2 bits blue) - for(uint32 i=0; i<256; i++) - palette[i] = -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - (((i & 0x01) * 33 + ((i & 0x02) >> 1) * 71 + ((i & 0x04) >> 2) * 151) << 24) - | ((((i & 0x08) >> 3) * 33 + ((i & 0x10) >> 4) * 71 + ((i & 0x20) >> 5) * 151) << 16) - | ((((i & 0x40) >> 6) * 71 + ((i & 0x80) >> 7) * 151) << 8) | 0xFF; -#else - ((i & 0x01) * 33 + ((i & 0x02) >> 1) * 71 + ((i & 0x04) >> 2) * 151) - | ((((i & 0x08) >> 3) * 33 + ((i & 0x10) >> 4) * 71 + ((i & 0x20) >> 5) * 151) << 8) - | ((((i & 0x40) >> 6) * 71 + ((i & 0x80) >> 7) * 151) << 16) | 0xFF000000; +#ifdef LOG_PIA1_IO +char piaRegsName[4][10] = { "PORTA", "PACTL", "PORTB", "PBCTL" }; #endif +uint8_t RdMem6809(uint16_t addr) +{ + uint8_t b; - // Zero out memory - for(long i=0; i<0x10000; i++) - gram[i] = grom[i] = sram[i] = srom[i] = 0; - - // Set up V6809 & V6808 execution contexts - - memset(&mainCPU, sizeof(V6809REGS), 0); - mainCPU.RdMem = RdMem6809; - mainCPU.WrMem = WrMem6809; - mainCPU.cpuFlags |= V6809_ASSERT_LINE_RESET; - - memset(&soundCPU, sizeof(V6808REGS), 0); - soundCPU.RdMem = RdMem6808; - soundCPU.WrMem = WrMem6808; - soundCPU.cpuFlags |= V6808_ASSERT_LINE_RESET; - - char ROMs[12][8] = { - "ROMs/01", "ROMs/02", "ROMs/03", "ROMs/04", "ROMs/05", "ROMs/06", - "ROMs/07", "ROMs/08", "ROMs/09", "ROMs/10", "ROMs/11", "ROMs/12" - }; - - for(int i=0; i<12; i++) + if (addr >= 0x9000 && addr <= 0xCFFF) // No ROM between $9000 - $CFFF... + b = gram[addr]; + else { - uint32 baseAddress = i * 0x1000; - - if (i > 8) - baseAddress += 0x4000; + if (!gram[0xC900] && addr <= 0x8FFF) // Check RAM $C900 bank switch + b = gram[addr]; + else + b = grom[addr]; + } + // A wee kludge (though I doubt it reads from anywhere other than $CB00)... + if ((addr & 0xFF00) == 0xCB00) #if 0 -WriteLog("Loading ROM image '%s' at $%04X...\n", ROMs[i], baseAddress); -#endif -// if (!LoadImg(ROMs[i], grom + (i * 0x1000), 0x1000)) - if (!LoadImg(ROMs[i], grom + baseAddress, 0x1000)) - { - WriteLog("Could not open file '%s'!\n", ROMs[i]); - return -1; - } + b = gram[0xCB00] & 0xFC; // Only bits 2-7 are connected... +#else + { +//Interesting, this code ALSO fucks up the demo... +//Except when the correct code is called in the scanline callback function... + uint32_t elapsedCycles = (uint32_t)(GetCurrentV6809Clock() - clockFrameStart); + uint32_t scanline = (uint32_t)((double)elapsedCycles / SCANLINE_DURATION_IN_CYCLES); +//Changes here don't seem to do much... +// uint32_t scanline = (uint32_t)(((double)elapsedCycles * M6809_CYCLE_IN_USEC) / 70.0); + b = (uint8_t)scanline & 0xFC; // Only bits 2-7 are connected... } +#endif - if (!LoadImg(SOUNDROM, srom + 0xF800, 0x800)) + // More kludge... + if ((addr == 0xC80C) && (gram[0xC80D] & 0x04)) // Read PORTA and DDR is set to Output { - WriteLog("Could not open file '%s'!\n", SOUNDROM); - return -1; + ClearLineOfCurrentV6809(V6809_ASSERT_LINE_IRQ); // Then clear the IRQ +//OK, this ALSO fucks up the execution of the demo... +// Which means that the timing is still off. :-/ +// mainCPU.cpuFlags &= ~V6809_ASSERT_LINE_IRQ; // Then clear the IRQ } - WriteLog("Stargate ROM images loaded...\n"); - WriteLog("About to initialize video...\n"); - - if (!InitVideo()) + if ((addr == 0xC80E) && (gram[0xC80F] & 0x04)) // Read PORTB and DDR is set to Output { - cout << "Aborting!" << endl; - return -1; + ClearLineOfCurrentV6809(V6809_ASSERT_LINE_IRQ); // Then clear the IRQ +//OK, this ALSO fucks up the execution of the demo... +// mainCPU.cpuFlags &= ~V6809_ASSERT_LINE_IRQ; // Then clear the IRQ } - // Have to do this *after* video init but *before* sound init...! - WriteLog("About to load machine state..."); - - if (!LoadMachineState()) - WriteLog("Machine state file not found!\n"); - else - WriteLog("done!\n"); - - if (!LoadImg(CMOS, gram + 0xCC00, 0x400)) - WriteLog("CMOS RAM not found!\n"); - - WriteLog("About to intialize audio...\n"); - SoundInit(); -// uint8 * keys = SDL_GetKeyState(NULL); - keys = SDL_GetKeyState(NULL); - -// running = true; // Set running status... - srom[0xF800] = 0x37; // Fix checksum so ST works... +//temp... +/*extern uint16_t pcr; +//if (addr >= 0xC000 && addr <= 0xCBFF) +if (addr == 0x9C59) + WriteLog("RdMem: Reading address %04X [=%02X, PC=%04X]\n", addr, b, pcr);//*/ +#ifdef LOG_PIA1_IO +/*if (addr >= 0xC80C && addr <= 0xC80F) + WriteLog("V6809 RdMem: Reading PIA (%s) address %04X [<-%02X, PC=%04X]\n", piaRegsName[addr&0x03], addr, b, GetCurrentV6809PC());//*/ +#endif + return b; +} -#if 0 +void WrMem6809(uint16_t addr, uint8_t b) +{ +//temp... +//extern V6809REGS regs; +//if (addr >= 0xC800 && addr <= 0xCBFE) +//if (addr == 0xC80F || addr == 0xC80D) +// WriteLog("WrMem: Writing address %04X with %02X [PC=%04X, $CB00=%02X]\n", addr, b, regs.pc, gram[0xCB00]);//*/ +//if (addr == 0xC80E) +/*if (addr >= 0xC800 && addr <= 0xC80F) + WriteLog("V6809 WrMem: Writing address %04X with %02X [PC=%04X, $CB00=%02X]\n", addr, b, mainCPU.pc, gram[0xCB00]);//*/ -//kludge... -//This didn't work--it still acted like the old way (interrupt @ VC = 0) -//gram[0xCB00] = 64*3; + gram[addr] = b; - WriteLog("Entering main loop...\n"); - while (running) + if (addr >= 0x0006 && addr < 0x97F7) // 304 pixels 152-128=24-16=8 { - SDL_PumpEvents(); // Force key events into the buffer. - gram[0xC804] = gram[0xC806] = gram[0xC80C] = 0; // Reset PIA ports... - - if (keys[SDLK_ESCAPE]) - running = false; // ESC to exit... - - if (keys[SDLK_SEMICOLON]) - gram[0xC804] |= 0x01; // Fire (;) - if (keys[SDLK_l]) - gram[0xC804] |= 0x02; // Thrust (L) - if (keys[SDLK_SPACE]) - gram[0xC804] |= 0x04; // Smart Bomb (space) - if (keys[SDLK_BACKSPACE]) - gram[0xC804] |= 0x08; // Hyperspace (BkSp) - if (keys[SDLK_2]) - gram[0xC804] |= 0x10; // Two Player Start (2) - if (keys[SDLK_1]) - gram[0xC804] |= 0x20; // One Player Start (1) - if (keys[SDLK_RETURN]) - gram[0xC804] |= 0x40; // Reverse (Enter) - if (keys[SDLK_f]) - gram[0xC804] |= 0x80; // Down (F) - - if (keys[SDLK_r]) - gram[0xC806] |= 0x01; // Up (R) - if (keys[SDLK_a]) - gram[0xC806] |= 0x02; // Inviso (A) - - if (keys[SDLK_F1]) - gram[0xC80C] |= 0x01; // Auto up (F1) - if (keys[SDLK_F2]) - gram[0xC80C] |= 0x02; // Advance (F2) - if (keys[SDLK_5]) - gram[0xC80C] |= 0x04; // Right Coin (5) - if (keys[SDLK_F3]) - gram[0xC80C] |= 0x08; // High Score Reset (F3) - if (keys[SDLK_3]) - gram[0xC80C] |= 0x10; // Left Coin (3) - if (keys[SDLK_4]) - gram[0xC80C] |= 0x20; // Center Coin (4) - if (keys[SDLK_F4]) - gram[0xC80C] |= 0x40; // Slam Switch (F4) - - if (keys[SDLK_F5]) // Sound CPU self-test (F5) - soundCPU.cpuFlags |= V6808_ASSERT_LINE_NMI; - if (keys[SDLK_F6]) // Reset the 6808 (F6) - soundCPU.cpuFlags |= V6808_ASSERT_LINE_RESET; - -/* -$CB00 is scanline counter, bits 2-7 (1 frame/240 =69.44... usec) - -Some places of interest to look at: - -RdMem: Reading address C80E [=0C, PC=15C3] <- Inside interrupt (read, then discarded)... -RdMem: Reading address CB00 [=43, PC=15C6] <- interrupt -RdMem: Reading address C80C [=00, PC=0758] <- input (?) -RdMem: Reading address C80C [=00, PC=07B9] <- input (?) -RdMem: Reading address C806 [=00, PC=078C] <- input -RdMem: Reading address C804 [=00, PC=2679] <- input -*/ - uint32 startTicks = SDL_GetTicks(); -// long video_clk = 0; -// gram[0xCB00] = 0; - -/* -//This is where the interrupt mask is restored in CC... Hmm... -//This enables interrupts *after* the previous interrupt has occurred... Hmm. -//Could $C80F (rom_pia_ctrlb) be the IRQ inhibit? Yes, it is! - - // the IRQ signal comes into CB1, and is set to VA11 - pia_1_cb1_w(0, scanline & 0x20); -... - // the COUNT240 signal comes into CA1, and is set to the logical AND of VA10-VA13 - pia_1_ca1_w(0, 0); -... - // the COUNT240 signal comes into CA1, and is set to the logical AND of VA10-VA13 - pia_1_ca1_w(0, 1); -*/ + // NOTE: Screen was 304 x 256, but we truncate the vertical dimension here... + uint16_t sx = (addr >> 7) & 0x01FE, sy = addr & 0x00FF; -//WriteLog("--> Start of frame...\n"); - for(int i=0; i<3; i++) + if (sy > 5 && sy < 246) { -//Not sure, but this *might* fix IRQ problem... -//Checking the PIA IRQ mask for an IRQ seems to work OK. Now if only the timing elsewhere was right... - if (gram[0xC80F] & 0x01) - mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ;//*/ - - Execute6809(&mainCPU, 4000); - mainCPU.clock -= 4000; // Remove 4K ticks from clock (in case it overflowed) -//Not sure, but this *might* fix IRQ problem... -//Checking the PIA IRQ mask for an IRQ seems to work OK. Now if only the timing elsewhere was right... -/* if (gram[0xC80F] & 0x01) - mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ;//*/ - - gram[0xCB00] += 64; // Update video counter... + uint32_t saddr = 8 + sx + ((sy - 6) * 320); // Calc screen address + scrBuffer[saddr + 0] = palette[color[b >> 4]]; + scrBuffer[saddr + 1] = palette[color[b & 0x0F]]; } - -//Hmm. -/*if (gram[0xC80E] & 0x01) - mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ;//*/ -//48 lines... (+ 16) -//gram[0xCB00] = 0; - Execute6809(&mainCPU, 3000); - mainCPU.clock -= 3000; // Remove 3K ticks from clock (in case it overflowed) -//Not sure, but this *might* fix IRQ problem... -//if (gram[0xC80F] & 0x01) -//This isn't the right port on the PIA, but it does seem to make it through the demo now... -//Lesse if this works... Seems to! - if (gram[0xC80D] & 0x01) // Do COUNT240 IRQ (if enabled!) - mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ; - -/*if (gram[0xC80F] & 0x01) - mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ; -gram[0xCB00] = 0; //*/ - - gram[0xCB00] += 48; // Update video counter... - - Execute6809(&mainCPU, 1000); - mainCPU.clock -= 1000; // Remove 1K ticks from clock (in case it overflowed) -//Eh? -//Ok, this is the interrupt it's looking for, but still... -//if (gram[0xC80F] & 0x01) -// mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ; - - gram[0xCB00] += 16; // Update video counter... - -// RenderScreenBuffer(); - RenderScreenBuffer2(); // 1 frame = 16667 cycles -// WriteLog("Main: Rendered back buffer. [6809 PC=%04X]\n", pcr); - - Execute6809(&mainCPU, 667); // Do QnD VBLANK - - // 1/60 sec = ? ms (16.6 ms) - while (SDL_GetTicks() - startTicks < 16); // Wait for next frame... - -//kludge, temp... -//Very interesting! It's the palette rotation that's slowing it down! -//Fixed now, but this allows the color rotation while the wrong timing is in effect... -/*for(int i=0; i<16; i++) - WrMem(0xC000 + i, gram[0x9C26 + i]);//*/ } - -/*uint16 pc = 0x15BA; -for(int i=0; i<200; i++) -//while (pc < 0x9000) - pc += Decode6809(pc);//*/ - -#else - - running = true; // Set running status... - - InitializeEventList(); // Clear the event list before we use it... - SetCallbackTime(FrameCallback, 16666.66666667); // Set frame to fire at 1/60 s interval -// SetCallbackTime(BlinkTimer, 250000); // Set up blinking at 1/4 s intervals - SetCallbackTime(ScanlineCallback, 520.83333334); // Set scanline callback at 1/32 of frame -// SetCallbackTime(ScanlineCallback, 520.83333334*32.00); // Set scanline callback at 1/32 of frame - startTicks = SDL_GetTicks(); - - WriteLog("Entering main loop...\n"); - - while (running) + else if (addr >= 0xC000 && addr <= 0xC00F) { - double timeToNextEvent = GetTimeToNextEvent(); - Execute6809(&mainCPU, USEC_TO_M6809_CYCLES(timeToNextEvent)); -//We MUST remove a frame's worth of time in order for the CPU to function... !!! FIX !!! -//(Fix so that this is not a requirement!) - mainCPU.clock -= USEC_TO_M6809_CYCLES(timeToNextEvent); - HandleNextEvent(); +// This approach doesn't take the BG color to the edges of the screen + color[addr - 0xC000] = b; + paletteDirty = true; + } + else if (addr == 0xC80E) + { + sram[0x0402] = b; // Connect PIAs in 6809 & 6808 + soundCPU.cpuFlags |= V6808_ASSERT_LINE_IRQ; // Start sound IRQ } -#ifdef __DEBUG__ -WriteLog("\n"); -WriteLog("$C900 = $%02X (0=RAM)\n", gram[0xC900]); -WriteLog("PC: %04X, X: %04X, Y: %04X, S: %04X, U: %04X, A: %02X, B: %02X, DP: %02X, CC: %02X\n", mainCPU.pc, mainCPU.x, mainCPU.y, mainCPU.s, mainCPU.u, mainCPU.a, mainCPU.b, mainCPU.dp, mainCPU.cc); -WriteLog("\n"); +#ifdef LOG_PIA1_IO +//if (addr >= 0xC80C && addr <= 0xC80F) +if (addr == 0xC80D) + WriteLog("V6809 WrMem: Writing PIA (%s) address %04X [->%02X, PC=%04X]\n", piaRegsName[addr&0x03], addr, b, GetCurrentV6809PC());//*/ +#endif +} -/*uint16 pc = mainCPU.pc;//0x15BA; -for(int i=0; i<200; i++) -//while (pc < 0x9000) -{ - pc += Decode6809(pc); - WriteLog("\n"); -}//*/ +// +// 6808 memory functions +// -/*uint32 pc = 0; -while (pc < 0xFFFF) +uint8_t RdMem6808(uint16_t addr) { - pc += Decode6809(pc); - WriteLog("\n"); -}//*/ -#endif - -#endif + return (addr < 0xF000 ? sram[addr] : srom[addr]); +} - SoundDone(); - VideoDone(); - SaveCMOS(); - SaveMachineState(); - LogDone(); +void WrMem6808(uint16_t addr, uint8_t b) +{ + sram[addr] = b; - return 0; + // A total guess, but let's try it... +//It probably depends on how the PIA is configured, so this is most likely wrong. +// It is wrong: IRQs are cleared on PIA PORTx reads! +// if (addr == 0x0401) +// soundCPU.cpuFlags &= ~V6808_ASSERT_LINE_IRQ; } static void FrameCallback(void) @@ -565,81 +447,110 @@ static void FrameCallback(void) SDL_PumpEvents(); // Force key events into the buffer. gram[0xC804] = gram[0xC806] = gram[0xC80C] = 0; // Reset PIA ports... - if (keys[SDLK_ESCAPE]) + if (keys[SDL_SCANCODE_ESCAPE]) running = false; // ESC to exit... -//Convert this stuff to use the settings module... !!! FIX !!! - if (keys[SDLK_SEMICOLON]) - gram[0xC804] |= 0x01; // Fire (;) - if (keys[SDLK_l]) - gram[0xC804] |= 0x02; // Thrust (L) - if (keys[SDLK_SPACE]) - gram[0xC804] |= 0x04; // Smart Bomb (space) - if (keys[SDLK_BACKSPACE]) - gram[0xC804] |= 0x08; // Hyperspace (BkSp) - if (keys[SDLK_2]) - gram[0xC804] |= 0x10; // Two Player Start (2) - if (keys[SDLK_1]) - gram[0xC804] |= 0x20; // One Player Start (1) - if (keys[SDLK_RETURN]) - gram[0xC804] |= 0x40; // Reverse (Enter) - if (keys[SDLK_f]) - gram[0xC804] |= 0x80; // Down (F) - - if (keys[SDLK_r]) - gram[0xC806] |= 0x01; // Up (R) - if (keys[SDLK_a]) - gram[0xC806] |= 0x02; // Inviso (A) - - if (keys[SDLK_F1]) - gram[0xC80C] |= 0x01; // Auto up (F1) - if (keys[SDLK_F2]) - gram[0xC80C] |= 0x02; // Advance (F2) - if (keys[SDLK_5]) - gram[0xC80C] |= 0x04; // Right Coin (5) - if (keys[SDLK_F3]) - gram[0xC80C] |= 0x08; // High Score Reset (F3) - if (keys[SDLK_3]) - gram[0xC80C] |= 0x10; // Left Coin (3) - if (keys[SDLK_4]) - gram[0xC80C] |= 0x20; // Center Coin (4) - if (keys[SDLK_F4]) - gram[0xC80C] |= 0x40; // Slam Switch (F4) - - if (keys[SDLK_F5]) // Sound CPU self-test (F5) + if (keys[settings.keyBindings[S_KEY_FIRE]]) gram[0xC804] |= 0x01; + if (keys[settings.keyBindings[S_KEY_THRUST]]) gram[0xC804] |= 0x02; + if (keys[settings.keyBindings[S_KEY_SMARTBOMB]]) gram[0xC804] |= 0x04; + if (keys[settings.keyBindings[S_KEY_HYPERSPACE]]) gram[0xC804] |= 0x08; + if (keys[settings.keyBindings[S_KEY_2P_START]]) gram[0xC804] |= 0x10; + if (keys[settings.keyBindings[S_KEY_1P_START]]) gram[0xC804] |= 0x20; + if (keys[settings.keyBindings[S_KEY_REVERSE]]) gram[0xC804] |= 0x40; + if (keys[settings.keyBindings[S_KEY_DOWN]]) gram[0xC804] |= 0x80; + + if (keys[settings.keyBindings[S_KEY_UP]]) gram[0xC806] |= 0x01; + if (keys[settings.keyBindings[S_KEY_INVISO]]) gram[0xC806] |= 0x02; + + if (keys[settings.keyBindings[S_KEY_AUTO_UP]]) gram[0xC80C] |= 0x01; + if (keys[settings.keyBindings[S_KEY_ADVANCE]]) gram[0xC80C] |= 0x02; + if (keys[settings.keyBindings[S_KEY_RIGHT_COIN]]) gram[0xC80C] |= 0x04; + if (keys[settings.keyBindings[S_KEY_HS_RESET]]) gram[0xC80C] |= 0x08; + if (keys[settings.keyBindings[S_KEY_LEFT_COIN]]) gram[0xC80C] |= 0x10; + if (keys[settings.keyBindings[S_KEY_CENTER_COIN]]) gram[0xC80C] |= 0x20; + if (keys[settings.keyBindings[S_KEY_SLAM_SWITCH]]) gram[0xC80C] |= 0x40; + + if (keys[SDL_SCANCODE_F5]) // Sound CPU self-test (F5) soundCPU.cpuFlags |= V6808_ASSERT_LINE_NMI; - if (keys[SDLK_F6]) // Reset the 6808 (F6) + if (keys[SDL_SCANCODE_F6]) // Reset the 6808 (F6) soundCPU.cpuFlags |= V6808_ASSERT_LINE_RESET; +//Temp, for testing... +extern bool disasm; +//disasm = true; + if (keys[SDL_SCANCODE_F9]) + disasm = true; + + if (paletteDirty) + { + for(uint32_t addr=0x0006; addr<0x97F7; addr++) + { + uint16_t sx = (addr >> 7) & 0x01FE, sy = addr & 0x00FF; + + if (sy > 5 && sy < 246) + { + uint32_t saddr = 8 + sx + ((sy - 6) * 320); // Calc screen address + uint8_t sb = gram[addr]; + + scrBuffer[saddr + 0] = palette[color[sb >> 4]]; + scrBuffer[saddr + 1] = palette[color[sb & 0x0F]]; + } + } + + paletteDirty = false; + } + + static bool fullscreenDebounce = false; + + if (keys[SDL_SCANCODE_F12]) + { + if (!fullscreenDebounce) + { + ToggleFullScreen(); + fullscreenDebounce = true; + } + } + else + fullscreenDebounce = false; + + RenderScreenBuffer(); // 1 frame = 1/60 sec ~ 16667 cycles + clockFrameStart = mainCPU.clock; - RenderScreenBuffer2(); // 1 frame = 1/60 sec ~ 16667 cycles - SetCallbackTime(FrameCallback, 16666.66666667); + // Wait for next frame... + while (SDL_GetTicks() - startTicks < 16) + SDL_Delay(1); - while (SDL_GetTicks() - startTicks < 16); // Wait for next frame... startTicks = SDL_GetTicks(); + SetCallbackTime(FrameCallback, FRAME_DURATION_IN_CYCLES * M6809_CYCLE_IN_USEC); } static void ScanlineCallback(void) { -// CA1 of PIA 1 maps to $C80C-F... <-- Count240 is in PIA1... -// What about COUNT240??? - -//wil wok? Yes, but still screws up on the demo... -/* if (gram[0xCB00] & 0x20) - if (gram[0xC80F] & 0x01) - mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ;//*/ +#if 0 if ((gram[0xCB00] & 0x20) && (gram[0xC80F] & 0x01)) mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ;//*/ +#else + mainCPU.cpuFlags &= ~V6809_ASSERT_LINE_IRQ; -//Is $C80E COUNT240? Hmm... Doesn't seem to be. Bleh. -/* if (gram[0xCB00] >= 240) - gram[0xC80E] = 0xFF; - else - gram[0xC80E] = 0x00;//*/ -// gram[0xC80E] = (gram[0xCB00] >= 240 ? 0xFF : 0x00); + if ((RdMem6809(0xCB00) & 0x20) && (gram[0xC80F] & 0x01)) + mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ;//*/ +#endif - gram[0xCB00] += 8; // Update video counter... +/* +The problem is that this is already asserted above, by virtue of the fact that +240 = $F0 = bit 5 is set! So this does nothing! So obviously, the above IRQ assertion +is wrong--just need to figure out how the write of $20 and $00 affects the PBCTRL in the PIA. +It looks like Stargate never asserts the COUNT240 IRQ, and could be because of the above... - SetCallbackTime(ScanlineCallback, 520.83333334); // Set scanline callback at 1/32 of frame +Apparently, COUNT240 is unimportant, at least as far as STARGATE is concerned... +*/ +// if ((gram[0xCB00] >= 240) && (gram[0xC80D] & 0x09)) // Do COUNT240 IRQ (if enabled!) +// mainCPU.cpuFlags |= V6809_ASSERT_LINE_IRQ; + + // This should set everything between $CB00-CBFF... +// gram[0xCB00] += 8; // Update video counter... +// gram[0xCB00] += 4; // Update video counter... + + SetCallbackTime(ScanlineCallback, SG2_PIA_CALLBACK_DURATION); } @@ -1025,3 +936,226 @@ PIA initialization: */ +#if 0 + +#define PIA_IRQ1 (0x80) +#define PIA_IRQ2 (0x40) + +#define IRQ1_ENABLED(c) ( (((c) >> 0) & 0x01)) +#define C1_LOW_TO_HIGH(c) ( (((c) >> 1) & 0x01)) +#define C1_HIGH_TO_LOW(c) (!(((c) >> 1) & 0x01)) +#define OUTPUT_SELECTED(c) ( (((c) >> 2) & 0x01)) +#define IRQ2_ENABLED(c) ( (((c) >> 3) & 0x01)) +#define STROBE_E_RESET(c) ( (((c) >> 3) & 0x01)) +#define STROBE_C1_RESET(c) (!(((c) >> 3) & 0x01)) +#define C2_SET(c) ( (((c) >> 3) & 0x01)) +#define C2_LOW_TO_HIGH(c) ( (((c) >> 4) & 0x01)) +#define C2_HIGH_TO_LOW(c) (!(((c) >> 4) & 0x01)) +#define C2_SET_MODE(c) ( (((c) >> 4) & 0x01)) +#define C2_STROBE_MODE(c) (!(((c) >> 4) & 0x01)) +#define C2_OUTPUT(c) ( (((c) >> 5) & 0x01)) +#define C2_INPUT(c) (!(((c) >> 5) & 0x01)) + +WRITE8_DEVICE_HANDLER( pia6821_ca1_w ) +{ + pia6821_state *p = get_token(device); + + /* limit the data to 0 or 1 */ + data = data ? TRUE : FALSE; + + LOG(("PIA #%s: set input CA1 = %d\n", device->tag, data)); + + /* the new state has caused a transition */ + if ((p->in_ca1 != data) && + ((data && C1_LOW_TO_HIGH(p->ctl_a)) || (!data && C1_HIGH_TO_LOW(p->ctl_a)))) + { + LOG(("PIA #%s: CA1 triggering\n", device->tag)); + + /* mark the IRQ */ + p->irq_a1 = TRUE; + + /* update externals */ + update_interrupts(device); + + /* CA2 is configured as output and in read strobe mode and cleared by a CA1 transition */ + if (C2_OUTPUT(p->ctl_a) && C2_STROBE_MODE(p->ctl_a) && STROBE_C1_RESET(p->ctl_a)) + set_out_ca2(device, TRUE); + } + + /* set the new value for CA1 */ + p->in_ca1 = data; + p->in_ca1_pushed = TRUE; +} + +WRITE8_DEVICE_HANDLER( pia6821_cb1_w ) +{ + pia6821_state *p = get_token(device); + + /* limit the data to 0 or 1 */ + data = data ? 1 : 0; + + LOG(("PIA #%s: set input CB1 = %d\n", device->tag, data)); + + /* the new state has caused a transition */ + if ((p->in_cb1 != data) && + ((data && C1_LOW_TO_HIGH(p->ctl_b)) || (!data && C1_HIGH_TO_LOW(p->ctl_b)))) + { + LOG(("PIA #%s: CB1 triggering\n", device->tag)); + + /* mark the IRQ */ + p->irq_b1 = 1; + + /* update externals */ + update_interrupts(device); + + /* If CB2 is configured as a write-strobe output which is reset by a CB1 + transition, this reset will only happen when a read from port B implicitly + clears the IRQ B1 flag. So we handle the CB2 reset there. Note that this + is different from what happens with port A. */ + } + + /* set the new value for CB1 */ + p->in_cb1 = data; + p->in_cb1_pushed = TRUE; +} + +static void update_interrupts(const device_config *device) +{ + pia6821_state *p = get_token(device); + int new_state; + + /* start with IRQ A */ + new_state = (p->irq_a1 && IRQ1_ENABLED(p->ctl_a)) || (p->irq_a2 && IRQ2_ENABLED(p->ctl_a)); + + if (new_state != p->irq_a_state) + { + p->irq_a_state = new_state; + devcb_call_write_line(&p->irq_a_func, p->irq_a_state); + } + + /* then do IRQ B */ + new_state = (p->irq_b1 && IRQ1_ENABLED(p->ctl_b)) || (p->irq_b2 && IRQ2_ENABLED(p->ctl_b)); + + if (new_state != p->irq_b_state) + { + p->irq_b_state = new_state; + devcb_call_write_line(&p->irq_b_func, p->irq_b_state); + } +} + +static void control_b_w(const device_config *device, UINT8 data) +{ + pia6821_state *p = get_token(device); + int temp; + + /* bit 7 and 6 are read only */ + data &= 0x3f; + + LOG(("PIA #%s: control B write = %02X\n", device->tag, data)); + + /* update the control register */ + p->ctl_b = data; + + if (C2_SET_MODE(p->ctl_b)) + /* set/reset mode - bit value determines the new output */ + temp = C2_SET(p->ctl_b); + else + /* strobe mode - output is always high unless strobed */ + temp = TRUE; + + set_out_cb2(device, temp); + + /* update externals */ + update_interrupts(device); +} + +static void control_a_w(const device_config *device, UINT8 data) +{ + pia6821_state *p = get_token(device); + + /* bit 7 and 6 are read only */ + data &= 0x3f; + + LOG(("PIA #%s: control A write = %02X\n", device->tag, data)); + + /* update the control register */ + p->ctl_a = data; + + /* CA2 is configured as output */ + if (C2_OUTPUT(p->ctl_a)) + { + int temp; + + if (C2_SET_MODE(p->ctl_a)) + /* set/reset mode - bit value determines the new output */ + temp = C2_SET(p->ctl_a); + else + /* strobe mode - output is always high unless strobed */ + temp = TRUE; + + set_out_ca2(device, temp); + } + + /* update externals */ + update_interrupts(device); +} + + +CTRL REGISTER: + +B7 B6 B5 B4 B3 B2 B1 B0 +-------------------------------------------------- +IRQA(B)1 IRQA(B)2 CA(B)2 Ctrl DDR CA(B)1 Ctrl + +Bits 6 & 7 are RO. IRQs are cleared on read of PORTA when not in DDR mode +DDR: 0: DDR selected, 1: Output register selected +CA1(CB1) Ctrl: B0: 0/1 Dis/enable interrupt IRQA(B) + B1: 0/1 IRQ set by Hi-to-Lo/Lo-to-Hi transition on CA(B)1 +CA2(CB2) Ctrl: If B5==0, B4 & B3 are similar to B1 & B0 + +Entering main loop... +V6809 WrMem: Writing PIA (PACTL) address C80D [->00, PC=F4DC] --> Set DDR on PORTA, IRQs off +V6809 WrMem: Writing PIA (PORTA) address C80C [->00, PC=F4DF] --> Set DDR to all input on PORTA +V6809 WrMem: Writing PIA (PACTL) address C80D [->3C, PC=F4E4] --> Set Output on PORTA, Set CA2 = 1, disable IRQA1 +V6809 WrMem: Writing PIA (PBCTL) address C80F [->00, PC=F4E7] --> Set DDR on PORTB, IRQs off +V6809 WrMem: Writing PIA (PORTB) address C80E [->C0, PC=F4EC] --> Set DDR to output on 6,7 input on 0-5 on PORTB +V6809 WrMem: Writing PIA (PBCTL) address C80F [->3C, PC=F4F1] --> Set Output on PORTA, Set CB2 = 1, disable IRQB1 +V6809 WrMem: Writing PIA (PORTB) address C80E [->C0, PC=F4F6] --> Send 1s on bits 6 & 7 on PORTB +V6809 WrMem: Writing PIA (PACTL) address C80D [->34, PC=F523] --> Set Output on PORTA, Set CA2 = 0, disable IRQA1 +V6809 WrMem: Writing PIA (PBCTL) address C80F [->34, PC=F526] --> Set Output on PORTB, Set CB2 = 0, disable IRQB1 +V6809 WrMem: Writing PIA (PORTB) address C80E [->00, PC=F529] --> Send 0s on bits 6 & 7 on PORTB +V6809 WrMem: Writing PIA (PORTA) address C80C [->00, PC=6076] --> Do nothing +V6809 WrMem: Writing PIA (PACTL) address C80D [->00, PC=6076] --> Set DDR on PORTA, IRQs off +V6809 WrMem: Writing PIA (PORTA) address C80C [->00, PC=607B] --> Set DDR to all input on PORTA +V6809 WrMem: Writing PIA (PACTL) address C80D [->34, PC=607B] --> Set Output on PORTA, Set CA2 = 0, disable IRQA1 +V6809 WrMem: Writing PIA (PORTB) address C80E [->00, PC=6076] --> Send 0s on bits 6 & 7 on PORTB +V6809 WrMem: Writing PIA (PBCTL) address C80F [->00, PC=6076] --> Set DDR on PORTB, IRQs off +V6809 WrMem: Writing PIA (PORTB) address C80E [->FF, PC=607B] --> Set DDR to all output on PORTB +V6809 WrMem: Writing PIA (PBCTL) address C80F [->35, PC=607B] --> Set Output on PORTB, Set CB2 = 0, enable IRQB1 +V6809 WrMem: Writing PIA (PORTB) address C80E [->3F, PC=6088] --> Send $3F on PORTB +V6809 WrMem: Writing PIA (PORTB) address C80E [->0C, PC=60DB] --> Send $0C on PORTB +V6809 WrMem: Writing PIA (PBCTL) address C80F [->34, PC=15C3] --> Set Output on PORTB, Set CB2 = 0, disable IRQB1 + 6809 RdMem: Reading PIA (PORTB) address C80E [=0C, PC=15C6] --> Clear IRQBs + 6809 RdMem: Reading PIA (PORTA) address C80C [=00, PC=075B] --> Clear IRQAs + 6809 RdMem: Reading PIA (PORTA) address C80C [=00, PC=07B9] --> Clear IRQAs + +V6809 WrMem: Writing PIA (PBCTL) address C80F [->35, PC=1644] --> Set Output on PORTB, Set CB2 = 0, enable IRQB1 +V6809 WrMem: Writing PIA (PBCTL) address C80F [->34, PC=15C3] --> Set Output on PORTB, Set CB2 = 0, disable IRQB1 + 6809 RdMem: Reading PIA (PORTB) address C80E [=0C, PC=15C6] --> Clear IRQBs +V6809 WrMem: Writing PIA (PBCTL) address C80F [->35, PC=1644] +V6809 WrMem: Writing PIA (PBCTL) address C80F [->34, PC=15C3] + 6809 RdMem: Reading PIA (PORTB) address C80E [=0C, PC=15C6] +V6809 WrMem: Writing PIA (PBCTL) address C80F [->35, PC=1644] +V6809 WrMem: Writing PIA (PBCTL) address C80F [->34, PC=15C3] + 6809 RdMem: Reading PIA (PORTB) address C80E [=0C, PC=15C6] +V6809 WrMem: Writing PIA (PBCTL) address C80F [->35, PC=1644] +V6809 WrMem: Writing PIA (PBCTL) address C80F [->34, PC=15C3] + 6809 RdMem: Reading PIA (PORTB) address C80E [=0C, PC=15C6] +V6809 WrMem: Writing PIA (PBCTL) address C80F [->35, PC=1644] +V6809 WrMem: Writing PIA (PBCTL) address C80F [->34, PC=15C3] + 6809 RdMem: Reading PIA (PORTB) address C80E [=0C, PC=15C6] +V6809 WrMem: Writing PIA (PBCTL) address C80F [->35, PC=1644] +V6809 WrMem: Writing PIA (PBCTL) address C80F [->34, PC=15C3] + 6809 RdMem: Reading PIA (PORTB) address C80E [=0C, PC=15C6] + +#endif