From 6bdd378e27a9bbf3a074e9c33c61195c8fcfef1c Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Sun, 16 Sep 2018 21:45:27 -0500 Subject: [PATCH] Conversion of V65C02 to pointers, misc. whitespace cleanups. --- Makefile | 3 +- src/apple2.cpp | 6 +- src/ay8910.cpp | 1 + src/crc32.cpp | 63 ++++ src/crc32.h | 13 + src/dis65c02.cpp | 55 ++-- src/dis65c02.h | 5 +- src/floppy.h | 1 + src/mmu.cpp | 2 +- src/sound.cpp | 53 +--- src/sound.h | 2 +- src/v65c02.cpp | 800 +++++++++++++++++++---------------------------- src/v65c02.h | 10 +- src/video.h | 37 +-- 14 files changed, 467 insertions(+), 584 deletions(-) create mode 100644 src/crc32.cpp create mode 100644 src/crc32.h diff --git a/Makefile b/Makefile index e6515e8..449664c 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # Unified Makefile for Apple 2 SDL # # by James Hammons -# (C) 2005-17 Underground Software +# (C) 2005-2018 Underground Software # This software is licensed under the GPL v3 # @@ -109,6 +109,7 @@ OBJS = \ obj/apple2-icon-64x64.o \ obj/ay8910.o \ obj/charset.o \ + obj/crc32.o \ obj/dis65c02.o \ obj/firmware.o \ obj/floppy.o \ diff --git a/src/apple2.cpp b/src/apple2.cpp index cb61084..b9bd4ff 100644 --- a/src/apple2.cpp +++ b/src/apple2.cpp @@ -494,7 +494,7 @@ static void AppleTimer(uint16_t cycles) if (mbvia[0].ier & 0x40) { mbvia[0].ifr |= (0x80 | 0x40); - AssertLine(V65C02_ASSERT_LINE_IRQ); + mainCPU.cpuFlags |= V65C02_ASSERT_LINE_IRQ; } } else @@ -512,7 +512,7 @@ static void AppleTimer(uint16_t cycles) if (mbvia[1].ier & 0x40) { mbvia[1].ifr |= (0x80 | 0x40); - AssertLine(V65C02_ASSERT_LINE_NMI); + mainCPU.cpuFlags |= V65C02_ASSERT_LINE_NMI; } } else @@ -531,7 +531,7 @@ static void AppleTimer(uint16_t cycles) if (cyclesForSample >= 21.26009) { #if 0 -sampleClock = GetCurrentV65C02Clock(); +sampleClock = mainCPU.clock; WriteLog(" cyclesForSample = %lf (%d samples, cycles=%d)\n", cyclesForSample, sampleClock - lastSampleClock, cycles); sampleCount++; lastSampleClock = sampleClock; diff --git a/src/ay8910.cpp b/src/ay8910.cpp index cfb293d..50862ed 100644 --- a/src/ay8910.cpp +++ b/src/ay8910.cpp @@ -1,3 +1,4 @@ +// // AY-3-8910 Emulator // // This was written mainly from the General Instruments datasheet for the 8910 diff --git a/src/crc32.cpp b/src/crc32.cpp new file mode 100644 index 0000000..8c26370 --- /dev/null +++ b/src/crc32.cpp @@ -0,0 +1,63 @@ +// +// CRC32 support +// +// by David Raingeard & James Hammons +// (C) 2010-2018 Underground Software +// +// JLH = James Hammons +// +// Who When What +// --- ---------- ----------------------------------------------------------- +// JLH 01/16/2010 Created this log ;-) +// + +#include "crc32.h" + + +static uint32_t crcTable[256] = +{ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D +}; + + +uint32_t CRC32(uint8_t * data, uint32_t length) +{ + uint32_t crc = 0xFFFFFFFF; + + for(uint32_t i=0; i> 8); + + return crc ^ 0xFFFFFFFF; +} + diff --git a/src/crc32.h b/src/crc32.h new file mode 100644 index 0000000..1821847 --- /dev/null +++ b/src/crc32.h @@ -0,0 +1,13 @@ +// +// CRC32.H +// + +#ifndef __CRC32_H__ +#define __CRC32_H__ + +#include + +uint32_t CRC32(uint8_t * data, uint32_t length); + +#endif // __CRC32_H__ + diff --git a/src/dis65c02.cpp b/src/dis65c02.cpp index 5869781..c5da552 100644 --- a/src/dis65c02.cpp +++ b/src/dis65c02.cpp @@ -2,7 +2,7 @@ // 65C02 disassembler // // by James Hammons -// (c) 2005 Underground Software +// (c) 2005-2018 Underground Software // #include "dis65c02.h" @@ -10,14 +10,9 @@ #include #include #include "log.h" -#include "v65c02.h" -// External shit - -extern V65C02REGS mainCPU;//Hm. Shouldn't we pass this shit in? ANSWER: YES. !!! FIX !!! - -// Private globals variables +// Private global variables static uint8_t op_mat[256] = { 14, 6, 0, 0, 2, 2, 2, 2, 14, 1, 14, 0, 8, 8, 8, 13, @@ -77,7 +72,7 @@ static uint8_t mnemonics[256][5] = { // // Display bytes in mem in hex // -static void DisplayBytes(char * outbuf, uint16_t src, uint32_t dst) +static void DisplayBytes(V65C02REGS * regs, char * outbuf, uint16_t src, uint32_t dst) { char buf[32]; sprintf(outbuf, "%04X: ", src); @@ -89,7 +84,7 @@ static void DisplayBytes(char * outbuf, uint16_t src, uint32_t dst) for(uint32_t i=src; iRdMem(i)); strcat(outbuf, buf); cnt++; } @@ -106,13 +101,13 @@ static void DisplayBytes(char * outbuf, uint16_t src, uint32_t dst) // // Decode a 65C02 instruction // -int Decode65C02(char * outbuf, uint16_t pc) +int Decode65C02(V65C02REGS * regs, char * outbuf, uint16_t pc) { char buf[32], buf2[32]; uint16_t addr = pc; uint16_t w; - uint8_t opcode = mainCPU.RdMem(addr++); // Get the opcode + uint8_t opcode = regs->RdMem(addr++); // Get the opcode switch (op_mat[opcode]) // Decode the addressing mode... { @@ -120,53 +115,53 @@ int Decode65C02(char * outbuf, uint16_t pc) sprintf(buf, "???"); break; case 1: // Immediate - sprintf(buf, "%s #$%02X", mnemonics[opcode], mainCPU.RdMem(addr++)); + sprintf(buf, "%s #$%02X", mnemonics[opcode], regs->RdMem(addr++)); break; case 2: // Zero page - sprintf(buf, "%s $%02X", mnemonics[opcode], mainCPU.RdMem(addr++)); + sprintf(buf, "%s $%02X", mnemonics[opcode], regs->RdMem(addr++)); break; case 3: // Zero page, X - sprintf(buf, "%s $%02X,X", mnemonics[opcode], mainCPU.RdMem(addr++)); + sprintf(buf, "%s $%02X,X", mnemonics[opcode], regs->RdMem(addr++)); break; case 4: // Zero page, Y - sprintf(buf, "%s $%02X,Y", mnemonics[opcode], mainCPU.RdMem(addr++)); + sprintf(buf, "%s $%02X,Y", mnemonics[opcode], regs->RdMem(addr++)); break; case 5: // Zero page indirect - sprintf(buf, "%s ($%02X)", mnemonics[opcode], mainCPU.RdMem(addr++)); + sprintf(buf, "%s ($%02X)", mnemonics[opcode], regs->RdMem(addr++)); break; case 6: // Zero page, X indirect - sprintf(buf, "%s ($%02X,X)", mnemonics[opcode], mainCPU.RdMem(addr++)); + sprintf(buf, "%s ($%02X,X)", mnemonics[opcode], regs->RdMem(addr++)); break; case 7: // Zero page, Y indirect - sprintf(buf, "%s ($%02X),Y", mnemonics[opcode], mainCPU.RdMem(addr++)); + sprintf(buf, "%s ($%02X),Y", mnemonics[opcode], regs->RdMem(addr++)); break; case 8: // Absolute - w = mainCPU.RdMem(addr++); - w |= mainCPU.RdMem(addr++) << 8; + w = regs->RdMem(addr++); + w |= regs->RdMem(addr++) << 8; sprintf(buf, "%s $%04X", mnemonics[opcode], w); break; case 9: // Absolute, X - w = mainCPU.RdMem(addr++); - w |= mainCPU.RdMem(addr++) << 8; + w = regs->RdMem(addr++); + w |= regs->RdMem(addr++) << 8; sprintf(buf, "%s $%04X,X", mnemonics[opcode], w); break; case 10: // Absolute, Y - w = mainCPU.RdMem(addr++); - w |= mainCPU.RdMem(addr++) << 8; + w = regs->RdMem(addr++); + w |= regs->RdMem(addr++) << 8; sprintf(buf, "%s $%04X,Y", mnemonics[opcode], w); break; case 11: // Indirect - w = mainCPU.RdMem(addr++); - w |= mainCPU.RdMem(addr++) << 8; + w = regs->RdMem(addr++); + w |= regs->RdMem(addr++) << 8; sprintf(buf, "%s ($%04X)", mnemonics[opcode], w); break; case 12: // Indirect, X - w = mainCPU.RdMem(addr++); - w |= mainCPU.RdMem(addr++) << 8; + w = regs->RdMem(addr++); + w |= regs->RdMem(addr++) << 8; sprintf(buf, "%s ($%04X,X)", mnemonics[opcode], w); break; case 13: // Relative - sprintf(buf, "%s $%04X", mnemonics[opcode], addr + (int16_t)((int8_t)mainCPU.RdMem(addr)) + 1); + sprintf(buf, "%s $%04X", mnemonics[opcode], addr + (int16_t)((int8_t)regs->RdMem(addr)) + 1); addr++; break; case 14: // Inherent @@ -174,7 +169,7 @@ int Decode65C02(char * outbuf, uint16_t pc) break; } - DisplayBytes(buf2, pc, addr); // Show bytes + DisplayBytes(regs, buf2, pc, addr); // Show bytes sprintf(outbuf, "%s %-14s", buf2, buf); // Display opcode & addressing, etc. return addr - pc; diff --git a/src/dis65c02.h b/src/dis65c02.h index fc1e4ac..5efda23 100644 --- a/src/dis65c02.h +++ b/src/dis65c02.h @@ -2,15 +2,16 @@ // DIS65C02.H // // by James Hammons -// (C) 2004 Underground Software +// (C) 2004-2018 Underground Software // #ifndef __DIS65C02_H__ #define __DIS65C02_H__ #include +#include "v65c02.h" -int Decode65C02(char * outbuf, uint16_t pc); +int Decode65C02(V65C02REGS *, char * outbuf, uint16_t pc); #endif // __DIS65C02_H__ diff --git a/src/floppy.h b/src/floppy.h index 2a25505..0438d65 100644 --- a/src/floppy.h +++ b/src/floppy.h @@ -89,3 +89,4 @@ class FloppyDrive }; #endif // __FLOPPY_H__ + diff --git a/src/mmu.cpp b/src/mmu.cpp index 74c80e2..653eac9 100644 --- a/src/mmu.cpp +++ b/src/mmu.cpp @@ -2,7 +2,7 @@ // mmu.cpp: Memory management // // by James Hammons -// (C) 2013 Underground Software +// (C) 2013-2018 Underground Software // // JLH = James Hammons // diff --git a/src/sound.cpp b/src/sound.cpp index df2de2b..67b3090 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -2,7 +2,7 @@ // Sound Interface // // by James Hammons -// (C) 2005 Underground Software +// (C) 2005-2018 Underground Software // // JLH = James Hammons // @@ -47,10 +47,6 @@ static bool soundInitialized = false; static bool speakerState = false; static uint16_t soundBuffer[SOUND_BUFFER_SIZE]; static uint32_t soundBufferPos; -//static uint64_t lastToggleCycles; -//static SDL_cond * conditional = NULL; -//static SDL_mutex * mutex = NULL; -//static SDL_mutex * mutex2 = NULL; static uint16_t sample; static uint8_t ampPtr = 12; // Start with -2047 - +2047 static int16_t amplitude[17] = { 0, 1, 2, 3, 7, 15, 31, 63, 127, 255, @@ -61,6 +57,10 @@ static int16_t amplitude[17] = { 0, 1, 2, 3, 7, 15, 31, 63, 127, 255, static void SDLSoundCallback(void * userdata, Uint8 * buffer, int length); +/* +N.B: We can convert this from the current callback model to a push model by using SDL_QueueAudio(SDL_AudioDeviceID id, const void * data, Uint32 len) where id is the audio device ID, data is a pointer to the sound buffer, and len is the size of the buffer in *bytes* (not samples!). To use this method, we need to set up things as usual but instead of putting the callback function pointer in desired.callback, we put a NULL there. The downside is that we can't tell if the buffer is being starved or not, which is why we haven't kicked it to the curb just yet--we want to know why we're still getting buffer starvation even if it's not as frequent as it used to be. :-/ +You can get the size of the audio already queued with SDL_GetQueuedAudioSize(SDL_AudioDeviceID id), which will return the size of the buffer in bytes (again, *not* samples!). +*/ // // Initialize the SDL sound system // @@ -81,14 +81,10 @@ void SoundInit(void) return; } -// conditional = SDL_CreateCond(); -// mutex = SDL_CreateMutex(); -// mutex2 = SDL_CreateMutex();// Let's try real signalling... soundBufferPos = 0; -// lastToggleCycles = 0; - sample = desired.silence; // ? wilwok ? yes + sample = desired.silence; // ? wilwok ? yes - SDL_PauseAudioDevice(device, 0); // Start playback! + SDL_PauseAudioDevice(device, 0);// Start playback! soundInitialized = true; WriteLog("Sound: Successfully initialized.\n"); } @@ -103,9 +99,6 @@ void SoundDone(void) { SDL_PauseAudioDevice(device, 1); SDL_CloseAudioDevice(device); -// SDL_DestroyCond(conditional); -// SDL_DestroyMutex(mutex); -// SDL_DestroyMutex(mutex2); WriteLog("Sound: Done.\n"); } } @@ -133,18 +126,11 @@ static uint32_t lastStarve = 0; static void SDLSoundCallback(void * /*userdata*/, Uint8 * buffer8, int length8) { sndFrmCnt++; -//WriteLog("SDLSoundCallback(): begin (soundBufferPos=%i)\n", soundBufferPos); - - // Let's try using a mutex for shared resource consumption... -//Actually, I think Lock/UnlockAudio() does this already... -//WriteLog("SDLSoundCallback: soundBufferPos = %i\n", soundBufferPos); -// SDL_mutexP(mutex2); // Recast this as a 16-bit type... uint16_t * buffer = (uint16_t *)buffer8; uint32_t length = (uint32_t)length8 / 2; -//WriteLog("SDLSoundCallback(): filling buffer...\n"); if (soundBufferPos < length) { WriteLog("*** Sound buffer starved (%d short) *** [%d delta %d]\n", length - soundBufferPos, sndFrmCnt, sndFrmCnt - lastStarve); @@ -177,17 +163,12 @@ lastStarve = sndFrmCnt; for(uint32_t i=0; i= (SOUND_BUFFER_SIZE - 1)) { //WriteLog("WriteSampleToBuffer(): Waiting for sound thread. soundBufferPos=%i, SOUNDBUFFERSIZE-1=%i\n", soundBufferPos, SOUND_BUFFER_SIZE-1); -// SDL_mutexV(mutex2); // Release it so sound thread can get it, -// SDL_mutexP(mutex); // Must lock the mutex for the cond to work properly... -// SDL_CondWait(conditional, mutex); // Sleep/wait for the sound thread -// SDL_mutexV(mutex); // Must unlock the mutex for the cond to work properly... -// SDL_mutexP(mutex2); // Re-lock it until we're done with it... SDL_Delay(1); } SDL_LockAudioDevice(device); soundBuffer[soundBufferPos++] = sample + adjustedMockingboard; SDL_UnlockAudioDevice(device); - -// soundBuffer[soundBufferPos++] = sample; -//WriteLog("WriteSampleToBuffer(): SDL_mutexV(mutex2)\n"); -// SDL_mutexV(mutex2); } @@ -236,7 +203,7 @@ void ToggleSpeaker(void) return; speakerState = !speakerState; - sample = (speakerState ? amplitude[ampPtr] : 0);//-amplitude[ampPtr]); + sample = (speakerState ? amplitude[ampPtr] : 0); } diff --git a/src/sound.h b/src/sound.h index 598fe1f..4f49e77 100644 --- a/src/sound.h +++ b/src/sound.h @@ -15,7 +15,7 @@ // Global variables (exported) -// Functions +// Exported functions void SoundInit(void); void SoundDone(void); diff --git a/src/v65c02.cpp b/src/v65c02.cpp index 43f6189..02dd846 100644 --- a/src/v65c02.cpp +++ b/src/v65c02.cpp @@ -1,8 +1,8 @@ // -// Virtual 65C02 Emulator v1.0 +// Virtual 65C02 Emulator v1.1 // // by James Hammons -// (c) 2005 Underground Software +// (c) 2005-2018 Underground Software // // JLH = James Hammons // @@ -28,73 +28,71 @@ #include "log.h" #endif -// Various macros -#define CLR_Z (regs.cc &= ~FLAG_Z) -#define CLR_ZN (regs.cc &= ~(FLAG_Z | FLAG_N)) -#define CLR_ZNC (regs.cc &= ~(FLAG_Z | FLAG_N | FLAG_C)) -#define CLR_V (regs.cc &= ~FLAG_V) -#define CLR_N (regs.cc &= ~FLAG_N) -#define SET_Z(r) (regs.cc = ((r) == 0 ? regs.cc | FLAG_Z : regs.cc & ~FLAG_Z)) -#define SET_N(r) (regs.cc = ((r) & 0x80 ? regs.cc | FLAG_N : regs.cc & ~FLAG_N)) +// Various helper macros + +#define CLR_Z (regs->cc &= ~FLAG_Z) +#define CLR_ZN (regs->cc &= ~(FLAG_Z | FLAG_N)) +#define CLR_ZNC (regs->cc &= ~(FLAG_Z | FLAG_N | FLAG_C)) +#define CLR_V (regs->cc &= ~FLAG_V) +#define CLR_N (regs->cc &= ~FLAG_N) +#define CLR_D (regs->cc &= ~FLAG_D) +#define SET_Z(r) (regs->cc = ((r) == 0 ? regs->cc | FLAG_Z : regs->cc & ~FLAG_Z)) +#define SET_N(r) (regs->cc = ((r) & 0x80 ? regs->cc | FLAG_N : regs->cc & ~FLAG_N)) +#define SET_I (regs->cc |= FLAG_I) //Not sure that this code is computing the carry correctly... Investigate! [Seems to be] -#define SET_C_ADD(a,b) (regs.cc = ((uint8_t)(b) > (uint8_t)(~(a)) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C)) -//#define SET_C_SUB(a,b) (regs.cc = ((uint8_t)(b) >= (uint8_t)(a) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C)) -#define SET_C_CMP(a,b) (regs.cc = ((uint8_t)(b) >= (uint8_t)(a) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C)) +#define SET_C_ADD(a,b) (regs->cc = ((uint8_t)(b) > (uint8_t)(~(a)) ? regs->cc | FLAG_C : regs->cc & ~FLAG_C)) +#define SET_C_CMP(a,b) (regs->cc = ((uint8_t)(b) >= (uint8_t)(a) ? regs->cc | FLAG_C : regs->cc & ~FLAG_C)) #define SET_ZN(r) SET_N(r); SET_Z(r) #define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b) -//#define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b) #define SET_ZNC_CMP(a,b,r) SET_N(r); SET_Z(r); SET_C_CMP(a,b) -//Small problem with the EA_ macros: ABS macros don't increment the PC!!! !!! FIX !!! -//NB: It's properly handled by everything that uses it, so it works, even if it's klunky -//Small problem with fixing it is that you can't do it in a single instruction, i.e., -//you have to read the value THEN you have to increment the PC. Unless there's another -//way to do that -//[DONE] -#define EA_IMM regs.pc++ -#define EA_ZP regs.RdMem(regs.pc++) -#define EA_ZP_X (regs.RdMem(regs.pc++) + regs.x) & 0xFF -#define EA_ZP_Y (regs.RdMem(regs.pc++) + regs.y) & 0xFF -#define EA_ABS FetchMemW(regs.pc) -#define EA_ABS_X FetchMemW(regs.pc) + regs.x -#define EA_ABS_Y FetchMemW(regs.pc) + regs.y -#define EA_IND_ZP_X RdMemW((regs.RdMem(regs.pc++) + regs.x) & 0xFF) -#define EA_IND_ZP_Y RdMemW(regs.RdMem(regs.pc++)) + regs.y -#define EA_IND_ZP RdMemW(regs.RdMem(regs.pc++)) +#define EA_IMM regs->pc++ +#define EA_ZP regs->RdMem(regs->pc++) +#define EA_ZP_X (regs->RdMem(regs->pc++) + regs->x) & 0xFF +#define EA_ZP_Y (regs->RdMem(regs->pc++) + regs->y) & 0xFF +#define EA_ABS FetchMemW(regs->pc) +#define EA_ABS_X FetchMemW(regs->pc) + regs->x +#define EA_ABS_Y FetchMemW(regs->pc) + regs->y +#define EA_IND_ZP_X RdMemW((regs->RdMem(regs->pc++) + regs->x) & 0xFF) +#define EA_IND_ZP_Y RdMemW(regs->RdMem(regs->pc++)) + regs->y +#define EA_IND_ZP RdMemW(regs->RdMem(regs->pc++)) -#define READ_IMM regs.RdMem(EA_IMM) -#define READ_ZP regs.RdMem(EA_ZP) -#define READ_ZP_X regs.RdMem(EA_ZP_X) -#define READ_ZP_Y regs.RdMem(EA_ZP_Y) -#define READ_ABS regs.RdMem(EA_ABS) -#define READ_ABS_X regs.RdMem(EA_ABS_X) -#define READ_ABS_Y regs.RdMem(EA_ABS_Y) -#define READ_IND_ZP_X regs.RdMem(EA_IND_ZP_X) -#define READ_IND_ZP_Y regs.RdMem(EA_IND_ZP_Y) -#define READ_IND_ZP regs.RdMem(EA_IND_ZP) +#define READ_IMM regs->RdMem(EA_IMM) +#define READ_ZP regs->RdMem(EA_ZP) +#define READ_ZP_X regs->RdMem(EA_ZP_X) +#define READ_ZP_Y regs->RdMem(EA_ZP_Y) +#define READ_ABS regs->RdMem(EA_ABS) +#define READ_ABS_X regs->RdMem(EA_ABS_X) +#define READ_ABS_Y regs->RdMem(EA_ABS_Y) +#define READ_IND_ZP_X regs->RdMem(EA_IND_ZP_X) +#define READ_IND_ZP_Y regs->RdMem(EA_IND_ZP_Y) +#define READ_IND_ZP regs->RdMem(EA_IND_ZP) -#define READ_IMM_WB(v) uint16_t addr = EA_IMM; v = regs.RdMem(addr) -#define READ_ZP_WB(v) uint16_t addr = EA_ZP; v = regs.RdMem(addr) -#define READ_ZP_X_WB(v) uint16_t addr = EA_ZP_X; v = regs.RdMem(addr) -#define READ_ABS_WB(v) uint16_t addr = EA_ABS; v = regs.RdMem(addr) -#define READ_ABS_X_WB(v) uint16_t addr = EA_ABS_X; v = regs.RdMem(addr) -#define READ_ABS_Y_WB(v) uint16_t addr = EA_ABS_Y; v = regs.RdMem(addr) -#define READ_IND_ZP_X_WB(v) uint16_t addr = EA_IND_ZP_X; v = regs.RdMem(addr) -#define READ_IND_ZP_Y_WB(v) uint16_t addr = EA_IND_ZP_Y; v = regs.RdMem(addr) -#define READ_IND_ZP_WB(v) uint16_t addr = EA_IND_ZP; v = regs.RdMem(addr) +#define READ_IMM_WB(v) uint16_t addr = EA_IMM; v = regs->RdMem(addr) +#define READ_ZP_WB(v) uint16_t addr = EA_ZP; v = regs->RdMem(addr) +#define READ_ZP_X_WB(v) uint16_t addr = EA_ZP_X; v = regs->RdMem(addr) +#define READ_ABS_WB(v) uint16_t addr = EA_ABS; v = regs->RdMem(addr) +#define READ_ABS_X_WB(v) uint16_t addr = EA_ABS_X; v = regs->RdMem(addr) +#define READ_ABS_Y_WB(v) uint16_t addr = EA_ABS_Y; v = regs->RdMem(addr) +#define READ_IND_ZP_X_WB(v) uint16_t addr = EA_IND_ZP_X; v = regs->RdMem(addr) +#define READ_IND_ZP_Y_WB(v) uint16_t addr = EA_IND_ZP_Y; v = regs->RdMem(addr) +#define READ_IND_ZP_WB(v) uint16_t addr = EA_IND_ZP; v = regs->RdMem(addr) + +#define WRITE_BACK(d) regs->WrMem(addr, (d)) -#define WRITE_BACK(d) regs.WrMem(addr, (d)) // Private global variables -static V65C02REGS regs; +static V65C02REGS * regs; + //This is probably incorrect, at least WRT to the $x7 and $xF opcodes... !!! FIX !!! -//Also this doesn't take into account the extra cycle it takes when an indirect fetch -//(ABS, ABS X/Y, ZP) crosses a page boundary, or extra cycle for BCD add/subtract... -#warning "Cycle counts are not accurate--!!! FIX !!!" +//Also this doesn't take into account the extra cycle it takes when an indirect +//fetch (ABS, ABS X/Y, ZP) crosses a page boundary, or extra cycle for BCD +//add/subtract... +#warning "Cycle counts are not 100% accurate--!!! FIX !!!" static uint8_t CPUCycles[256] = { #if 0 7, 6, 1, 1, 5, 3, 5, 1, 3, 2, 2, 1, 6, 4, 6, 1, @@ -170,27 +168,6 @@ static uint8_t _65C02Cycles[256] = { 2, 5, 5, 2, 4, 4, 6, 2, 2, 4, 4, 2, 4, 4, 6, 2 }; #endif -#if 0 -// ExtraCycles: -// +1 if branch taken -// +1 if page boundary crossed -#define BRANCH_TAKEN { \ - base = regs.pc; \ - regs.pc += addr; \ - if ((base ^ regs.pc) & 0xFF00) \ - uExtraCycles=2; \ - else \ - uExtraCycles=1; \ - } - -{ - oldpc = regs.pc; - regs.pc += v; - if ((oldc ^ regs.pc) & 0xFF00) - regs.clock++; - regs.clock++; -} -#endif /* 6502 cycles (includes illegal opcodes): @@ -713,26 +690,23 @@ static uint8_t _65C02Cycles[256] = { case 0xFF: INV NOP CYC(2) break; */ -// Private function prototypes - -static uint16_t RdMemW(uint16_t); -static uint16_t FetchMemW(uint16_t addr); // // Read a uint16_t out of 65C02 memory (big endian format) // static inline uint16_t RdMemW(uint16_t address) { - return (uint16_t)(regs.RdMem(address + 1) << 8) | regs.RdMem(address + 0); + return (uint16_t)(regs->RdMem(address + 1) << 8) | regs->RdMem(address + 0); } + // // Read a uint16_t out of 65C02 memory (big endian format) and increment PC // static inline uint16_t FetchMemW(uint16_t address) { - regs.pc += 2; - return (uint16_t)(regs.RdMem(address + 1) << 8) | regs.RdMem(address + 0); + regs->pc += 2; + return (uint16_t)(regs->RdMem(address + 1) << 8) | regs->RdMem(address + 0); } @@ -763,9 +737,9 @@ ADC Immediate ADC #Oper 69 2 2 //This is non-optimal, but it works--optimize later. :-) #define OP_ADC_HANDLER(m) \ - uint16_t sum = (uint16_t)regs.a + (m) + (uint16_t)(regs.cc & FLAG_C); \ + uint16_t sum = (uint16_t)regs->a + (m) + (uint16_t)(regs->cc & FLAG_C); \ \ - if (regs.cc & FLAG_D) \ + if (regs->cc & FLAG_D) \ { \ if ((sum & 0x0F) > 0x09) \ sum += 0x06; \ @@ -774,12 +748,10 @@ ADC Immediate ADC #Oper 69 2 2 sum += 0x60; \ } \ \ - regs.cc = (regs.cc & ~FLAG_C) | (sum >> 8); \ - regs.cc = (~(regs.a ^ (m)) & (regs.a ^ sum) & 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V); \ - regs.a = sum & 0xFF; \ - SET_ZN(regs.a) - -//OLD V detection: regs.cc = ((regs.a ^ (m) ^ sum ^ (regs.cc << 7)) & 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V); + regs->cc = (regs->cc & ~FLAG_C) | (sum >> 8); \ + regs->cc = (~(regs->a ^ (m)) & (regs->a ^ sum) & 0x80 ? regs->cc | FLAG_V : regs->cc & ~FLAG_V); \ + regs->a = sum & 0xFF; \ + SET_ZN(regs->a) static void Op69(void) // ADC # { @@ -850,8 +822,8 @@ Absolute,Y AND Abs,Y 39 3 4 // AND opcodes #define OP_AND_HANDLER(m) \ - regs.a &= m; \ - SET_ZN(regs.a) + regs->a &= m; \ + SET_ZN(regs->a) static void Op29(void) // AND # { @@ -915,28 +887,16 @@ Absolute ASL Abs 0E 3 6 Absolute,X ASL Abs,X 1E 3 7 */ -/*static void Op78(void) // LSL ABS -{ - uint8_t tmp; uint16_t addr; - addr = FetchW(); - tmp = regs.RdMem(addr); - (tmp&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift hi bit into Carry - tmp <<= 1; - regs.WrMem(addr, tmp); - (tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB); // Adjust Zero flag - (tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7); // Adjust Negative flag -}*/ - // ASL opcodes #define OP_ASL_HANDLER(m) \ - regs.cc = ((m) & 0x80 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C); \ + regs->cc = ((m) & 0x80 ? regs->cc | FLAG_C : regs->cc & ~FLAG_C); \ (m) <<= 1; \ SET_ZN((m)) static void Op0A(void) // ASL A { - OP_ASL_HANDLER(regs.a); + OP_ASL_HANDLER(regs->a); } static void Op06(void) // ASL ZP @@ -996,128 +956,128 @@ static void Op0F(void) // BBR0 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (!(regs.a & 0x01)) - regs.pc += m; + if (!(regs->a & 0x01)) + regs->pc += m; } static void Op1F(void) // BBR1 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (!(regs.a & 0x02)) - regs.pc += m; + if (!(regs->a & 0x02)) + regs->pc += m; } static void Op2F(void) // BBR2 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (!(regs.a & 0x04)) - regs.pc += m; + if (!(regs->a & 0x04)) + regs->pc += m; } static void Op3F(void) // BBR3 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (!(regs.a & 0x08)) - regs.pc += m; + if (!(regs->a & 0x08)) + regs->pc += m; } static void Op4F(void) // BBR4 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (!(regs.a & 0x10)) - regs.pc += m; + if (!(regs->a & 0x10)) + regs->pc += m; } static void Op5F(void) // BBR5 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (!(regs.a & 0x20)) - regs.pc += m; + if (!(regs->a & 0x20)) + regs->pc += m; } static void Op6F(void) // BBR6 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (!(regs.a & 0x40)) - regs.pc += m; + if (!(regs->a & 0x40)) + regs->pc += m; } static void Op7F(void) // BBR7 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (!(regs.a & 0x80)) - regs.pc += m; + if (!(regs->a & 0x80)) + regs->pc += m; } static void Op8F(void) // BBS0 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (regs.a & 0x01) - regs.pc += m; + if (regs->a & 0x01) + regs->pc += m; } static void Op9F(void) // BBS1 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (regs.a & 0x02) - regs.pc += m; + if (regs->a & 0x02) + regs->pc += m; } static void OpAF(void) // BBS2 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (regs.a & 0x04) - regs.pc += m; + if (regs->a & 0x04) + regs->pc += m; } static void OpBF(void) // BBS3 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (regs.a & 0x08) - regs.pc += m; + if (regs->a & 0x08) + regs->pc += m; } static void OpCF(void) // BBS4 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (regs.a & 0x10) - regs.pc += m; + if (regs->a & 0x10) + regs->pc += m; } static void OpDF(void) // BBS5 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (regs.a & 0x20) - regs.pc += m; + if (regs->a & 0x20) + regs->pc += m; } static void OpEF(void) // BBS6 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (regs.a & 0x40) - regs.pc += m; + if (regs->a & 0x40) + regs->pc += m; } static void OpFF(void) // BBS7 { int16_t m = (int16_t)(int8_t)READ_IMM; - if (regs.a & 0x80) - regs.pc += m; + if (regs->a & 0x80) + regs->pc += m; } /* @@ -1130,12 +1090,12 @@ BEQ Relative BEQ Oper F0 2 2 #define HANDLE_BRANCH_TAKEN(m) \ { \ - uint16_t oldpc = regs.pc; \ - regs.pc += m; \ - regs.clock++; \ + uint16_t oldpc = regs->pc; \ + regs->pc += m; \ + regs->clock++; \ \ - if ((oldpc ^ regs.pc) & 0xFF00) \ - regs.clock++; \ + if ((oldpc ^ regs->pc) & 0xFF00) \ + regs->clock++; \ } // Branch opcodes @@ -1144,7 +1104,7 @@ static void Op90(void) // BCC { int16_t m = (int16_t)(int8_t)READ_IMM; - if (!(regs.cc & FLAG_C)) + if (!(regs->cc & FLAG_C)) HANDLE_BRANCH_TAKEN(m) } @@ -1152,7 +1112,7 @@ static void OpB0(void) // BCS { int16_t m = (int16_t)(int8_t)READ_IMM; - if (regs.cc & FLAG_C) + if (regs->cc & FLAG_C) HANDLE_BRANCH_TAKEN(m) } @@ -1160,7 +1120,7 @@ static void OpF0(void) // BEQ { int16_t m = (int16_t)(int8_t)READ_IMM; - if (regs.cc & FLAG_Z) + if (regs->cc & FLAG_Z) HANDLE_BRANCH_TAKEN(m) } @@ -1174,20 +1134,21 @@ Absolute,X BIT Abs,X 3C 3 4 // BIT opcodes -/* 1. The BIT instruction copies bit 6 to the V flag, and bit 7 to the N flag (except in immediate - addressing mode where V & N are untouched.) The accumulator and the operand are ANDed and the - Z flag is set appropriately. */ +/* 1. The BIT instruction copies bit 6 to the V flag, and bit 7 to the N flag + (except in immediate addressing mode where V & N are untouched.) The + accumulator and the operand are ANDed and the Z flag is set + appropriately. */ #define OP_BIT_HANDLER(m) \ - int8_t result = regs.a & (m); \ - regs.cc &= ~(FLAG_N | FLAG_V); \ - regs.cc |= ((m) & 0xC0); \ + int8_t result = regs->a & (m); \ + regs->cc &= ~(FLAG_N | FLAG_V); \ + regs->cc |= ((m) & 0xC0); \ SET_Z(result) static void Op89(void) // BIT # { int8_t m = READ_IMM; - int8_t result = regs.a & m; + int8_t result = regs->a & m; SET_Z(result); } @@ -1228,34 +1189,30 @@ static void Op30(void) // BMI { int16_t m = (int16_t)(int8_t)READ_IMM; - if (regs.cc & FLAG_N) + if (regs->cc & FLAG_N) HANDLE_BRANCH_TAKEN(m) -// regs.pc += m; } static void OpD0(void) // BNE { int16_t m = (int16_t)(int8_t)READ_IMM; - if (!(regs.cc & FLAG_Z)) + if (!(regs->cc & FLAG_Z)) HANDLE_BRANCH_TAKEN(m) -// regs.pc += m; } static void Op10(void) // BPL { int16_t m = (int16_t)(int8_t)READ_IMM; - if (!(regs.cc & FLAG_N)) + if (!(regs->cc & FLAG_N)) HANDLE_BRANCH_TAKEN(m) -// regs.pc += m; } static void Op80(void) // BRA { int16_t m = (int16_t)(int8_t)READ_IMM; HANDLE_BRANCH_TAKEN(m) -// regs.pc += m; } /* @@ -1268,20 +1225,20 @@ static void Op00(void) // BRK #if 1 WriteLog("\n*** BRK ***\n\n"); WriteLog(" [PC=%04X, SP=%04X, CC=%s%s.%s%s%s%s%s, A=%02X, X=%02X, Y=%02X]\n", - regs.pc, 0x0100 + regs.sp, - (regs.cc & FLAG_N ? "N" : "-"), (regs.cc & FLAG_V ? "V" : "-"), - (regs.cc & FLAG_B ? "B" : "-"), (regs.cc & FLAG_D ? "D" : "-"), - (regs.cc & FLAG_I ? "I" : "-"), (regs.cc & FLAG_Z ? "Z" : "-"), - (regs.cc & FLAG_C ? "C" : "-"), regs.a, regs.x, regs.y); + regs->pc, 0x0100 + regs->sp, + (regs->cc & FLAG_N ? "N" : "-"), (regs->cc & FLAG_V ? "V" : "-"), + (regs->cc & FLAG_B ? "B" : "-"), (regs->cc & FLAG_D ? "D" : "-"), + (regs->cc & FLAG_I ? "I" : "-"), (regs->cc & FLAG_Z ? "Z" : "-"), + (regs->cc & FLAG_C ? "C" : "-"), regs->a, regs->x, regs->y); #endif - regs.cc |= FLAG_B; // Set B - regs.pc++; // RTI comes back to the instruction one byte after the BRK - regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8); // Save PC and CC - regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF); - regs.WrMem(0x0100 + regs.sp--, regs.cc); - regs.cc |= FLAG_I; // Set I - regs.cc &= ~FLAG_D; // & clear D - regs.pc = RdMemW(0xFFFE); // Grab the IRQ vector & go... + regs->cc |= FLAG_B; // Set B + regs->pc++; // RTI comes back to the instruction one byte after the BRK + regs->WrMem(0x0100 + regs->sp--, regs->pc >> 8); // Save PC and CC + regs->WrMem(0x0100 + regs->sp--, regs->pc & 0xFF); + regs->WrMem(0x0100 + regs->sp--, regs->cc); + regs->cc |= FLAG_I; // Set I + regs->cc &= ~FLAG_D; // & clear D + regs->pc = RdMemW(0xFFFE); // Grab the IRQ vector & go... } /* @@ -1295,18 +1252,16 @@ static void Op50(void) // BVC { int16_t m = (int16_t)(int8_t)READ_IMM; - if (!(regs.cc & FLAG_V)) + if (!(regs->cc & FLAG_V)) HANDLE_BRANCH_TAKEN(m) -// regs.pc += m; } static void Op70(void) // BVS { int16_t m = (int16_t)(int8_t)READ_IMM; - if (regs.cc & FLAG_V) + if (regs->cc & FLAG_V) HANDLE_BRANCH_TAKEN(m) -// regs.pc += m; } /* @@ -1315,7 +1270,7 @@ CLC Implied CLC 18 1 2 static void Op18(void) // CLC { - regs.cc &= ~FLAG_C; + regs->cc &= ~FLAG_C; } /* @@ -1324,7 +1279,7 @@ CLD Implied CLD D8 1 2 static void OpD8(void) // CLD { - regs.cc &= ~FLAG_D; + CLR_D; } /* @@ -1333,7 +1288,7 @@ CLI Implied CLI 58 1 2 static void Op58(void) // CLI { - regs.cc &= ~FLAG_I; + regs->cc &= ~FLAG_I; } /* @@ -1342,7 +1297,7 @@ CLV Implied CLV B8 1 2 static void OpB8(void) // CLV { - regs.cc &= ~FLAG_V; + regs->cc &= ~FLAG_V; } /* @@ -1359,35 +1314,9 @@ Absolute,Y CMP Abs,Y D9 3 4 // CMP opcodes -/* -Here's the latest: The CMP is NOT generating the Z flag when A=$C0! - -FABA: A0 07 LDY #$07 [PC=FABC, SP=01FF, CC=---B-IZ-, A=00, X=00, Y=07] -FABC: C6 01 DEC $01 [PC=FABE, SP=01FF, CC=N--B-I--, A=00, X=00, Y=07] -FABE: A5 01 LDA $01 [PC=FAC0, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07] -FAC0: C9 C0 CMP #$C0 [PC=FAC2, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07] -FAC2: F0 D7 BEQ $FA9B [PC=FAC4, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07] -FAC4: 8D F8 07 STA $07F8 [PC=FAC7, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07] -FAC7: B1 00 LDA ($00),Y -*** Read at I/O address C007 - [PC=FAC9, SP=01FF, CC=---B-IZ-, A=00, X=00, Y=07] -FAC9: D9 01 FB CMP $FB01,Y [PC=FACC, SP=01FF, CC=---B-I--, A=00, X=00, Y=07] -FACC: D0 EC BNE $FABA [PC=FABA, SP=01FF, CC=---B-I--, A=00, X=00, Y=07] - -Should be fixed now... (was adding instead of subtracting!) - -Small problem here... First two should set the carry while the last one should clear it. !!! FIX !!! [DONE] - -FDF0: C9 A0 CMP #$A0 [PC=FDF2, SP=01F1, CC=---B-IZ-, A=A0, X=02, Y=03] -FD7E: C9 E0 CMP #$E0 [PC=FD80, SP=01F4, CC=N--B-I--, A=A0, X=02, Y=03] -FD38: C9 9B CMP #$9B [PC=FD3A, SP=01F2, CC=---B-I-C, A=A0, X=02, Y=03] - -Compare sets flags as if a subtraction had been carried out. If the value in the accumulator is equal or greater than the compared value, the Carry will be set. The equal (Z) and sign (S) flags will be set based on equality or lack thereof and the sign (i.e. A>=$80) of the accumulator. -*/ - #define OP_CMP_HANDLER(m) \ - uint8_t result = regs.a - (m); \ - SET_ZNC_CMP(m, regs.a, result) + uint8_t result = regs->a - (m); \ + SET_ZNC_CMP(m, regs->a, result) static void OpC9(void) // CMP # { @@ -1452,8 +1381,8 @@ Absolute CPX Abs EC 3 4 // CPX opcodes #define OP_CPX_HANDLER(m) \ - uint8_t result = regs.x - (m); \ - SET_ZNC_CMP(m, regs.x, result) + uint8_t result = regs->x - (m); \ + SET_ZNC_CMP(m, regs->x, result) static void OpE0(void) // CPX # { @@ -1482,8 +1411,8 @@ Absolute CPY Abs CC 3 4 // CPY opcodes #define OP_CPY_HANDLER(m) \ - uint8_t result = regs.y - (m); \ - SET_ZNC_CMP(m, regs.y, result) + uint8_t result = regs->y - (m); \ + SET_ZNC_CMP(m, regs->y, result) static void OpC0(void) // CPY # { @@ -1509,8 +1438,8 @@ DEA Accumulator DEA 3A 1 2 static void Op3A(void) // DEA { - regs.a--; - SET_ZN(regs.a); + regs->a--; + SET_ZN(regs->a); } /* @@ -1558,28 +1487,14 @@ static void OpDE(void) // DEC ABS, X WRITE_BACK(m); } -/* -Here's one problem: DEX is setting the N flag! - -D3EE: A2 09 LDX #$09 [PC=D3F0, SP=01F7, CC=---B-I-C, A=01, X=09, Y=08] -D3F0: 98 TYA [PC=D3F1, SP=01F7, CC=N--B-I-C, A=08, X=09, Y=08] -D3F1: 48 PHA [PC=D3F2, SP=01F6, CC=N--B-I-C, A=08, X=09, Y=08] -D3F2: B5 93 LDA $93,X [PC=D3F4, SP=01F6, CC=---B-IZC, A=00, X=09, Y=08] -D3F4: CA DEX [PC=D3F5, SP=01F6, CC=N--B-I-C, A=00, X=08, Y=08] -D3F5: 10 FA BPL $D3F1 [PC=D3F7, SP=01F6, CC=N--B-I-C, A=00, X=08, Y=08] -D3F7: 20 84 E4 JSR $E484 [PC=E484, SP=01F4, CC=N--B-I-C, A=00, X=08, Y=08] - -should be fixed now... -*/ - /* DEX Implied DEX CA 1 2 */ static void OpCA(void) // DEX { - regs.x--; - SET_ZN(regs.x); + regs->x--; + SET_ZN(regs->x); } /* @@ -1588,8 +1503,8 @@ DEY Implied DEY 88 1 2 static void Op88(void) // DEY { - regs.y--; - SET_ZN(regs.y); + regs->y--; + SET_ZN(regs->y); } /* @@ -1607,8 +1522,8 @@ Absolute,Y EOR Abs,Y 59 3 4 // EOR opcodes #define OP_EOR_HANDLER(m) \ - regs.a ^= m; \ - SET_ZN(regs.a) + regs->a ^= m; \ + SET_ZN(regs->a) static void Op49(void) // EOR # { @@ -1670,8 +1585,8 @@ INA Accumulator INA 1A 1 2 static void Op1A(void) // INA { - regs.a++; - SET_ZN(regs.a); + regs->a++; + SET_ZN(regs->a); } /* @@ -1725,8 +1640,8 @@ INX Implied INX E8 1 2 static void OpE8(void) // INX { - regs.x++; - SET_ZN(regs.x); + regs->x++; + SET_ZN(regs->x); } /* @@ -1735,8 +1650,8 @@ INY Implied INY C8 1 2 static void OpC8(void) // INY { - regs.y++; - SET_ZN(regs.y); + regs->y++; + SET_ZN(regs->y); } /* @@ -1749,37 +1664,30 @@ JMP Absolute JMP Abs 4C 3 3 static void Op4C(void) // JMP ABS { - regs.pc = RdMemW(regs.pc); + regs->pc = RdMemW(regs->pc); } static void Op6C(void) // JMP (ABS) { -// uint16_t addr = RdMemW(regs.pc); -//#ifdef __DEBUG__ -//WriteLog("\n[JMP ABS]: addr fetched = %04X, bytes at %04X = %02X %02X (RdMemw=%04X)\n", -// addr, addr, regs.RdMem(addr), regs.RdMem(addr+1), RdMemW(addr)); -//#endif -// addr = RdMemW(addr); - regs.pc = RdMemW(RdMemW(regs.pc)); + regs->pc = RdMemW(RdMemW(regs->pc)); } static void Op7C(void) // JMP (ABS, X) { - regs.pc = RdMemW(RdMemW(regs.pc) + regs.x); + regs->pc = RdMemW(RdMemW(regs->pc) + regs->x); } /* JSR Absolute JSR Abs 20 3 6 */ -//This is not jumping to the correct address... !!! FIX !!! [DONE] static void Op20(void) // JSR { - uint16_t addr = RdMemW(regs.pc); - regs.pc++; // Since it pushes return address - 1... - regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8); - regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF); - regs.pc = addr; + uint16_t addr = RdMemW(regs->pc); + regs->pc++; // Since it pushes return address - 1... + regs->WrMem(0x0100 + regs->sp--, regs->pc >> 8); + regs->WrMem(0x0100 + regs->sp--, regs->pc & 0xFF); + regs->pc = addr; } /* @@ -1797,8 +1705,8 @@ Absolute,Y LDA Abs,Y B9 3 4 // LDA opcodes #define OP_LDA_HANDLER(m) \ - regs.a = m; \ - SET_ZN(regs.a) + regs->a = m; \ + SET_ZN(regs->a) static void OpA9(void) // LDA # { @@ -1865,8 +1773,8 @@ Absolute,Y LDX Abs,Y BE 3 4 // LDX opcodes #define OP_LDX_HANDLER(m) \ - regs.x = m; \ - SET_ZN(regs.x) + regs->x = m; \ + SET_ZN(regs->x) static void OpA2(void) // LDX # { @@ -1909,8 +1817,8 @@ Absolute,Y LDY Abs,X BC 3 4 // LDY opcodes #define OP_LDY_HANDLER(m) \ - regs.y = m; \ - SET_ZN(regs.y) + regs->y = m; \ + SET_ZN(regs->y) static void OpA0(void) // LDY # { @@ -1953,13 +1861,13 @@ Absolute,X LSR Abs,X 5E 3 7 // LSR opcodes #define OP_LSR_HANDLER(m) \ - regs.cc = ((m) & 0x01 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C); \ + regs->cc = ((m) & 0x01 ? regs->cc | FLAG_C : regs->cc & ~FLAG_C); \ (m) >>= 1; \ CLR_N; SET_Z((m)) static void Op4A(void) // LSR A { - OP_LSR_HANDLER(regs.a); + OP_LSR_HANDLER(regs->a); } static void Op46(void) // LSR ZP @@ -2017,8 +1925,8 @@ Absolute,Y ORA Abs,Y 19 3 4 // ORA opcodes #define OP_ORA_HANDLER(m) \ - regs.a |= m; \ - SET_ZN(regs.a) + regs->a |= m; \ + SET_ZN(regs->a) static void Op09(void) // ORA # { @@ -2080,13 +1988,13 @@ PHA Implied PHA 48 1 3 static void Op48(void) // PHA { - regs.WrMem(0x0100 + regs.sp--, regs.a); + regs->WrMem(0x0100 + regs->sp--, regs->a); } static void Op08(void) // PHP { - regs.cc |= FLAG_UNK; // Make sure that the unused bit is always set - regs.WrMem(0x0100 + regs.sp--, regs.cc); + regs->cc |= FLAG_UNK; // Make sure that the unused bit is always set + regs->WrMem(0x0100 + regs->sp--, regs->cc); } /* @@ -2095,7 +2003,7 @@ PHX Implied PHX DA 1 3 static void OpDA(void) // PHX { - regs.WrMem(0x0100 + regs.sp--, regs.x); + regs->WrMem(0x0100 + regs->sp--, regs->x); } /* @@ -2104,7 +2012,7 @@ PHY Implied PHY 5A 1 3 static void Op5A(void) // PHY { - regs.WrMem(0x0100 + regs.sp--, regs.y); + regs->WrMem(0x0100 + regs->sp--, regs->y); } /* @@ -2113,13 +2021,13 @@ PLA Implied PLA 68 1 4 static void Op68(void) // PLA { - regs.a = regs.RdMem(0x0100 + ++regs.sp); - SET_ZN(regs.a); + regs->a = regs->RdMem(0x0100 + ++regs->sp); + SET_ZN(regs->a); } static void Op28(void) // PLP { - regs.cc = regs.RdMem(0x0100 + ++regs.sp); + regs->cc = regs->RdMem(0x0100 + ++regs->sp); } /* @@ -2128,8 +2036,8 @@ PLX Implied PLX FA 1 4 static void OpFA(void) // PLX { - regs.x = regs.RdMem(0x0100 + ++regs.sp); - SET_ZN(regs.x); + regs->x = regs->RdMem(0x0100 + ++regs->sp); + SET_ZN(regs->x); } /* @@ -2138,8 +2046,8 @@ PLY Implied PLY 7A 1 4 static void Op7A(void) // PLY { - regs.y = regs.RdMem(0x0100 + ++regs.sp); - SET_ZN(regs.y); + regs->y = regs->RdMem(0x0100 + ++regs->sp); + SET_ZN(regs->y); } /* @@ -2227,14 +2135,14 @@ Absolute,X ROL Abs,X 3E 3 7 // ROL opcodes #define OP_ROL_HANDLER(m) \ - uint8_t tmp = regs.cc & 0x01; \ - regs.cc = ((m) & 0x80 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C); \ + uint8_t tmp = regs->cc & 0x01; \ + regs->cc = ((m) & 0x80 ? regs->cc | FLAG_C : regs->cc & ~FLAG_C); \ (m) = ((m) << 1) | tmp; \ SET_ZN((m)) static void Op2A(void) // ROL A { - OP_ROL_HANDLER(regs.a); + OP_ROL_HANDLER(regs->a); } static void Op26(void) // ROL ZP @@ -2280,14 +2188,14 @@ Absolute,X ROR Abs,X 7E 3 7 // ROR opcodes #define OP_ROR_HANDLER(m) \ - uint8_t tmp = (regs.cc & 0x01) << 7; \ - regs.cc = ((m) & 0x01 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C); \ + uint8_t tmp = (regs->cc & 0x01) << 7; \ + regs->cc = ((m) & 0x01 ? regs->cc | FLAG_C : regs->cc & ~FLAG_C); \ (m) = ((m) >> 1) | tmp; \ SET_ZN((m)) static void Op6A(void) // ROR A { - OP_ROR_HANDLER(regs.a); + OP_ROR_HANDLER(regs->a); } static void Op66(void) // ROR ZP @@ -2328,12 +2236,9 @@ RTI Implied RTI 40 1 6 static void Op40(void) // RTI { - regs.cc = regs.RdMem(0x0100 + ++regs.sp); -//clear I (seems to be the case, either that or clear it in the IRQ setup...) -//I can't find *any* verification that this is the case. -// regs.cc &= ~FLAG_I; - regs.pc = regs.RdMem(0x0100 + ++regs.sp); - regs.pc |= (uint16_t)(regs.RdMem(0x0100 + ++regs.sp)) << 8; + regs->cc = regs->RdMem(0x0100 + ++regs->sp); + regs->pc = regs->RdMem(0x0100 + ++regs->sp); + regs->pc |= (uint16_t)(regs->RdMem(0x0100 + ++regs->sp)) << 8; } /* @@ -2342,11 +2247,9 @@ RTS Implied RTS 60 1 6 static void Op60(void) // RTS { - regs.pc = regs.RdMem(0x0100 + ++regs.sp); - regs.pc |= (uint16_t)(regs.RdMem(0x0100 + ++regs.sp)) << 8; - regs.pc++; // Since it pushes return address - 1... -//printf("*** RTS: PC = $%04X, SP= $1%02X\n", regs.pc, regs.sp); -//fflush(stdout); + regs->pc = regs->RdMem(0x0100 + ++regs->sp); + regs->pc |= (uint16_t)(regs->RdMem(0x0100 + ++regs->sp)) << 8; + regs->pc++; // Since it pushes return address - 1... } /* @@ -2366,9 +2269,9 @@ Absolute,Y SBC Abs,Y F9 3 4 //This is non-optimal, but it works--optimize later. :-) //This is correct except for the BCD handling... !!! FIX !!! [Possibly DONE] #define OP_SBC_HANDLER(m) \ - uint16_t sum = (uint16_t)regs.a - (m) - (uint16_t)((regs.cc & FLAG_C) ^ 0x01); \ + uint16_t sum = (uint16_t)regs->a - (m) - (uint16_t)((regs->cc & FLAG_C) ^ 0x01); \ \ - if (regs.cc & FLAG_D) \ + if (regs->cc & FLAG_D) \ { \ if ((sum & 0x0F) > 0x09) \ sum -= 0x06; \ @@ -2377,22 +2280,10 @@ Absolute,Y SBC Abs,Y F9 3 4 sum -= 0x60; \ } \ \ - regs.cc = (regs.cc & ~FLAG_C) | (((sum >> 8) ^ 0x01) & FLAG_C); \ - regs.cc = ((regs.a ^ (m)) & (regs.a ^ sum) & 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V); \ - regs.a = sum & 0xFF; \ - SET_ZN(regs.a) - -/* -D5AF: 38 SEC [PC=D5B0, SP=01F6, CC=---B-I-C, A=4C, X=00, Y=06] - -*** HERE'S where it sets the D flag on a subtract... Arg! - -D5B0: F1 9D SBC ($9D),Y [PC=D5B2, SP=01F6, CC=N--BDI--, A=FE, X=00, Y=06] - -Fixed. :-) -*/ - -//OLD V detection: regs.cc = ((regs.a ^ (m) ^ sum ^ (regs.cc << 7)) & 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V); + regs->cc = (regs->cc & ~FLAG_C) | (((sum >> 8) ^ 0x01) & FLAG_C); \ + regs->cc = ((regs->a ^ (m)) & (regs->a ^ sum) & 0x80 ? regs->cc | FLAG_V : regs->cc & ~FLAG_V); \ + regs->a = sum & 0xFF; \ + SET_ZN(regs->a) static void OpE9(void) // SBC # { @@ -2454,7 +2345,7 @@ SEC Implied SEC 38 1 2 static void Op38(void) // SEC { - regs.cc |= FLAG_C; + regs->cc |= FLAG_C; } /* @@ -2463,7 +2354,7 @@ SED Implied SED F8 1 2 static void OpF8(void) // SED { - regs.cc |= FLAG_D; + regs->cc |= FLAG_D; } /* @@ -2472,7 +2363,7 @@ SEI Implied SEI 78 1 2 static void Op78(void) // SEI { - regs.cc |= FLAG_I; + SET_I; } /* @@ -2564,42 +2455,42 @@ Absolute,Y STA Abs,Y 99 3 5 static void Op85(void) { - regs.WrMem(EA_ZP, regs.a); + regs->WrMem(EA_ZP, regs->a); } static void Op95(void) { - regs.WrMem(EA_ZP_X, regs.a); + regs->WrMem(EA_ZP_X, regs->a); } static void Op8D(void) { - regs.WrMem(EA_ABS, regs.a); + regs->WrMem(EA_ABS, regs->a); } static void Op9D(void) { - regs.WrMem(EA_ABS_X, regs.a); + regs->WrMem(EA_ABS_X, regs->a); } static void Op99(void) { - regs.WrMem(EA_ABS_Y, regs.a); + regs->WrMem(EA_ABS_Y, regs->a); } static void Op81(void) { - regs.WrMem(EA_IND_ZP_X, regs.a); + regs->WrMem(EA_IND_ZP_X, regs->a); } static void Op91(void) { - regs.WrMem(EA_IND_ZP_Y, regs.a); + regs->WrMem(EA_IND_ZP_Y, regs->a); } static void Op92(void) { - regs.WrMem(EA_IND_ZP, regs.a); + regs->WrMem(EA_IND_ZP, regs->a); } /* @@ -2612,19 +2503,17 @@ Absolute STX Abs 8E 3 4 static void Op86(void) { - regs.WrMem(EA_ZP, regs.x); + regs->WrMem(EA_ZP, regs->x); } static void Op96(void) { -// BUG!!! [FIXED] -//WAS: regs.WrMem(EA_ZP_X, regs.x); - regs.WrMem(EA_ZP_Y, regs.x); + regs->WrMem(EA_ZP_Y, regs->x); } static void Op8E(void) { - regs.WrMem(EA_ABS, regs.x); + regs->WrMem(EA_ABS, regs->x); } /* @@ -2637,17 +2526,17 @@ Absolute STY Abs 8C 3 4 static void Op84(void) { - regs.WrMem(EA_ZP, regs.y); + regs->WrMem(EA_ZP, regs->y); } static void Op94(void) { - regs.WrMem(EA_ZP_X, regs.y); + regs->WrMem(EA_ZP_X, regs->y); } static void Op8C(void) { - regs.WrMem(EA_ABS, regs.y); + regs->WrMem(EA_ABS, regs->y); } /* @@ -2661,22 +2550,22 @@ Absolute,X STZ Abs,X 9E 3 5 static void Op64(void) { - regs.WrMem(EA_ZP, 0x00); + regs->WrMem(EA_ZP, 0x00); } static void Op74(void) { - regs.WrMem(EA_ZP_X, 0x00); + regs->WrMem(EA_ZP_X, 0x00); } static void Op9C(void) { - regs.WrMem(EA_ABS, 0x00); + regs->WrMem(EA_ABS, 0x00); } static void Op9E(void) { - regs.WrMem(EA_ABS_X, 0x00); + regs->WrMem(EA_ABS_X, 0x00); } /* @@ -2685,8 +2574,8 @@ TAX Implied TAX AA 1 2 static void OpAA(void) // TAX { - regs.x = regs.a; - SET_ZN(regs.x); + regs->x = regs->a; + SET_ZN(regs->x); } /* @@ -2695,8 +2584,8 @@ TAY Implied TAY A8 1 2 static void OpA8(void) // TAY { - regs.y = regs.a; - SET_ZN(regs.y); + regs->y = regs->a; + SET_ZN(regs->y); } /* @@ -2707,8 +2596,8 @@ Absolute TRB Abs 1C 3 6 // TRB opcodes #define OP_TRB_HANDLER(m) \ - SET_Z(m & regs.a); \ - m &= ~regs.a + SET_Z(m & regs->a); \ + m &= ~regs->a static void Op14(void) // TRB ZP { @@ -2734,8 +2623,8 @@ Absolute TSB Abs 0C 3 6 // TSB opcodes #define OP_TSB_HANDLER(m) \ - SET_Z(m & regs.a); \ - m |= regs.a + SET_Z(m & regs->a); \ + m |= regs->a static void Op04(void) // TSB ZP { @@ -2759,8 +2648,8 @@ TSX Implied TSX BA 1 2 static void OpBA(void) // TSX { - regs.x = regs.sp; - SET_ZN(regs.x); + regs->x = regs->sp; + SET_ZN(regs->x); } /* @@ -2769,8 +2658,8 @@ TXA Implied TXA 8A 1 2 static void Op8A(void) // TXA { - regs.a = regs.x; - SET_ZN(regs.a); + regs->a = regs->x; + SET_ZN(regs->a); } /* @@ -2779,7 +2668,7 @@ TXS Implied TXS 9A 1 2 static void Op9A(void) // TXS { - regs.sp = regs.x; + regs->sp = regs->x; } /* @@ -2787,13 +2676,13 @@ TYA Implied TYA 98 1 2 */ static void Op98(void) // TYA { - regs.a = regs.y; - SET_ZN(regs.a); + regs->a = regs->y; + SET_ZN(regs->a); } static void Op__(void) { - regs.cpuFlags |= V65C02_STATE_ILLEGAL_INST; + regs->cpuFlags |= V65C02_STATE_ILLEGAL_INST; } @@ -2801,7 +2690,7 @@ static void Op__(void) // Ok, the exec_op[] array is globally defined here basically to save // a LOT of unnecessary typing. Sure it's ugly, but hey, it works! // -void (* exec_op[256])() = { +static void (* exec_op[256])() = { Op00, Op01, Op__, Op__, Op04, Op05, Op06, Op07, Op08, Op09, Op0A, Op__, Op0C, Op0D, Op0E, Op0F, Op10, Op11, Op12, Op__, Op14, Op15, Op16, Op17, Op18, Op19, Op1A, Op__, Op1C, Op1D, Op1E, Op1F, Op20, Op21, Op__, Op__, Op24, Op25, Op26, Op27, Op28, Op29, Op2A, Op__, Op2C, Op2D, Op2E, Op2F, @@ -2821,17 +2710,6 @@ void (* exec_op[256])() = { }; -// -// Internal "memcpy" (so we don't have to link with any external libraries!) -// -static void myMemcpy(void * dst, void * src, uint32_t size) -{ - uint8_t * d = (uint8_t *)dst, * s = (uint8_t *)src; - - for(uint32_t i=0; iclock + (uint64_t)cycles - regs->overflow; - while (regs.clock < endCycles) + while (regs->clock < endCycles) { #if 0 static bool weGo = false; -if (regs.pc == 0x80AE) +if (regs->pc == 0x80AE) { dumpDis = true; weGo = true; } -else if (regs.pc == 0xFCA8 && weGo) +else if (regs->pc == 0xFCA8 && weGo) { dumpDis = false; - WriteLog("\n*** DELAY (A=$%02X)\n\n", regs.a); + WriteLog("\n*** DELAY (A=$%02X)\n\n", regs->a); } -else if (regs.pc == 0xFCB3 && weGo) +else if (regs->pc == 0xFCB3 && weGo) { dumpDis = true; } #endif #if 0 -/*if (regs.pc == 0x4007) +/*if (regs->pc == 0x4007) { dumpDis = true; }//*/ -if (regs.pc == 0x444B) +if (regs->pc == 0x444B) { WriteLog("\n*** End of wait...\n\n"); dumpDis = true; }//*/ -if (regs.pc == 0x444E) +if (regs->pc == 0x444E) { WriteLog("\n*** Start of wait...\n\n"); dumpDis = false; }//*/ #endif -/*if (regs.pc >= 0xC600 && regs.pc <=0xC6FF) +/*if (regs->pc >= 0xC600 && regs->pc <=0xC6FF) { dumpDis = true; } else dumpDis = false;//*/ -/*if (regs.pc == 0xE039) +/*if (regs->pc == 0xE039) { dumpDis = true; }//*/ #if 0 -/*if (regs.pc == 0x0801) +/*if (regs->pc == 0x0801) { WriteLog("\n*** DISK BOOT subroutine...\n\n"); dumpDis = true; }//*/ -if (regs.pc == 0xE000) +if (regs->pc == 0xE000) { #if 0 WriteLog("\n*** Dump of $E000 routine ***\n\n"); @@ -2954,60 +2827,60 @@ if (regs.pc == 0xE000) WriteLog("\n*** DISK part II subroutine...\n\n"); dumpDis = true; }//*/ -if (regs.pc == 0xD000) +if (regs->pc == 0xD000) { WriteLog("\n*** CUSTOM DISK READ subroutine...\n\n"); dumpDis = false; }//*/ -if (regs.pc == 0xD1BE) +if (regs->pc == 0xD1BE) { // WriteLog("\n*** DISK part II subroutine...\n\n"); dumpDis = true; }//*/ -if (regs.pc == 0xD200) +if (regs->pc == 0xD200) { WriteLog("\n*** CUSTOM SCREEN subroutine...\n\n"); dumpDis = false; }//*/ -if (regs.pc == 0xD269) +if (regs->pc == 0xD269) { // WriteLog("\n*** DISK part II subroutine...\n\n"); dumpDis = true; }//*/ #endif -//if (regs.pc == 0xE08E) -/*if (regs.pc == 0xAD33) +//if (regs->pc == 0xE08E) +/*if (regs->pc == 0xAD33) { WriteLog("\n*** After loader ***\n\n"); dumpDis = true; }//*/ -/*if (regs.pc == 0x0418) +/*if (regs->pc == 0x0418) { WriteLog("\n*** CUSTOM DISK READ subroutine...\n\n"); dumpDis = false; } -if (regs.pc == 0x0) +if (regs->pc == 0x0) { dumpDis = true; }//*/ #ifdef __DEBUGMON__ //WAIT is commented out here because it's called by BELL1... -if (regs.pc == 0xFCA8) +if (regs->pc == 0xFCA8) { WriteLog("\n*** WAIT subroutine...\n\n"); dumpDis = false; }//*/ -if (regs.pc == 0xFBD9) +if (regs->pc == 0xFBD9) { WriteLog("\n*** BELL1 subroutine...\n\n"); // dumpDis = false; }//*/ -if (regs.pc == 0xFC58) +if (regs->pc == 0xFC58) { WriteLog("\n*** HOME subroutine...\n\n"); // dumpDis = false; }//*/ -if (regs.pc == 0xFDED) +if (regs->pc == 0xFDED) { WriteLog("\n*** COUT subroutine...\n\n"); dumpDis = false; @@ -3015,7 +2888,7 @@ if (regs.pc == 0xFDED) #endif #if 0 // ProDOS debugging -if (regs.pc == 0x2000) +if (regs->pc == 0x2000) dumpDis = true; #endif @@ -3023,137 +2896,114 @@ if (regs.pc == 0x2000) static char disbuf[80]; if (dumpDis) { - Decode65C02(disbuf, regs.pc); + Decode65C02(regs, disbuf, regs->pc); WriteLog("%s", disbuf); } #endif - uint8_t opcode = regs.RdMem(regs.pc++); + uint8_t opcode = regs->RdMem(regs->pc++); -//if (!(regs.cpuFlags & V65C02_STATE_ILLEGAL_INST)) +//if (!(regs->cpuFlags & V65C02_STATE_ILLEGAL_INST)) //instCount[opcode]++; - // We need this because the opcode execute could add 1 or 2 cycles - uint64_t clockSave = regs.clock; + // We need this because the opcode function could add 1 or 2 cycles + // which aren't accounted for in CPUCycles[]. + uint64_t clockSave = regs->clock; // Execute that opcode... exec_op[opcode](); - regs.clock += CPUCycles[opcode]; + regs->clock += CPUCycles[opcode]; - // Tell the timer function how many PHI2s have elapsed - if (regs.Timer) -// regs.Timer(CPUCycles[opcode]); - regs.Timer(regs.clock - clockSave); + // Tell the timer function (if any) how many PHI2s have elapsed... + if (regs->Timer) + regs->Timer(regs->clock - clockSave); #ifdef __DEBUG__ if (dumpDis) - WriteLog(" [PC=%04X, SP=01%02X, CC=%s%s.%s%s%s%s%s, A=%02X, X=%02X, Y=%02X]\n", - regs.pc, regs.sp, - (regs.cc & FLAG_N ? "N" : "-"), (regs.cc & FLAG_V ? "V" : "-"), - (regs.cc & FLAG_B ? "B" : "-"), (regs.cc & FLAG_D ? "D" : "-"), - (regs.cc & FLAG_I ? "I" : "-"), (regs.cc & FLAG_Z ? "Z" : "-"), - (regs.cc & FLAG_C ? "C" : "-"), regs.a, regs.x, regs.y); + WriteLog(" [SP=01%02X, CC=%s%s.%s%s%s%s%s, A=%02X, X=%02X, Y=%02X]\n", + regs->sp, + (regs->cc & FLAG_N ? "N" : "-"), (regs->cc & FLAG_V ? "V" : "-"), + (regs->cc & FLAG_B ? "B" : "-"), (regs->cc & FLAG_D ? "D" : "-"), + (regs->cc & FLAG_I ? "I" : "-"), (regs->cc & FLAG_Z ? "Z" : "-"), + (regs->cc & FLAG_C ? "C" : "-"), regs->a, regs->x, regs->y); #endif #ifdef __DEBUGMON__ -if (regs.pc == 0xFCB3) // WAIT exit point +if (regs->pc == 0xFCB3) // WAIT exit point { dumpDis = true; }//*/ -/*if (regs.pc == 0xFBEF) // BELL1 exit point +/*if (regs->pc == 0xFBEF) // BELL1 exit point { dumpDis = true; }//*/ -/*if (regs.pc == 0xFC22) // HOME exit point +/*if (regs->pc == 0xFC22) // HOME exit point { dumpDis = true; }//*/ -if (regs.pc == 0xFDFF) // COUT exit point +if (regs->pc == 0xFDFF) // COUT exit point { dumpDis = true; } -if (regs.pc == 0xFBD8) +if (regs->pc == 0xFBD8) { WriteLog("\n*** BASCALC set BASL/H = $%04X\n\n", RdMemW(0x0028)); }//*/ #endif //These should be correct now... - if (regs.cpuFlags & V65C02_ASSERT_LINE_RESET) + if (regs->cpuFlags & V65C02_ASSERT_LINE_RESET) { // Not sure about this... - regs.sp = 0xFF; - regs.cc = FLAG_I; // Reset the CC register - regs.pc = RdMemW(0xFFFC); // And load PC with the RESET vector + regs->sp = 0xFF; + regs->cc = FLAG_I; // Reset the CC register + regs->pc = RdMemW(0xFFFC); // And load PC with RESET vector - context->cpuFlags = 0; // Clear CPU flags... - regs.cpuFlags = 0; + regs->cpuFlags = 0; // Clear CPU flags... #ifdef __DEBUG__ -WriteLog("\n*** RESET *** (PC = $%04X)\n\n", regs.pc); +WriteLog("\n*** RESET *** (PC = $%04X)\n\n", regs->pc); #endif } - else if (regs.cpuFlags & V65C02_ASSERT_LINE_NMI) + else if (regs->cpuFlags & V65C02_ASSERT_LINE_NMI) { #ifdef __DEBUG__ WriteLog("\n*** NMI ***\n\n"); #endif - regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8); // Save PC and CC - regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF); - regs.WrMem(0x0100 + regs.sp--, regs.cc); - regs.cc |= FLAG_I; // Set I - regs.cc &= ~FLAG_D; // & clear D - regs.pc = RdMemW(0xFFFA); // And do it! + regs->WrMem(0x0100 + regs->sp--, regs->pc >> 8); // Save PC & CC + regs->WrMem(0x0100 + regs->sp--, regs->pc & 0xFF); + regs->WrMem(0x0100 + regs->sp--, regs->cc); + SET_I; + CLR_D; + regs->pc = RdMemW(0xFFFA); // Jump to NMI vector - regs.clock += 7; - context->cpuFlags &= ~V65C02_ASSERT_LINE_NMI;// Reset the asserted line (NMI)... - regs.cpuFlags &= ~V65C02_ASSERT_LINE_NMI; // Reset the asserted line (NMI)... + regs->clock += 7; + regs->cpuFlags &= ~V65C02_ASSERT_LINE_NMI; // Reset NMI line } - else if (regs.cpuFlags & V65C02_ASSERT_LINE_IRQ) + else if ((regs->cpuFlags & V65C02_ASSERT_LINE_IRQ) + // IRQs are maskable, so check if the I flag is clear + && (!(regs->cc & FLAG_I))) { - if (!(regs.cc & FLAG_I)) // Process an interrupt (I=0)? - { #ifdef __DEBUG__ WriteLog("\n*** IRQ ***\n\n"); -WriteLog("Clock=$%X\n", regs.clock); +WriteLog("Clock=$%X\n", regs->clock); //dumpDis = true; #endif - regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8); // Save PC and CC - regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF); - regs.WrMem(0x0100 + regs.sp--, regs.cc); - regs.cc |= FLAG_I; // Set I - regs.cc &= ~FLAG_D; // & clear D - regs.pc = RdMemW(0xFFFE); // And do it! + regs->WrMem(0x0100 + regs->sp--, regs->pc >> 8); // Save PC & CC + regs->WrMem(0x0100 + regs->sp--, regs->pc & 0xFF); + regs->WrMem(0x0100 + regs->sp--, regs->cc); + SET_I; + CLR_D; + regs->pc = RdMemW(0xFFFE); // Jump to IRQ vector - regs.clock += 7; - context->cpuFlags &= ~V65C02_ASSERT_LINE_IRQ; // Reset the asserted line (IRQ)... - regs.cpuFlags &= ~V65C02_ASSERT_LINE_IRQ; // Reset the asserted line (IRQ)... - } + regs->clock += 7; + regs->cpuFlags &= ~V65C02_ASSERT_LINE_IRQ; // Reset IRQ line } } // If we went longer than the passed in cycles, make a note of it so we can - // subtract it out from a subsequent run. It's guaranteed to be positive, - // because the condition that exits the main loop above is written such - // that regs.clock has to be larger than endCycles to exit from it. - regs.overflow = regs.clock - endCycles; - - myMemcpy(context, ®s, sizeof(V65C02REGS)); -} - - -// -// Get the clock of the currently executing CPU -// -uint64_t GetCurrentV65C02Clock(void) -{ - return regs.clock; -} - - -// -// Assert 65C02 line in current context -// -void AssertLine(uint16_t flags) -{ - regs.cpuFlags |= flags; + // subtract it out from a subsequent run. It's guaranteed to be non- + // negative, because the condition that exits the main loop above is + // written such that regs->clock has to be equal or larger than endCycles + // to exit from it. + regs->overflow = regs->clock - endCycles; } diff --git a/src/v65c02.h b/src/v65c02.h index 52cb4e8..b81be31 100644 --- a/src/v65c02.h +++ b/src/v65c02.h @@ -2,7 +2,7 @@ // Virtual 65C02 Header file // // by James Hammons -// (c) 2005 Underground Software +// (c) 2005-2018 Underground Software // #ifndef __V65C02_H__ @@ -37,7 +37,7 @@ struct V65C02REGS uint8_t a; // 65C02 A register uint8_t x; // 65C02 X index register uint8_t y; // 65C02 Y register - uint64_t clock; // 65C02 clock (@ 1 MHz, wraps at 570,842 years) + uint64_t clock; // 65C02 clock (@1 MHz, wraps at 570,842 years) uint8_t (* RdMem)(uint16_t); // Address of BYTE read routine void (* WrMem)(uint16_t, uint8_t); // Address of BYTE write routine void (* Timer)(uint16_t); // Address of Timer routine @@ -49,11 +49,9 @@ struct V65C02REGS extern bool dumpDis; -// Function prototypes +// Exported functions -void Execute65C02(V65C02REGS *, uint32_t); // Function to execute 65C02 instructions -uint64_t GetCurrentV65C02Clock(void); // Get the clock of the currently executing CPU -void AssertLine(uint16_t); // Assert 65C02 line in current context +void Execute65C02(V65C02REGS *, uint32_t); #endif // __V65C02_H__ diff --git a/src/video.h b/src/video.h index 8d70a90..daa1423 100644 --- a/src/video.h +++ b/src/video.h @@ -8,12 +8,21 @@ #include // These are double the normal width because we use sub-pixel rendering. -//#define VIRTUAL_SCREEN_WIDTH 280 -#define VIRTUAL_SCREEN_WIDTH 560 -//#define VIRTUAL_SCREEN_HEIGHT 192 -#define VIRTUAL_SCREEN_HEIGHT 384 +#define VIRTUAL_SCREEN_WIDTH (280 * 2) +#define VIRTUAL_SCREEN_HEIGHT (192 * 2) -// Global variables (exported) +// Exported functions + +void TogglePalette(void); +void CycleScreenTypes(void); +void SpawnMessage(const char * text, ...); +bool InitVideo(void); +void VideoDone(void); +void RenderAppleScreen(SDL_Renderer *); +void ToggleFullScreen(void); +void ToggleTickDisplay(void); + +// Exported variables extern bool flash; extern bool textMode; @@ -25,21 +34,5 @@ extern bool col80Mode; extern SDL_Renderer * sdlRenderer; extern SDL_Window * sdlWindow; -// Functions (exported) - -//void SetupBlurTable(void); -void TogglePalette(void); -void CycleScreenTypes(void); -void SpawnMessage(const char * text, ...); -bool InitVideo(void); -void VideoDone(void); -void RenderAppleScreen(SDL_Renderer *); -void ToggleFullScreen(void); -void ToggleTickDisplay(void); - -// Exported crap - -//extern uint32_t * scrBuffer; -//extern int scrPitch; - #endif // __VIDEO_H__ +