From: Shamus Hammons Date: Fri, 13 Jan 2023 17:28:11 +0000 (-0600) Subject: Code cleanup, final fix for sprite lag problem. X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=thunder;a=commitdiff_plain;h=8ba4c4438d796f83851cd53914dff928193ed658 Code cleanup, final fix for sprite lag problem. It only took about 10 or so years to fix this. :-P --- diff --git a/.gitignore b/.gitignore index 4b5053c..7e5f3de 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,12 @@ MAME 0.71 driver/ obj/ ROMs/ sounds/ +test/ +mame/ +*.wav +*.raw +*.pcx *.log +*.txt thunder diff --git a/doc/notes.txt b/doc/notes.txt index 0f2499c..04b808a 100644 --- a/doc/notes.txt +++ b/doc/notes.txt @@ -124,55 +124,3 @@ Pin 35: Same as other processor (1.538 MHz) pin 34: Same as other processor (1.538 MHz) Hope this helps! ;) - - -ROM_START( rthunder ) - ROM_REGION( 0x18000, REGION_CPU1, 0 ) - ROM_LOAD( "rt3-1b.9c", 0x8000, 0x8000) /* 9d empty */ - - ROM_REGION( 0x40000, REGION_USER1, 0 ) /* bank switched data for CPU1 */ - ROM_LOAD( "rt1-17.f1", 0x00000, 0x10000) - ROM_LOAD( "rt1-18.h1", 0x10000, 0x10000) - ROM_LOAD( "rt1-19.k1", 0x20000, 0x10000) - ROM_LOAD( "rt1-20.m1", 0x30000, 0x10000) - - ROM_REGION( 0x18000, REGION_CPU2, 0 ) - ROM_LOAD( "rt3-2b.12c", 0x08000, 0x8000) - ROM_LOAD( "rt3-3.12d", 0x10000, 0x8000) - - ROM_REGION( 0x18000, REGION_GFX1, ROMREGION_DISPOSE ) - ROM_LOAD( "rt1-7.7r", 0x00000, 0x10000) /* plane 1,2 */ - ROM_LOAD( "rt1-8.7s", 0x10000, 0x08000) /* plane 3 */ - - ROM_REGION( 0x0c000, REGION_GFX2, ROMREGION_DISPOSE ) - ROM_LOAD( "rt1-5.4r", 0x00000, 0x08000) /* plane 1,2 */ - ROM_LOAD( "rt1-6.4s", 0x08000, 0x04000) /* plane 3 */ - - ROM_REGION( 0x80000, REGION_GFX3, ROMREGION_DISPOSE ) - ROM_LOAD( "rt1-9.12h", 0x00000, 0x10000) - ROM_LOAD( "rt1-10.12k", 0x10000, 0x10000) - ROM_LOAD( "rt1-11.12l", 0x20000, 0x10000) - ROM_LOAD( "rt1-12.12m", 0x30000, 0x10000) - ROM_LOAD( "rt1-13.12p", 0x40000, 0x10000) - ROM_LOAD( "rt1-14.12r", 0x50000, 0x10000) - ROM_LOAD( "rt1-15.12t", 0x60000, 0x10000) - ROM_LOAD( "rt1-16.12u", 0x70000, 0x10000) - - ROM_REGION( 0x1420, REGION_PROMS, 0 ) - ROM_LOAD( "mb7124e.3r", 0x0000, 0x0200) /* red & green components */ - ROM_LOAD( "mb7116e.3s", 0x0200, 0x0200) /* blue component */ - ROM_LOAD( "mb7138h.4v", 0x0400, 0x0800) /* tiles colortable */ - ROM_LOAD( "mb7138h.6v", 0x0c00, 0x0800) /* sprites colortable */ - ROM_LOAD( "mb7112e.6u", 0x1400, 0x0020) /* tile address decoder (used at runtime) */ - - ROM_REGION( 0x10000, REGION_CPU3, 0 ) - ROM_LOAD( "rt1-4.6b", 0x04000, 0x8000) - ROM_LOAD( "rt1-mcu.bin", 0x0f000, 0x1000) - - ROM_REGION( 0x40000, REGION_SOUND1, 0 ) /* PCM samples for Hitachi CPU */ - ROM_LOAD( "rt1-21.f3", 0x00000, 0x10000) - ROM_LOAD( "rt1-22.h3", 0x10000, 0x10000) - /* k3 empty */ - /* m3 empty */ -ROM_END - diff --git a/makefile b/makefile index fdf79bc..5f2d1b6 100644 --- a/makefile +++ b/makefile @@ -6,7 +6,7 @@ # This software is licensed under the GPL v3 or later # -ifeq "$(OSTYPE)" "msys" # Win32 +ifeq "$(OSTYPE)" "msys" # Win32 SYSTYPE = __GCCWIN32__ EXESUFFIX = .exe diff --git a/src/dis63701.h b/src/dis63701.h index 8fcad9c..8019140 100644 --- a/src/dis63701.h +++ b/src/dis63701.h @@ -4,7 +4,6 @@ // by James Hammons // (C) 2004, 2014 Underground Software // - #ifndef __DIS63701_H__ #define __DIS63701_H__ diff --git a/src/dis6809.h b/src/dis6809.h index a08851e..35ed32d 100644 --- a/src/dis6809.h +++ b/src/dis6809.h @@ -4,14 +4,11 @@ // by James Hammons // (C) 2004, 2014 Underground Software // - #ifndef __DIS6809_H__ #define __DIS6809_H__ -//#include "types.h" #include "v6809.h" -//int Decode6809(uint16); int Decode6809(V6809REGS); #endif // __DIS6809_H__ diff --git a/src/gui.h b/src/gui.h index a5d4c6f..6dfb03f 100644 --- a/src/gui.h +++ b/src/gui.h @@ -4,7 +4,6 @@ // by James Hammmons // (C) 1998, 2014 Underground Software // - #ifndef __GUI_H__ #define __GUI_H__ diff --git a/src/log.cpp b/src/log.cpp index c39a0b3..97f0733 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -19,7 +19,6 @@ static FILE * logStream = NULL; static uint32_t logSize = 0; - bool InitLog(const char * path) { logStream = fopen(path, "wrt"); @@ -30,14 +29,12 @@ bool InitLog(const char * path) return true; } - void LogDone(void) { if (logStream) fclose(logStream); } - // // This logger is used mainly to ensure that text gets written to the log file // even if the program crashes. The performance hit is acceptable in this case! @@ -62,4 +59,3 @@ void WriteLog(const char * text, ...) va_end(arg); fflush(logStream); // Make sure that text is written! } - diff --git a/src/log.h b/src/log.h index 3367c34..3e4a5d3 100644 --- a/src/log.h +++ b/src/log.h @@ -1,7 +1,6 @@ // // LOG.H // - #ifndef __LOG_H__ #define __LOG_H__ diff --git a/src/psg.cpp b/src/psg.cpp index 5d6e669..ec849c5 100644 --- a/src/psg.cpp +++ b/src/psg.cpp @@ -15,15 +15,14 @@ // // Notes: // ------ -// The emulator creates signed 16-bit samples. Make sure there's enough room in -// your buffer for them! +// The emulator creates signed 16-bit samples. Make sure there's enough room +// in your buffer for them! // #include "psg.h" #include #include - struct Voice { uint8_t leftVolume; @@ -37,11 +36,9 @@ struct Voice static Voice voice[8]; static uint8_t memory[0x200]; -//static static uint32_t sampleRate = 44100; static uint32_t divisor; - void InitPSG(uint32_t s/*=44100*/) { sampleRate = s; @@ -52,10 +49,9 @@ void InitPSG(uint32_t s/*=44100*/) voice[i].noiseSeed = 1; } - // -// Note that it doesn't wipe out the buffer passed in, if you want it wiped, -// you have to wipe it yourself. :-) +// Note that it doesn't wipe out the buffer passed in; if you want it wiped, +// you have to wipe it yourself. :-) // void UpdatePSG(uint8_t * buffer, int count) { @@ -137,7 +133,6 @@ if F == 22050, then counter += 0.5 for each sample. } } - void WritePSG(uint16_t address, uint8_t data) { if ((address >= 0x100) && (address <= 0x13F)) @@ -154,7 +149,7 @@ void WritePSG(uint16_t address, uint8_t data) break; case 1: voice[channel].waveform = data >> 4; - voice[channel].frequency = ((data & 0x0F) << 16) + voice[channel].frequency = ((data & 0x0F) << 16) | (voice[channel].frequency & 0x0FFFF); #if 0 printf("PSG: Setting waveform on channel %i to %i...\n", channel, voice[channel].waveform); @@ -202,9 +197,7 @@ if (data & 0x0F) memory[address & 0x01FF] = data; } - uint8_t ReadPSG(uint16_t address) { return memory[address & 0x01FF]; } - diff --git a/src/screen.cpp b/src/screen.cpp index d3f5672..f089270 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -41,7 +41,6 @@ uint8_t spr_color_index; // Sprite color index extern bool show_text; // Whether or not to show text - // // Render the NAMCO screen // @@ -109,7 +108,6 @@ PP = which 4K block to write to? RenderScreenBuffer(); } - // // Render tilemap // @@ -121,14 +119,10 @@ static inline void DrawScreen(uint16_t ramBlock, uint16_t xAddress, uint16_t yAd for(uint8_t sy=0; sy<29; sy++) { for(uint8_t sx=0; sx<37; sx++) - { - DrawChar(sx, sy, ramBase, tileBase << 16, xAddress & 0x07, yAddress & 0x07, transparent); - } } } - // // Draw character on screen // @@ -174,10 +168,8 @@ static inline void DrawChar(uint8_t sx, uint8_t sy, uint16_t ramBase, uint32_t t } } - // // Copy sprites in sprite RAM from positions 4-9 to 10-15 -// (N.B.: This still doesn't solve the shifting signs on the walls problem...) // void CopySprites(void) { @@ -192,9 +184,10 @@ void CopySprites(void) } } - // -// Draw sprites at priority level (new code) +// Draw sprites at priority level +// We read from the sprite copy RAM to render sprites, as that seems to be the +// way the real H/W does it. // void DrawSprites(uint8_t priority) { @@ -202,42 +195,44 @@ void DrawSprites(uint8_t priority) // // Offset Note // ------ -------------------------------------------------------------------- -// 4 h.fb .nnn (f = horz. flip, h = horz. expand, b = sprite offset lo +// 4 (10) h.fb .nnn (f = horz. flip, h = horz. expand, b = sprite offset lo // bit, nnn = upper bits of sprite #) -// 5 Lower 7 bits of sprite # -// 6 Sprite color index (top 7 bits only), bottom bit is bit 8 of X +// 5 (11) Lower 7 bits of sprite # +// 6 (12) Sprite color index (top 7 bits only), bottom bit is bit 8 of X // position -// 7 Sprite X position (bits 0-7) -// 8 Top two bits are sprite priority, bits 4 & 2 are sprite offset hi +// 7 (13) Sprite X position (bits 0-7) +// 8 (14) Top two bits are sprite priority, bits 4 & 2 are sprite offset hi // bit, vert. expand -// 9 Sprite Y position (192 - value) +// 9 (15) Sprite Y position (192 - value) - extern uint8_t gram1[]; // Game RAM space + extern uint8_t gram1[]; // Game RAM space for(uint16_t i=0x5800; i<0x6000; i+=0x10) { - if ((gram1[i + 8 + 6] & 0xC0) == priority) // Check for correct layer... - { - spr_color_index = gram1[i + 6 + 6] >> 1; // Set color... - uint16_t x = ((gram1[i + 6 + 6] & 0x01) << 8) | gram1[i + 7 + 6]; + uint8_t * sprRAM = &gram1[i]; - if (x > 512 - 32) - x -= 512; // Handle neg x values + // Skip sprite if it's not on the correct layer... + if ((sprRAM[14] & 0xC0) != priority) + continue; - uint16_t y = 192 - gram1[i + 9 + 6]; - uint8_t flip = gram1[i + 4 + 6] & 0x20; // Horizontal flip - uint32_t spr_num = ((gram1[i + 4 + 6] & 0x07) << 9) - | ((gram1[i + 5 + 6] & 0x7F) << 2) - | ((gram1[i + 4 + 6] & 0x10) >> 4) - | ((gram1[i + 8 + 6] & 0x10) >> 3); + spr_color_index = sprRAM[12] >> 1; // Set color... + uint16_t x = ((sprRAM[12] & 0x01) << 8) | sprRAM[13]; - // Draw sprite... - Sprite(spr_num, x, y, flip, gram1[i + 4 + 6] & 0x80, gram1[i + 8 + 6] & 0x04); - } + if (x > 512 - 32) + x -= 512; // Handle neg x values + + uint16_t y = 192 - sprRAM[15]; + uint8_t horzFlip = sprRAM[10] & 0x20; + uint32_t spr_num = ((sprRAM[10] & 0x07) << 9) + | ((sprRAM[11] & 0x7F) << 2) + | ((sprRAM[10] & 0x10) >> 4) + | ((sprRAM[14] & 0x10) >> 3); + + // Draw the sprite... + Sprite(spr_num, x, y, horzFlip, sprRAM[10] & 0x80, sprRAM[14] & 0x04); } } - static inline void DrawSpriteBlock(uint32_t & sprnum, uint16_t x, uint16_t y, uint16_t xStart, uint16_t xEnd, int16_t xInc) { extern uint8_t spr_rom[]; @@ -263,7 +258,6 @@ static inline void DrawSpriteBlock(uint32_t & sprnum, uint16_t x, uint16_t y, ui } } - static inline void DrawSpriteBlock2(uint32_t & sprnum, uint16_t x, uint16_t y, uint16_t xStart, uint16_t xEnd, int16_t xInc) { extern uint8_t spr_rom[]; @@ -289,7 +283,6 @@ static inline void DrawSpriteBlock2(uint32_t & sprnum, uint16_t x, uint16_t y, u } } - // // Sprite handler // @@ -343,7 +336,6 @@ void Sprite(uint32_t sprnum, uint16_t x, uint16_t y, uint8_t flip, } } - int FindPCXName(void) { static int pcxNum = -1; // This needs to go elsewhere... (or does it?) @@ -366,7 +358,6 @@ int FindPCXName(void) return -1; } - void SavePCXSnapshot(void) { char filename[30]; @@ -465,4 +456,3 @@ void SavePCXSnapshot(void) // Success! fclose(fw); } - diff --git a/src/sound.cpp b/src/sound.cpp index e366830..f2af13a 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -17,8 +17,8 @@ #include "resource.h" #include "ym2151.h" - -#define SAMPLE_RATE 48000 +#define SAMPLE_RATE 48000 +#define BUFFER_SIZE 512 // Function prototypes void SoundFunc(void *, Uint8 *, int); @@ -27,37 +27,28 @@ void SoundFunc(void *, Uint8 *, int); extern uint8_t voice_rom[]; // PCM data pointer static bool soundInitialized = false; -const float sampleBase = (float)SAMPLE_RATE/6000.0; // Voice is between 5512.5 and 6000 Hz -bool snd_go = false; -bool chan1_go = false, chan2_go = false;//, chan3_go = false; -bool /*chan4_go = false, chan5_go = false,*/ chan6_go = false; -uint8_t * sndp1, * sndp2, /* sndp3, * sndp4, * sndp5,*/ * sndp6; -uint32_t rom_pos, end_pos; +const float sampleBase = (float)SAMPLE_RATE / 6000.0; // Voice is between 5512.5 and 6000 Hz +bool chan1_go = false, chan2_go = false; +bool chan6_go = false; +uint8_t * sndp1, * sndp2, * sndp6; uint32_t spos1, end_pos1; uint32_t spos2, end_pos2; -//uint32_t spos3, end_pos3; -//uint32_t spos4, end_pos4; -//uint32_t spos5, end_pos5; uint32_t spos6, end_pos6; -float sample1; -int16_t prevSamp1; -//int8_t delta_x1; -float sample2; -int16_t prevSamp2; -//int8_t delta_x2; +float sample1, sample2; +int16_t prevSamp1, prevSamp2; uint16_t snd_num; -uint8_t * snd_array[3] = { sunknown, scya, scamera }; // From RESOURCE.H +// From RESOURCE.H +uint8_t * snd_array[3] = { sunknown, scya, scamera }; uint32_t snd_lens[3] = { sunknownlen, scyalen, scameralen }; - void InitSound(void) { // params 1, 4 & 5 are useless -// if (YMInit(1, 3579580, 22050, 16, 512))//, (SAMPLE **)sbp)) - if (YMInit(1, 3579580, SAMPLE_RATE, 16, 512)) +// if (YMInit(1, 3579580, SAMPLE_RATE, 16, 512)) + if (YMInit(3579580, SAMPLE_RATE)) { printf("SOUND: Could not init YM2151 emulator!\n"); - return;// -1; + return; } InitPSG(SAMPLE_RATE); @@ -66,11 +57,11 @@ void InitSound(void) desired.freq = SAMPLE_RATE; desired.format = AUDIO_S16; desired.channels = 1; - desired.samples = 1024; + desired.samples = BUFFER_SIZE * 2; // Size is in BYTES, so x2 desired.callback = SoundFunc; desired.userdata = NULL; - // Also, should check to see if it got the hardware it needed, correct sample size, etc. + // Also, should check to see if it got the hardware it needed, correct sample size, etc. (actually, SDL guarantees we get what we asked for--I think) if (SDL_OpenAudio(&desired, &obtained) < 0) { soundInitialized = false; @@ -83,21 +74,12 @@ void InitSound(void) soundInitialized = true; } - void SpawnSound(int type, int snd, int channel/* = 0*/) { -// extern uint32_t psg_lens[16]; -// extern uint8_t * psg_adrs[16]; -// extern uint32_t voc_lens[32]; -// extern uint8_t * voc_adrs[32]; -// extern uint32_t fm_lens[14]; -// extern uint8_t * fm_adrs[14]; - if (!soundInitialized) return; snd_num = snd; -// SpawnMsg(MSHOWNUMS); // Voice type sounds... if (type == GAMESOUND) @@ -139,43 +121,6 @@ void SpawnSound(int type, int snd, int channel/* = 0*/) chan2_go = true; } } -#if 0 - else if (type == PSGSOUND) - { - if (snd_num & 0x10) // Second channel? - { - spos3 = 0; - end_pos3 = psg_lens[snd_num & 0x0F]; - sndp3 = psg_adrs[snd_num & 0x0F]; - chan3_go = true; - - if (spos3 == end_pos3) - chan3_go = false; // No sound loaded, so don't do it! - } - else // First channel - { - spos4 = 0; - end_pos4 = psg_lens[snd_num & 0x0F]; - sndp4 = psg_adrs[snd_num & 0x0F]; - chan4_go = true; - - if (spos4 == end_pos4) - chan4_go = false; // No sound loaded, so don't do it! - } - } -#endif -#if 0 - else if (type == FMSOUND) - { - spos5 = 0; - end_pos5 = fm_lens[snd_num]; - sndp5 = fm_adrs[snd_num]; - chan5_go = true; - - if (spos5 == end_pos5) - chan5_go = false; // No sound loaded, so don't do it! - } -#endif else if (type == USERSOUND) { spos6 = 0; @@ -185,23 +130,18 @@ void SpawnSound(int type, int snd, int channel/* = 0*/) } } - void SoundFunc(void * userdata, Uint8 * buffer, int num) { - static bool psg1go = false, psg2go = false; - // Length / 2 is because it's set up for 16-bit samples -// YM2151UpdateOne(buffer, length / 2); - // Have to go into ym2151.cpp and change this manually back to 8 bit + // We do num / 2 because num is in BYTES, and the buffer uses signed WORDs. YM2151UpdateOne(buffer, num / 2); -// return; UpdatePSG(buffer, num / 2); // 0-22 different sounds... - uint16_t cnt = 0;//, sample; + uint16_t cnt = 0; uint8_t start_samp1, end_samp1, start_samp2, end_samp2; int16_t samp1 = 0, samp2 = 0, samp6 = 0; // Zero samples... - if (!(chan1_go || chan2_go /*|| chan3_go || chan4_go || chan5_go*/ || chan6_go)) + if (!(chan1_go || chan2_go || chan6_go)) return; while (cnt != (num / 2)) @@ -245,7 +185,6 @@ void SoundFunc(void * userdata, Uint8 * buffer, int num) { uint8_t voiceSample = voice_rom[spos2++]; samp2 = ((int16_t)voiceSample - 128) * 160; -// samp2 = voice_rom[spos2++]; if (voiceSample == 0xFF) { @@ -267,42 +206,6 @@ void SoundFunc(void * userdata, Uint8 * buffer, int num) sample2 -= 1.0; } -#if 0 - if (chan3_go) - { - samp3 = ((psg1go ? sndp3[spos3++] : sndp3[spos3]) - 128) * 160; - psg1go = !psg1go; - - if (spos3 == end_pos3) - { - chan3_go = false; - samp3 = 0; // Kill channel 3 if done... - } - } - - if (chan4_go) - { - samp4 = ((psg2go ? sndp4[spos4++] : sndp4[spos4]) - 128) * 160; - psg2go = !psg2go; - - if (spos4 == end_pos4) - { - chan4_go = false; - samp4 = 0; // Kill channel 4 if done... - } - } - - if (chan5_go) - { - samp5 = sndp5[spos5++]; - - if (spos5 == end_pos5) - { - chan5_go = false; - samp5 = 128; // Kill channel 5 if done... - } - } -#endif if (chan6_go) { samp6 = sndp6[spos6++]; @@ -315,14 +218,10 @@ void SoundFunc(void * userdata, Uint8 * buffer, int num) } // Mix 'em... -// sample = samp1 + samp2 + samp3 + samp4 + samp5 + samp6 - 640; int32_t sample = samp1 + samp2 + samp6; sample += ((int16_t *)buffer)[cnt]; // If it overflowed, clip it -// if (sample & 0xFFFF0000) -// sample = (sample & 0x8000 ? 0x00 : 0xFF); -// sample = (sample & 0x80000000 ? 0x0000 : 0xFFFF); if (sample > 32767) sample = 32767; else if (sample < -32767) @@ -331,4 +230,3 @@ void SoundFunc(void * userdata, Uint8 * buffer, int num) ((int16_t *)buffer)[cnt++] = (int16_t)sample; } } - diff --git a/src/sound.h b/src/sound.h index 39ee96f..d4e11a0 100644 --- a/src/sound.h +++ b/src/sound.h @@ -14,14 +14,11 @@ #define SCYA 1 #define SCAMERA 2 - // Functions void InitSound(void); void SpawnSound(int, int, int channel = 0); - // Exported vars extern uint16_t snd_num; #endif // __SOUND_H__ - diff --git a/src/thunder.cpp b/src/thunder.cpp index bd0cc85..2914a96 100644 --- a/src/thunder.cpp +++ b/src/thunder.cpp @@ -2,7 +2,7 @@ // Thunder: A Rolling Thunder Emulator // // by James Hammons -// (C) 2004, 2014 Underground Software +// (C) 2004, 2023 Underground Software // // JLH = James Hammons // @@ -12,9 +12,10 @@ // JLH 08/12/2009 Stabilized emulation so that it works // JLH 04/04/2014 Converted to SDL 2 // JLH 04/17/2014 Removed a metric fuck-tonne of cruft, added YM2151 & MCU +// JLH 01/13/2023 Finally fixed the sprite lag problem :-D // -#define THUNDER_VERSION "1.2.0" +#define THUNDER_VERSION "1.2.1" #include #include @@ -32,7 +33,6 @@ #include "video.h" #include "ym2151.h" - #define ROM1 "rt3-1b.9c" #define ROM2 "rt3-2b.12c" #define ROM3 "rt3-3.12d" @@ -62,7 +62,6 @@ #define PROM5 "mb7112e.6u" #define MCUROM "rt1-mcu.bin" - // Global defines uint8_t gram1[0x10000], grom1[0x10000], grom2[0x10000]; @@ -80,11 +79,13 @@ uint32_t banksw1, banksw2; // MCU inputs Byte input1, input2, input3, input4, input5; +// Copy sprites flag +bool copySprites = false; + // Function prototypes uint8_t MCUReadMemory(uint16_t address); void MCUWriteMemory(uint16_t address, uint8_t data); - // // Read a byte from memory // @@ -107,14 +108,11 @@ uint8_t MainReadMemory(uint16_t addr) return grom1[addr]; } - // // Write a byte to memory // void MainWriteMemory(uint16_t address, uint8_t data) { - extern bool disasm; - if (address == 0x6000) SpawnSound(GAMESOUND, gram1[0x6200], 0); // Do voice chan 1 if (address == 0x6400) @@ -129,25 +127,15 @@ void MainWriteMemory(uint16_t address, uint8_t data) gram1[address] = data; if (address == 0x5FF2) - CopySprites(); + copySprites = true; if (address == 0x8800) charBankSwitch = false; // Char banksw1 if (address == 0x8C00) charBankSwitch = true; // Char banksw2 - if (address == 0x8400) // Frame go strobe? VBlank acknowledge? - { -// BlitChar(charROM, gram1); - - // IRQ Ack (may also be frame go...) - ClearLineOfCurrentV6809(V6809_ASSERT_LINE_IRQ); -#if 1 - if (disasm) - WriteLog("WriteMem: CPU #1 Acknowledging IRQ...\n", data); -#endif - } + if (address == 0x8400) // Frame go strobe? VBlank acknowledge? + ClearLineOfCurrentV6809(V6809_LINE_IRQ); // IRQ Ack } - // // Read a byte from memory (2nd processor) // @@ -166,14 +154,11 @@ uint8_t SubReadMemory(uint16_t address) return grom2[address]; } - // // Write a byte to memory (2nd processor) // void SubWriteMemory(uint16_t address, uint8_t data) { - extern bool disasm; - // Set sprite data bank switch if (address == 0xD803) banksw2 = (uint32_t)(data & 0x03) << 13; @@ -185,20 +170,12 @@ void SubWriteMemory(uint16_t address, uint8_t data) gram1[address - 0x2000] = data; if (address == 0x1FF2) - CopySprites(); + copySprites = true; if (address == 0x8800) - { - // IRQ Ack (may also be frame go...) - ClearLineOfCurrentV6809(V6809_ASSERT_LINE_IRQ); -#if 1 - if (disasm) - WriteLog("WriteMem: CPU #2 Acknowledging IRQ...\n", data); -#endif - } + ClearLineOfCurrentV6809(V6809_LINE_IRQ); // IRQ Ack } - uint8_t MCUReadMemory(uint16_t address) { if (address < 0x20) @@ -221,7 +198,6 @@ uint8_t MCUReadMemory(uint16_t address) return mcuMem[address]; } - void MCUWriteMemory(uint16_t address, uint8_t data) { static uint8_t ymRegister; @@ -254,32 +230,27 @@ void MCUWriteMemory(uint16_t address, uint8_t data) mcuMem[address] = data; } - uint8_t V63701ReadPort1(void) { // printf("V63701ReadPort1: Read $%02X...\n", input3.byte); return input3.byte; } - uint8_t V63701ReadPort2(void) { return 0xFF; } - void V63701WritePort1(uint8_t data) { // printf("V63701WritePort1: Wrote $%02X...\n", data); } - void V63701WritePort2(uint8_t data) { // printf("V63701WritePort2: Wrote $%02X...\n", data); } - // // Generic Load file into image space // (No error checking performed! Responsibility of caller!) @@ -298,19 +269,18 @@ bool LoadImg(const char * filename, uint8_t * mem, uint32_t address, uint32_t le return false; } - fread(&mem[address], 1, length, file); + size_t ignored = fread(&mem[address], 1, length, file); fclose(file); return true; } - // // Read color PROMs // bool ReadColorPROMs(void) { - FILE * file1 = fopen("./ROMs/"PROM3, "rb"); + FILE * file1 = fopen("./ROMs/" PROM3, "rb"); if (file1) { @@ -321,7 +291,7 @@ bool ReadColorPROMs(void) fclose(file1); } - file1 = fopen("./ROMs/"PROM4, "rb"); + file1 = fopen("./ROMs/" PROM4, "rb"); if (file1) { @@ -332,8 +302,8 @@ bool ReadColorPROMs(void) fclose(file1); } - file1 = fopen("./ROMs/"PROM1, "rb"); - FILE * file2 = fopen("./ROMs/"PROM2, "rb"); + file1 = fopen("./ROMs/" PROM1, "rb"); + FILE * file2 = fopen("./ROMs/" PROM2, "rb"); // If open was successful... if (file1 && file2) @@ -355,7 +325,7 @@ bool ReadColorPROMs(void) // PROM5 has the following in it (tile address decoder): // 00: 00 20 40 60 02 22 42 62 04 24 44 64 06 26 46 66 - // 10: 88 A8 C8 E8 8A AA CA EA 8C AC CC EC 8E AE CE EE + // 10: 88 A8 C8 E8 8A AA CA EA 8C AC CC EC 8E AE CE EE if (!file1) { @@ -366,19 +336,18 @@ bool ReadColorPROMs(void) return true; } - // // Unpack font data // bool UnpackFonts(void) { // 0x4000 $800 chars - FILE * file1 = fopen("./ROMs/"ROM7, "rb"); - FILE * file2 = fopen("./ROMs/"ROM8, "rb"); + FILE * file1 = fopen("./ROMs/" ROM7, "rb"); + FILE * file2 = fopen("./ROMs/" ROM8, "rb"); if (!file1 || !file2) { - printf("Could not open either "ROM7" or "ROM8"!\n"); + printf("Could not open either " ROM7 " or " ROM8 "!\n"); return false; } @@ -403,12 +372,12 @@ bool UnpackFonts(void) fclose(file1); fclose(file2); - file1 = fopen("./ROMs/"ROM5, "rb"); - file2 = fopen("./ROMs/"ROM6, "rb"); + file1 = fopen("./ROMs/" ROM5, "rb"); + file2 = fopen("./ROMs/" ROM6, "rb"); if (!file1 || !file2) { - printf("Could not open either "ROM5" or "ROM6"!\n"); + printf("Could not open either " ROM5 " or " ROM6 "!\n"); return false; } @@ -436,7 +405,6 @@ bool UnpackFonts(void) return true; } - // // Main loop // @@ -444,16 +412,14 @@ int main(int argc, char * argv[]) { InitLog("thunder.log"); - extern bool disasm; // From 'V6809.CPP' - bool running; // CPU running state flag... SDL_Event event; // SDL "event" uint32_t ticks, oldTicks; uint8_t frameTickCount = 0; - printf("THUNDER v"THUNDER_VERSION" by James Hammons\n"); - printf("Serial #20149417 / Prerelease\n"); - printf("© 2003, 2014 Underground Software\n\n"); + printf("THUNDER v" THUNDER_VERSION " by James Hammons\n"); + printf("Serial #20230113 / Prerelease\n"); + printf("© 2003, 2023 Underground Software\n\n"); printf("This emulator is free software. If you paid for it you were RIPPED OFF\n\n"); // SDL_WM_SetCaption("Thunder v"THUNDER_VERSION" ", "Thunder"); @@ -532,17 +498,17 @@ int main(int argc, char * argv[]) memset(&cpu1, 0, sizeof(V6809REGS)); cpu1.RdMem = MainReadMemory; cpu1.WrMem = MainWriteMemory; - cpu1.cpuFlags |= V6809_ASSERT_LINE_RESET; + cpu1.cpuFlags |= V6809_LINE_RESET; memset(&cpu2, 0, sizeof(V6809REGS)); cpu2.RdMem = SubReadMemory; cpu2.WrMem = SubWriteMemory; - cpu2.cpuFlags |= V6809_ASSERT_LINE_RESET; + cpu2.cpuFlags |= V6809_LINE_RESET; memset(&mcu, 0, sizeof(V63701REGS)); mcu.RdMem = MCUReadMemory; mcu.WrMem = MCUWriteMemory; - mcu.cpuFlags |= V63701_ASSERT_LINE_RESET; + mcu.cpuFlags |= V63701_LINE_RESET; running = true; @@ -553,7 +519,7 @@ int main(int argc, char * argv[]) InitGUI(); // Reset # of coins // Set up DIP switches... - input4.bit.b0 = 1; // DSW B-0: Contiues (1 = 6, 0 = 3) + input4.bit.b0 = 1; // DSW B-0: Continues (1 = 6, 0 = 3) input4.bit.b1 = 1; // DSW B-2: ??? input4.bit.b2 = 1; // DSW B-4: Difficulty (1 = normal, 0 = easy) input4.bit.b3 = 1; // DSW B-6: Bonus lives (70K/200K = 1, 100K/300K = 0) @@ -579,9 +545,6 @@ WriteLog("About to set up screen...\n"); WriteLog("About to set up audio...\n"); InitSound(); -//memset(scrBuffer, 0xFF, VIRTUAL_SCREEN_WIDTH*VIRTUAL_SCREEN_HEIGHT*sizeof(uint32_t)); -//RenderScreenBuffer(); - WriteLog("About to enter main loop...\n"); while (running) { @@ -590,11 +553,6 @@ WriteLog("About to enter main loop...\n"); // Dipswitches are presented to the main CPUs as 0 or 1 at locations // $423D - $425B by the MCU -//testing... (works) -//gram1[0x423D] = 1; - //gram1[0x423D] = self_test; // Reset DSW1-1 -// gram1[0x4268] = 0; // Reset Video test - // SDL key handling... SDL_Event event; @@ -948,9 +906,9 @@ WriteLog("About to enter main loop...\n"); #endif // We can do this here because we're not executing the cores yet. - cpu1.cpuFlags |= V6809_ASSERT_LINE_IRQ; - cpu2.cpuFlags |= V6809_ASSERT_LINE_IRQ; - mcu.cpuFlags |= V63701_ASSERT_LINE_IRQ; + cpu1.cpuFlags |= V6809_LINE_IRQ; + cpu2.cpuFlags |= V6809_LINE_IRQ; + mcu.cpuFlags |= V63701_LINE_IRQ; // while (cpu1.clock < 25000) // 1.538 MHz = 25633.333... cycles per frame (1/60 s) // 25600 cycles/frame @@ -959,21 +917,33 @@ WriteLog("About to enter main loop...\n"); // 40 works, until it doesn't... :-P // 640 * 40 // 800 * 32 +// 20 seems to work... :-) // Interesting, putting IRQs at 30 Hz makes it run at the correct speed. Still hangs in the demo, though. - for(int i=0; i<640; i++) +// for(int i=0; i<640; i++) + for(int i=0; i<1280; i++) { // Gay, but what are ya gonna do? // There's better ways, such as keeping track of when slave writes to master, etc... - Execute6809(&cpu1, 40); - Execute6809(&cpu2, 40); +// Execute6809(&cpu1, 40); +// Execute6809(&cpu2, 40); + Execute6809(&cpu1, 20); + Execute6809(&cpu2, 20); // MCU runs at 1,536,000 Hz // 1536000 / 60 / 640 == 40 - Execute63701(&mcu, 40); +// Execute63701(&mcu, 40); + Execute63701(&mcu, 20); } BlitChar(charROM, gram1); + // Make sure that the sprite RAM lags by one frame... :-) + if (copySprites) + { + CopySprites(); + copySprites = false; + } + frameTickCount++; if (frameTickCount == 3) @@ -992,126 +962,3 @@ WriteLog("About to enter main loop...\n"); return 1; } - -#if 0 -/* -Hitachi uC runs at 6.144 MHz -YM2151 runs at 3.579580 MHz - - -Rolling Thunder Memory map --------------------------- -Most of the decoding is done by custom chips (CUS47 and CUS41), so the memory -map is inferred by program behaviour. The customs also handle internally irq -and watchdog. - -The main CPU memory map is the same in all games because CUS47 is used by all -games. The sub CPU and sound CPU, on the other hand, change because CUS41 is -replaced by other chips. - -All RAM is shared between main and sub CPU, except for sound RAM which is -shared between main and sound CPU; the portion of object RAM that is overlapped -by sound RAM is used exclusively by the sub CPU. - -MAIN CPU: - -Address Dir Data Name Description -------------------- --- -------- --------- ----------------------- -000x xxxx xxxx xxxx R/W xxxxxxxx SCROLL0 tilemap 0/1 RAM (shared with sub CPU) -001x xxxx xxxx xxxx R/W xxxxxxxx SCROLL1 tilemap 2/3 RAM (shared with sub CPU) -0100 00xx xxxx xxxx R/W xxxxxxxx SOUND sound RAM (through CUS30, shared with MCU) -0100 0000 xxxx xxxx R/W xxxxxxxx portion holding the sound wave data -0100 0001 00xx xxxx R/W xxxxxxxx portion holding the sound registers -010x xxxx xxxx xxxx R/W xxxxxxxx OBJECT work RAM (shared with sub CPU) [1] -0101 1xxx xxxx xxxx R/W xxxxxxxx portion holding sprite registers -011x xxxx xxxx xxxx R xxxxxxxx ROM 9D program ROM (banked) [2] -1xxx xxxx xxxx xxxx R xxxxxxxx ROM 9C program ROM -1000 00-- ---- ---- W -------- watchdog reset (RES generated by CUS47) -1000 01-- ---- ---- W -------- main CPU irq acknowledge (IRQ generated by CUS47) -1000 1x-- ---- ---- W -------- BANK tile gfx bank select (data is in A10) (latch in CUS47) -1001 00-- ---- -x0x W xxxxxxxx LATCH0 tilemap 0/1 X scroll + priority -1001 00-- ---- -x10 W xxxxxxxx LATCH0 tilemap 0/1 Y scroll -1001 00-- ---- --11 W ------xx BAMNKM ROM 9D bank select -1001 01-- ---- -x0x W xxxxxxxx LATCH1 tilemap 2/3 X scroll + priority -1001 01-- ---- -x10 W xxxxxxxx LATCH1 tilemap 2/3 Y scroll -1001 01-- ---- --11 W ------xx BAMNKS ROM 12D bank select -1100 00-- ---- ---- W xxxxxxxx BACKCOLOR background color - -[1] Note that this is partially overlapped by sound RAM -[2] In Rolling Thunder and others, replaced by the ROM/voice expansion board - - -SUB CPU: - -Address Dir Data Name Description -------------------- --- -------- --------- ----------------------- -000x xxxx xxxx xxxx R/W xxxxxxxx SUBOBJ work RAM (shared with main CPU) -0001 1xxx xxxx xxxx R/W xxxxxxxx portion holding sprite registers -001x xxxx xxxx xxxx R/W xxxxxxxx SUBSCR0 tilemap 0/1 RAM (shared with main CPU) -010x xxxx xxxx xxxx R/W xxxxxxxx SUBSCR1 tilemap 2/3 RAM (shared with main CPU) -011x xxxx xxxx xxxx R xxxxxxxx ROM 12D program ROM (banked) [1] -1xxx xxxx xxxx xxxx R xxxxxxxx ROM 12C program ROM -1000 0--- ---- ---- W -------- watchdog reset (MRESET generated by CUS41) -1000 1--- ---- ---- W -------- main CPU irq acknowledge (generated by CUS41) -1101 0--- ---- -x0x W xxxxxxxx LATCH0 tilemap 0/1 X scroll + priority -1101 0--- ---- -x10 W xxxxxxxx LATCH0 tilemap 0/1 Y scroll -1101 0--- ---- --11 W ------xx BAMNKM ROM 9D bank select -1101 1--- ---- -x0x W xxxxxxxx LATCH1 tilemap 2/3 X scroll + priority -1101 1--- ---- -x10 W xxxxxxxx LATCH1 tilemap 2/3 Y scroll -1101 1--- ---- --11 W ------xx BAMNKS ROM 12D bank select - -[1] Only used by Rolling Thunder - - -MCU: - -Address Dir Data Name Description -------------------- --- -------- --------- ----------------------- -0000 0000 xxxx xxxx MCU internal registers, timers, ports and RAM -0001 xxxx xxxx xxxx R/W xxxxxxxx RAM 3F sound RAM (through CUS30, partially shared with main CPU) -0001 0000 xxxx xxxx R/W xxxxxxxx portion holding the sound wave data -0001 0001 00xx xxxx R/W xxxxxxxx portion holding the sound registers -0010 0--- --00 ---x R/W xxxxxxxx YMCS YM2151 -0010 0--- --01 ---- n.c. -0010 0--- --10 ---- R xxxxxxxx PORTA switch inputs -0010 0--- --11 ---- R xxxxxxxx PORTB dip switches -01xx xxxx xxxx xxxx R xxxxxxxx ROM 6B program ROM (lower half) -10xx xxxx xxxx xxxx R xxxxxxxx ROM 6B program ROM (upper half) -1011 0--- ---- ---- W unknown (CUS41) -1011 1--- ---- ---- W unknown (CUS41) -1111 xxxx xxxx xxxx R xxxxxxxx MCU internal ROM - - -Notes: ------ -- There are two watchdogs, one per CPU (or maybe three). Handling them - separately is necessary to allow entering service mode without manually - resetting in rthunder and genpeitd: only one of the CPUs stops writing to - the watchdog. - -- The sprite hardware buffers spriteram: the program writes the sprite list to - offsets 4-9 of every 16-byte block, then at the end writes to offset 0x1ff2 - of sprite RAM to signal the chip that the list is complete. The chip will - copy the list from 4-9 to 10-15 and use it from there. This has not been - verified on the real hardware, but it is the most logical way of doing it. - Emulating this behaviour and not using an external buffer is important in - rthunder: when you insert a coin, the whole sprite RAM is cleared, but 0x1ff2 - is not written to. If we buffered spriteram to an external buffer, this would - cause dangling sprites because the buffer would not be updated. - -- spriteram buffering fixes sprite lag, but causes a glitch in rthunder when - entering a door. The *closed* door is made of tiles, but the *moving* door is - made of sprites. Since sprites are delayed by 1 frame, when you enter a door - there is one frame where neither the tile-based closed door nor the - sprite-based moving door is shown, so it flickers. This behavior has been - confirmed on a real PCB. - -TODO: ----- -- The two unknown writes for the MCU are probably watchdog reset and irq acknowledge, - but they don't seem to work as expected. During the first few frames they are - written out of order and hooking them up in the usual way causes the MCU to - stop receiving interrupts. -*/ -#endif - diff --git a/src/v63701.cpp b/src/v63701.cpp index ea225bd..31e2fb0 100644 --- a/src/v63701.cpp +++ b/src/v63701.cpp @@ -29,14 +29,6 @@ // work well. It's a fair sight better than the one that's in MAME, // that's for sure. :-D -// Some random thoughts: Could there be a performance gain by breaking -// out the flags in regs.cc into separate uint8_t variables (or bools)? -// You'd have to convert on entering and exiting the emulation loop, but I -// think the perfomance hit would be negligible compared to the gain in not -// having to mask and shift flags all the time. Investigate after the -// conversion to macro style opcodes is completed. :-) -// [DONE--remain to be seen if there is any performance increase] - #define __DEBUG__ #define TEST_DONT_BRANCH_OPTIMIZATION @@ -143,7 +135,6 @@ static uint16_t RdMemW(uint16_t); static uint16_t FetchMemW(uint16_t); static inline void HandleInterrupt(uint16_t, uint16_t flag = 0); - // // Read a word out of 63701 memory (little endian format) // @@ -152,7 +143,6 @@ static inline uint16_t RdMemW(uint16_t address) return (uint16_t)(regs.RdMem(address) << 8) | regs.RdMem(address + 1); } - // // Fetch a word out of 63701 memory (little endian format). Increments PC // @@ -162,7 +152,6 @@ static inline uint16_t FetchMemW(uint16_t address) return (uint16_t)(regs.RdMem(address) << 8) | regs.RdMem(address + 1); } - // // 63701 OPCODE IMPLEMENTATION // @@ -204,97 +193,83 @@ static void Op8B(void) // ADDA # OP_ADD_HANDLER(m, regs.d.acc.a); } - static void Op9B(void) // ADDA ZP { uint16_t m = READ_ZP; OP_ADD_HANDLER(m, regs.d.acc.a); } - static void OpAB(void) // ADDA ZP, X { uint16_t m = READ_ZP_X; OP_ADD_HANDLER(m, regs.d.acc.a); } - static void OpBB(void) // ADDA ABS { uint16_t m = READ_ABS; OP_ADD_HANDLER(m, regs.d.acc.a); } - static void OpCB(void) // ADDB # { uint16_t m = READ_IMM; OP_ADD_HANDLER(m, regs.d.acc.b); } - static void OpDB(void) // ADDB ZP { uint16_t m = READ_ZP; OP_ADD_HANDLER(m, regs.d.acc.b); } - static void OpEB(void) // ADDB ZP, X { uint16_t m = READ_ZP_X; OP_ADD_HANDLER(m, regs.d.acc.b); } - static void OpFB(void) // ADDB ABS { uint16_t m = READ_ABS; OP_ADD_HANDLER(m, regs.d.acc.b); } - static void Op1B(void) // ABA { OP_ADD_HANDLER(regs.d.acc.b, regs.d.acc.a); } - static void Op3A(void) // ABX { // Seems this one does *not* affect any flags... regs.x += (uint16_t)regs.d.acc.b; } - static void OpC3(void) // ADDD # { uint16_t m = READ_IMM16; OP_ADD_HANDLER16(m, regs.d.word); } - static void OpD3(void) // ADDD ZP { uint16_t m = READ_ZP16; OP_ADD_HANDLER16(m, regs.d.word); } - static void OpE3(void) // ADDD ZP, X { uint16_t m = READ_ZP_X16; OP_ADD_HANDLER16(m, regs.d.word); } - static void OpF3(void) // ADDD ABS { uint16_t m = READ_ABS16; OP_ADD_HANDLER16(m, regs.d.word); } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -318,56 +293,48 @@ static void Op89(void) // ADCA # OP_ADC_HANDLER(m, regs.d.acc.a); } - static void Op99(void) // ADCA ZP { uint16_t m = READ_ZP; OP_ADC_HANDLER(m, regs.d.acc.a); } - static void OpA9(void) // ADCA ZP, X { uint16_t m = READ_ZP_X; OP_ADC_HANDLER(m, regs.d.acc.a); } - static void OpB9(void) // ADCA ABS { uint16_t m = READ_ABS; OP_ADC_HANDLER(m, regs.d.acc.a); } - static void OpC9(void) // ADCB # { uint16_t m = READ_IMM; OP_ADC_HANDLER(m, regs.d.acc.b); } - static void OpD9(void) // ADCB ZP { uint16_t m = READ_ZP; OP_ADC_HANDLER(m, regs.d.acc.b); } - static void OpE9(void) // ADCB ZP, X { uint16_t m = READ_ZP_X; OP_ADC_HANDLER(m, regs.d.acc.b); } - static void OpF9(void) // ADCB ABS { uint16_t m = READ_ABS; OP_ADC_HANDLER(m, regs.d.acc.b); } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -388,56 +355,48 @@ static void Op84(void) // ANDA # OP_AND_HANDLER(m, regs.d.acc.a); } - static void Op94(void) // ANDA ZP { uint8_t m = READ_ZP; OP_AND_HANDLER(m, regs.d.acc.a); } - static void OpA4(void) // ANDA ZP, X { uint16_t m = READ_ZP_X; OP_AND_HANDLER(m, regs.d.acc.a); } - static void OpB4(void) // ANDA ABS { uint16_t m = READ_ABS; OP_AND_HANDLER(m, regs.d.acc.a); } - static void OpC4(void) // ANDB # { uint8_t m = READ_IMM; OP_AND_HANDLER(m, regs.d.acc.b); } - static void OpD4(void) // ANDB ZP { uint8_t m = READ_ZP; OP_AND_HANDLER(m, regs.d.acc.b); } - static void OpE4(void) // ANDB ZP, X { uint16_t m = READ_ZP_X; OP_AND_HANDLER(m, regs.d.acc.b); } - static void OpF4(void) // ANDB ABS { uint16_t m = READ_ABS; OP_AND_HANDLER(m, regs.d.acc.b); } - static void Op61(void) // AIM ZP, X (AND immediate with index) { uint8_t m; @@ -447,7 +406,6 @@ static void Op61(void) // AIM ZP, X (AND immediate with index) WRITE_BACK(m); } - static void Op71(void) // AIM ZP (AND immediate with zero page) { uint8_t m; @@ -457,7 +415,6 @@ static void Op71(void) // AIM ZP (AND immediate with zero page) WRITE_BACK(m); } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -477,49 +434,42 @@ static void Op85(void) // BITA # OP_BIT_HANDLER(m, regs.d.acc.a); } - static void Op95(void) // BITA ZP { uint8_t m = READ_ZP; OP_BIT_HANDLER(m, regs.d.acc.a); } - static void OpA5(void) // BITA ZP, X { uint8_t m = READ_ZP_X; OP_BIT_HANDLER(m, regs.d.acc.a); } - static void OpB5(void) // BITA ABS { uint8_t m = READ_ABS; OP_BIT_HANDLER(m, regs.d.acc.a); } - static void OpC5(void) // BITB # { uint8_t m = READ_IMM; OP_BIT_HANDLER(m, regs.d.acc.b); } - static void OpD5(void) // BITB ZP { uint8_t m = READ_ZP; OP_BIT_HANDLER(m, regs.d.acc.b); } - static void OpE5(void) // BITB ZP, X { uint8_t m = READ_ZP_X; OP_BIT_HANDLER(m, regs.d.acc.b); } - static void OpF5(void) // BITB ABS { uint8_t m = READ_ABS; @@ -543,7 +493,6 @@ static void Op6F(void) // CLR ZP, X SET_Z(0); } - static void Op7F(void) // CLR ABS { regs.WrMem(EA_ABS, 0); @@ -551,7 +500,6 @@ static void Op7F(void) // CLR ABS SET_Z(0); } - static void Op4F(void) // CLRA { regs.d.acc.a = 0; @@ -559,7 +507,6 @@ static void Op4F(void) // CLRA SET_Z(0); } - static void Op5F(void) // CLRB { regs.d.acc.b = 0; @@ -591,56 +538,48 @@ static void Op81(void) // CMPA # OP_CMP_HANDLER(m, regs.d.acc.a); } - static void Op91(void) // CMPA ZP { uint8_t m = READ_ZP; OP_CMP_HANDLER(m, regs.d.acc.a); } - static void OpA1(void) // CMPA ZP, X { uint8_t m = READ_ZP_X; OP_CMP_HANDLER(m, regs.d.acc.a); } - static void OpB1(void) // CMPA ABS { uint8_t m = READ_ABS; OP_CMP_HANDLER(m, regs.d.acc.a); } - static void OpC1(void) // CMPB # { uint8_t m = READ_IMM; OP_CMP_HANDLER(m, regs.d.acc.b); } - static void OpD1(void) // CMPB ZP { uint8_t m = READ_ZP; OP_CMP_HANDLER(m, regs.d.acc.b); } - static void OpE1(void) // CMPB ZP, X { uint8_t m = READ_ZP_X; OP_CMP_HANDLER(m, regs.d.acc.b); } - static void OpF1(void) // CMPB ABS { uint8_t m = READ_ABS; OP_CMP_HANDLER(m, regs.d.acc.b); } - static void Op11(void) // CBA { OP_CMP_HANDLER(regs.d.acc.b, regs.d.acc.a); @@ -670,7 +609,6 @@ static void Op63(void) // COM ZP, X WRITE_BACK(m); } - static void Op73(void) // COM ABS { uint8_t m; @@ -679,13 +617,11 @@ static void Op73(void) // COM ABS WRITE_BACK(m); } - static void Op43(void) // COMA { OP_COM_HANDLER(regs.d.acc.a); } - static void Op53(void) // COMB { OP_COM_HANDLER(regs.d.acc.b); @@ -715,7 +651,6 @@ static void Op60(void) // NEG ZP, X WRITE_BACK(m); } - static void Op70(void) // NEG ABS { uint8_t m; @@ -724,13 +659,11 @@ static void Op70(void) // NEG ABS WRITE_BACK(m); } - static void Op40(void) // NEGA { OP_NEG_HANDLER(regs.d.acc.a); } - static void Op50(void) // NEGB { OP_NEG_HANDLER(regs.d.acc.b); @@ -781,7 +714,6 @@ static void Op6A(void) // DEC ZP, X WRITE_BACK(m); } - static void Op7A(void) // DEC ABS { uint8_t m; @@ -790,13 +722,11 @@ static void Op7A(void) // DEC ABS WRITE_BACK(m); } - static void Op4A(void) // DECA { OP_DEC_HANDLER(regs.d.acc.a); } - static void Op5A(void) // DECB { OP_DEC_HANDLER(regs.d.acc.b); @@ -822,56 +752,48 @@ static void Op88(void) // EORA # OP_EOR_HANDLER(m, regs.d.acc.a); } - static void Op98(void) // EORA ZP { uint8_t m = READ_ZP; OP_EOR_HANDLER(m, regs.d.acc.a); } - static void OpA8(void) // EORA ZP, X { uint8_t m = READ_ZP_X; OP_EOR_HANDLER(m, regs.d.acc.a); } - static void OpB8(void) // EORA ABS { uint8_t m = READ_ABS; OP_EOR_HANDLER(m, regs.d.acc.a); } - static void OpC8(void) // EORB # { uint8_t m = READ_IMM; OP_EOR_HANDLER(m, regs.d.acc.b); } - static void OpD8(void) // EORB ZP { uint8_t m = READ_ZP; OP_EOR_HANDLER(m, regs.d.acc.b); } - static void OpE8(void) // EORB ZP, X { uint8_t m = READ_ZP_X; OP_EOR_HANDLER(m, regs.d.acc.b); } - static void OpF8(void) // EORB ABS { uint8_t m = READ_ABS; OP_EOR_HANDLER(m, regs.d.acc.b); } - static void Op65(void) // EIM ZP, X (EOR immediate with index) { uint8_t m; @@ -881,7 +803,6 @@ static void Op65(void) // EIM ZP, X (EOR immediate with index) WRITE_BACK(m); } - static void Op75(void) // EIM ZP (EOR immediate with zero page) { uint8_t m; @@ -891,7 +812,6 @@ static void Op75(void) // EIM ZP (EOR immediate with zero page) WRITE_BACK(m); } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -915,7 +835,6 @@ static void Op6C(void) // INC ZP, X WRITE_BACK(m); } - static void Op7C(void) // INC ABS { uint8_t m; @@ -924,13 +843,11 @@ static void Op7C(void) // INC ABS WRITE_BACK(m); } - static void Op4C(void) // INCA { OP_INC_HANDLER(regs.d.acc.a); } - static void Op5C(void) // INCB { OP_INC_HANDLER(regs.d.acc.b); @@ -956,56 +873,48 @@ static void Op86(void) // LDAA # OP_LDA_HANDLER(m, regs.d.acc.a); } - static void Op96(void) // LDAA ZP { uint8_t m = READ_ZP; OP_LDA_HANDLER(m, regs.d.acc.a); } - static void OpA6(void) // LDAA ZP, X { uint8_t m = READ_ZP_X; OP_LDA_HANDLER(m, regs.d.acc.a); } - static void OpB6(void) // LDAA ABS { uint8_t m = READ_ABS; OP_LDA_HANDLER(m, regs.d.acc.a); } - static void OpC6(void) // LDAB # { uint8_t m = READ_IMM; OP_LDA_HANDLER(m, regs.d.acc.b); } - static void OpD6(void) // LDAB ZP { uint8_t m = READ_ZP; OP_LDA_HANDLER(m, regs.d.acc.b); } - static void OpE6(void) // LDAB ZP, X { uint8_t m = READ_ZP_X; OP_LDA_HANDLER(m, regs.d.acc.b); } - static void OpF6(void) // LDAB ABS { uint8_t m = READ_ABS; OP_LDA_HANDLER(m, regs.d.acc.b); } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -1026,56 +935,48 @@ static void Op8A(void) // ORAA # OP_ORA_HANDLER(m, regs.d.acc.a); } - static void Op9A(void) // ORAA ZP { uint8_t m = READ_ZP; OP_ORA_HANDLER(m, regs.d.acc.a); } - static void OpAA(void) // ORAA ZP, X { uint8_t m = READ_ZP_X; OP_ORA_HANDLER(m, regs.d.acc.a); } - static void OpBA(void) // ORAA ABS { uint8_t m = READ_ABS; OP_ORA_HANDLER(m, regs.d.acc.a); } - static void OpCA(void) // ORAB # { uint8_t m = READ_IMM; OP_ORA_HANDLER(m, regs.d.acc.b); } - static void OpDA(void) // ORAB ZP { uint8_t m = READ_ZP; OP_ORA_HANDLER(m, regs.d.acc.b); } - static void OpEA(void) // ORAB ZP, X { uint8_t m = READ_ZP_X; OP_ORA_HANDLER(m, regs.d.acc.b); } - static void OpFA(void) // ORAB ABS { uint8_t m = READ_ABS; OP_ORA_HANDLER(m, regs.d.acc.b); } - static void Op62(void) // OIM ZP, X (ORA immediate with index) { uint8_t m; @@ -1085,7 +986,6 @@ static void Op62(void) // OIM ZP, X (ORA immediate with index) WRITE_BACK(m); } - static void Op72(void) // OIM ZP (ORA immediate with zero page) { uint8_t m; @@ -1095,7 +995,6 @@ static void Op72(void) // OIM ZP (ORA immediate with zero page) WRITE_BACK(m); } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -1110,37 +1009,31 @@ static void Op36(void) // PSHA PUSH(regs.d.acc.a); } - static void Op37(void) // PSHB { PUSH(regs.d.acc.b); } - static void Op32(void) // PULA { regs.d.acc.a = PULL; } - static void Op33(void) // PULB { regs.d.acc.b = PULL; } - static void Op38(void) // PULX { regs.x = PULL16; } - static void Op3C(void) // PSHX { PUSH16(regs.x); } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -1166,7 +1059,6 @@ static void Op69(void) // ROL ZP, X WRITE_BACK(m); } - static void Op79(void) // ROL ABS { uint8_t m; @@ -1175,13 +1067,11 @@ static void Op79(void) // ROL ABS WRITE_BACK(m); } - static void Op49(void) // ROLA { OP_ROL_HANDLER(regs.d.acc.a); } - static void Op59(void) // ROLB { OP_ROL_HANDLER(regs.d.acc.b); @@ -1212,7 +1102,6 @@ static void Op66(void) // ROR ZP, X WRITE_BACK(m); } - static void Op76(void) // ROR ABS { uint8_t m; @@ -1221,13 +1110,11 @@ static void Op76(void) // ROR ABS WRITE_BACK(m); } - static void Op46(void) // RORA { OP_ROR_HANDLER(regs.d.acc.a); } - static void Op56(void) // RORB { OP_ROR_HANDLER(regs.d.acc.b); @@ -1258,7 +1145,6 @@ static void Op68(void) // ASL ZP, X WRITE_BACK(m); } - static void Op78(void) // ASL ABS { uint8_t m; @@ -1267,19 +1153,16 @@ static void Op78(void) // ASL ABS WRITE_BACK(m); } - static void Op48(void) // ASLA { OP_ASL_HANDLER(regs.d.acc.a); } - static void Op58(void) // ASLB { OP_ASL_HANDLER(regs.d.acc.b); } - static void Op05(void) // ASLD { uint8_t newCarry = (regs.d.word & 0x8000) >> 15; @@ -1290,7 +1173,6 @@ static void Op05(void) // ASLD flagV = flagN ^ flagC; } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -1316,7 +1198,6 @@ static void Op67(void) // ASR ZP, X WRITE_BACK(m); } - static void Op77(void) // ASR ABS { uint8_t m; @@ -1325,19 +1206,16 @@ static void Op77(void) // ASR ABS WRITE_BACK(m); } - static void Op47(void) // ASRA { OP_ASR_HANDLER(regs.d.acc.a); } - static void Op57(void) // ASRB { OP_ASR_HANDLER(regs.d.acc.b); } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -1363,7 +1241,6 @@ static void Op64(void) // LSR ZP, X WRITE_BACK(m); } - static void Op74(void) // LSR ABS { uint8_t m; @@ -1372,19 +1249,16 @@ static void Op74(void) // LSR ABS WRITE_BACK(m); } - static void Op44(void) // LSRA { OP_LSR_HANDLER(regs.d.acc.a); } - static void Op54(void) // LSRB { OP_LSR_HANDLER(regs.d.acc.b); } - static void Op04(void) // LSRD { uint8_t newCarry = regs.d.word & 0x01; @@ -1395,7 +1269,6 @@ static void Op04(void) // LSRD flagV = flagN ^ flagC; } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -1408,37 +1281,31 @@ static void Op97(void) // STAA ZP regs.WrMem(EA_ZP, regs.d.acc.a); } - static void OpA7(void) // STAA ZP, X { regs.WrMem(EA_ZP_X, regs.d.acc.a); } - static void OpB7(void) // STAA ABS { regs.WrMem(EA_ABS, regs.d.acc.a); } - static void OpD7(void) // STAB ZP { regs.WrMem(EA_ZP, regs.d.acc.b); } - static void OpE7(void) // STAB ZP, X { regs.WrMem(EA_ZP_X, regs.d.acc.b); } - static void OpF7(void) // STAB ABS { regs.WrMem(EA_ABS, regs.d.acc.b); } - // These are illegal instructions! #if 0 static void Op87(void) // STA # @@ -1465,7 +1332,6 @@ static void OpC7(void) // STB # } #endif - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -1497,90 +1363,77 @@ static void Op80(void) // SUBA # OP_SUB_HANDLER(m, regs.d.acc.a); } - static void Op90(void) // SUBA ZP { uint16_t m = READ_ZP; OP_SUB_HANDLER(m, regs.d.acc.a); } - static void OpA0(void) // SUBA ZP, X { uint16_t m = READ_ZP_X; OP_SUB_HANDLER(m, regs.d.acc.a); } - static void OpB0(void) // SUBA ABS { uint16_t m = READ_ABS; OP_SUB_HANDLER(m, regs.d.acc.a); } - static void OpC0(void) // SUBB # { uint16_t m = READ_IMM; OP_SUB_HANDLER(m, regs.d.acc.b); } - static void OpD0(void) // SUBB ZP { uint16_t m = READ_ZP; OP_SUB_HANDLER(m, regs.d.acc.b); } - static void OpE0(void) // SUBB ZP, X { uint16_t m = READ_ZP_X; OP_SUB_HANDLER(m, regs.d.acc.b); } - static void OpF0(void) // SUBB ABS { uint16_t m = READ_ABS; OP_SUB_HANDLER(m, regs.d.acc.b); } - static void Op10(void) // SBA { OP_SUB_HANDLER(regs.d.acc.b, regs.d.acc.a); } - static void Op83(void) // SUBD # { uint16_t m = READ_IMM16; OP_SUB_HANDLER16(m, regs.d.word); } - static void Op93(void) // SUBD ZP { uint16_t m = READ_ZP16; OP_SUB_HANDLER16(m, regs.d.word); } - static void OpA3(void) // SUBD ZP, X { uint16_t m = READ_ZP_X16; OP_SUB_HANDLER16(m, regs.d.word); } - static void OpB3(void) // SUBD ABS { uint16_t m = READ_ABS16; OP_SUB_HANDLER16(m, regs.d.word); } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -1603,49 +1456,42 @@ static void Op82(void) // SBCA # OP_SBC_HANDLER(m, regs.d.acc.a); } - static void Op92(void) // SBCA ZP { uint16_t m = READ_ZP; OP_SBC_HANDLER(m, regs.d.acc.a); } - static void OpA2(void) // SBCA ZP, X { uint16_t m = READ_ZP_X; OP_SBC_HANDLER(m, regs.d.acc.a); } - static void OpB2(void) // SBCA ABS { uint16_t m = READ_ABS; OP_SBC_HANDLER(m, regs.d.acc.a); } - static void OpC2(void) // SBCB # { uint16_t m = READ_IMM; OP_SBC_HANDLER(m, regs.d.acc.b); } - static void OpD2(void) // SBCB ZP { uint16_t m = READ_ZP; OP_SBC_HANDLER(m, regs.d.acc.b); } - static void OpE2(void) // SBCB ZP, X { uint16_t m = READ_ZP_X; OP_SBC_HANDLER(m, regs.d.acc.b); } - static void OpF2(void) // SBCB ABS { uint16_t m = READ_ABS; @@ -1666,7 +1512,6 @@ static void Op16(void) // TAB CLR_V; } - static void Op17(void) // TBA { regs.d.acc.a = regs.d.acc.b; @@ -1706,7 +1551,6 @@ static void Op6D(void) // TST ZP, X #endif } - static void Op7D(void) // TST ABS { #if 0 @@ -1719,19 +1563,16 @@ static void Op7D(void) // TST ABS #endif } - static void Op4D(void) // TSTA { OP_TST_HANDLER(regs.d.acc.a); } - static void Op5D(void) // TSTB { OP_TST_HANDLER(regs.d.acc.b); } - static void Op6B(void) // TIM ZP, X (TST immediate with index) { // uint8_t m; @@ -1741,7 +1582,6 @@ static void Op6B(void) // TIM ZP, X (TST immediate with index) // WRITE_BACK(m); } - static void Op7B(void) // TIM ZP (TST immediate with zero page) { // uint8_t m; @@ -1751,7 +1591,6 @@ static void Op7B(void) // TIM ZP (TST immediate with zero page) // WRITE_BACK(m); } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -1774,21 +1613,18 @@ static void Op8C(void) // CPX # OP_CPX_HANDLER(m); } - static void Op9C(void) // CPX ZP { uint16_t m = READ_ZP16; OP_CPX_HANDLER(m); } - static void OpAC(void) // CPX ZP, X { uint16_t m = READ_ZP_X16; OP_CPX_HANDLER(m); } - static void OpBC(void) // CPX ABS { uint16_t m = READ_ABS16; @@ -1810,20 +1646,17 @@ static void Op09(void) // DEX SET_Z(regs.x); } - static void Op34(void) // DES { regs.s--; } - static void Op08(void) // INX { regs.x++; SET_Z(regs.x); } - static void Op31(void) // INS { regs.s++; @@ -1849,84 +1682,72 @@ static void OpCE(void) // LDX # OP_LD_HANDLER(regs.x); } - static void OpDE(void) // LDX ZP { regs.x = READ_ZP16; OP_LD_HANDLER(regs.x); } - static void OpEE(void) // LDX ZP, X { regs.x = READ_ZP_X16; OP_LD_HANDLER(regs.x); } - static void OpFE(void) // LDX ABS { regs.x = READ_ABS16; OP_LD_HANDLER(regs.x); } - static void Op8E(void) // LDS # { regs.s = READ_IMM16; OP_LD_HANDLER(regs.s); } - static void Op9E(void) // LDS ZP { regs.s = READ_ZP16; OP_LD_HANDLER(regs.s); } - static void OpAE(void) // LDS ZP, X { regs.s = READ_ZP_X16; OP_LD_HANDLER(regs.s); } - static void OpBE(void) // LDS ABS { regs.s = READ_ABS16; OP_LD_HANDLER(regs.s); } - static void OpCC(void) // LDD # { regs.d.word = READ_IMM16; OP_LD_HANDLER(regs.d.word); } - static void OpDC(void) // LDD ZP { regs.d.word = READ_ZP16; OP_LD_HANDLER(regs.d.word); } - static void OpEC(void) // LDD ZP, X { regs.d.word = READ_ZP_X16; OP_LD_HANDLER(regs.d.word); } - static void OpFC(void) // LDD ABS { regs.d.word = READ_ABS16; OP_LD_HANDLER(regs.d.word); } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -1949,42 +1770,36 @@ static void OpDF(void) // STX ZP OP_ST_HANDLER(m, regs.x); } - static void OpEF(void) // STX ZP, X { uint16_t m = EA_ZP_X; OP_ST_HANDLER(m, regs.x); } - static void OpFF(void) // STX ABS { uint16_t m = EA_ABS; OP_ST_HANDLER(m, regs.x); } - static void Op9F(void) // STS ZP { uint16_t m = EA_ZP; OP_ST_HANDLER(m, regs.s); } - static void OpAF(void) // STS ZP, X { uint16_t m = EA_ZP_X; OP_ST_HANDLER(m, regs.s); } - static void OpBF(void) // STS ABS { uint16_t m = EA_ABS; OP_ST_HANDLER(m, regs.s); } - // These are illegal instructions! #if 0 // Store immediate--nonsensical opcodes :-P @@ -1995,7 +1810,6 @@ static void Op8F(void) // STS # OP_ST_HANDLER(effectiveAddress, regs.s); } - static void OpCF(void) // STX # { uint16_t effectiveAddress = regs.pc; @@ -2003,7 +1817,6 @@ static void OpCF(void) // STX # OP_ST_HANDLER(effectiveAddress, regs.x); } - static void OpCD(void) // STD # { uint16_t effectiveAddress = regs.pc; @@ -2012,28 +1825,24 @@ static void OpCD(void) // STD # } #endif - static void OpDD(void) // STD ZP { uint16_t m = EA_ZP; OP_ST_HANDLER(m, regs.d.word); } - static void OpED(void) // STD ZP, X { uint16_t m = EA_ZP_X; OP_ST_HANDLER(m, regs.d.word); } - static void OpFD(void) // STD ABS { uint16_t m = EA_ABS; OP_ST_HANDLER(m, regs.d.word); } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -2046,7 +1855,6 @@ static void Op35(void) // TXS regs.s = regs.x - 1; } - static void Op30(void) // TSX { regs.x = regs.s + 1; @@ -2078,14 +1886,12 @@ static void Op20(void) // BRA regs.pc += m; } - static void Op21(void) // BRN { int16_t m = (int16_t)(int8_t)READ_IMM; // regs.pc += m; } - static void Op24(void) // BCC { // NOTE: We can optimize this by following the maxim: "Don't branch!" by @@ -2103,7 +1909,6 @@ static void Op24(void) // BCC #endif } - static void Op25(void) // BCS { int16_t m = (int16_t)(int8_t)READ_IMM; @@ -2116,7 +1921,6 @@ static void Op25(void) // BCS #endif } - static void Op27(void) // BEQ { int16_t m = (int16_t)(int8_t)READ_IMM; @@ -2129,7 +1933,6 @@ static void Op27(void) // BEQ #endif } - static void Op2C(void) // BGE { int16_t m = (int16_t)(int8_t)READ_IMM; @@ -2142,7 +1945,6 @@ static void Op2C(void) // BGE #endif } - static void Op2E(void) // BGT { int16_t m = (int16_t)(int8_t)READ_IMM; @@ -2155,7 +1957,6 @@ static void Op2E(void) // BGT #endif } - static void Op22(void) // BHI { int16_t m = (int16_t)(int8_t)READ_IMM; @@ -2168,7 +1969,6 @@ static void Op22(void) // BHI #endif } - static void Op2F(void) // BLE { int16_t m = (int16_t)(int8_t)READ_IMM; @@ -2181,7 +1981,6 @@ static void Op2F(void) // BLE #endif } - static void Op23(void) // BLS { int16_t m = (int16_t)(int8_t)READ_IMM; @@ -2194,7 +1993,6 @@ static void Op23(void) // BLS #endif } - static void Op2D(void) // BLT { int16_t m = (int16_t)(int8_t)READ_IMM; @@ -2207,7 +2005,6 @@ static void Op2D(void) // BLT #endif } - static void Op2B(void) // BMI { int16_t m = (int16_t)(int8_t)READ_IMM; @@ -2220,7 +2017,6 @@ static void Op2B(void) // BMI #endif } - static void Op26(void) // BNE { int16_t m = (int16_t)(int8_t)READ_IMM; @@ -2233,7 +2029,6 @@ static void Op26(void) // BNE #endif } - static void Op28(void) // BVC { int16_t m = (int16_t)(int8_t)READ_IMM; @@ -2246,7 +2041,6 @@ static void Op28(void) // BVC #endif } - static void Op29(void) // BVS { int16_t m = (int16_t)(int8_t)READ_IMM; @@ -2259,7 +2053,6 @@ static void Op29(void) // BVS #endif } - static void Op2A(void) // BPL { int16_t m = (int16_t)(int8_t)READ_IMM; @@ -2287,20 +2080,17 @@ static void Op8D(void) // BSR regs.pc += m; } - static void Op6E(void) // JMP ZP, X { uint16_t m = EA_ZP_X; regs.pc = m; } - static void Op7E(void) // JMP ABS { regs.pc = EA_ABS; } - static void Op9D(void) // JSR ZP { uint16_t m = (uint16_t)EA_ZP; @@ -2308,7 +2098,6 @@ static void Op9D(void) // JSR ZP regs.pc = m; } - static void OpAD(void) // JSR ZP, X { uint16_t m = EA_ZP_X; @@ -2316,7 +2105,6 @@ static void OpAD(void) // JSR ZP, X regs.pc = m; } - static void OpBD(void) // JSR ABS { uint16_t m = EA_ABS; @@ -2324,7 +2112,6 @@ static void OpBD(void) // JSR ABS regs.pc = m; } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -2339,7 +2126,6 @@ static void Op01(void) // NOP { } - static void Op3B(void) // RTI { regs.cc = PULL; @@ -2350,13 +2136,11 @@ static void Op3B(void) // RTI UNPACK_FLAGS; } - static void Op39(void) // RTS { regs.pc = PULL16; } - static void Op3F(void) // SWI { // It seems that the SWI is non-maskable, unlike the IRQ... @@ -2373,7 +2157,6 @@ static void Op3F(void) // SWI HandleInterrupt(0xFFFA); } - static void Op3E(void) // WAI { #ifdef __DEBUG__ @@ -2388,7 +2171,6 @@ WriteLog("*** WAI STATE ASSERTED ***\n"); regs.cpuFlags |= V63701_STATE_WAI; // And signal that we're in WAI mode } - // Multiply opcode static void Op3D(void) // MUL @@ -2397,7 +2179,6 @@ static void Op3D(void) // MUL flagC = regs.d.acc.b >> 7; // bug? No, this is how it really does it } - // Exchange X and D opcode static void Op18(void) // XGDX @@ -2408,7 +2189,6 @@ static void Op18(void) // XGDX regs.d.word = temp; } - // Sleep opcode (similar to WAI) static void Op1A(void) // SLP @@ -2421,7 +2201,6 @@ static void Op1A(void) // SLP regs.cpuFlags |= V63701_STATE_WAI; } - // Undocumented opcode ($12 & $13) static void OpUN(void) // Undocumented @@ -2429,7 +2208,6 @@ static void OpUN(void) // Undocumented regs.x += regs.RdMem(regs.s + 1); } - /* Operation |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg| | |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #| |HINZVC| @@ -2448,50 +2226,42 @@ static void Op0C(void) // CLC flagC = 0; } - static void Op0E(void) // CLI { flagI = 0; } - static void Op0A(void) // CLV { flagV = 0; } - static void Op0D(void) // SEC { flagC = 1; } - static void Op0F(void) // SEI { flagI = 1; } - static void Op0B(void) // SEV { flagV = 1; } - static void Op06(void) // TAP { regs.cc = regs.d.acc.a; UNPACK_FLAGS; } - static void Op07(void) // TPA { regs.d.acc.a = PACK_FLAGS; } - /* OP Operation Code, in Hexadecimal ~ Number of MPU cycles required @@ -2548,7 +2318,6 @@ static void Op07(void) // TPA 4: M=Xh, M+1=Xl */ - static void Op__(void) { // TRAP is non-maskable, unlike the IRQ... Also, highest priority after @@ -2557,7 +2326,6 @@ static void Op__(void) // regs.cpuFlags |= V63701_STATE_ILLEGAL_INST; } - // // 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! @@ -2581,7 +2349,6 @@ static void (* exec_op[256])() = { OpF0, OpF1, OpF2, OpF3, OpF4, OpF5, OpF6, OpF7, OpF8, OpF9, OpFA, OpFB, OpFC, OpFD, OpFE, OpFF }; - // // Internal "memcpy" (so we don't have to link with any external libraries!) // @@ -2593,7 +2360,6 @@ static void myMemcpy(void * dst, void * src, uint32_t size) d[i] = s[i]; } - #ifdef __DEBUG__ //int instCount[256]; bool V63701LogGo = false; @@ -2640,7 +2406,7 @@ if (V63701LogGo) if (regs.cpuFlags & V63701_STATE_WAI) { // Only bail out if no interrupts/resets are pending - if (!(regs.cpuFlags & (V63701_ASSERT_LINE_IRQ | V63701_ASSERT_LINE_NMI | V63701_ASSERT_LINE_RESET | V63701_ASSERT_TIMER_OVERFLOW | V63701_ASSERT_OUTPUT_COMPARE | V63701_ASSERT_INPUT_CAPTURE))) + if (!(regs.cpuFlags & (V63701_LINE_IRQ | V63701_LINE_NMI | V63701_LINE_RESET | V63701_TIMER_OVERFLOW | V63701_OUTPUT_COMPARE | V63701_INPUT_CAPTURE))) // Burn any remaining cycles... regs.clock = endCycles; } @@ -2668,8 +2434,8 @@ if (V63701LogGo) if (regs.tcsr.bit.eoci) { - regs.cpuFlags |= V63701_ASSERT_OUTPUT_COMPARE; - regsPointer->cpuFlags |= V63701_ASSERT_OUTPUT_COMPARE; + regs.cpuFlags |= V63701_OUTPUT_COMPARE; + regsPointer->cpuFlags |= V63701_OUTPUT_COMPARE; } } @@ -2681,8 +2447,8 @@ if (V63701LogGo) if (regs.tcsr.bit.etoi) { - regs.cpuFlags |= V63701_ASSERT_TIMER_OVERFLOW; - regsPointer->cpuFlags |= V63701_ASSERT_TIMER_OVERFLOW; + regs.cpuFlags |= V63701_TIMER_OVERFLOW; + regsPointer->cpuFlags |= V63701_TIMER_OVERFLOW; } } #ifdef __DEBUG__ @@ -2692,7 +2458,7 @@ if (V63701LogGo) #endif } - if (regs.cpuFlags & V63701_ASSERT_LINE_RESET) + if (regs.cpuFlags & V63701_LINE_RESET) { #ifdef __DEBUG__ if (V63701LogGo) @@ -2707,15 +2473,15 @@ if (V63701LogGo) context->cpuFlags = 0; // Clear all lingering flags... regs.cpuFlags = 0; } - else if (regs.cpuFlags & V63701_ASSERT_LINE_NMI) + else if (regs.cpuFlags & V63701_LINE_NMI) { #ifdef __DEBUG__ if (V63701LogGo) WriteLog("*** NMI LINE ASSERTED ***\n"); #endif - HandleInterrupt(0xFFFC, V63701_ASSERT_LINE_NMI); + HandleInterrupt(0xFFFC, V63701_LINE_NMI); } - else if (regs.cpuFlags & V63701_ASSERT_LINE_IRQ) + else if (regs.cpuFlags & V63701_LINE_IRQ) { #ifdef __DEBUG__ if (V63701LogGo) @@ -2729,10 +2495,10 @@ if (V63701LogGo) WriteLog(" IRQ TAKEN!\n"); //V63701LogGo = true; #endif - HandleInterrupt(0xFFF8, V63701_ASSERT_LINE_IRQ); + HandleInterrupt(0xFFF8, V63701_LINE_IRQ); } } - else if (regs.cpuFlags & V63701_ASSERT_INPUT_CAPTURE) + else if (regs.cpuFlags & V63701_INPUT_CAPTURE) { #ifdef __DEBUG__ if (V63701LogGo) @@ -2746,10 +2512,10 @@ if (V63701LogGo) WriteLog(" IC TAKEN!\n"); //V63701LogGo = true; #endif - HandleInterrupt(0xFFF6, V63701_ASSERT_INPUT_CAPTURE); + HandleInterrupt(0xFFF6, V63701_INPUT_CAPTURE); } } - else if (regs.cpuFlags & V63701_ASSERT_OUTPUT_COMPARE) + else if (regs.cpuFlags & V63701_OUTPUT_COMPARE) { #ifdef __DEBUG__ if (V63701LogGo) @@ -2763,10 +2529,10 @@ if (V63701LogGo) WriteLog(" OC TAKEN!\n"); //V63701LogGo = true; #endif - HandleInterrupt(0xFFF4, V63701_ASSERT_OUTPUT_COMPARE); + HandleInterrupt(0xFFF4, V63701_OUTPUT_COMPARE); } } - else if (regs.cpuFlags & V63701_ASSERT_TIMER_OVERFLOW) + else if (regs.cpuFlags & V63701_TIMER_OVERFLOW) { #ifdef __DEBUG__ if (V63701LogGo) @@ -2780,7 +2546,7 @@ if (V63701LogGo) WriteLog(" TO TAKEN!\n"); //V63701LogGo = true; #endif - HandleInterrupt(0xFFF2, V63701_ASSERT_TIMER_OVERFLOW); + HandleInterrupt(0xFFF2, V63701_TIMER_OVERFLOW); } } } @@ -2795,7 +2561,6 @@ if (V63701LogGo) myMemcpy(context, ®s, sizeof(V63701REGS)); } - // // Get the clock of the currently executing CPU // @@ -2804,7 +2569,6 @@ uint64_t GetCurrentV63701Clock(void) return regs.clock; } - static inline void HandleInterrupt(uint16_t vector, uint16_t flag/*= 0*/) { if (regs.cpuFlags & V63701_STATE_WAI) @@ -2828,7 +2592,6 @@ static inline void HandleInterrupt(uint16_t vector, uint16_t flag/*= 0*/) regsPointer->cpuFlags &= ~(flag | V63701_STATE_WAI); } - uint8_t InternalRegisterRead(uint16_t address) { switch (address & 0x1F) @@ -2881,7 +2644,6 @@ uint8_t InternalRegisterRead(uint16_t address) return 0x00; } - void InternalRegisterWrite(uint16_t address, uint8_t data) { uint8_t writeData; @@ -2952,4 +2714,3 @@ void InternalRegisterWrite(uint16_t address, uint8_t data) #endif } } - diff --git a/src/v63701.h b/src/v63701.h index 2e711dc..19842b3 100644 --- a/src/v63701.h +++ b/src/v63701.h @@ -4,7 +4,6 @@ // by James Hammons // (C) 2014 Underground Software // - #ifndef __V63701_H__ #define __V63701_H__ @@ -19,14 +18,14 @@ #define FLAG_V 0x02 // oVerflow #define FLAG_C 0x01 // Carry -#define V63701_ASSERT_LINE_RESET 0x0001 // v63701 RESET line -#define V63701_ASSERT_LINE_IRQ 0x0002 // v63701 IRQ line -#define V63701_ASSERT_LINE_NMI 0x0004 // v63701 NMI line -#define V63701_STATE_WAI 0x0008 // v63701 wait for IRQ line -#define V63701_ASSERT_TIMER_OVERFLOW 0x0010 -#define V63701_ASSERT_OUTPUT_COMPARE 0x0020 -#define V63701_ASSERT_INPUT_CAPTURE 0x0040 -#define V63701_ASSERT_TRAP 0x0080 // Illegal instruction executed flag +#define V63701_LINE_RESET 0x0001 // v63701 RESET line +#define V63701_LINE_IRQ 0x0002 // v63701 IRQ line +#define V63701_LINE_NMI 0x0004 // v63701 NMI line +#define V63701_STATE_WAI 0x0008 // v63701 wait for IRQ line +#define V63701_TIMER_OVERFLOW 0x0010 +#define V63701_OUTPUT_COMPARE 0x0020 +#define V63701_INPUT_CAPTURE 0x0040 +#define V63701_TRAP 0x0080 // Illegal instruction executed flag //#define V6809_START_DEBUG_LOG 0x8000 // Debug log go (temporary!) // Useful structs @@ -135,4 +134,3 @@ extern void V63701WritePort1(uint8_t); extern void V63701WritePort2(uint8_t); #endif // __V63701_H__ - diff --git a/src/v6809.cpp b/src/v6809.cpp old mode 100755 new mode 100644 index a6c07fc..bd92926 --- a/src/v6809.cpp +++ b/src/v6809.cpp @@ -1,10 +1,10 @@ // -// Virtual 6809 v1.4.1 +// Virtual 6809 v1.4.2 // -// by James L. Hammons -// (C) 1997, 2009, 2014 Underground Software +// by James Hammons +// (C) 1997, 2009, 2014, 2023 Underground Software // -// JLH = James L. Hammons +// JLH = James Hammons // // WHO WHEN WHAT // --- ---------- ----------------------------------------------------------- @@ -13,18 +13,11 @@ // JLH 11/11/2006 Removed all SignedX() references // JLH 09/29/2009 Converted V6809 to macro implementation! // JLH 04/17/2014 Misc. cleanups, fixes to missing instructions +// JLH 01/03/2023 Added missing clock cycles to indexed memory accesses // -#define __DEBUG__ - #include "v6809.h" -#ifdef __DEBUG__ -#include "dis6809.h" // Temporary... -#include "log.h" // Temporary... -bool disasm = false;//so we can extern this shit -#endif - #define TEST_DONT_BRANCH_OPTIMIZATION // Various macros @@ -40,16 +33,8 @@ bool disasm = false;//so we can extern this shit #define SET_V(a,b,r) (flagV = (((b) ^ (a) ^ (r) ^ ((r) >> 1)) & 0x80) >> 7) #define SET_V16(a,b,r) (flagV = (((b) ^ (a) ^ (r) ^ ((r) >> 1)) & 0x8000) >> 15) #define SET_H(a,b,r) (flagH = (((a) ^ (b) ^ (r)) & 0x10) >> 4) - -//Not sure that this code is computing the carry correctly... Investigate! [Seems to be] -//#define SET_C_ADD(a,b) (flagC = ((uint8_t)(b) > (uint8_t)(~(a)) ? 1 : 0)) -//#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) (flagC = ((uint8_t)(b) >= (uint8_t)(a) ? 1 : 0)) #define SET_ZN(r) SET_N(r); SET_Z(r) #define SET_ZN16(r) SET_N16(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) #define EA_IMM regs.pc++ #define EA_DP (regs.dp << 8) | regs.RdMem(regs.pc++) @@ -153,6 +138,9 @@ static const uint8_t page2Cycles[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // $Fx }; +// Cycle counts for PUL/PSHx instructions +static uint8_t bitCount[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; + // Private function prototypes static uint16_t RdMemW(uint16_t addr); @@ -163,7 +151,6 @@ static void WriteEXG(uint8_t, uint16_t); // Set TFR/EXG data static uint16_t DecodeReg(uint8_t); // Decode register data static uint16_t DecodeIDX(uint8_t); // Decode IDX data - // // Read word from memory function // @@ -172,7 +159,6 @@ static inline uint16_t RdMemW(uint16_t addr) return (uint16_t)(regs.RdMem(addr) << 8) | regs.RdMem(addr + 1); } - // // Fetch a word from memory function. Increments PC // @@ -182,7 +168,6 @@ static inline uint16_t FetchMemW(uint16_t addr) return (uint16_t)(regs.RdMem(addr) << 8) | regs.RdMem(addr + 1); } - // // Write word to memory function // @@ -192,7 +177,6 @@ static inline void WrMemW(uint16_t addr, uint16_t w) regs.WrMem(addr + 1, w & 0xFF); } - // // Function to read TFR/EXG post byte // @@ -240,7 +224,6 @@ static uint16_t ReadEXG(uint8_t code) return retval; } - // // Function to set TFR/EXG data // @@ -271,7 +254,6 @@ static void WriteEXG(uint8_t code, uint16_t data) } } - // // Function to decode register data // @@ -294,17 +276,34 @@ static uint16_t DecodeReg(uint8_t reg) return retval; } - // // Function to decode IDX data // static uint16_t DecodeIDX(uint8_t code) { +/* +Cycle counts are now taken into account here... + + 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +90 5 6 5 6 3 4 4 0 4 7 0 7 4 8 0 5 +B0 5 6 5 6 3 4 4 0 4 7 0 7 4 8 0 5 +D0 5 6 5 6 3 4 4 0 4 7 0 7 4 8 0 5 +F0 5 6 5 6 3 4 4 0 4 7 0 7 4 8 0 5 + +80 2 3 2 3 0 1 1 0 1 4 0 4 1 5 0 5 +A0 2 3 2 3 0 1 1 0 1 4 0 4 1 5 0 5 +C0 2 3 2 3 0 1 1 0 1 4 0 4 1 5 0 5 +E0 2 3 2 3 0 1 1 0 1 4 0 4 1 5 0 5 +*/ uint16_t addr, woff; + int16_t offset; uint8_t reg = (code & 0x60) >> 5, idxind = (code & 0x10) >> 4, lo_nyb = code & 0x0F; if (!(code & 0x80)) // Hi bit unset? Then decode 4 bit offset + { addr = DecodeReg(reg) + (idxind ? lo_nyb - 16 : lo_nyb); + regs.clock++; + } else { if (idxind) @@ -321,6 +320,7 @@ static uint16_t DecodeIDX(uint8_t code) case 2: regs.u += 2; break; case 3: regs.s += 2; break; } + regs.clock += 6; break; case 3: switch (reg) @@ -332,45 +332,63 @@ static uint16_t DecodeIDX(uint8_t code) } woff = DecodeReg(reg); addr = RdMemW(woff); + regs.clock += 6; break; case 4: woff = DecodeReg(reg); addr = RdMemW(woff); + regs.clock += 3; break; case 5: woff = DecodeReg(reg) + (int16_t)(int8_t)regs.b; addr = RdMemW(woff); + regs.clock += 4; break; case 6: woff = DecodeReg(reg) + (int16_t)(int8_t)regs.a; addr = RdMemW(woff); + regs.clock += 4; break; case 8: woff = DecodeReg(reg) + (int16_t)(int8_t)regs.RdMem(regs.pc++); addr = RdMemW(woff); + regs.clock += 4; break; case 9: woff = DecodeReg(reg) + FetchMemW(regs.pc); addr = RdMemW(woff); + regs.clock += 7; break; case 11: woff = DecodeReg(reg) + ((regs.a << 8) | regs.b); addr = RdMemW(woff); + regs.clock += 7; break; case 12: // woff = regs.pc + (int16_t)(int8_t)regs.RdMem(regs.pc++); +#if 1 + // I believe this is the correct interpretation + offset = (int16_t)(int8_t)regs.RdMem(regs.pc++); + woff = regs.pc + offset; +#else woff = regs.pc + (int16_t)(int8_t)regs.RdMem(regs.pc); regs.pc++; +#endif addr = RdMemW(woff); + regs.clock += 4; break; case 13: woff = regs.pc + FetchMemW(regs.pc); addr = RdMemW(woff); + regs.clock += 8; break; case 15: woff = FetchMemW(regs.pc); addr = RdMemW(woff); + regs.clock += 5; break; + default: + addr = 0; } } else @@ -386,6 +404,7 @@ static uint16_t DecodeIDX(uint8_t code) case 2: regs.u++; break; case 3: regs.s++; break; } + regs.clock += 2; break; case 1: addr = DecodeReg(reg); @@ -396,32 +415,71 @@ static uint16_t DecodeIDX(uint8_t code) case 2: regs.u += 2; break; case 3: regs.s += 2; break; } + regs.clock += 3; + break; + case 2: + switch(reg) + { + case 0: regs.x--; break; + case 1: regs.y--; break; + case 2: regs.u--; break; + case 3: regs.s--; break; + } + addr = DecodeReg(reg); + regs.clock += 2; + break; + case 3: + switch(reg) + { + case 0: regs.x -= 2; break; + case 1: regs.y -= 2; break; + case 2: regs.u -= 2; break; + case 3: regs.s -= 2; break; + } + addr = DecodeReg(reg); + regs.clock += 3; + break; + case 4: + addr = DecodeReg(reg); + break; + case 5: + addr = DecodeReg(reg) + (int16_t)(int8_t)regs.b; + regs.clock++; + break; + case 6: + addr = DecodeReg(reg) + (int16_t)(int8_t)regs.a; + regs.clock++; break; - case 2: { switch(reg) - { - case 0: regs.x--; break; - case 1: regs.y--; break; - case 2: regs.u--; break; - case 3: regs.s--; break; - } - addr = DecodeReg(reg); break; } - case 3: { switch(reg) - { - case 0: regs.x--; regs.x--; break; - case 1: regs.y--; regs.y--; break; - case 2: regs.u--; regs.u--; break; - case 3: regs.s--; regs.s--; break; - } - addr = DecodeReg(reg); break; } - case 4: { addr = DecodeReg(reg); break; } - case 5: { addr = DecodeReg(reg) + (int16_t)(int8_t)regs.b; break; } - case 6: { addr = DecodeReg(reg) + (int16_t)(int8_t)regs.a; break; } - case 8: { addr = DecodeReg(reg) + (int16_t)(int8_t)regs.RdMem(regs.pc++); break; } - case 9: { addr = DecodeReg(reg) + FetchMemW(regs.pc); break; } - case 11: { addr = DecodeReg(reg) + ((regs.a << 8) | regs.b); break; } -// case 12: { addr = regs.pc + (int16_t)(int8_t)regs.RdMem(regs.pc++); break; } - case 12: { addr = regs.pc + (int16_t)(int8_t)regs.RdMem(regs.pc); regs.pc++; break; } - case 13: { addr = regs.pc + FetchMemW(regs.pc); break; } + case 8: + addr = DecodeReg(reg) + (int16_t)(int8_t)regs.RdMem(regs.pc++); + regs.clock++; + break; + case 9: + addr = DecodeReg(reg) + FetchMemW(regs.pc); + regs.clock += 4; + break; + case 11: + addr = DecodeReg(reg) + ((regs.a << 8) | regs.b); + regs.clock += 4; + break; + case 12: +// addr = regs.pc + (int16_t)(int8_t)regs.RdMem(regs.pc++); +#if 1 + // I believe this is the correct interpretation of the above + offset = (int16_t)(int8_t)regs.RdMem(regs.pc++); + addr = regs.pc + offset; +#else + addr = regs.pc + (int16_t)(int8_t)regs.RdMem(regs.pc); + regs.pc++; +#endif + regs.clock++; + break; + case 13: + addr = regs.pc + FetchMemW(regs.pc); + regs.clock += 5; + break; + default: + addr = 0; } } } @@ -464,72 +522,54 @@ static uint16_t DecodeIDX(uint8_t code) acc = sum & 0xFF; \ SET_ZN(acc) -/* -Old flag handling code: - (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Adjust Carry - ((regs.a^tmp^addr)&0x10 ? regs.cc |= 0x20 : regs.cc &= 0xDF); // Set Half carry - ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow - regs.a = addr & 0xFF; // Set accumulator - (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB); // Adjust Zero - (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7); // Adjust Negative -*/ - static void Op89(void) // ADCA # { uint16_t m = READ_IMM; OP_ADC_HANDLER(m, regs.a); } - static void Op99(void) // ADCA DP { uint16_t m = READ_DP; OP_ADC_HANDLER(m, regs.a); } - static void OpA9(void) // ADCA IDX { uint16_t m = READ_IDX; OP_ADC_HANDLER(m, regs.a); } - static void OpB9(void) // ADCA ABS { uint16_t m = READ_ABS; OP_ADC_HANDLER(m, regs.a); } - static void OpC9(void) // ADCB # { uint16_t m = READ_IMM; OP_ADC_HANDLER(m, regs.b); } - static void OpD9(void) // ADCB DP { uint16_t m = READ_DP; OP_ADC_HANDLER(m, regs.b); } - static void OpE9(void) // ADCB IDX { uint16_t m = READ_IDX; OP_ADC_HANDLER(m, regs.b); } - static void OpF9(void) // ADCB ABS { uint16_t m = READ_ABS; OP_ADC_HANDLER(m, regs.b); } - /* +-----------------------------------------------------------------+ | Opcode | | Addressing | | | @@ -570,115 +610,83 @@ static void OpF9(void) // ADCB ABS loreg = acc & 0xFF; \ SET_ZN16(acc) -/* -Old flags: - (addr > 0xFF ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Set Carry flag - ((regs.a^tmp^addr)&0x10 ? regs.cc |= 0x20 : regs.cc &= 0xDF); // Set Half carry - ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow - regs.a = addr & 0xFF; // Set accumulator - (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB); // Set Zero flag - (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7); // Set Negative flag - - dr += addr; - (dr > 0xFFFF ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Adjust Carry flag - dr &= 0xFFFF; - (dr == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB); // Adjust Zero flag - (dr&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7); // Adjust Negative flag - ((ds^addr^dr^(regs.cc<<15))&0x8000 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerfl - regs.a = dr>>8; regs.b = dr&0xFF; - regs.clock += 4; -*/ - static void Op3A(void) // ABX { regs.x += (uint16_t)regs.b; } - static void Op8B(void) // ADDA # { uint16_t m = READ_IMM; OP_ADD_HANDLER(m, regs.a); } - static void Op9B(void) // ADDA DP { uint16_t m = READ_DP; OP_ADD_HANDLER(m, regs.a); } - static void OpAB(void) // ADDA IDX { uint16_t m = READ_IDX; OP_ADD_HANDLER(m, regs.a); } - static void OpBB(void) // ADDA ABS { uint16_t m = READ_ABS; OP_ADD_HANDLER(m, regs.a); } - static void OpC3(void) // ADDD # { uint32_t m = READ_IMM16; OP_ADD_HANDLER16(m, regs.a, regs.b); } - static void OpCB(void) // ADDB # { uint16_t m = READ_IMM; OP_ADD_HANDLER(m, regs.b); } - static void OpD3(void) // ADDD DP { uint32_t m = READ_DP16; OP_ADD_HANDLER16(m, regs.a, regs.b); } - static void OpDB(void) // ADDB DP { uint16_t m = READ_DP; OP_ADD_HANDLER(m, regs.b); } - static void OpE3(void) // ADDD IDX { uint32_t m = READ_IDX16; OP_ADD_HANDLER16(m, regs.a, regs.b); } - static void OpEB(void) // ADDB IDX { uint16_t m = READ_IDX; OP_ADD_HANDLER(m, regs.b); } - static void OpF3(void) // ADDD ABS { uint32_t m = READ_ABS16; OP_ADD_HANDLER16(m, regs.a, regs.b); } - static void OpFB(void) // ADDB ABS { uint16_t m = READ_ABS; OP_ADD_HANDLER(m, regs.b); } - /* +-----------------------------------------------------------------+ | Opcode | | Addressing | | | @@ -961,8 +969,6 @@ static void Op25(void) // BLO/CS { // C int16_t offset = (int16_t)(int8_t)READ_IMM; -//if (disasm) -// WriteLog("[offset=%04X,flagC=%08X]", offset, flagC); #ifdef TEST_DONT_BRANCH_OPTIMIZATION regs.pc += offset * flagC; @@ -1745,7 +1751,7 @@ static void Op3C(void) // CWAI static void Op3E(void) // RESET { - regs.cpuFlags |= V6809_ASSERT_LINE_RESET; + regs.cpuFlags |= V6809_LINE_RESET; } static void Op3F(void) // SWI @@ -1810,21 +1816,13 @@ static void Op12() // NOP { } -/* -D3F8: A6 47 LDA (7),U CC=--H----- A=30 B=00 DP=9C X=3C72 Y=CE5C S=BFFF U=BAF0 PC=D3FA -D3FA: 8B 01 ADDA #$01 CC=--H----- A=31 B=00 DP=9C X=3C72 Y=CE5C S=BFFF U=BAF0 PC=D3FC -D3FC: 19 DAA CC=--H----- A=37 B=00 DP=9C X=3C72 Y=CE5C S=BFFF U=BAF0 PC=D3FD -*/ - static void Op19() // DAA { uint16_t result = (uint16_t)regs.a; -// if ((regs.a & 0x0F) > 0x09 || (regs.cc & FLAG_H)) if ((regs.a & 0x0F) > 0x09 || flagH) result += 0x06; -// if ((regs.a & 0xF0) > 0x90 || (regs.cc & FLAG_C) || ((regs.a & 0xF0) > 0x80 && (regs.a & 0x0F) > 0x09)) if ((regs.a & 0xF0) > 0x90 || flagC || ((regs.a & 0xF0) > 0x80 && (regs.a & 0x0F) > 0x09)) result += 0x60; @@ -2005,19 +2003,16 @@ static void Op0C(void) // INC DP WRITE_BACK(m); } - static void Op4C(void) // INCA { OP_INC_HANDLER(regs.a); } - static void Op5C(void) // INCB { OP_INC_HANDLER(regs.b); } - static void Op6C(void) // INC IDX { uint8_t m; @@ -2026,7 +2021,6 @@ static void Op6C(void) // INC IDX WRITE_BACK(m); } - static void Op7C(void) // INC ABS { uint8_t m; @@ -2035,7 +2029,6 @@ static void Op7C(void) // INC ABS WRITE_BACK(m); } - /* +-----------------------------------------------------------------+ | Opcode | | Addressing | | | @@ -2060,7 +2053,6 @@ static void Op0E(void) // JMP DP regs.pc = m; } - static void Op17(void) // LBSR { uint16_t word = FetchMemW(regs.pc); @@ -2068,13 +2060,11 @@ static void Op17(void) // LBSR regs.pc += word; } - static void Op39(void) // RTS { PULLS16(regs.pc); } - static void Op3B(void) // RTI { PULLS(regs.cc); @@ -2095,19 +2085,16 @@ static void Op3B(void) // RTI PULLS16(regs.pc); } - static void Op6E(void) // JMP IDX { regs.pc = EA_IDX; } - static void Op7E(void) // JMP ABS { regs.pc = EA_ABS; } - static void Op8D(void) // BSR { uint16_t word = (int16_t)(int8_t)READ_IMM; @@ -2115,7 +2102,6 @@ static void Op8D(void) // BSR regs.pc += word; } - static void Op9D(void) // JSR DP { uint16_t word = EA_DP; @@ -2123,7 +2109,6 @@ static void Op9D(void) // JSR DP regs.pc = word; } - static void OpAD(void) // JSR IDX { uint16_t word = EA_IDX; @@ -2131,7 +2116,6 @@ static void OpAD(void) // JSR IDX regs.pc = word; } - static void OpBD(void) // JSR ABS { uint16_t word = EA_ABS; @@ -2139,7 +2123,6 @@ static void OpBD(void) // JSR ABS regs.pc = word; } - /* +-----------------------------------------------------------------+ | Opcode | | Addressing | | | @@ -2524,16 +2507,6 @@ static void Op3D(void) // MUL flagC = (res >= 0x80 ? 1 : 0); \ m = res -/* - UINT16 r,t; - DIRBYTE(t); - r = -t; - CLR_NZVC; - SET_FLAGS8(0,t,r); - WM(EAD,r); -#define SET_FLAGS8(a,b,r) {SET_N8(r);SET_Z8(r);SET_V8(a,b,r);SET_C8(r);} -#define SET_C8(a) CC|=((a&0x100)>>8) -*/ static void Op00(void) // NEG DP { uint8_t m; @@ -2674,7 +2647,6 @@ static void Op34(void) // PSHS } // Count bits in each nybble to come up with correct cycle counts... - uint8_t bitCount[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; regs.clock += (1 * bitCount[m & 0x0F]) + (2 * bitCount[m >> 4]); } @@ -2703,7 +2675,6 @@ static void Op35(void) // PULS PULLS16(regs.pc); // Count bits in each nybble to come up with correct cycle counts... - uint8_t bitCount[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; regs.clock += (1 * bitCount[m & 0x0F]) + (2 * bitCount[m >> 4]); } @@ -2732,7 +2703,6 @@ static void Op36(void) // PHSU } // Count bits in each nybble to come up with correct cycle counts... - uint8_t bitCount[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; regs.clock += (1 * bitCount[m & 0x0F]) + (2 * bitCount[m >> 4]); } @@ -2761,7 +2731,6 @@ static void Op37(void) // PULU PULLU16(regs.pc); // Count bits in each nybble to come up with correct cycle counts... - uint8_t bitCount[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; regs.clock += (1 * bitCount[m & 0x0F]) + (2 * bitCount[m >> 4]); } @@ -2786,14 +2755,6 @@ static void Op37(void) // PULU flagC = (m >> 7) & 0x01; \ m = res -/* - UINT16 t,r; - DIRBYTE(t); - r = (CC & CC_C) | (t << 1); - CLR_NZVC; - SET_FLAGS8(t,t,r); - WM(EAD,r); -*/ static void Op09(void) // ROL DP { uint8_t m; @@ -3255,33 +3216,28 @@ static void Op0D(void) // TST DP OP_TST_HANDLER(m); } - static void Op4D(void) // TSTA { OP_TST_HANDLER(regs.a); } - static void Op5D(void) // TSTB { OP_TST_HANDLER(regs.b); } - static void Op6D(void) // TST IDX { uint8_t m = READ_IDX; OP_TST_HANDLER(m); } - static void Op7D(void) // TST ABS { uint8_t m = READ_ABS; OP_TST_HANDLER(m); } - // // Undocumented Opcodes // @@ -3290,26 +3246,10 @@ static void Op01(void) Op00(); // NEG DP } - -//temp, for testing... -#ifdef __DEBUG__ -static uint8_t backTrace[256]; -static uint16_t btPC[256]; -static int btPtr = 0;//*/ -#endif static void Op__(void) // Illegal opcode { regs.clock++; -// illegal = true; regs.cpuFlags |= V6809_STATE_ILLEGAL_INST; -#ifdef __DEBUG__ -/*WriteLog("V6809: Executed illegal opcode %02X at PC=%04X...\n\nBacktrace:\n\n", regs.RdMem(regs.pc - 1), regs.pc - 1); -for(int i=0; i<256; i++) -{ - Decode6809(btPC[(btPtr + i) & 0xFF]); - WriteLog("\n"); -}//*/ -#endif } // @@ -3381,30 +3321,24 @@ static void (* exec_op2[256])() = { Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__, Op__ }; - // These are here to save typing a ton of forward declarations... - // Page 1 opcode static void Op10(void) { -// exec_op1[regs.RdMem(regs.pc++)](); uint8_t opcode = regs.RdMem(regs.pc++); exec_op1[opcode](); regs.clock += page1Cycles[opcode]; } - // Page 2 opcode static void Op11(void) { -// exec_op2[regs.RdMem(regs.pc++)](); uint8_t opcode = regs.RdMem(regs.pc++); exec_op2[opcode](); regs.clock += page2Cycles[opcode]; } - // // Internal "memcpy" (so we don't have to link with any external libraries!) // @@ -3416,24 +3350,14 @@ static void myMemcpy(void * dst, void * src, uint32_t size) d[i] = s[i]; } - // // Function to execute 6809 instructions // -//#define DEBUG_ILLEGAL -#ifdef DEBUG_ILLEGAL -#include "log.h" -#include "dis6809.h" -uint8_t btPtr = 0; -uint8_t backTrace[256]; -V6809REGS btRegs[256]; -bool tripped = false; -#endif void Execute6809(V6809REGS * context, uint32_t cycles) { // If this is not in place, the clockOverrun calculations can cause the // V6809 to get stuck in an infinite loop. - if (cycles == 0) + if (cycles == 0) // Nothing to do, so bail! return; myMemcpy(®s, context, sizeof(V6809REGS)); @@ -3452,53 +3376,6 @@ void Execute6809(V6809REGS * context, uint32_t cycles) while (regs.clock < endCycles) { -#ifdef DEBUG_ILLEGAL -if (!tripped) -{ - backTrace[btPtr] = regs.RdMem(regs.pc); - btRegs[btPtr] = regs; - btPtr = (btPtr + 1) & 0xFF; - - if (regs.cpuFlags & V6809_STATE_ILLEGAL_INST) - { - WriteLog("V6809: Executed illegal instruction!!!!\n\nBacktrace:\n\n"); - regs.cpuFlags &= ~V6809_STATE_ILLEGAL_INST; - - for(uint16_t i=btPtr; i 1) - WriteLog("\n\n!!! FLAG OUT OF BOUNDS !!!\n\n"); -#endif -//static bool disasm = false; -/*//if (regs.pc == 0x15BA) disasm = true; -//if (regs.pc == 0xFE76) disasm = true; -if (regs.x == 0xFED4) disasm = true; -if (disasm) Decode6809(regs.pc); -//if (regs.pc == 0x164A) disasm = false;//*/ - -//temp, for testing... -/*backTrace[btPtr] = regs.RdMem(regs.pc); -btPC[btPtr] = regs.pc; -btPtr = (btPtr + 1) & 0xFF;//*/ -#endif -// exec_op0[regs.RdMem(regs.pc++)](); uint8_t opcode = regs.RdMem(regs.pc++); exec_op0[opcode](); regs.clock += page0Cycles[opcode]; @@ -3509,22 +3386,18 @@ btPtr = (btPtr + 1) & 0xFF;//*/ // uint32_t flags = context->cpuFlags; uint32_t flags = regs.cpuFlags; - if (flags & V6809_ASSERT_LINE_RESET) // *** RESET handler *** + // *** RESET handler *** + if (flags & V6809_LINE_RESET) { -#ifdef __DEBUG__ -if (disasm) WriteLog("\nV6809: RESET line asserted!\n"); -#endif flagF = flagI = 1; // Set F, I regs.dp = 0; // Reset direct page register regs.pc = RdMemW(0xFFFE); // And load PC with the RESET vector - context->cpuFlags &= ~V6809_ASSERT_LINE_RESET; - regs.cpuFlags &= ~V6809_ASSERT_LINE_RESET; + context->cpuFlags &= ~V6809_LINE_RESET; + regs.cpuFlags &= ~V6809_LINE_RESET; } - else if (flags & V6809_ASSERT_LINE_NMI) // *** NMI handler *** + // *** NMI handler *** + else if (flags & V6809_LINE_NMI) { -#ifdef __DEBUG__ -if (disasm) WriteLog("\nV6809: NMI line asserted!\n"); -#endif flagE = 1; // Set Entire flag regs.cc = PACK_FLAGS; // Mash flags back into the CC register @@ -3540,19 +3413,12 @@ if (disasm) WriteLog("\nV6809: NMI line asserted!\n"); flagI = flagF = 1; // Set IRQ/FIRQ suppress flags regs.pc = RdMemW(0xFFFC); // And load PC with the NMI vector regs.clock += 19; -// context->cpuFlags &= ~V6809_ASSERT_LINE_NMI;// Reset the asserted line (NMI)... -// regs.cpuFlags &= ~V6809_ASSERT_LINE_NMI; // Reset the asserted line (NMI)... } - else if (flags & V6809_ASSERT_LINE_FIRQ) // *** FIRQ handler *** + // *** FIRQ handler *** + else if (flags & V6809_LINE_FIRQ) { -#ifdef __DEBUG__ -if (disasm) WriteLog("\nV6809: FIRQ line asserted!\n"); -#endif if (!flagF) // Is the FIRQ masked (F == 1)? { -#ifdef __DEBUG__ -if (disasm) WriteLog(" FIRQ taken...\n"); -#endif flagE = 0; // Clear Entire flag regs.cc = PACK_FLAGS; // Mash flags back into the CC register @@ -3562,20 +3428,13 @@ if (disasm) WriteLog(" FIRQ taken...\n"); flagI = flagF = 1; // Set IRQ/FIRQ suppress flags regs.pc = RdMemW(0xFFF6); // And load PC with the IRQ vector regs.clock += 10; -// context->cpuFlags &= ~V6809_ASSERT_LINE_FIRQ; // Reset the asserted line (FIRQ)... -// regs.cpuFlags &= ~V6809_ASSERT_LINE_FIRQ; // Reset the asserted line (FIRQ)... } } - else if (flags & V6809_ASSERT_LINE_IRQ) // *** IRQ handler *** + // *** IRQ handler *** + else if (flags & V6809_LINE_IRQ) { -#ifdef __DEBUG__ -if (disasm) WriteLog("\nV6809: IRQ line asserted!\n"); -#endif if (!flagI) // Is the IRQ masked (I == 1)? { -#ifdef __DEBUG__ -if (disasm) WriteLog(" IRQ taken...\n"); -#endif flagE = 1; // Set the Entire flag regs.cc = PACK_FLAGS; // Mash flags back into the CC register @@ -3591,19 +3450,8 @@ if (disasm) WriteLog(" IRQ taken...\n"); flagI = 1; // Specs say that it doesn't affect FIRQ... or FLAG_F [WAS: Set IRQ/FIRQ suppress flags] regs.pc = RdMemW(0xFFF8); // And load PC with the IRQ vector regs.clock += 19; -// Apparently, not done here! -// context->cpuFlags &= ~V6809_ASSERT_LINE_IRQ; // Reset the asserted line (IRQ)... -// regs.cpuFlags &= ~V6809_ASSERT_LINE_IRQ; // Reset the asserted line (IRQ)... } } -#ifdef __DEBUG__ -if (disasm) WriteLog("CC=%s%s%s%s%s%s%s%s A=%02X B=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X\n", - (flagE ? "E" : "-"), (flagF ? "F" : "-"), (flagH ? "H" : "-"), (flagI ? "I" : "-"), - (flagN ? "N" : "-"), (flagZ ? "Z" : "-"), (flagV ? "V" : "-"), (flagC ? "C" : "-"), - regs.a, regs.b, regs.dp, regs.x, regs.y, regs.s, regs.u, regs.pc);//*/ -/*WriteLog("\tA=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X\n", - regs.a, regs.b, regs.cc, regs.dp, regs.x, regs.y, regs.s, regs.u, regs.pc);//*/ -#endif } // Keep track of how much we overran so we can adjust on the next run... @@ -3613,7 +3461,6 @@ if (disasm) WriteLog("CC=%s%s%s%s%s%s%s%s A=%02X B=%02X DP=%02X X=%04X Y=%04X S= myMemcpy(context, ®s, sizeof(V6809REGS)); } - // // Get the clock of the currently executing CPU // @@ -3622,7 +3469,6 @@ uint64_t GetCurrentV6809Clock(void) return regs.clock; } - // // Get the PC of the currently executing CPU // @@ -3631,49 +3477,15 @@ uint16_t GetCurrentV6809PC(void) return regs.pc; } - // Set a line of the currently executing CPU void SetLineOfCurrentV6809(uint32_t line) { regs.cpuFlags |= line; } - // Clear a line of the currently executing CPU void ClearLineOfCurrentV6809(uint32_t line) { -#ifdef __DEBUG__ -if (disasm) - WriteLog("V6809: Clearing line %s...", (line == V6809_ASSERT_LINE_IRQ ? "IRQ" : "OTHER")); -#endif regs.cpuFlags &= ~line; } - -#if 0 -FE54: 27 6A BEQ $FEC0 CC=EF-I-Z-- A=39 B=01 DP=00 X=FEE2 Y=F51 -E S=BFFF U=0000 PC=FEC0 -FEC0: 6E A4 JMP ,Y CC=EF-I-Z-- A=39 B=01 DP=00 X=FEE2 Y=F51E S=BFFF - U=0000 PC=F51E -F51E: 86 34 LDA #$34 CC=EF-I---- A=34 B=01 DP=00 X=FEE2 Y=F51E S=BFFF - U=0000 PC=F520 -F520: B7 C8 0D STA $C80D CC=EF-I---- A=34 B=01 DP=00 X=FEE2 Y=F51E S=BFFF U=0000 PC=F523 -F523: B7 C8 0F STA $C80F CC=EF-I---- A=34 B=01 DP=00 X=FEE2 Y=F51E S=BFFF U=0000 PC=F526 -F526: 7F C8 0E CLR $C80EV6809: Clearing line IRQ... CC=EF-I-Z-- A=34 B=01 DP=00 X=FEE2 Y=F51E S=BFFF U=0000 PC=F529 -F529: 86 9C LDA #$9C CC=EF-IN--- A=9C B=01 DP=00 X=FEE2 Y=F51E S=BFFF U=0000 PC=F52B -F52B: 1F 8B TFR A,DP CC=EF-IN--- A=9C B=01 DP=9C X=FEE2 Y=F51E S=BFFF U=0000 PC=F52D -F52D: 10 CE BF FF LDS #$BFFF CC=EF-IN--- A=9C B=01 DP=9C X=FEE2 Y=F51E S=BFFF U=0000 PC=F531 -F531: BD 13 BD JSR $13BD CC=EF-IN--- A=9C B=01 DP=9C X=FEE2 Y=F51E S=BFFD U=0000 PC=13BD -13BD: 34 76 PSHS A B X Y U CC=EF-IN--- A=9C B=01 DP=9C X=FEE2 Y=F51E S=BFF5 U=0000 PC=13BF -13BF: CE 9C 00 LDU #$9C00 CC=EF-IN--- A=9C B=01 DP=9C X=FEE2 Y=F51E S=BFF5 U=9C00 PC=13C2 -13C2: 8E 00 00 LDX #$0000 CC=EF-I-Z-- A=9C B=01 DP=9C X=0000 Y=F51E S=BFF5 U=9C00 PC=13C5 -13C5: 1F 12 TFR X,Y CC=EF-I-Z-- A=9C B=01 DP=9C X=0000 Y=0000 S=BFF5 U=9C00 PC=13C7 -13C7: 1F 10 TFR X,D CC=EF-I-Z-- A=00 B=00 DP=9C X=0000 Y=0000 S=BFF5 U=9C00 PC=13C9 -13C9: 36 36 PSHU A B X Y CC=EF-I-Z-- A=00 B=00 DP=9C X=0000 Y=0000 S=BFEF U=9C00 PC=13CB -13CB: 36 36 PSHU A B X Y CC=EF-I-Z-- A=00 B=00 DP=9C X=0000 Y=0000 S=BFE9 U=9C00 PC=13CD -13CD: 36 36 PSHU A B X Y CC=EF-I-Z-- A=00 B=00 DP=9C X=0000 Y=0000 S=BFE3 U=9C00 PC=13CF -13CF: 36 36 PSHU A B X Y CC=EF-I-Z-- A=00 B=00 DP=9C X=0000 Y=0000 S=BFDD U=9C00 PC=13D1 -13D1: 36 36 PSHU A B X Y CC=EF-I-Z-- A=00 B=00 DP=9C X=0000 Y=0000 S=BFD7 U=9C00 PC=13D3 -13D3: 36 10 PSHU X CC=EF-I-Z-- A=00 B=00 DP=9C X=0000 Y=0000 S=BFD5 U=9C00 PC=13D5 -13D5: 11 83 00 00 CMPU #$0000 CC=EF-IN--- A=00 B=00 DP=9C X=0000 Y=000 -#endif diff --git a/src/v6809.h b/src/v6809.h old mode 100755 new mode 100644 index ae8a337..2e40414 --- a/src/v6809.h +++ b/src/v6809.h @@ -2,10 +2,8 @@ // Virtual 6809 Header file // // by James L. Hammons -// // (C) 1997, 2004 Underground Software // - #ifndef __V6809_H__ #define __V6809_H__ @@ -22,13 +20,12 @@ #define FLAG_V 0x02 // oVerflow #define FLAG_C 0x01 // Carry -#define V6809_ASSERT_LINE_RESET 0x0001 // v6809 RESET line -#define V6809_ASSERT_LINE_IRQ 0x0002 // v6809 IRQ line -#define V6809_ASSERT_LINE_FIRQ 0x0004 // v6809 FIRQ line -#define V6809_ASSERT_LINE_NMI 0x0008 // v6809 NMI line +#define V6809_LINE_RESET 0x0001 // v6809 RESET line +#define V6809_LINE_IRQ 0x0002 // v6809 IRQ line +#define V6809_LINE_FIRQ 0x0004 // v6809 FIRQ line +#define V6809_LINE_NMI 0x0008 // v6809 NMI line #define V6809_STATE_SYNC 0x0010 // v6809 SYNC line #define V6809_STATE_ILLEGAL_INST 0x0020 // Illegal instruction executed flag - //#define V6809_START_DEBUG_LOG EQU 0020h // Debug log go (temporary!) // Useful structs @@ -60,4 +57,3 @@ void SetLineOfCurrentV6809(uint32_t line); // Set a line of the currently execu void ClearLineOfCurrentV6809(uint32_t line); // Clear a line of the currently executing CPU #endif // __V6809_H__ - diff --git a/src/video.h b/src/video.h index 8e59dfb..acacc76 100644 --- a/src/video.h +++ b/src/video.h @@ -1,7 +1,6 @@ // // VIDEO.H: Header file // - #ifndef __VIDEO_H__ #define __VIDEO_H__ @@ -25,4 +24,3 @@ extern uint32_t scrBuffer[]; //extern uint32_t mainScrBuffer[]; #endif // __VIDEO_H__ - diff --git a/src/ym2151.cpp b/src/ym2151.cpp index 653d0e5..29d7e99 100644 --- a/src/ym2151.cpp +++ b/src/ym2151.cpp @@ -13,7 +13,6 @@ #include #include - // Missing shit (from M.A.M.E.) #if 1 @@ -30,7 +29,6 @@ void * timer_set(int foo, int bar, void (* baz)(int)) { printf("STUB: timer_set( #endif - /* ** some globals ... */ @@ -114,22 +112,6 @@ signed int * BuffTemp = NULL; /*temporary buffer for speedup purposes*/ static void (* envelope_calc[5])(OscilRec *); static void (* register_writes[256])(uint8_t, uint8_t, uint8_t); -//save output as raw 16-bit sample - just in case you would like to listen to it offline ;-) -//#define SAVE_SAMPLE -//#define SAVE_SEPARATE_CHANNELS - -#ifdef SAVE_SAMPLE -#ifdef SAVE_SEPARATE_CHANNELS -FILE * sample1; -FILE * sample2; -FILE * sample3; -FILE * sample4; -FILE * sample5; -FILE * sample6; -#endif -FILE * samplesum; -#endif - int PMTab[8]; /*8 channels */ /* this table is used for PM setup of LFO */ @@ -211,7 +193,6 @@ static signed int deltas[9*12*64];/*9 octaves, 12 semitones, 64 'cents' */ static signed int LFOdeltas[256]; /*frequency deltas for LFO*/ - void sin_init(void) { int x, i; @@ -283,21 +264,8 @@ void sin_init(void) decib45[x] = i; //if (errorlog) fprintf(errorlog,"decib45[%04x]=%08x\n",x,i ); } - -#ifdef SAVE_SAMPLE -#ifdef SAVE_SEPARATE_CHANNELS -sample1=fopen("samp.raw","wb"); -sample2=fopen("samp2.raw","wb"); -sample3=fopen("samp3.raw","wb"); -sample4=fopen("samp4.raw","wb"); -sample5=fopen("samp5.raw","wb"); -sample6=fopen("samp6.raw","wb"); -#endif -samplesum=fopen("sampsum.raw","wb"); -#endif } - void hertz(void) { int i, j, oct; @@ -459,7 +427,6 @@ void hertz(void) } } - void envelope_attack(OscilRec * op) { if ((op->attack_volume -= op->delta_AR) < MIN_VOLUME_INDEX) //is volume index min already ? @@ -471,7 +438,6 @@ void envelope_attack(OscilRec * op) op->volume = attack_curve[op->attack_volume>>ENV_SH]; } - void envelope_decay(OscilRec * op) { if ((op->volume += op->delta_D1R) > op->D1L) @@ -481,7 +447,6 @@ void envelope_decay(OscilRec * op) } } - void envelope_sustain(OscilRec * op) { if ((op->volume += op->delta_D2R) > MAX_VOLUME_INDEX) @@ -491,7 +456,6 @@ void envelope_sustain(OscilRec * op) } } - void envelope_release(OscilRec * op) { if ((op->volume += op->delta_RR) > MAX_VOLUME_INDEX) @@ -501,18 +465,15 @@ void envelope_release(OscilRec * op) } } - void envelope_nothing(OscilRec *op) { } - inline void envelope_KOFF(OscilRec * op) { op->state = 3; /*release*/ } - inline void envelope_KON(OscilRec * op) { /*this is to remove the gap time if TL>0*/ @@ -523,7 +484,6 @@ inline void envelope_KON(OscilRec * op) op->OscilFB = 0; /*Clear feedback after key on */ } - void refresh_chip(YM2151 * PSG) { uint16_t kc_index_oscil, kc_index_channel, mul; @@ -567,14 +527,12 @@ void refresh_chip(YM2151 * PSG) } } - void write_YM_NON_EMULATED(uint8_t n, uint8_t r, uint8_t v) { if (errorlog) fprintf(errorlog, "Write to non emulated register %02x value %02x\n", r, v); } - void write_YM_KON(uint8_t n, uint8_t r, uint8_t v) { uint8_t chan; @@ -603,25 +561,21 @@ void write_YM_KON(uint8_t n, uint8_t r, uint8_t v) envelope_KOFF(&PSG->Oscils[chan + 24]); } - void write_YM_CLOCKA1(uint8_t n, uint8_t r, uint8_t v) { YMPSG[n].Regs[r] = v; } - void write_YM_CLOCKA2(uint8_t n, uint8_t r, uint8_t v) { YMPSG[n].Regs[r] = v & 0x03; } - void write_YM_CLOCKB(uint8_t n, uint8_t r, uint8_t v) { YMPSG[n].Regs[r] = v; } - static void timer_callback_a(int n) { YM2151 * PSG = &YMPSG[n]; @@ -635,7 +589,6 @@ static void timer_callback_a(int n) PSG->TimATimer = 0; } - static void timer_callback_b(int n) { YM2151 * PSG = &YMPSG[n]; @@ -649,7 +602,6 @@ static void timer_callback_b(int n) PSG->TimBTimer = 0; } - void write_YM_CLOCKSET(uint8_t n, uint8_t r, uint8_t v) { YM2151 * PSG = &(YMPSG[n]); @@ -712,13 +664,11 @@ void write_YM_CLOCKSET(uint8_t n, uint8_t r, uint8_t v) } } - void write_YM_CT1_CT2_W(uint8_t n, uint8_t r, uint8_t v) { YMPSG[n].Regs[r] = v; } - void write_YM_CONNECT_BASE(uint8_t n, uint8_t r, uint8_t v) { // NOTE: L/R Channel enables are ignored! This emu is mono! @@ -731,21 +681,18 @@ void write_YM_CONNECT_BASE(uint8_t n, uint8_t r, uint8_t v) PSG->FeedBack[chan] = FEED[(v >> 3) & 7]; } - void write_YM_KC_BASE(uint8_t n, uint8_t r, uint8_t v) { YMPSG[n].KC[r - YM_KC_BASE] = v; //freq_calc(chan,PSG); } - void write_YM_KF_BASE(uint8_t n, uint8_t r, uint8_t v) { YMPSG[n].KF[r - YM_KF_BASE] = v >> 2; //freq_calc(chan,PSG); } - void write_YM_PMS_AMS_BASE(uint8_t n, uint8_t r, uint8_t v) { // uint8_t chan, i; @@ -765,21 +712,18 @@ void write_YM_PMS_AMS_BASE(uint8_t n, uint8_t r, uint8_t v) } - void write_YM_DT1_MUL_BASE(uint8_t n, uint8_t r, uint8_t v) { YMPSG[n].Regs[r] = v; //freq_calc(chan,PSG); } - void write_YM_TL_BASE(uint8_t n, uint8_t r, uint8_t v) { v &= 0x7F; YMPSG[n].Oscils[r - YM_TL_BASE].TL = v << (ENV_BITS - 7); /*7bit TL*/ } - void write_YM_KS_AR_BASE(uint8_t n, uint8_t r, uint8_t v) { uint8_t op; @@ -792,7 +736,6 @@ void write_YM_KS_AR_BASE(uint8_t n, uint8_t r, uint8_t v) PSG->Oscils[op].AR = (v & 0x1F) << 1; } - void write_YM_AMS_D1R_BASE(uint8_t n, uint8_t r, uint8_t v) { uint8_t op = r - YM_AMS_D1R_BASE; @@ -805,7 +748,6 @@ void write_YM_AMS_D1R_BASE(uint8_t n, uint8_t r, uint8_t v) YMPSG[n].Oscils[op].D1R = (v & 0x1F) << 1; } - void write_YM_DT2_D2R_BASE(uint8_t n, uint8_t r, uint8_t v) { YM2151 * PSG = &(YMPSG[n]); @@ -816,7 +758,6 @@ void write_YM_DT2_D2R_BASE(uint8_t n, uint8_t r, uint8_t v) //freq_calc(chan,PSG); } - void write_YM_D1L_RR_BASE(uint8_t n, uint8_t r, uint8_t v) { OscilRec * osc = &YMPSG[n].Oscils[r - YM_D1L_RR_BASE]; @@ -825,7 +766,6 @@ void write_YM_D1L_RR_BASE(uint8_t n, uint8_t r, uint8_t v) osc->RR = ((v & 0x0F) << 2) | 0x02; } - /* ** Initialize YM2151 emulator(s). ** @@ -834,14 +774,16 @@ void write_YM_D1L_RR_BASE(uint8_t n, uint8_t r, uint8_t v) ** 'rate' is sampling rate and 'bufsiz' is the size of the ** buffer that should be updated at each interval */ -int YMInit(int num, int clock, int rate, int sample_bits, int bufsiz)//, SAMPLE ** buffer) +//int YMInit(int num, int clock, int rate, int sample_bits, int bufsiz)//, SAMPLE ** buffer) +int YMInit(int clock, int rate) { int i; if (YMPSG) return (-1); /* duplicate init. */ - YMNumChips = num; +// YMNumChips = num; + YMNumChips = 1; YM2151_SAMPFREQ = rate; #if 0 @@ -852,7 +794,7 @@ int YMInit(int num, int clock, int rate, int sample_bits, int bufsiz)//, SAMPLE #endif YM2151_CLOCK = clock; - YMBufSize = bufsiz; +// YMBufSize = bufsiz; envelope_calc[0] = envelope_attack; envelope_calc[1] = envelope_decay; @@ -930,7 +872,6 @@ int YMInit(int num, int clock, int rate, int sample_bits, int bufsiz)//, SAMPLE return 0; } - void YMShutdown() { if (!YMPSG) @@ -952,34 +893,19 @@ void YMShutdown() } YM2151_SAMPFREQ = YMBufSize = 0; - -#ifdef SAVE_SAMPLE -#ifdef SAVE_SEPARATE_CHANNELS -fclose(sample1); -fclose(sample2); -fclose(sample3); -fclose(sample4); -fclose(sample5); -fclose(sample6); -#endif -fclose(samplesum); -#endif } - /* write a register on YM2151 chip number 'n' */ void YMWriteReg(int n, int r, int v) { register_writes[(uint8_t)r]((uint8_t)n, (uint8_t)r, (uint8_t)v); } - uint8_t YMReadReg(uint8_t n) { return YMPSG[n].TimIRQ; } - /* ** reset all chip registers. */ @@ -1018,14 +944,12 @@ void YMResetChip(int num) PSG->TimIRQ = 0; } - static inline signed int op_calc(OscilRec * OP, signed int pm) { return sin_tab[(((OP->phase += OP->freq) >> FREQ_SH) + (pm)) & SIN_MASK] [OP->TL + (OP->volume >> ENV_SH)]; } - //void YM2151UpdateOne(int num, int endp) void YM2151UpdateOne(void * BUF, int endp) { @@ -1037,9 +961,6 @@ void YM2151UpdateOne(void * BUF, int endp) OscilRec * OP0, * OP1, * OP2, * OP3; uint16_t i; signed int k, wy; -#ifdef SAVE_SEPARATE_CHANNELS - signed int pom; -#endif refresh_chip(PSG); @@ -1101,10 +1022,6 @@ void YM2151UpdateOne(void * BUF, int endp) case 6: *(PSGBUF) = op_calc(OP2, wy) + op_calc(OP1, 0) + op_calc(OP3, 0); break; default: *(PSGBUF) = wy + op_calc(OP2, 0) + op_calc(OP1, 0) + op_calc(OP3, 0); break; } -#ifdef SAVE_SEPARATE_CHANNELS -fputc((uint16_t)(*PSGBUF) & 0xFF, sample1); -fputc(((uint16_t)(*PSGBUF) >> 8) & 0xFF, sample1); -#endif } //chan1 @@ -1127,9 +1044,6 @@ fputc(((uint16_t)(*PSGBUF) >> 8) & 0xFF, sample1); else OP0->OscilFB = 0; -#ifdef SAVE_SEPARATE_CHANNELS -pom = *(PSGBUF); -#endif switch(PSG->ConnectTab[1]) { case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break; @@ -1141,11 +1055,6 @@ pom = *(PSGBUF); case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break; default: *(PSGBUF) += wy + op_calc(OP2, 0) + op_calc(OP1, 0) + op_calc(OP3, 0); break; } - -#ifdef SAVE_SEPARATE_CHANNELS -fputc((uint16_t)((*PSGBUF)-pom)&0xff,sample2); -fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample2); -#endif } //chan2 @@ -1167,9 +1076,6 @@ for( PSGBUF = &BuffTemp[PSG->bufp]; PSGBUF < &BuffTemp[endp]; PSGBUF++ ) else OP0->OscilFB = 0; -#ifdef SAVE_SEPARATE_CHANNELS - pom=*(PSGBUF); -#endif switch(PSG->ConnectTab[2]) { case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break; @@ -1181,10 +1087,6 @@ for( PSGBUF = &BuffTemp[PSG->bufp]; PSGBUF < &BuffTemp[endp]; PSGBUF++ ) case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break; default:*(PSGBUF) += wy + op_calc(OP2,0) + op_calc(OP1,0) + op_calc(OP3,0);break; } -#ifdef SAVE_SEPARATE_CHANNELS -fputc((uint16_t)((*PSGBUF)-pom)&0xff,sample3); -fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample3); -#endif } //chan3 @@ -1206,9 +1108,6 @@ for( PSGBUF = &BuffTemp[PSG->bufp]; PSGBUF < &BuffTemp[endp]; PSGBUF++ ) else OP0->OscilFB = 0; -#ifdef SAVE_SEPARATE_CHANNELS - pom=*(PSGBUF); -#endif switch(PSG->ConnectTab[3]) { case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break; @@ -1220,10 +1119,6 @@ for( PSGBUF = &BuffTemp[PSG->bufp]; PSGBUF < &BuffTemp[endp]; PSGBUF++ ) case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break; default:*(PSGBUF) += wy + op_calc(OP2,0) + op_calc(OP1,0) + op_calc(OP3,0);break; } -#ifdef SAVE_SEPARATE_CHANNELS -fputc((uint16_t)((*PSGBUF)-pom)&0xff,sample4); -fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample4); -#endif } //chan4 @@ -1246,10 +1141,6 @@ fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample4); else OP0->OscilFB = 0; - #ifdef SAVE_SEPARATE_CHANNELS - pom = *(PSGBUF); - #endif - switch(PSG->ConnectTab[4]) { case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break; @@ -1261,11 +1152,6 @@ fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample4); case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break; default:*(PSGBUF) += wy + op_calc(OP2,0) + op_calc(OP1,0) + op_calc(OP3,0);break; } - -#ifdef SAVE_SEPARATE_CHANNELS -fputc((uint16_t)((*PSGBUF)-pom)&0xff,sample5); -fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample5); -#endif } //chan5 @@ -1287,9 +1173,6 @@ for( PSGBUF = &BuffTemp[PSG->bufp]; PSGBUF < &BuffTemp[endp]; PSGBUF++ ) else OP0->OscilFB = 0; -#ifdef SAVE_SEPARATE_CHANNELS - pom=*(PSGBUF); -#endif switch(PSG->ConnectTab[5]) { case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break; @@ -1301,10 +1184,6 @@ for( PSGBUF = &BuffTemp[PSG->bufp]; PSGBUF < &BuffTemp[endp]; PSGBUF++ ) case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break; default:*(PSGBUF) += wy + op_calc(OP2,0) + op_calc(OP1,0) + op_calc(OP3,0);break; } -#ifdef SAVE_SEPARATE_CHANNELS -fputc((uint16_t)((*PSGBUF)-pom)&0xff,sample6); -fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample6); -#endif } //chan6 @@ -1379,17 +1258,14 @@ for( PSGBUF = &BuffTemp[PSG->bufp]; PSGBUF < &BuffTemp[endp]; PSGBUF++ ) { k = *(PSGBUF++); -#ifdef SAVE_SAMPLE -fputc((uint16_t)(-k) & 0xFF, samplesum); -fputc(((uint16_t)(-k) >> 8) & 0xFF, samplesum); -#endif - #if 1 // if (sample_16bit) { /*16 bit mode*/ k >>= FINAL_SH16; //AUDIO_CONV - k <<= 2; +// We don't shift by 2, as it's too loud (eventually, we need to do proper volume control here) +// k <<= 2; + k <<= 1; if (k > 32767) k = 32767; @@ -1417,7 +1293,6 @@ fputc(((uint16_t)(-k) >> 8) & 0xFF, samplesum); PSG->bufp = endp; } - /* ** called to update all chips */ @@ -1433,7 +1308,6 @@ void YM2151Update(void) } } - /* ** return the buffer into which YM2151Update() has just written it's sample ** data @@ -1443,9 +1317,7 @@ SAMPLE * YMBuffer(int n) return YMPSG[n].Buf; } - void YMSetIrqHandler(int n, void(* handler)(void)) { YMPSG[n].handler = handler; } - diff --git a/src/ym2151.h b/src/ym2151.h index 06b330d..3892863 100644 --- a/src/ym2151.h +++ b/src/ym2151.h @@ -117,7 +117,8 @@ typedef struct ym2151_f { ** 'rate' is sampling rate and 'bufsiz' is the size of the ** buffer that should be updated at each interval */ -int YMInit(int num, int clock, int rate, int sample_bits, int bufsiz); //, SAMPLE ** buffer); +//int YMInit(int num, int clock, int rate, int sample_bits, int bufsiz); //, SAMPLE ** buffer); +int YMInit(int clock, int rate); /* ** shutdown the YM2151 emulators ... diff --git a/test/union.cpp b/test/union.cpp index ef052ab..99c32a3 100644 --- a/test/union.cpp +++ b/test/union.cpp @@ -1,82 +1,49 @@ // Union bit fields... -//#include -//#include -#include -#include +#include +#include +#include #include -#include +#include #include #include -using namespace std; - union { - struct { - unsigned char C: 1; // Carry flag - unsigned char V: 1; // oVerflow flag - unsigned char Z: 1; // Zero flag - unsigned char N: 1; // Negative flag - unsigned char I: 1; // IRQ flag - unsigned char H: 1; // Half carry flag - unsigned char F: 1; // Fast IRQ flag - unsigned char E: 1; // Entire flag - } flag; - unsigned char byte; } cc; + struct { + unsigned char C: 1; // Carry flag + unsigned char V: 1; // oVerflow flag + unsigned char Z: 1; // Zero flag + unsigned char N: 1; // Negative flag + unsigned char I: 1; // IRQ flag + unsigned char H: 1; // Half carry flag + unsigned char F: 1; // Fast IRQ flag + unsigned char E: 1; // Entire flag + } flag; + unsigned char byte; } cc; union BYTE { - struct { - unsigned char b0: 1; unsigned char b1: 1; unsigned char b2: 1; - unsigned char b3: 1; unsigned char b4: 1; unsigned char b5: 1; - unsigned char b6: 1; unsigned char b7: 1; - } bit; - unsigned char byte; }; + struct { + unsigned char b0: 1; unsigned char b1: 1; unsigned char b2: 1; + unsigned char b3: 1; unsigned char b4: 1; unsigned char b5: 1; + unsigned char b6: 1; unsigned char b7: 1; + } bit; + unsigned char byte; }; union WORD { - struct { unsigned char lo: 8; unsigned char hi: 8; } b; - unsigned int word; } hilo; - + struct { unsigned char lo: 8; unsigned char hi: 8; } b; + unsigned int word; } hilo; -int main(int, char * []) +void main() { - for(int i=0; i<256; i++) - { - cc.byte = i; - cout << (cc.flag.E ? "1" : ".") << " " << (cc.flag.F ? "1" : ".") << " " - << (cc.flag.H ? "1" : ".") << " " << (cc.flag.I ? "1" : ".") << " " - << (cc.flag.N ? "1" : ".") << " " << (cc.flag.Z ? "1" : ".") << " " - << (cc.flag.V ? "1" : ".") << " " << (cc.flag.C ? "1" : ".") << endl; - } - - hilo.word = 0x6A44; - cout << hex << hilo.word << " " - << (int) hilo.b.lo << " " << (int) hilo.b.hi << endl; - - BYTE b; - b.byte = (unsigned char)0xA5; - cout << "Byte = " << hex << (int)b.byte << ", bits = " - << (b.bit.b7 ? "1" : "0") - << (b.bit.b6 ? "1" : "0") - << (b.bit.b5 ? "1" : "0") - << (b.bit.b4 ? "1" : "0") - << (b.bit.b3 ? "1" : "0") - << (b.bit.b2 ? "1" : "0") - << (b.bit.b1 ? "1" : "0") - << (b.bit.b0 ? "1" : "0") - << endl; - - b.bit.b4 ^= 1; - cout << "Byte = " << hex << (int)b.byte << ", bits = " - << (b.bit.b7 ? "1" : "0") - << (b.bit.b6 ? "1" : "0") - << (b.bit.b5 ? "1" : "0") - << (b.bit.b4 ? "1" : "0") - << (b.bit.b3 ? "1" : "0") - << (b.bit.b2 ? "1" : "0") - << (b.bit.b1 ? "1" : "0") - << (b.bit.b0 ? "1" : "0") - << endl; - - return 0; + for(int i=0; i<256; i++) + { + cc.byte = i; + cout << cc.flag.E << " " << cc.flag.F << " " + << cc.flag.H << " " << cc.flag.I << " " + << cc.flag.N << " " << cc.flag.Z << " " + << cc.flag.V << " " << cc.flag.C << endl; + } + hilo.word = 0x6A44; + cout << hex << hilo.word << " " + << (int) hilo.b.lo << " " << (int) hilo.b.hi << endl; } -