diff options
Diffstat (limited to 'source')
59 files changed, 1989 insertions, 6816 deletions
diff --git a/source/apu.c b/source/apu.c index 28214e1..b051744 100644 --- a/source/apu.c +++ b/source/apu.c @@ -37,9 +37,7 @@ uint8_t APUROM [64]; void S9xResetAPU() { int32_t i, j; - Settings.APUEnabled = true; - memset(IAPU.RAM, 0, 0x100); memset(IAPU.RAM + 0x20, 0xFF, 0x20); memset(IAPU.RAM + 0x60, 0xFF, 0x20); @@ -49,7 +47,7 @@ void S9xResetAPU() for (i = 1; i < 256; i++) memcpy(IAPU.RAM + (i << 8), IAPU.RAM, 0x100); - memset(APU.OutPorts, 0, 4); + memset(APU.OutPorts, 0, sizeof(APU.OutPorts)); IAPU.DirectPage = IAPU.RAM; // memmove converted: Different mallocs [Neb] // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb] @@ -68,7 +66,7 @@ void S9xResetAPU() IAPU.APUExecuting = Settings.APUEnabled; IAPU.WaitAddress1 = NULL; IAPU.WaitAddress2 = NULL; - IAPU.WaitCounter = 0; + IAPU.WaitCounter = 1; APU.ShowROM = true; IAPU.RAM [0xf1] = 0x80; @@ -89,7 +87,7 @@ void S9xResetAPU() APU.DSP [APU_ENDX] = 0; APU.DSP [APU_KOFF] = 0; APU.DSP [APU_KON] = 0; - APU.DSP [APU_FLG] = APU_MUTE | APU_ECHO_DISABLED; + APU.DSP[APU_FLG] = APU_SOFT_RESET | APU_MUTE; APU.KeyedChannels = 0; S9xResetSound(true); @@ -335,7 +333,7 @@ void S9xFixEnvelope(int32_t channel, uint8_t gain, uint8_t adsr1, uint8_t adsr2) if(S9xSetSoundMode(channel, MODE_ADSR)) S9xSetSoundADSR(channel, adsr1 & 0xf, (adsr1 >> 4) & 7, adsr2 & 0x1f, (adsr2 >> 5) & 7, 8); } // Gain mode - else if ((gain & 0x80) == 0) + else if (!(gain & 0x80)) { if (S9xSetSoundMode(channel, MODE_GAIN)) { @@ -346,9 +344,7 @@ void S9xFixEnvelope(int32_t channel, uint8_t gain, uint8_t adsr1, uint8_t adsr2) else if (gain & 0x40) { // Increase mode - if(S9xSetSoundMode(channel, (gain & 0x20) ? - MODE_INCREASE_BENT_LINE : - MODE_INCREASE_LINEAR)) + if(S9xSetSoundMode(channel, (gain & 0x20) ? MODE_INCREASE_BENT_LINE : MODE_INCREASE_LINEAR)) S9xSetEnvelopeRate(channel, gain, 1, 127, (3 << 28) | gain); } else if (gain & 0x20) @@ -365,30 +361,30 @@ void S9xFixEnvelope(int32_t channel, uint8_t gain, uint8_t adsr1, uint8_t adsr2) void S9xSetAPUControl(uint8_t byte) { - if ((byte & 1) != 0 && !APU.TimerEnabled [0]) + if ((byte & 1) && !APU.TimerEnabled [0]) { APU.Timer [0] = 0; IAPU.RAM [0xfd] = 0; if ((APU.TimerTarget [0] = IAPU.RAM [0xfa]) == 0) APU.TimerTarget [0] = 0x100; } - if ((byte & 2) != 0 && !APU.TimerEnabled [1]) + if ((byte & 2) && !APU.TimerEnabled [1]) { APU.Timer [1] = 0; IAPU.RAM [0xfe] = 0; if ((APU.TimerTarget [1] = IAPU.RAM [0xfb]) == 0) APU.TimerTarget [1] = 0x100; } - if ((byte & 4) != 0 && !APU.TimerEnabled [2]) + if ((byte & 4) && !APU.TimerEnabled [2]) { APU.Timer [2] = 0; IAPU.RAM [0xff] = 0; if ((APU.TimerTarget [2] = IAPU.RAM [0xfc]) == 0) APU.TimerTarget [2] = 0x100; } - APU.TimerEnabled [0] = (bool) (byte & 1); - APU.TimerEnabled [1] = (bool) (byte & 2); - APU.TimerEnabled [2] = (bool) (byte & 4); + APU.TimerEnabled [0] = !!(byte & 1); + APU.TimerEnabled [1] = !!(byte & 2); + APU.TimerEnabled [2] = !!(byte & 4); if (byte & 0x10) IAPU.RAM [0xF4] = IAPU.RAM [0xF5] = 0; @@ -432,9 +428,8 @@ uint8_t S9xGetAPUDSP() case APU_OUTX + 0x60: case APU_OUTX + 0x70: if(SoundData.channels [reg >> 4].state == SOUND_SILENT) - return (0); - return ((SoundData.channels [reg >> 4].sample >> 8) | - (SoundData.channels [reg >> 4].sample & 0xff)); + return 0; + return (SoundData.channels [reg >> 4].sample >> 8) | (SoundData.channels [reg >> 4].sample & 0xff); case APU_ENVX + 0x00: case APU_ENVX + 0x10: case APU_ENVX + 0x20: @@ -450,7 +445,7 @@ uint8_t S9xGetAPUDSP() default: break; } - return (byte); + return byte; } #endif diff --git a/source/apu.h b/source/apu.h index 8944377..0197a20 100644 --- a/source/apu.h +++ b/source/apu.h @@ -78,8 +78,8 @@ void S9xSetAPUDSP(uint8_t byte); uint8_t S9xGetAPUDSP(void); bool S9xInitSound(void); void S9xPrintAPUState(void); -extern uint16_t S9xAPUCycles [256]; // Scaled cycle lengths -extern uint16_t S9xAPUCycleLengths [256]; // Raw data. +extern uint8_t S9xAPUCycles [256]; // Scaled cycle lengths +extern uint8_t S9xAPUCycleLengths [256]; // Raw data. extern void (*S9xApuOpcodes [256])(void); #define APU_VOL_LEFT 0x00 diff --git a/source/c4.h b/source/c4.h index 7ab3964..3c47d5f 100644 --- a/source/c4.h +++ b/source/c4.h @@ -29,5 +29,4 @@ int16_t _atan2(int16_t x, int16_t y); extern int16_t C4CosTable[]; extern int16_t C4SinTable[]; - #endif diff --git a/source/c4emu.c b/source/c4emu.c index 7805dc5..300e421 100644 --- a/source/c4emu.c +++ b/source/c4emu.c @@ -15,7 +15,7 @@ uint8_t S9xGetC4(uint16_t Address) { if (Address == 0x7f5e) return 0; - return (Memory.C4RAM [Address - 0x6000]); + return Memory.C4RAM [Address - 0x6000]; } static uint8_t C4TestPattern [12 * 4] = @@ -68,8 +68,7 @@ static void C4ConvOAM() SprY = READ_WORD(srcptr + 2) - globalY; SprName = srcptr[5]; SprAttr = srcptr[4] | srcptr[0x06]; // XXX: mask bits? - - sprptr = S9xGetMemPointer(READ_3WORD(srcptr + 7)); + sprptr = S9xGetMemPointer(READ_3WORD(srcptr + 7)); if (*sprptr != 0) { int32_t SprCnt; @@ -314,7 +313,6 @@ static void C4DrawWireFrame() int16_t X1, Y1, Z1; int16_t X2, Y2, Z2; uint8_t Color; - int32_t i; for (i = Memory.C4RAM[0x0295]; i > 0; i--, line += 5) { @@ -345,7 +343,6 @@ static void C4TransformLines() int32_t i; uint8_t *ptr; uint8_t* ptr2; - C4WFX2Val = Memory.C4RAM[0x1f83]; C4WFY2Val = Memory.C4RAM[0x1f86]; C4WFDist = Memory.C4RAM[0x1f89]; @@ -353,18 +350,17 @@ static void C4TransformLines() // transform vertices ptr = Memory.C4RAM; + + for (i = READ_WORD(Memory.C4RAM + 0x1f80); i > 0; i--, ptr += 0x10) { - for (i = READ_WORD(Memory.C4RAM + 0x1f80); i > 0; i--, ptr += 0x10) - { - C4WFXVal = READ_WORD(ptr + 1); - C4WFYVal = READ_WORD(ptr + 5); - C4WFZVal = READ_WORD(ptr + 9); - C4TransfWireFrame(); - - // displace - WRITE_WORD(ptr + 1, C4WFXVal + 0x80); - WRITE_WORD(ptr + 5, C4WFYVal + 0x50); - } + C4WFXVal = READ_WORD(ptr + 1); + C4WFYVal = READ_WORD(ptr + 5); + C4WFZVal = READ_WORD(ptr + 9); + C4TransfWireFrame(); + + // displace + WRITE_WORD(ptr + 1, C4WFXVal + 0x80); + WRITE_WORD(ptr + 5, C4WFYVal + 0x50); } WRITE_WORD(Memory.C4RAM + 0x600, 23); WRITE_WORD(Memory.C4RAM + 0x602, 0x60); @@ -403,7 +399,6 @@ static void C4BitPlaneWave() uint32_t waveptr = Memory.C4RAM[0x1f83]; uint16_t mask1 = 0xc0c0; uint16_t mask2 = 0x3f3f; - int32_t i, j; for (j = 0; j < 0x10; j++) { @@ -426,8 +421,7 @@ static void C4BitPlaneWave() waveptr = (waveptr + 1) & 0x7f; mask1 = (mask1 >> 2) | (mask1 << 6); mask2 = (mask2 >> 2) | (mask2 << 6); - } - while (mask1 != 0xc0c0); + } while (mask1 != 0xc0c0); dst += 16; do @@ -450,8 +444,7 @@ static void C4BitPlaneWave() waveptr = (waveptr + 1) & 0x7f; mask1 = (mask1 >> 2) | (mask1 << 6); mask2 = (mask2 >> 2) | (mask2 << 6); - } - while (mask1 != 0xc0c0); + } while (mask1 != 0xc0c0); dst += 16; } } diff --git a/source/catsfc_griffin.c b/source/catsfc_griffin.c deleted file mode 100644 index 8b4666c..0000000 --- a/source/catsfc_griffin.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "../copyright" - -#include "apu.c" -#include "c4.c" -#include "c4emu.c" -#include "cheats2.c" -#include "cheats.c" -#include "clip.c" -#include "cpu.c" -#include "cpuexec.c" -#include "cpuops.c" -#include "data.c" -#include "dma.c" -#include "dsp1.c" -#include "fxdbg.c" -#include "fxemu.c" -#include "fxinst.c" -#include "gfx.c" -#include "globals.c" -#include "memmap.c" -#include "obc1.c" -#include "ppu.c" -#include "sdd1.c" -#include "sdd1emu.c" -#include "seta010.c" -#include "seta011.c" -#include "seta018.c" -#include "seta.c" -#include "soundux.c" -#include "spc700.c" -#include "spc7110.c" -#include "srtc.c" -#include "tile.c" - -#include "../libretro.c" diff --git a/source/changes.txt b/source/changes.txt deleted file mode 100644 index 3aabb22..0000000 --- a/source/changes.txt +++ /dev/null @@ -1,2155 +0,0 @@ -Snes9x 1.43 (WIP1) -- Win32: added .avi output feature (blip) -- Win32: fixed frame timings >100ms, added frame advance (blip) -- Rewrote Unfreeze, renamed it S9xUnfreezeFromStream, - failing to load a freeze file no longer resets emulation (blip) -- Fixed Unfreeze to restore IPPU.HDMA properly (blip) -- Rewrote OBC1 code to match the real chip (Overload) -- More updates the to DSP-1 code, fixes to projection (Overload, Andreas Naive) -- Unix/X11: Rewrote keyboard setup code (Bisqwit) -- Added movie recording+rerecording support (blip, Bisqwit) -- Added -hidemenu CLI switch (funkyass) -- fixed broken Win32 filters (lantus) -- Added internal support for emulating the new-style SNES (MKendora) -- Cleaned up many quirks of the cheat search engine (MKendora, Don Vincenzo) -- Fix mosaic in hires SNES modes (Tokimeki Memorial) (MKendora, zones) -- Rewrote Legend's hack, added another game to it (MKendora) -- Optimized the Open ROM dialog (MKendora) -- Rewrote the Seta DSP map (The Dumper, MKendora) -- Began string isolation for the UI, eases translation (funkyass) -- added -nopatch -nocheat, and -cheat CLI items (MKendora) -- fixed a UI typo (funkyass) -- fixed several C core stack ops in emulation mode (MKendora) -- split emulation mode ops from native mode ops (MKendora) -- Seta special chip emulation enhancements (Feather, The Dumper, Overload, MKendora) -- code tweaks to the ST010 (Nach, pagefault) -- fix some C/asm quirks and HDMA quirks (all my fault) (MKendora) -- several timing hacks to fix games (lantus) -- improved checksumming for odd mirrorings (MKendora) -- Snes9x uses a standard zlib instead of a packaged one (PBortas) -- Exhaust Heat 2 and regional ports are playable (Feather, The Dumper, Overload, MKendora) -- Game Doctor dumps that are 24 Mbit are now supported by - a force option (MKendora, Nach) -- SuperFx interleave format is now considered deprecated. - Support will be removed in future versions (Team decision) -- made SuperFx interleave detection a compile option (MKendora) -- added memory maps for slotted games (MKendora) -- fixed a typo in the usage messages (MKendora) -- fixed the bug that had nuked optimizations (The Dumper) -- restored full speed optimizations in release builds (funkyass) -- Added non-speed-hack version of color subtraction. (zones) -- Fixed mouse offset in resized X11 window. (PhaethonH) -- Fixed a (presumably) long-standing bug: Mode 6's BG is - depth 4, not depth 8! (anomie) -- Unix: unmap all joystick buttons before applying -joymapX (anomie) -- Win32: added a define to disable pausing when focus is lost, NOPAUSE (funkyass) -- Win32: Changed the default for Auto-save SRAM to 15 sec (funkyass) -- Dreamcast: Added SH4 assembler (PBortas, Marcus Comstedt, Per Hedbor) - - -Snes9x 1.42 -- Added 8-bit rendering filters (funkyass) -- Added Sanity Checks for the Display Dialog (funkyass) -- New Layout for the Joypad Dialog, (funkyass) -- Fixed that anoying Joypad dialog bug. Now check to see - if the axis exists before asking for the info form it (funkyass) -- Added full POV support. (funkyass) -- Fixed sram sizes for SuperFx games (Nach, MKendora) -- Stopped saving sram for games with no battery (Nach, Mkendora) -- Killed the gray line and slightly optimized Win32 GL (MKendora) -- stack wrapping fix in C core (MKendora) -- removed some dead hacks (Oda Nobunaga and Dezaemon) (MKendora) -- fixed some DMA and HDMA modes (anomie, MKendora) -- improved HDMA timing (anomie) -- cleaned up load and deinterleave code (MKendora) -- removed old UI DLL (MKendora) -- new cheat dialogs (MKendora) -- started Unicode preparation in Win32 UI (MKendora) -- Implement odd sprite sizes, sprite priority rotation. (anomie) -- RTO code that hopefully works. MK's #define is - "MK_DEBUG_RTO" to try to debug the RTO code. (anomie) -- SDD1 decompression support for Linux. Also added a new - command line option -sdd1-pack. (anomie) -- Added correct VRAM read logic. #define CORRECT_VRAM_READS - if you want it. (anomie) -- removed the non-VAR_CYCLES path (MKendora) -- changed access timing map to be address-based. (MKendora, anomie) -- DSP-1 updates (Overload, Andreas Naive) -- S-DD1 decompression support (Andreas Naive) -- optimized S-DD1 code (anomie) -- S-DD1 can use packs or decompression (MKendora) -- More work on Exhaust Heat 2 (MKendora, Overload, The Dumper) -- separated ROM detection from file reading (lantus) -- fixed a mirroring bug in LoROMs (MKendora) -- cleaned up some mapping issues (MKendora) -- ST018 games now boot before locking up (Mkendora, Overload) -- SA-1 state was not completely reset, crashed Marvelous (zones) -- Removed sample caching. It caused problems, and was not - noticably faster. (MKendora) -- Fixed interlace without breaking the displays for MK (anomie) -- Fixed a PPU OpenBus hack (anomie) -- Moved SPC7110 and S-DD1 regs to speed up the general case - of reading the $4xxx registers (MKendora) -- altered Hi/Lo ROM detection to fix a few misdetects. (MKendora) -- Implemented RTO flags. With MK's implementation of $213F's - interlace bit, we now pass the SNES Test Cart's - Electronics Test (anomie) -- Fix sprite windowing bug (anomie) -- Way back in 1.40 MK changed the Windows port to default - to a plain old joypad instead of the MP5. And then we - removed the hacks for games that dislike the MP5. So - we need to change the defaults elsewhere too... (anomie) -- cleaned up the hacks section somewhat (MKendora) -- removed some interleave hacks (MKendora) -- fixed a bug in KartContents (MKendora) -- transparency fix for Jurassic Park (lantus) -- A hidden Win32 feature (MKendora) -- Kludged Mark Davis until I get stable APU timing (MKendora) -- Win32 renders overscan always, fixes some jumpy games (MKendora, lantus) -- Fixed an FMOD bug (MKendora) -- cosmetic tweaks (Everyone) -- Fixed 2 special chip bugs in the C core (zones) -- Added some sanity fixes to the C core, fixes MLBPA - Baseball for C core users (zones) -- updated zlib source (includes 1.1.4-1 patch) (MKendora) -- compiler warning fixes (PBortas) -- Updated the SuperFx asm core (pagefault) -- Kludged Unix compilation to produce working SuperFx (PBortas) - with the asm core. -- Kludged VC to deal with optimization weirdness (MKendora) -- Hacked Robocop vs. Terminator using Daffy Duck hack. Stops - flashing. (MKendora) -- Added some defines to the asm core (MKendora) -- Added possibility to take screenshots on Unix (PBortas) -- Initialize the C SuperFx core better (PBortas) -- Kludge a Japanese golf game until the APU timing is fixed (MKendora) - - -Snes9x 1.41-1 - -- Oops, in the asm CPU core i was stomping on %eax too - early, so register $4210 wasn't getting set properly. (anomie) - - -Snes9x 1.41 - -- Win32 controllers now stay the same between games (MKendora) -- Win 32 Open ROM dialog fixes (MKendora) -- Win32 Display dialog fixes (funkyass) -- Win32 OpenGL ratio tweaking. (Reduces the gray line) (kode54) -- Fixed Win32 superscope for those having issues (MKendora) -- Generic accuracy fix in main SUperscope emulation (MKendora) -- sprite bug fixed (gah! How'd we miss that) (anomie) -- SPC saving compatibility fix (Caz and zones) -- Window clipping update (anomie) -- Mode 7 clipping fix (TRAC) -- latching fix (anomie) -- BS BIOS checksum and mapping fix (MKendora) -- Working Uniracers hack (dma.cpp) (anomie) -- HDMA Indirect Address fix for Romancing Saga 2 (anomie) -- Better savestate hack, does it break anything? (anomie) -- C4 C core fixes. Mostly Trapezoid (thanks Nach), - some s/short/int16/, some indentation. (anomie) -- Damn, but the indentation in ppu.cpp was screwed up. - Killed some dead code too (twas commented forevermore). (anomie) -- fixed a potential crash in S-DD1 logging (MKendora) -- Improved accuracy of Hi/LoROM detection (~500 ROM test) (MKendora) -- Hack for Moryou Senki Madara 2, don't call - SelectTileRenderer from DrawOBJS if BGMode is 5 or 6. A - real fix requires at least rewriting SelectTileRenderer, - or inlining a special version in DrawOBJS. (anomie) -- DMA traces: add additional address info to reads too. (anomie) -- Killed the old Borland Joypad dialog (funkyass) -- Fixed issues with Dezaemon and CT, maybe others (anomie, MKendora) -- Changed the internal snapshot key from \ to VK_F12 (funkyass) - Fixes issues with non-US keyboard layouts. -- Fixed OAM reset to not occur during forced blank. (anomie) -- Killed some dead OAM reset code that doesn't need saving. (anomie) -- Unix/X11: Fixed screen jumping. CT enables overscan mid- - frame for only one frame, and we now update the rendered - screen height accordingly. Other ports are still broken. (anomie) -- Unix/X11: Fixed possible TV mode crash. (anomie) -- Fixed OAM reset timing (beginning of V-Blank rather than - end) for R-TYPE 3 (J). (anomie) -- Unix/X11: Fixed OpenGL target (PBortas) -- Unix/OSS: Fixed big endian sound (PBortas/ernstp) -- Tweaked the About Dialog so its read-only and no scroll (funkyass) - - -Snes9x 1.40 - -- cleaned up a sound skipping code issue. Same as the - RTC issue (lantus) -- re-fixed the invalid BRR header behavior twice (Lord Nightmare, FatlXception, Mkendora) -- More BS mapping fixes. (The Dumper, MKendora) -- Fixed Ranma Bun no 1 - Chonai Gekitou Hen (J) and - Street Combat (U). Interlace is not supported in the - non-Hi-res modes, as far as I can tell. (MKendora) -- Also fixes Maka Maka (J). Frank Yang's report, and - anomie's code both provided clues to this one. -- Removed special casing on setting 5c77 version to one. - This seems to be true for U and J units always. I need - it checked out on PAL... (neviksti) -- Using SNEeSe's values for 5c78 and 5A22. Note we know - that the 5c78 version can also be 1 or 2, instead of 3. (TRAC, neviksti) -- Added turbo buttons. Credit/blame for the design goes - to slack, Nave, Gogo, and myself. (MKendora) -- fixed a bug in turbo (slack, MKendora) -- Tried merging the behavior of Old $4200 with new $4200 (MKendora) -- Made $4200's return value match what VSMC Explorer - showed on Fancia's SNES (MKendora) -- Fixed a matrix multiplcation bug in ZSNES state loads (MKendora) -- Fixed Dezaemon and Ys3 mode 7 (lantus) -- Fixed H-DMA modes 5-7. Thanks to The Dumper for the - extra motivation needed. GunForce and Genocide 2 work. (The Dumper, MKendora) -- Fixed BG3 Priority. I'm stupid. anomie had fixed it, - but lantus fixed it again, because I didn't use it. (anomie, lantus) -- Added a Star Fox 2 hack, and an interleave skip (The Dumper, lantus, MKendora) -- Cleared BS setting on load (lantus) -- Fix for Mode 7 priorities. fixes F-1 Grand Prix (all 3) (anomie) -- JANJYU GAKUEN 2 needs Multi-tap 5 off. (Frank Yang, MKendora) -- HONKAKUHA IGO GOSEI: No multi-tap 5, allow mouse (lantus, MKendora) -- Added a few missed conditional compiles (Nach) -- disabled multitap 5 by default, added menu to enable (MKendora) -- special thanks to anomie and lantus. One of them is - responsible for a bug fix I forgot already. (anomie, lantus) -- Removed several Multitap5 disable hacks. (MKendora) -- Added an SPC dumping upgrade from kode54 (kode54) -- cleaned up some resource leaks (MKendora) -- I forgot this since 1.39mk, but SPC700 flag fixes (anomie) -- Mode 7 interpolation screen flip fix (anomie) -- Updated SPC7110 code a bit, for compatibility (Daniel, anomie) -- Changed RTC saving. (Byte exact to old format on Win32) - The submitted patch for "safety" doubled the file size, - so I had to write it in explicitly little-endian. (MKendora) -- Removed the old hidden cursor (MKendora) -- Applied a WAI correction from anomie. (anomie) -- Added a patch for Pseudo hi-res (anomie) -- Hacked around Word writes to $7F:FFFF. Thanks to lantus - and The Dumper for verification. (MKendora) -- PPC compile fix? and debugger reversion (anomie) -- Set defaults differently to improve sound quality. (MKendora) -- Clear Force load settings after Init (lantus) -- Made menu reset a soft reset. Fixed BL Sound Test & more (CaitSith2) -- Fixed word writes to block bounds in asm core. (MKendora) -- redone version of my bounds fix, only this one WORKS! (TRAC) -- Thanks to TRAC for the AT&T syntax refresher! (TRAC) -- Fixed screen saver disable (kode54) -- Fixed OAM and sprite priority in the asm core (anomie) -- Proper Interlace fix for mid-frame changes (anomie) -- Fixed OpenGL to accomodate previous patch (MKendora) -- Ported the "Settings" dialog to VC (MKendora) -- Fixed ROM Info bugs (_pentium_five, MKendora) -- Fixed non-stretched interlacing, but it's s.l.o.w. (anomie) -- Superscope and Mouse need to be enabled by the menu. (MKendora) -- Fixed HiROM sram reads in asm and C cores (anomie, MKendora) -- Added Company 48 to the list. Thanks to _pentium_five_ (StatMat) -- Set Super Drift Out's S-ram correctly. (Snes9xppSE Team) -- Fixed NTSC timing. Helps ToP Intro greatly (kode54) -- Added several entries to the company list, from uCON64 (Nach) -- Lots more companies (StatMat, Nach) -- Fixed Win32 Superscope support (NT kernel only?) (MKendora) -- Added ZSNES OBC1 code ported from asm to C (sanmaiwashi) -- Implemented Justifier emulation (neviksti, MKendora) -- Fixed Rudora no Hihou's clip window bug (anomie) -- Fixed Flintstones sprite issue (lantus) -- Fixed sram mappings for Big Sky Troopers and - Taikyoku - IGO Goliath. Both map in bank F0 (MKendora) -- Fixed a possible crash when switching audio settings (MKendora) -- Added per-pack gfx pack configuration (MKendora) -- Fixed glitches in DSP-1 games (Flintstones fix) (lantus) -- Added delay to Superscope latching. Fixes X-Zone. (neviksti, MKendora, zones) -- Added DSP-2 support (Overload, The Dumper, Lord Nightmare, - MKendora, neviksti) -- Fixed Super Bases Loaded 2 (and J/K ports) DSP-1 seems - to ignore the A15 line in LoROM maps (MKendora) -- Corrected $4200 again (The Dumper) -- Corrected $2100, $2102, and $2102 read behavior (anomie) -- Fixed Cancel on the Sound Options dialog. (MKendora) -- Fixed the sound options dialog (Thanks, Quattro) (MKendora) -- updated DSP-1 support to match chip better (Overload, neviksti, The Dumper) -- added a few Ops to the DSP-4 routine (Nothing plays yet) (neviksti, The Dumper, Overload, MKendora) -- added screenshot support (anomie, sanmaiwashi) -- stubbed the ST010 chip in Exhaust Heat 2 (Overload, MKendora) -- hacked around War 2410's lockup (pagefault, _Demo_, MKendora) -- updated tests for type 1 ROMs (based on reset vector) (MKendora) -- Emulation mode CPU fix (The Dumper) -- Open Bus fixes (anomie) -- Better Expansion port emulation (anomie) -- More Open Bus fixes (Overload, anomie) -- HDMA fixes (fix colors only in Full Throttle Racing) (anomie) -- Migrated DKJM2 onto the Tales map (MKendora) -- Tried to remove Dragon Knight 4 hack (LoROM sram fix) (MKendora) -- Fixed ROM Mirroring for LoROMs (<= 32 Mbit) (MKendora, TRAC) -- blocked wram to wram DMAs (neviksti) -- fixed HiROM mirroring, too. Thanks TRAC! (MKendora, TRAC) -- fixed C core RMW and Push ops to write in the correct - order, fixes Michael Jordan gfx. (anomie, Overload, MKendora) -- set RDIO to start as 0xFF, fixes SuperFx games. (anomie, Overload) -- New connect dialog (funkyass) -- better conditional compile of FMOD (funkyass) -- fixed screenshot code when libpng is not used (funkyass) -- added portability fixes (zones) -- fixed asm Pushes (anomie) -- fixed asm LoROM s-ram decode (MKendora) -- migrated DEZAEMON to standard LoROM map (MKendora) -- fixed the Madara 2 OpenGL bug (key found in Rudra) (MKendora) -- fixed asm RMW instructions (MKendora) -- fixed ADC opcode (The Dumper) -- added DSP-2 Op09 (The Dumper) -- updated C4 C code (anomie) -- updated C4 asm code (Nach) -- Keep OpenGL in ratio (kode54) -- Replaced many more Borland dialogs (funkyass, MKendora, Nach) -- Added CRC32 to displayed ROM Info (Nach, MKendora) -- Fix cheat support (The Dumper) -- improved DMA timing (MKendora, Overload, The Dumper) -- Fixed Mode 7 math, removed Dezaemon, Gaia, Ys 3 hacks (TRAC, MKendora) -- Mode 7 flip fix (TRAC) -- Multiple safety and initialization fixes (zones) -- Platform safety fixes (PBortas) -- Memmap cleanups (MKendora) -- More preliminary work on special chips (The Dumper, Overload, MKendora) -- Added color coding (MKendora) -- Another HDMA fix (anomie) -- added another known hack to the hacked games list (Nach) -- ToP memmap changes (MKendora) -- Checksum calculation changes (MKendora) -- Special cased a few games for OAM issues (MKendora) -- Reverted OAM reset to 1.39 timing (MKendora) -- Reworked vram wrapping (zones, Mkendora) -- Fixed $4210 and Super Professional Baseball 2 (Overload, MKendora) -- Fixed APU RAM init (Overload, MKendora) -- More support for Exhaust Heat 2 (not playable) (The Dumper, Overload, neviksti) -- removed some debris from save states (MKendora) -- fixed? Doom's save state bug (MKendora) -- simple overdump detection warning (MKendora) - - -1.39mk3b - -- Fixed the RTC detection. FINALLY done correctly (lantus, MKendora) - - -1.39mk3a - -- neatened up the company table. (MKendora) -- fixed a mistake in the ROM Info box (MKendora) -- Added a Calulcated Size field to ROM INfo. (MKendora) -- Added 3 more companies to the ROM Info table (MKendora) -- Fixed BS detection (The Dumper) -- Added a Legend-specific hack to get sound. I remembered - it being mentioned in the changelog. (Gary Henderson) -- Unbroke the Star Ocean special cases (Trigger of Time, MKendora) -- Company 255 is not Hudson-ZFE detects all Hudson games - without it, except a corrupt dump (StatMat, MKendora) -- fixed a bug in the redone detection for the SPC7110 (CaitSith2) -- 44Khz sound should be 44.1Kz. Changed, though you'll - need to re-set 44.1Khz to make it take effect. Not sure - if this affects non-Windows ports. (MKendora) -- Added 32Khz playback (MKendora) -- Inproved BS ROM mapping (_Demo_, The Dumper, MKendora) - - -1.39mk3 - -- Honkaku Syogi Fuunji Ryuou (J) fixed (force no multitap) (Frank Yang) - Also Fixed Super Castles (j). - Also fixed a bunch more. This dude e-mailed like 100 bugs - to my hosts, some already fixed in Snes9x1.39mk2, but - about 7 were clearly multi-tap5. -- also fixed Dekitate High School. Error was in Japanese (Frank Yang, Tomato) -- fixed 2 memory leaks (Aaron) -- Dai Kaiju Monogotari 2 works as a 40 Mbit ROM. (MKendora, The Dumper) -- Fixed the Flashback bug. Lots of info led to this. (neviksti, MKendora) - Thanks neviksti, The Dumper, TRAC, and FatlXception - for clarifying the behavior. -- Fixed Sailor Moon Fuwa Fuwa Panic 2 to work with (neviksti, MKendora) - previous fix. It's a total hack, but it should sound - just like the old Snes9x did. neviksti strikes again! -- Dirty hack to make 3 games deinterleave properly: (MKendora) - Wizardry 4, Mark Davis, and Honkakuha Igo Gosei(FX) - all work as well as the deinterleaved counterparts. - (The last is a hacked game, and you should get the - non-FX version) -- Fixed Seima Jyuden Beasts and Blades. Another Multitap, (Frank Yang) - but for some reason, the hack requires the C cpu core. - Thanks to Tomato for taking a stab at the error message, - as well. It was too vague to be of use, he said. I - just tried it because it worked on other games. -- Res Arcana fixed. Another Frank Yang report, another J (Frank Yang, MKendora) - error, but I can read kana well enough with a table! -- Removed a Terranigma specific hack. Not sure, but the (anomie) - new behavior might have fixed Tin-Tin in Tibet's colors. -- Dirty hack to work around a dirty hack. Both Yoshi's (MKendora) - Island (E) dumps should work now -- Added the JumboLoROM memory map, Extends LoROM support (The Dumper, neviksti, MKendora) - to 48+ Megabits. -- added an EXTBG fix, since iirc, TRAC is using it as well (anomie) - Does it actually fix anything? -- Fixed crash in DSP Op06 (The Dumper) -- Fixed a GUI error on my part (Trigger of Time) -- Cleaned up some of the SPC7110 detection/size code. (MKendora) -- Merged in XBox port changes to SPC7110 code (lantus) -- Added a call to Memory.Deinit when exiting. (lantus, MKendora) -- Many memory leaks fixed while chatting with lantus (lantus, MKendora) -- Fixed that stubborn open/close leak (lantus) - - -1.39mk2 - -- hacked in Shien's Revenge (anomie) -- fixed Orge Battle's green lines. (CPU source for DMA) (anomie) - - Looks interesting, and might apply to other DMA cases? -- maybe "fixed" DKC's barrels? by treating $2001 - as unmapped. The game worked before with a hack. (MKendora) -- optimized SPC7110 slightly by removing extra setup work (MKendora) -- Fixed DBZ 3 (Korean). S. Korea is, in fact, NTSC. (MKendora) -- Fixed a hard-coded value in the SPC7110 (MKendora) -- Added a Win port ROM Info dialog (MKendora) - - some companies aren't in the table I used. - If you encounter an Unimplemented company, - report it the the Snes9x development forum, with - the correct company and the number. - - -1.39mk -- SPC7110 support based on Dark Force's docs. (Dark Force, zsKnight, - The Dumper, MKendora) - Trust me when I say those guys deserve the credit more - than me. From what I'm told, Dark Force is the man - behind most of the reverse engineering, but they all - did a much harder bunch of work than I did following - their specs. It's plain and simple that these three - are the masterminds behind all SPC7110 support. - - Dark Force for reverse engineering the chip (Extremely tough work!) - zsKnight for the original core, and probably other things - The Dumper for dumping the packs and doing hardware tests. - - Also thanks to CaitSith2 for numerous bug reports - and a lot of bug fixes. - -- Theme Park hack removed, fixed via PPU latching (anomie, MKendora, TRAC) -- WWF Wrestlemania hack removed (anomie, TRAC) -- Strike Gunner hack fixed (anomie, MKendora, TRAC) -- FF:MQ text fixed. May help other sprite issues. (TRAC) -- Umi Hara Kawa Se timing corrected. (anomie) -- S-DD1 packs load by the same rules as ZSNES (MKendora) -- SPC7110 code builds in linux (Lord Nightmare, zinx) -- Added The Dumper's DSP-1 updates (The Dumper) -- SPC7110 is correctly displayed on load, RTC also noted. (MKendora) -- Fixed a potential graphics problem (TRAC) - no known games fixed, but who knows? -- Fixed Ballz3D (pagefault) -- Re-fixed Ballz3D, via DSP op 0F (The Dumper) -- included some of anomie's fixes. Many caused me grief, - so only Marko's Magic Football is intentionally fixed. (anomie) -- finished zsnes save support, though I don't know how - well it will work with SPC7110 games (MKendora) -- Added a new soundux.cpp again to fix some noise. - (Fixes the GW "fart track") (Lord Nightmare, info from Anti-Res) -- Added 3 cache modes for SPC7110 games (MKendora) -- Added new BRR decoder. Requires sample caching - and the Anti-Res decoder be disabled. (FatlXception, port by Lord Nightmare) -- Added CaitSith2's RTC debugger. define RTC_DEBUGGER in - project settings to enable it. (CaitSith2) -- SPC7110 per-game cumulative logging (MKendora) -- other fixes that I've forgotten (sanma iwashi, TRAC, anomie, ????) - -- "I'm not worthy" thanks to the original SPC7110 crew (DF, zsKnight, and the Dumper) -- Thanks again to the same people, because they deserve it! -- thanks to The Dumper, Dejap, TRAC, and all the ZSNES crew for technical assistance -- Thanks to most of the Snes9x mods for testing (no thanks to you, Raptor ;) -- and thanks to TRAC and #mkendora for letting me vent at you. - -1.39 -- Added SDD-1 unknown graphics data logging at the dumper's request. A bit late - but might help with Street Fighter 2 Alpha's data dumping. Creates a - romname.dat file in the freeze file folder. -- Implemented 16-bit texture support for OpenGL modes in Windows and Linux. - Had to support a new pixel format type to do it - RGB5551 (one bit of alpha) - which caused me some major problems - black was no longer always pixel value - zero! -- Removed the Bump map OpenGL mode from the Windows port (didn't look so good - anyway and was slow). -- Added a hidden novelty OpenGL mode (clue: a keyboard shortcut activates it) -- Reverted back to FMod version 3.20 after reports that version 3.33 broke - AD3 support. -- Implemented a better work-around for the broken select system call in the - Linux kernel - the original work-around was long-winded and stopped working - when I implemented OpenGL support under Linux. -- Added the same speed-up hack to the OpenGL code that the Glide code already - supported. Basically, if your OpenGL implementation supports 16-bit textures - then OpenGL mode should be as fast, or faster than the 3dfx Glide mode. -- Hopefully fixed Glide support. -- Reverted back to the original colour blending code. The newer code, although - more accurate in most cases, had too many glitches and was slower. -- Included multiple Japanese games fixes from Iswashi San. -- Fixed a timing problem caused by a speed up hack that was affecting Top Gear - 300. No the game still isn't playable yet, but I noticed the problem while - investigating the DSP-4 chip used by the game. -1.38 -- Added support for Star Ocean and Street Fighter 2 Alpha decompressed graphics - packs from dejap. Used a binary chop search rather than a linear search to - locate correct decompressed graphics more quickly - should help emulation - speed during later stages of the game. -- Included OpenGL support into the Linux port and speeded up the Windows OpenGL - implementation slightly. The real speed up would occur if I could figure out - how/if 16-bit textures are supported in OpenGL because at the moment the - 16-bit software rendered SNES image must be converted to 24-bit before being - uploaded as a texture... -- Included the latest ZSNES DSP-1 code. Now Pilotwings, SD Racer and Suzuka 8 - Hours are playable. Aim For The Ace, Super Air Diver 1 & 2 and Syutoko Battle 94 - are also playable, but with bugs. Thanks to zsKnight, _demo_, et al for all - their hard work. -- Another Daffy Duck: Marvin Missions screen flicker problem worked around - - writing to the IRQ enable register shouldn't clear any pending IRQs, but - Sieken 3 seems to require this or else the game hangs. Special-cased Daffy - Duck for now. -- An NMI emulation bug was triggering a Panic Bomberman World game bug, - crashing it. Basically, if a game enables NMIs after the normal trigger - point, the NMI should not trigger if the game has already read the NMI clear - register. -- Panic Bomberman World requires SPC700 memory to be initialised to zero on - reset otherwise the game hangs when a tune finishes and another one should - start. -- Added mouse pointer auto-hide to the Windows port. Much better than the turn - the mouse pointer into a black dot method I was using before. -- Included the latest ZSNES Super FX code. Not sure if it fixes actually fixes - any games. -- Added an offset hack for Strike Gunner to get the scrolling ground layer - to line up correctly - another offset-per-tile bug hacked around for now. -- Arrr! Left in some debugging code in the last release that prevented all - games that need the slower SPC700 timing from working. Removed it. -- Hmm. The broken cut-scenes in Deep Space 9 seem to indicate that I haven't - got the emulated clock speed of the 65c816 CPU correct yet. And not by a - little bit - a 9% too slow error. Hacked special timing for the game for now. -- Added triple-buffering to Windows port - enabling double-buffering actually - enables triple-buffering if you have enough free video RAM, defaulting to - double-buffering if you don't. -- Fixed another crash bug in the interpolated mode 7 code - if no scaling - was being used (either up or down) and screen repeat was enabled and the - screen was flipped horizontally, the routine would crash Snes9x. Was causing - Snes9x to crash during rock monster boss stage of Castlevania 4. -- Oops. Got the initialisation of the default SNES screen width and height - round the wrong way - could cause a X Windows System error message on the - UNIX port after loading a ZSNES freeze file. -- Included the unofficial Windows port emulation fixes for several games including - Kentouou World championship and TKO Super Championship. -- Included Iwashi San's improved Anti Res. sound sample decoding routine and - updated the C version to match. -- Included Anti Res. improved sample decompression code he sent me ages ago, - but for some reason I didn't include. Sorry. This version seems good enough - to leave enabled all the time. -1.37 -- Added fix for Captain America's corrupt graphics - a ROM bug causes it to - read from what I thought should be an unmapped memory area, but it expects - the value returned to be zero. -- Added code to support games that switch to the hi-res. SNES screen mode part - way down the screen while using the 3dfx bi-linear filter mode. The code - basically has to back out of the speed up hack it was using when the game - switches resolutions. -- Fixed support for games that have mixed lo-res. (256x224), medium res. - (512x224) and hi-res. (512x448) all on the same screen - corrects the display - of Majin Tensei 2. -- Added support for games that use sub-screen addition to the back-drop layer - while displaying hi-res. graphics - something I thought the SNES couldn't do - but the game Marvelous uses this. -- Reworked the UNIX/Linux output image handling code: the image doesn't always - have to be scaled when hi-res. support is enabled, the PutImage operation - only updates the area of the screen it has to, the SNES image is now always - centred in the window/full-screen area and if the SNES image changes size - between frames, the old screen areas are now correctly cleared. -- Fixed the corrupt graphics problem during the battle scene of Last Bible 3 - - it requires that previously unknown DMA mode 5 should just act the same as - DMA mode 1. -- Fixed a nasty bug when H-IRQs were being reused on the same scanline - a logic - bug could cause H-DMA processing for that line to be skipped. Was causing - the bridge and the start banners to be the wrong colours in Top Gear 2. -- Added Kreed's display processing modes to the Linux port, including his new - asm version of the Super2xSaI mode and the new software bi-linear filtering - mode. -- Think I might have figured out the odd Mode 7 glitch problems the games - Illusion and Gaia and Chase HQ were having. My original fix was to mod the - centre X & Y values with 1024, but looks like the true fix is to mod - X + horizontal offset and Y + vertical offset with 1024 when screen wrapping - is enabled. -- Disabled H-DMA'ing into V-RAM via registers 2118/2119. The game Hook - deliberately does this causing graphic corruption while dialog boxes are - displayed. Maybe the real SNES disallowed this and it was left in the game by - mistake? Not sure what effect the game was trying to produce because - disabling the emulation of this feature doesn't seem to affect the game at - all, other than stopping the corruption. - + Also fixes graphics junk problem on first screen of Bugs Bunny. -- Added a 'region-free' timing hack for Power Rangers Fight - without it the - NTSC version was displaying badly glitching graphics; I'd already fixed the - PAL version. -- Added true priority-per-pixel mode 7 support (the previous support was just - a hack to get the colours correct) - level 2 of Contra 3 used this feature. -- The Japanese, German, French and Spanish version of Illusion of Gaia needs the - slow SPC700 timing. -- Deleted the Breath of Fire 2 S-RAM hack for the hacker intro version - - according to reports it was causing problems for the non-hacked version. -- Legend, the PAL version, never sets the sound master volume control - Snes9x - was defaulting this to off, I guess the real SNES must default it to full - volume; changed Snes9x. The NTSC version of Legend does set the master - volume level, but sets it to off just after the title screen. Hmm. The -nmv - command-line switch allows you to hear sound in this version. -- Panic Bomber World was tripping an SA-1 emulation bug - the WAI instruction - emulation code was setting the 'waiting for interrupt' flag on the wrong CPU - causing the main SNES to skip an instruction when the next interrupt occurred. -- Panic Bomber World, Bomberman 4 and UFO Kamen Yakisoban all need the slower - SPC700 timing. -- Oops! The Super Formation Soccer 95 fix was causing Aero 2 to lock up. This - means I have no no idea what value the DMA in progress register should - represent. I've hacked it and made it toggle between 0 and $ff on each read - which gets both games working, for now... -- The ROM de-interleaving code always assumed the blocks were rearranged based - on a power of two, but Francois found a copy of Soldiers of Fortune where - this was not the case. Corrected the code. -1.36 -- Finally worked out why the menu items weren't being highlighted in several - ROMs, including Battletoads, U.N. Squadron and All Japan Pro Wrestling. - Two problems: its seems the SNES does halve the colour value result when - blending colours when only the fixed colour addition/subtraction is enabled, - but doesn't halve the result when sub-screen is being blended and its a clear - part of the sub-screen. The second problem was that I had an optimisation - that prevented the time consuming colour blending code from being called if - the colour being added/subtracted was black - adding zero to a number doesn't - affect the result, but not performing the side-effect of halving the result - does affect the final value... -- Super Formation Soccer 95 requires that the DMA enabled register doesn't - always return zero, otherwise the game locks up. -- Thanks to several people reporting a screen flickering problem in the - pseudo 3-d section of Jurassic Park 2 I've fixed a nasty problem in H-IRQ - handling code which could cause double-triggers or skip IRQs altogether. - With this fix I can now remove the special hacks for Ninja Warriors Again, - Chuck Rock and F-1 Grand Prix. -- More games needing the slow SPC700 timing: - Zennihon Puroresu 2, Soulblazer and Robotrek. -- The CPU idle time skipping code was skipping cycles during a software delay - loop in Itchy and Scratchy, causing screen flicker. -- Looks like reading the value of register $2137 shouldn't clear a pending - IRQ - was causing screen flicker on Yoshi's Island. -- Actraiser 1 & 2 both need the slow SPC700 timing. -- Terranigma reads a sound channel's current sample output value and waits for - it to be zero before preceeding. I forgot to always return zero when a - channel was silent. This mistake was causing the game to lock up. - + Itchy and Scratchy and was causing the music to stop and samples to be cut - short in the Mario Early Years series. -- Added a hack for Secret of the Evermore - at several points in the game, just - as the plane is about to land, it reads from unknown registers $4000 and - $4001 and, if it doesn't get the value its looking for, the game hangs or - displays corrupt graphics. -- Silva Saga 2 was accidentally triggering a colour blending hack I put in - place Kirby Dreamland 3 and Kirby Superstar. -- The ZSNES freeze-file loading code could leave a file open if the file wasn't - a valid ZSNES freeze file. -- Super Punch-out requires certain DMA registers to be updated after the DMA - completes. Snes9x used to do that, but I must have accidentally left the code - commented out whilst investigating a different problem in another game. -1.35 -- Added a recently played game list to the Windows port File menu so you can - quickly load up your favourite games. -- Included IPS patching support based on code from Neill Corlett - just rename - the patch file to match your ROM image name but with a .ips extension and - copy it into your ROM or freeze-file folder. -- Added John Weidman's and Darkforce's S-RTC, (Real Time Clock) emulation code. - The only game that seems to use it is Dai Kaijyu Monogatari II. -- Included code from Nose000 for games with 128Kbytes of S-RAM. Now - Sound Novel-Tcool, Thoroughbred Breeder 3, RPG-Tcool 2 and Dezaemon are - supported. -- The Windows port now has an option to make the 'turbo speed' button a toggle - button. -- The optimised fixed colour addition/subtraction code was ignoring the colour - window. Thanks to John Weidman for pointing this out. -- Added mode 7 and hi-res. hack for Dezaemon from Nose000 - the mode 7 hack - looks interesting (to me); I wonder if some other games would benefit? -- Both Tales of Phantasia and Star Ocean need custom sound CPU timing. Hmm. - That's 4 ROMs now, there will be more... That means I still haven't - discovered all the major SNES timing quirks. :-( -- Windows port now has an option to save the S-RAM data at any time. -- Windows port saving SPC dumps now auto-increments the filename. -- Added work-around for a Super Robot Wars Ex ROM bug - the game was checking - the wrong PPU register for end of h-blank. The game must have only worked by - chance rather than by design on a real SNES. -1.34 -- Corrected the colour addition/subtraction and halve the result code not to - halve the result when only the fixed colour is used, i.e. the sub-screen is - clear. Discovered and fixed this awhile ago, but I accidentally reintroduced - the bug when adding some optimisations a few versions back. -- Finally cleared the last of the offset per tile background mode bugs. There - was something odd about the tile at the left-hand edge of the screen that I - couldn't figure out - well now I have. Yoshi's Island level 6 boss screen, - Mario RPG mine cart screen and Jim Power title screen now all display - correctly. -- Made reading blank areas of the SNES memory map return the middle byte of - the address - fixes Home Alone which tries to execute code in an empty part - of its memory map but only works because the real SNES seems to return the - middle byte of the address - $60 in this case, which corresponds to the - ReTurn from Subroutine instruction. -- Added auto-cycle skipping disable for Earth Worm Jim 2 and several other - games that spool sample data using H-DMA as the sample is being played. - Improves some sound effects in these games. -- Fixed joy-pad routines to only report up or left if down or right are also - pressed respectively. Works around a game bug in Empire Strikes Back in the - asteroid stage where the game crashes if both left and right are pressed - - something impossible to do on the original SNES game-pad. -- Added custom SPC700 timing for Rendering Ranger R2 - the game now works with - full sound. No idea why it needs custom SPC700 timing. -- The ROM type detection was broken for Treasure Hunter G and Test Drive 2 - - fixed the code so type 2 ROMs can be LoROM. -- Adjusted the main CPU cycles per scan-line from 341 to 342 to give an exact - match for the timing required for Earth Worm Jim 2. All EWJ2 needs now - for perfect sound emulation is a method of synchronising the emulation - speed to the host hardware's sound card playback rate, oh, and a fast CPU! - The Linux port already has this but seems to be broken because games - play at double-speed when this option is enabled. -- Some SPC700 code in Earth Worm Jim 2 seemed to prove that I had guessed the - clock speed of the SPC700 sound CPU incorrectly - out by almost a factor of - two, in fact. Changed the relative emulated clock speed of SPC700. Now - Chrono Trigger doesn't lock up at certain points anymore, the special SPC700 - timing for games written by the Human Software company isn't required and - you can hear some more of the sound samples in Earth Worm Jim 2, etc. -- H-IRQ triggering code was broken - if a ROM turned on H-IRQ but later turned - it off, Snes9x could continued to generate H-IRQs, crashing some games. -- Added a generic test for Human Entertainment games - they need special - sound CPU timing to work. Gets Taekwon-Do working. -- Disabled offset-per-tile mode for Theme Park; the world map screen is corrupt - with it enabled. -- Yet more changes to the offset-per-tile backgrounds modes 2 and 4. Added - 64 tile wide screen support for Mario RPG's mine cart ride and fixed multiple - bugs with the handling of horizontal offset-per-tile used in Chrono Trigger's - fade in of the space ship. -- New feature: Snes9x can now load ZSNES freeze state files! Just copy them - into the freeze file folder and Snes9x will load them when you load a freeze - file, but only if the corresponding native format Snes9x freeze file doesn't - exist. -- Added memory map hack for Batman - Revenge of the Joker: its ROM header block - is in the wrong location and Snes9x incorrectly detected its ROM type. -- Fixed an off-by-one-pixel clip window 2 bug when the window was set to clip - outside the window area; clip window 1 was already correct. Removed the bright - line bug at the left edge when the combat screen is appearing in Starfox and - the clip problem when text boxes zoom-out in Yoshi's Island. -- Jim Power's title screen seems to prove that the per-tile offset data on - mode 2 isn't ignored for the left most tile as I originally thought. - Modified the code. -- The recent timing changes highlighted another problem with Daffy Duck - - changed IRQ enable register to only clear pending IRQs if one has been pending - for several microseconds. -- Speeded up the sprite data register handling slightly. -- Finally got Aero the AcroBat 2 working, after many hours of investigation, - spread over several years - literally! Two problems. The SNES doesn't seem - to consider scan-line line zero to be part of the v-blank period even though - the line is never drawn and V-IRQs at the start of the scan-line have to be - delayed until a few microseconds into the line - Traverse: Starlight & Prairie - required this as well, so I removed the original, Traverse specific hack. - There's a problem with the in-game music that I'll investigate at a later - date. - - The in-game music problem just required ENVX emulation to be switched on, - off by default on the Linux port, on by default on the Windows port. -- Fixed the mode 7 corruption problem on the title screen of Chase HQ using the - same trick as Illusion of Gaia - i.e. mod the mode 7 centre X & Y values with - 1024. -- Fixed another crash bug in the interpolated mode 7 code - a portion of - the code was ignoring the screen flip value and the fact that X render - direction reversed if the screen was flipped horizontally. Was causing a - crash on the whale boss screen of Kirby Superstar. -- Mortal Kombat 3 now auto-adjusts emulated cycles per scan-line work-around - a speech sample being cut short. -- Added sample data register reading support to the sound DSP - somehow I - seem to have missed implementing this. Not sure if any ROM actually reads - the value. -- Followed Sumire Kinoshita's suggestion and stopped clearing the ENDX flags - when the value is read, against my better judgement, and it does actually - improve speech samples in several games. Ooops! The Mortal Kombat series, - Magical Drop 2 and Metal Combat are the ones I've discovered so far. -- WWF Arcade now auto-adjusts the cycles per scan-line value to work-around - a sound sample repeat problem. -- Hmm. There's something about offset-per-tile mode I don't understand - WWF - Wrestlemania Arcade is getting corrupt graphics; not sure what effect the - ROM is trying to produce. Disabled offset-per-tile mode for the game for now. -- Fixed Street Racer player 1 wobble problem during the soccer game by auto- - adjusting the cycles per scan-line value slightly. -- Made Power Rangers Fight auto-adjust emulated cycles per scan-line to work - around a slight timing problem that causes an NMI to corrupt register - values that an IRQ handler is trying to update. Without it the scrolling - back-drop and fighter graphics are corrupt. -- Illusion of Gaia seems to need the mode 7 centre X & Y values to be mod 1024 - if the screen repeat flag is set. Fixes the island fly-over bug right at - the end of the intro but breaks a few other games. Hmm. Made it auto-switch - on for this game only. -- Added memory map support for Radical Dreamers. Thanks to satellite hut master - for the information. -- Made updates to the top bit of the sprite write address register be ignored - unless the low byte had been written to first. A ROM coding bug in - James Pond II requires this, otherwise it writes a junk byte value into the - main character's X position and Robocod wobbles around all over the place. -- Reverted back to pre 1.31 way of initialising unknown register values - - Rock and Roll Racing was reading a junk register value and using the value - to set up DMA, which in turn was causing corruption on the player select - screen. -- Added Star Ocean memory map - thanks zsKnight! The original ROM I was testing - was corrupt, no wonder I couldn't figure out the memory map myself! The game - still isn't playable, though, due to missing S-DD1 graphics decompression - (+ encryption?) emulation. -- Started to dump some compressed data values from Street Fighter 2 Alpha in - the hope that one day someone will be able to crack the S-DD1's compression - algorithm. -1.33a -- C4 emulation wasn't being automatically enabled for Rockman X2 / X3 - the - Japanese versions of Megaman X2 / X3. -- Fixed the Super FX plot table pointer that I accidentally broke while saving - 1Mb of workspace RAM - it was stopping all Super FX games from working. -1.33 -- Noticed another problem with the CPU_SHUTDOWN code - Chrono Trigger locked - up during the intro but only when using the asm code CPU core. Found the - algorithm difference between the code and made the CPU match what the C - version was doing. Still not sure why it caused a problem in the first place. -- Changed colour subtraction code to use Lindsey Dubb's newer version he sent - me some time ago but I 'forgot' to include. I say forgot, but I really put - off including it because, although it improves most games that use the - effect, it does result in one or two slight visual glitches. -- Hacked in zsKnight's C4 emulation asm code - now both Megaman X2 and X3 are - playable. Still got to complete the reverse engineering of the i386 asm code - to C so other, non-Intel ports can have C4 emulation. -- Shuffled the keyboard mapping a bit on the Linux port so now Tab key acts as - an emulation speed turbo button, `, # and ~ act as superscope turbo and - / acts as the superscope pause button. -- Fixed asm CPU_SHUTDOWN code that I accidentally broke while trying to - optimise it! Thanks to all the people who noticed Snes9x's frame skipping - had changed between releases. Frames rates should be improved again for more - than 50% of games. -- Re-enabled in-lining of the C SNES memory access routines, improves frame - rate by one or two on slower machines. -- Optimised the asm 65c816 addressing mode emulation code a little. -- Included some code changes making life easier for the Mac porter, John Stiles. -- Added memory map support for Sufami Turbo using information supplied by - Nose0000. No idea if it works because I don't have the ROM. -- Spent a few minutes trying to figure out the Star Ocean memory map so at - least the sound effects could be heard. But gave up after a couple of hours - due to laziness. If anyone knows the memory map details, let me know please! -1.32a -- The delay loading of the OpenGL DLLs on the Windows port was causing the - OpenGL initialisation code to fail. Reverted back to normal DDL loading but - with the side effect that Windows 95 users must visit the Microsoft web site - and download the OpenGL add-on before Snes9x will work for them. -- Corrected the OpenGL bump-map display option - my attempt to get the - bi-linear OpenGL display option to work with Voodoo card's limited texture - size had broken the bump-map mode. -1.32 -- Changed the Windows port to delay load the two OpenGL DLLs, so now they're - only loaded if you switch to OpenGL mode. The original version of Windows 95 - didn't include the OpenGL DDLs, so Snes9x wouldn't even start on that - platform; now it should. -- Added yet another sound buffer option to the Windows port - this time the - block size of sound data to mix. Some DirectSound sound card drivers only - report the play position moving in steps rather than continuous amounts and - Snes9x's default mix block size turned out to be smaller than this step - value on several cards. - Snes9x couldn't work out out where the true play position was accurately - enough resulting in broken, noisy sound output. -- Modified the Windows frame timer code to use semaphores rather than events - - they should make Snes9x more reliable at not missing frame sync pulses when - Windows is busy doing background tasks. -- Added SA-1 shutdown code - basically, Snes9x now stops emulating SA-1 CPU - instructions when the SA-1 enters an idle loop waiting for the main SNES - CPU to give it something to do. All SA-1 run much faster and smoother now. -- Added multi-axis joystick/game controller support to the Windows port and - tweaked the dead-zone threshold position a little. -- It looks like the SNES PPU was designed to support 128K of V-RAM but only - 64K was fitted; Snes9x wasn't wrapping all V-RAM address to stay within the - 64K limit causing a corrupt title screen on ReX Ronan - there will be others. -- Added amend functionality to the Windows Cheat Entry dialog and added extra - text boxes for direct address and cheat value input rather than only being - able to type in a Game Genie or Pro-Action Reply code. -- BS Suttehakkun2 was crashing just before start of play - the ROM was - performing a junk DMA that was corrupting RAM, crashing the game when it - went searching for a particular value. -- F-1 Grand Prix requires IRQ triggering when IRQ scan-line register set to - current scan line, but Chuck Rock objects. Hmm. Chuck Rock seems to indicate - the CPU emulation is running too fast, but I can't see where the mistake is. - Special-cased Chuck Rock for now. -- Optimised SNES DMA handling slightly - copying data to SNES V-RAM is now - significantly faster. -- Windows Cheat search dialog was ignoring data type parameter in various - places which was causing problems when larger numbers were being searched - for. -- Forced unknown PPU register reads to always return 0 - a coding bug in - Equinox shows that this is required. An earlier fix didn't work. -- Puya Puya 2 & remix were objecting to an NMI being triggered when enabling - NMIs after scan-line 226, but Ys 5 seems to require this. Hmm. Added a hack - to support both games. -1.31 -- Snes9x DirectSound code modified - the mixing block size is now always 10ms - for Windows 95/98/2000 and 20ms for NT 4.x, now there should be no need to - enable Sync Sound when a large sound buffer is required (helps emulation - speed). The maximum sound buffer length values have been updated to reflect - the smaller mixing block size. -- Changed the DirectSound code back to use an offset from the play position - as the place to write new sample data into the sound buffer - on NT 4.x the - write position seems to vary randomly rather than being a fixed distance - in front of the play position as documented. Now I know why I used the play - position originally! -- Changed the DirectSound code to fill the sound buffer at the write position - supplied by DirectSound, rather than just before the current play position - - should help reduce latency. -- Added an auto-detect method for interleaved mode 2 Super FX ROM images - - well, not really auto-detect: if the game crashes and its a Super FX game, - Snes9x assumes its in interleaved mode 2, de-mangles the ROM image and tries - to run the game again. -- Had to update the Snes9x Windows registry version number as the additional - diagonal settings make old registry settings incompatible. -- Added diagonal keyboard controls to the Windows port, as requested by - several users. -- Changed PPU code to return zero when reading non-existent registers - the - game Equinox relies on this due to an original game coding bug. -- Included FMOD sound driver support to Windows port - people experiencing - broken sound or delayed sound, etc, might want to give it a try. -- Tales of Phantasia - un-interleaved format ROM memory map changes to match - odd ZSNES format, now the hacked ROM works. -- Changed NMI again. Made reading or writing to PPU register 0x4210 - clear NMI pending flag again, without this Super Tennis does not work. -- Changed NMI timing back to be the same as several versions ago and just - special cased Cacoma Knight instead - although kept the code to prevent - the re-triggering of an NNI more than once in the same frame. -1.30 -- Forgot to force GUI surface to be displayed when some dialogs where popped - up - problem only happened on full-screen mode with triple or double - buffering enabled, or when using 3dfx mode. It appeared as if Snes9x had - locked up, but pressing Esc would pop down the hidden dialog. -- Added a couple of options to the Settings dialog. Now its possible to - disable S-RAM auto-save which was causing Snes9x to write to the hard disk - every 30 seconds on some games, causing the occasional skipped frame. -- Fixed Reset option which was accidentally broken when Netplay support was - added. -- Added support for Dirt Racer - it leaves the Super FX chip running all the - time, so the default CPU emulation method never allocated any time to other - CPUs and the emulation seemed to lock up. -- NMI timing changed again. Now an NMI can only be triggered once per - frame and enabling an NMI after the normal trigger scan line triggers - an NMI immediately. This fixes display glitches in Ys 5, Stargate and - Daffy Duck. -- Fixed the WAI instruction to only 'wake up' once an actual NMI has - triggered, rather than just waking up when it should have triggered. - This fixes Battletoads, broken since version 1.29(ish). -- Changed NMI again. Made reading or writing to PPU register 0x4210 not - clear NMI pending flag. Seems to allow all the NMI timing sensitive ROMs - I had on my list to now work without any special hacks. Illusion of - Gaia now works again. -- Another NMI fix - cleared the CPU pending NMI flag at start of frame; - Battletoads intro was crashing without this. A long DMA was stopping the - SNES CPU so it couldn't and shouldn't respond to the NMI signal from the PPU. -- Fixed Netplay problem when game didn't have any S-RAM and Sync Using Reset - was being used. An error dialog was displayed and the client would disconnect - from the server. -1.30b#1 -- The Windows auto-frame skip code was broken - badly. It didn't re-sync a - timer value with timer events being generated, causing Snes9x to deliberately - stop and wait for an event when it didn't need to, slowing down the overall - emulation speed and increasing the number of frames skipped. -- Improved the Windows cheat search dialog - its now possible to compare - against a value and more comparison functions are available. -- Finally worked out why Voodoo 3 support was so buggy in Snes9x - the Voodoo 3 - card generates a WM_DISPLAYCHANGE message when switching to Voodoo mode (the - Voodoo 1 and 2 cards don't); Snes9x thought that some other application had - changed the screen depth or resolution and tried to adjust its window to - match - triggering another WM_DISPLAYCHANGE message. No idea how the code - worked at all; it must have been only by chance and very dependant on the - driver version you were using! -- Implemented Netplay on the Windows port - but its buggy as hell. I seem to - be having major Windows multi-threading problems. Comments I've seen seem to - suggest that Windows 95/98 don't implement true multi-threading; hmm... -- Not happy with the current Netplay, so I scrapped it and tried again; - the protocol is much improved and not using select to control game timing - seems to have removed lots of the threading-type problems I was having. -- Attempted to switch to just using Borland's C++ Builder to build the Windows - port - and failed, again. Although C++ Builder can build Snes9x from sources, - it can't then link in the asm CPU cores. I had hoped Borland might have - fixed this with their latest release - they haven't. -- Several attempts to get Anti Resonance's super-fast sound CPU and sound DSP - code working in Snes9x, but all failed. Part of the problem was his code was - written using TASM and the object files it generated would only work under - Windows - but all my SNES debugging code was in the Linux port. Anti' fixed - that, and I then had some success getting his code working, but its just too - unstable at the moment for a main-stream release. -- Included an option to use Anti Resonance's alternate sample decoding routine; - it can approximate the wind and noise sound effects heard in several Square - Soft games. -- Thanks to Lindsey Dubb for the mode 7 bi-linear filtering code - it - generates a nice smooth image when a game scales the screen using the SNES' - mode 7, but you'll a fast machine if you don't want the frame rate to drop. -- Thanks again to Lindsey Dubb, he improved the colour addition/subtraction - subtraction routines - they are just a little slower but now mostly perform - full 15-bit precision addition and subtraction rather than the previous - 13-bits of precision. Many more colour shades can be seen - look at the - improved shading on the Mario Kart or F-Zero track for example. -- Added a reverse stereo option, for people with sound cards that swap the two - channels. -- Added a sound config dialog to the Windows port - now you can access extra - sound options that have always been there, but just no GUI interface to - access them. -- Fixed the 32-bit windowed support on the Windows port. -- Adjusted the NMI timing by a few microseconds to get Metal Warriors working - again. -- Added a few more sound playback rate choices. Most modern sound cards allow - any value to be used from a large range, rather than just a select few, may - be I ought to add text field so you could just type a value in? -- Used Factory Setup 4 to build a new installer package for the Windows port - - just shipping a zip file was confusing novice users and many (mostly AOL - users) seemed to have an odd program mapped to .zip files, further confusing - the issue. -1.29 -- Disabled the SPC700 noise feature simulation used by Chrono Trigger and - Final Fantasy 3 until I work out why its being triggered by sound effects - that don't use it. -- Rewrote/reorganised the DirectX and 3D/fx handling code, now both are never - enabled at the same time in Snes9X. It might fix the crashing problems some - Window port users are seeing. Changing between DirectX and Voodoo 3D/fx - modes now requires Snes9X to be restarted. -- Tracked down and fixed the Chrono Trigger black screen problem on the Windows - port: a rogue asm instruction was left in by mistake after some code edits - - it was only by chance that the code worked on the Linux port. -- Added some SNES debug options to the Windows port, but disabled by default, - on the shipped version. -- Clicking on the column headings in the OpenROM dialog in the Windows port - now sorts by that column; plus added some slight screen update optimisations. -- Added an optimisation to graphics rendering: don't add or subtract - sub-screen from background layers, or clear the sub-screen, if SNES fixed - colour is black and no background layers are enabled on sub-screen, even if - ROM tries to enable translucency effects for every background layer. - Discovered Sonic was doing this, there will be others. -- Forgot to enable auto S-RAM save on Windows port, oops! -1.28 -- Warning dialog added to the Windows port - if a ROM is loaded from a - read-only directory, e.g. a CD, and the freeze file folder is set to be the - same as the ROM image folder, then a warning is displayed when the game first - starts. -- The Windows port now supports 5 joy-pads - Snes9x always did support 5 but - the Windows port lacked the GUI option to enable and configure it. -- Added an about dialog to the Windows port. -- The Windows port now has a simple settings dialog, only one option so far - - changing the freeze file and S-RAM save directory; much better than having to - use regedit at least. -- Added a new cheat search dialog, you can use it to find where games are - storing life counters, health levels, etc. and then add cheats that stop the - values from changing. -- Added a cheat code entry dialog to the Windows port; now Game Genie, - Pro-Action Replay and Gold Finger codes can be graphically entered and - edited. -- Added a master cheat codes on/off toggle, available from the Cheats menu - on the Windows port. -- Extended the number of cheats per game from 10 to 75. -- Changed cheat code to reapply cheat every emulated frame so if RAM is being - patched the cheat value is continuously applied. -- Wrote some new cheat search code, the code won't be useful until I get around - to writing a cheat search dialog. -- Added automatic cheat code loading and saving using the same file format as - ZSNES. -- Rewrote large parts of the Snes9x cheat handling code ready for adding - cheat dialogs to the Windows port. -1.27 -- Added a flag to only enable SPC700 noise 'feature' when Chrono Trigger or - Final Fantasy 3 are loaded - the conditions that I thought were necessary to - trigger the feature where sometimes being met by other games. -- Added a simulation of the SPC700 noise 'feature' where some games, notably - Chrono Trigger and Final Fantasy 3, play samples that deliberately overrun - outside a 16-bit value, the SPC700 sound DSP then for some reason starts to - generate a type of noise sound which the games use to generate wind and - swish type sound effects. Thanks to ZSNES for some of the information. -- Fixed another sound interpolation problem, thanks to Mikael Bouillot - - the initial value of the sample byte being played was not being set correctly - when processing fractional offsets. -- Added auto S-RAM save option; S-RAM is automatically written to a .srm file - a few seconds (30 by default) after a ROM writes to it - useful for people - who were playing games long into to night, only to lose their progress - after a power cut or machine crash. -- NMI delay code changed again - the fix for Cacoma Knight was breaking - Tuff E Nuff; it would seem delaying NMI until the start of h-blank to too - long, added a cycle counter instead. -- Fixed yet another clip window bug - clip window was being incorrectly set - at no range if colour window was enabled but background layer clip window - was disabled (meaning layer should not be clipped). - Fixes the sunken ship level on FF5. -- Worked out (by example) how to add keyboard accelerators to the Windows port, - now toggling full screen using ALT+Return works. -- Added mouse-warp to the Windows port so the the cursor doesn't wonder off the - Window while SNES mouse emulation is enabled. -- Improved 3dfx support on Windows port - load dialog doesn't drop out of - bi-linear mode and underlying window zooms to full-screen so its easy to find - and click on the menu bar with the mouse. -- Added Mouse and Superscope SNES emulation support to the Windows port, use - '7' on the keyboard to select. -- Windows cursor now hidden unless super scope emulation is enabled. -- Windows port now has command line parsing - cheapo way of adding Game Genie, - Pro Action Replay cheat codes, disabling sound CPU emulation for the - corrupt copy of Star Fox 2, etc. Also allows ROM images to be dropped onto - the Snes9x icon. -- Cacoma Knight seems to provide proof that Snes9x triggers the SNES - non-maskable interrupt (NMI) too early. Changed interrupt to trigger at the - start of the next horizontal blank period. Will have to watch for it - causing problems for other ROMs. -- Added a translucency hack - when a ROM tries to create a stipple background - pattern by enabling pseudo hi-res. and not enabling a background layer on - one of the screens, Snes9x changes the effect to use transparency effects - instead (the real SNES can't do transparency effects with pseudo hi-res. - enabled). Now the water in Kirby 3 is translucent. -- SA-1 CPU reset bug fixed, now Jumpin' Derby boots and plays but with major - graphics problems. -- Fixed nasty asm SA-1 custom hardware read/write bug that was causing the - course map not to be displayed on Augusta Masters and Pebble Beach. -- Added SA-1 character conversion DMA support for all SNES depths, now - Augusta Masters and Pebble Beach work. -- Merged in minor code changes for Linux running on the Alpha processor. Thanks - to Sadruddin Rejeb for the changes. -- Added four more auto-multi-player-adaptor-emulation-off presets based on - code from Mystagogus. -- Added DirectX3D output image processing support to the Windows port... and - removed it again because it causes my desktop machine to lock up. Back to - the drawing board... -1.26 -- Fixed memory leak that crept in when SA-1 support was added when loading a - game freeze file. -- Added SPC dumping option based on code from Cyber Warrior X that he sent me - ages ago but I've just found again while looking for something else! -- Merged in most of the Amiga PPC port source code changes into the main - source code tree. -- Keying on a sound channel seems to clear its last-sound-sample-block-just- - played flag. Chaos Engine/Soldiers of Fortune needs this. -- Add multi-thread support to the UNIX ports for sound playing - required in - the Linux port to work around a Sound Blaster Live driver bug and useful if - you have multiple CPUs in your machine to help spread the emulation workload. -1.25 -- Added BS 24Mbit ROM memory map, for Derby Stallion 96 and Sound Novel-TCool. - No idea if it works. Thanks to Nose0000 for the info and code. -- Corrected unzip code not to loop forever if an encrypted zip file is loaded - - an error is generated instead. -- Changed relative SPC700 cycle length for Mortal Kombat 3 to fix sample - repeat problems - I wish I knew exactly how fast the SPC700 is clocked. - Maybe I should write a test ROM and run it on a real SNES? -1.24 -- 3dfx speed hack back again, only disabled when Seiken 3 is loaded. -- Some minor SA-1 speed ups added - the SA-1 instruction skipping code will - have to wait until I have more time. -1.23 -- Corrected a SA-1 reset bug that reset the SA-1 RAM bank pointer back to block - zero but didn't clear the RAM bank register. Was causing Kirby 3 to crash. -- Fixed a wave clipping problem with interpolated sound that was causing noise - on sound output when certain sound samples were played. -- Fixed a bug in the sync-sound code that could overrun the sound buffer by a - few bytes causing clicks on the sound output. -- The sound sample repeat bug that has plagued Snes9x ever since is was called - Snes96 finally bit the dust - Snes9x continued to play sample loops - even if the game dynamically updated the sample not to loop. Fixes the - stutter in the Mortal Kombat series and improves the sound from several games - that download sound samples in real-time as they are played. -- Rewrote the code the handled the SPC700's 64 byte shadow RAM area to fix a - possible sample corruption problem with ROMs that stored samples that - cross the 64 byte start area. -- Added code to allow ROMs to change the sample being played the next time the - channel loops or is keyed on - not sure if it fixes anything but seems more - correct. -- Added a zero-frequency fix to the stereo sound mixing code that I'd already - added to the mono code some time ago. -- Changed the code to set the end-of-sample flag just before the last block is - played, rather than just after. Seems to help improve the sound on some - games. -- Sound sample start code now doesn't reset the channel's envelope volume level - to zero before starting the sample - helps reduce the clicks being heard when - a channel envelope volume level hadn't reached zero before being keyed on - again. -- Changed initialisation of sample-end-register to 0 rather than 255 - seems - more logical now I've thought about it. Not sure if it helps anything. -1.22 -- Finally fixed the corrupt copy of Donkey Kong Country not working problem - - Snes9x thought the ROM used the same memory map as Street Fighter Alpha 2. -- Added explode, un-shrink and un-reduce decompression modes support to the - unzip code. -- Fixed offset per tile bug that crept in after me trying to fix the Starfox - on-tilt bug. -- Made some fixes to the C Super FX emulation code, enough to get most 'FX - games playable on the Mac port. -1.21 -- Finally worked out how character DMA worked on the SA-1 and implemented a - hacky, slow version, but its enough to get the level up screens displaying - correctly on Mario RPG. -- Incorporated ZSNES' new optimised Super FX asm code - had to track down and - fix a nasty memory overwrite bug in the code first to get it to work. -- Changed sample mixing code to not automatically wrap offsets to - keep inside the sound buffer, external port code is now expected to do that. - Helped me fix a problem in the Windows port that prevented very large sound - buffers from working, which are required for some badly written sound card - drivers. -- Corrected a bug in the SA-1 C code where incorrect processor emulation - functions where called if the code was compiled with in-lining turned off. -- Fixed crash bug in Super Mario RPG on the level up screen - forgot to mask - the enable bit from the RAM bank register. Thanks to Christian Wolf for - sending me a freeze file which made it easy to find the problem. -- Fixed a lockup bug in the window clipping code, if the ROM ever turned off - the sub-screen completely the clipping code would enter an infinite loop. - Fixes The Cartoon Addams. -- Made the Daffy Duck NMI fix only enable when Daffy Duck is loaded - fix was - causing problems for Breath Of Fire 1 and 2. -1.20 -- Windows port no longer sets DirectSound to exclusive mode, so its now - possible to hear sound output from Windows apps while Snes9x has focus. -- Fixed the freeze file loading and saving on the Windows port. -- More GUI settings are saved in the registry on the Windows port now. -- Added 3D/FX image scaling/filtering support to the Windows port. -- Added the TV mode from the Mac/Linux ports to the Windows port. -- Incorporated Kreed's new output image routines into the Windows port that - fixes RGB555 display colour problems. Many thanks to Kreed. -- New auto-frame rate timing code on the Windows port, stops the silly speed - up problems when the old code tried to 'catch up' after the emulator had - been paused. -- Increased the DirectSound secondary buffer length on the Windows port to - hopefully fix all the static/broken sound output problems some people were - experiencing. -- Altered the ZSNES Super FX asm code so the Windows port could use it - all - previous versions of the Windows port were shipped using the C Super FX - emulation code which is a lot slower. -- Implemented interpolated and sync-sound options on the Windows port. -- Added an image stretch option to the Windows port - stretches the SNES image - to fill the whole screen or the Window. Looks really good on my TNT card - since that chips seems to filter the image as it scales it. -- Implemented Windowed mode on the Windows port. -- Added special SPC700 cycle timing for Empire Strikes Back. -- Fixed the missing polygon problem for Super FX games - thanks to zsknight - for the information. -- Implemented SA-1 support required for Mario RPG, Kirby Superstar, - Paradius 3, etc. but since only a good image of Mario RPG exists, I could - only test that game. -- Fixed a graphics clip window bug: inverting the area of a clip area that - only consisted of empty bands should become the full width of the screen; - Mario Kart's rear-view mirror display needs it. -- Fixed mode 7 render code to use correct z-buffer when rendering onto the - sub-screen. Fixes Final Fantasy V title screen. -- Added horizontal offset per tile support in the offset per tile modes 2 - and 6, and switchable horizontal/vertical offset in mode 4. Fixes Chrono - Trigger in several places and Mario All Stars title screens. -- Changed SPC700 relative cycle length to 14, needed for Stunt Car Racer. -- Enabled immediate triggering of NMI if NMI enable flag set while scan-line - was on first line of v-blank. Needed to fix a background jitter bug in - Daffy Duck: The Marvin Missions. -- Altered ROM load code to ignore corrupt ROM map type byte in ROM header, - preventing the code erroneously detecting what it thinks are interleaved - ROMs. Fixes EEK! The cat, Formation Soccer, the corrupt copy of Donkey - Kong Country, ... -- Disabled IRQ re-triggering if V-IRQ registers set to the current line. Fixes - Chuck Rock. -- Fixed missing sprites in Andre Agassi Tennis - writing to low byte only of - the sprite write address register seems to also clear the hi-byte. -1.19 -- Games written by the Japanese software company Human seem to need special - SPC700 sound CPU timing, so the ROM load and reset routines now check the - software author company and adjust the CPU cycle length accordingly. - It gets Clock Tower, Super Fire Pro-wrestling Premium, etc working. -- Added ROM check sum calculation and testing code - Snes9x can now detect - pure, corrupt or hacked ROMs. -- Noticed a fast way to implement the SNES 4096 colour mode, so I implemented - it. Now the colours in ActRaiser 2 look correct. -- Corrected a noise frequency error thanks to information from Takehiro. -- Added a 'start in full screen mode' flag to the Linux port. -- While debugging the new graphics code I thought of a fast way to implement - the SNES direct colour mode, tried it out and now the colours in Actraiser 2 - are correct. -- Blast, forgot about the colour window and fixed colour effects. The separate - sub-screen is back again, but all the other graphics speed ups are there. -- Now I've got a z-buffer I keep finding other ways to optimise the SNES - graphics rendering - no need for a separate sub-screen, no need to clear - the sub-screen to the fixed colour, no need to waste CPU time on translucency - effects on hidden pixels, no need to completely clear the main-screen to the - back drop colour, etc., etc. -- Implemented a software z-buffer and changed the SNES graphics rendering to - use it (required change for future 3D card support). Finally fixes the - sprite-to-sprite priority bug that some games suffer from. Also a big speed - increasing for some games (10 fps+), others are slight losers. -- Added code to skip the rendering of completely transparent graphic tiles - rather than comparing each pixel to see if it is transparent; helps the - frame rate a bit on some games. -- Added a fixed for Tetris & Dr. Mario - the game didn't like a multi-player 5 - adaptor plugged in to the real SNES when being played, so turned off the - adaptor emulation for this game. -- Added hack for Final Fantasy II - if sync sound isn't on, make attack rate of - 1ms actually 0ms (old v1.16 behaviour). Causes a slight click but its better - than samples being cut short. -- Fixed a clip window area invert bug if the colour window was enabled on - on one window and the other window was being used to clip a background layer. - Fixes the finial (I hope) display problem with Gun Hazard. -- Added code to intersect the clip window areas if both a colour window and - a background layer clip window were enabled at the same time. Required by - Gun Hazard. -- Forgot to mark graphic clip windows as needing recomputing when the master - colour window inside/outside/on/off/main-screen/sub-screen PPU register was - updated. Was causing display problems for Gun Hazard. -- Internal H-DMA execution accelerator pointer variables where not always - being recomputed when started H-DMA part way into a frame. Was causing - display problems for Gun Hazard. -- Made H-DMA continue for one extra scan-line to fix a disappearing monster - problem in Dragon Quest 5. Thanks to Alex Jackson for the bug report. -- Zoop seems to require volume envelope height reading by the sound CPU to - always return 0 when the channel is in gain mode. -- The sound code was ignoring updates to the ADSR volume envelope rates while - one was in progress. Fixed that and now the bird song at the start of - Chrono Trigger sounds correct. -- Had to disable the CPU shutdown code for loops reading the horizontal beam - position, it was causing problems for Star Fox. Still no polygons though. -- Oops, sound DSP noise output was broken - accidentally deleted an important - line while removing debug code ready for the last release. -- Added initial 3Dfx support to the Linux port - basically using the Voodoo - card as a bi-linear filtering, scaling blitter. Actually slightly slower than - TV mode, for non-scrolling images due to poor texture upload speeds to the - card, but the full-screen feature is nice and the speed doesn't drop as more - of the screen changes. -1.18 -- Implemented a sync-sound mode where sound data gets generated in sync with - SPC700 instructions being executed. Finally the sound Williams Arcade - classics can be heard. Also helps slight sound timing problems in many other - games but doesn't fix Mortal Kombat 2 like I thought it would - its - sound routine programmers must have been on drugs or something! -- Added interpolated sound - gives low frequency sounds much more bass similar - to a real SNES especially with the playback rate ramped up to 44KHz. -- Added on-screen messages as various emulation options are toggled on and off - using the in-game keys. -- Fixed a PPU register read bug with the sprite register write position. Thanks - to Takehiro TOMINAGA for the bug report. -- Altered the auto-frame skip timing code to only wait and re-sync to the end - of frame when frames haven't been skipped. Again thanks to Takehiro. -- Speeded up the colour addition and subtraction code using ideas from - Takehiro. -1.17 -- Linux and UNIX sound code now driven directly from signal timer handler - rather than the timer handler just setting a flag which had to be polled in - the main emulation code. Slightly faster execution. -- Fixed the crash bug in the ZSNES Super FX asm code with Vortex - the game's - polygons still aren't visible though. -- Implemented bent-line increase and exponential decay and sustain volume - envelopes - they should match, or at least be very similar to the real SNES - sound DSP chip now. -- It would seem ROMs can key on sound channels even if the channel hasn't - been keyed-off, Pac-In-Time requires it. Changed code to allow it. -- Quick mod to ZSNES Super FX code to get Winter Gold working - it was already - working with the C Super FX code. -- Added emulation of the extra 1/2 scan-line per frame on PAL and NTSC - - should help improve music speed emulation. -- Worked around the click sound heard when ROMs use 0 volume envelope attack - rate. -- Removed the 'check for IRQ already happened' H-IRQ position register setting - code - it was causing problems for Ninja Warriors and was not required by - F1 Grand Prix. -- Fixed a bug in the new sound code - the sustain part of the - attack-decay-sustain-release volume envelope was being skipped if the - sustain level wasn't at 100%. The fix has helped some music notes from - being cut off early in a few games. -- Added fix to Pro Action Reply support (again). Thanks to Paul Shoener III for - the original fix and Gil Pedersen for reminding me to apply it! -- Finally fixed the Tales of Phantasia 'bum note' problem! The ROM set its - sample directory to the upper-most page and I forget to code for the hidden - 64 bytes of RAM, that appear when the boot ROM is switched off, when fetching - sample addresses. -- Adjusted the relative cycle length between the 65c816 and the SPC700 slightly - to get Terranigma working again. -- Oops, the emulated joypads 3 and 4 via the emulated Multi-player 5 interface - weren't working. Thanks to Steffen Schwenke for the bug report. -- Optimised the echo sound code - by-passed the the FIR filter code if only - a pass-through FIR filter was defined by the ROM. -- Modified V and H-IRQ register changing code to trigger an IRQ immediately if - V-IRQ is enabled and the scan-lines match and either H-IRQ is not enabled or - the electron beam position has already gone past the trigger point. Fixes - the screen flicker in F1 Grand Prix. -- Modified the priority-per-pixel mode 7 code to use BG#1's clipping data if - the top bit of the mode 7 pixel is set. Fixes initial track drive-through - display in F1 Grand Prix. -- Modified the sprite priority levels for the priority-per-pixel mode 7 - display. Now the car can be seen in F1 Grand Prix. -- Wrote a sound DSP register recording scheme which 'plays back' the register - changes in sync with the sound generation code. I'm bit disappointed, it - only improves the sound in a very few games... Scrapped the code, it actually - causes more problems than it fixes. Oh, well, another 3 weeks work wasted... -- Fixed a SPC700 wake up problem for Lufia I - made the SPC700 also wake up - when the 65c816 read from one of the four comm ports. -- Included lots of sound code speed ups and sound quality improvements - from Takehiro TOMINAGA - many thanks go to him. -1.16 -- Fixed a case where the -forcelorom option didn't work - the case was - required for Formation Soccer which claims in its ROM header to use the - same memory map as Super FX ROM, it doesn't. -- Pulled apart a real SNES using a crowbar (great fun), just to look at what - speed the SPC700 is actually clocked at for more accurate relative emulation - speed. -- Implemented SPC700 cycle counting in the hope the improved timing would fix - Tales'; no such luck but at least the -ratio option is obsolete now. -- Implemented executing SPC700 instructions during DMA, fixes BSZelda and - Goal lock up at start and music pausing briefly when ROMs do lots of DMA, - usually between game screens. -- Scrapped the i386 asm SPC700 code - it was the cause of the music not - restarting after a battle in Chrono Trigger and FF3 and I didn't realise - because the bug had already occurred in the test freeze-file I had. - Thanks to John Stiles for pointing out that the Mac port didn't have the - missing music problem. -- Fixed RGB subtraction bug on displays with only 5 bits for green, e.g. RGB555 - displays. The GREEN_HI_BIT variable was always set to a value for 6 bit - green displays. -- Added the SA-1 memory map, still a long way to go before any SA-1 game will - run. -1.15 -- Jumped versions to keep in sync with the DOS port release. -1.14 -- Improved 8-bit sound generation slightly, but it still sounds very poor - compared to 16-bit sound. -1.13 -- Implemented the Tales of Phantasia memory map using the information supplied - by zsKnight. Had to also implement a de-interleave routine to work around - a ROM feature and Snes9x CPU instruction fetching implementation detail. -- Added a frames-per-second on-screen display option. -- Fixed the final glitch bug with the Mario Kart track display - the byte code - for the termination of the DSP1 raster command wasn't been recognised. -- Disabled a NMI/DMA hack for Rise of the Robots, was causing problems for - Mario Kart and 'Robots wasn't working correctly anyway. -- Optimised the mode 7 rendering a little. -- Changed tile rendering code to use offsets into screen buffer rather than - direct pointers ready for z-buffer implementation. -1.12 -- Changed V-blank NMI to occur immediately after a WAI instruction, Toy Story - required this. -- Fixed reading of H-DMA line counter register, Top Gear 3000 needed this. -- Ripped off large parts of ZSNES's DSP1 code (with _Demo_'s and zsKnight's - approval). Now Mario Kart works almost 100%. -- Added a check to see if a vertical scan-line IRQ register change will cause - a H-IRQ later on the current scan-line. Pilot Wings needed this. -- Fixed possible crash bug in clip window code when both windows had two - spans. Could actually cause Chrono Trigger to crash the emulator. -- Fixed a lock-up problem with the C Super FX code, Star Fox and executing - a few 'FX instructions per scan-line (required for Winter Gold). -1.11 -- Partially fixed the DOS netplay server - the server timer is running too - slowly and it doesn't deal with disconnects correctly yet. -- Corrected the sound echo delay - it was varying with the sound playback - rate chosen by the user - it shouldn't have been. -- Implemented DOS netplay code - DOS server code still not working though. -- Removed all floating point calculations from the sound generation code. -- Fiddled with the pitch modulation code - my guess is the output of a - channel that is used to modulate the frequency of another channel is - automatically muted by the SPC700 chip. Just a guess, but the wind from - FF3 sounds 'better' but far from perfect. -- Optimised the tile palette index calculation. -- Optimised the planar to chunky tile conversion code. -- Fixed X11 port to always scale SNES image if hi-res. only (no interpolation) - support is enabled. -- Added zipped ROM image support using Gilles Vollant unzip code and - some code that Ivar (Lestat) sent me a long time ago. -- 65c816 asm RTI instruction was destroying the program bank in emulation mode, - the C code was already correct. Caused C64E to break. -1.10 -- Finished NetPlay v1 - allows up to five networked machines to play - multi-player SNES games, one player on each machine. -- Switchable full-screen mode added to Linux X11 port, some code and ideas - nicked from Maciej Babinski's original Snes9x XFree86 DGA Linux port, the - UAE Amiga emulator, plus lots of my own code. -1.08 -- Bug fixes to C Super FX emulation - now Winter Gold works correctly again. -1.07 -- More DSP1 work. Mario Kart is now playable! The character projection code - is still broken so the opponents and obstacles aren't always positioned - correctly on screen and you keep bumping into them, but I can still keep - coming first! -- Started work on NetPlay support. -- Decreased sound card DMA buffer size on DOS port to improve sound generation - and sound CPU synchronisation in some games. -- Included Linux joystick driver patches from Vojtech Pavlik so the port can - use the new v1.x joystick drivers, again written by Vojtech Pavlik. Allows - use of Micro$oft Sidewinder pads, NES and SNES pads, PlayStation pads, - Gamepad Pros, etc. -- Added halve-the-result colour subtraction. -1.06 -- Extended code to allow support for multiple 16-bit screen formats, - switchable at run-time, rather just supporting one, selectable at compile - time. -- Added XFree86 DGA Linux port - code from Maciej Babinski. -- More fixes to the X11 image format conversion and setup code. -- The asm SetByte routine wasn't wrapping writes to S-RAM correctly, allowing - some ROMs to think they were running on a copier and put up an error - screen. Thanks to Nu of #rom for the report. -- Added 'TV-Mode' support (interpolation and scan-lines) to the DOS and - UNIX ports from code based on John Stiles work. -- Added v-sync option to the DOS port. -- Added fix to Pro Action Reply support, thanks to Paul Shoener III. -- Added ggi support (untested) to Linux port using patches from - Alexander Larsson (alla@lysator.liu.se). -- Added 16 to 24/32 bit image conversion routines to the UNIX X11 code. -- The SPC700 OR1 instruction was broken. Thanks to Pyrgopolinices for the - report. -- DOS port was having trouble splitting and joining path names - caused - problems when specifying the full path name of a ROM when the ROM image - was on another drive. -- If a ROM reset the sound DSP and then turned on echo effects but kept - the same echo delay setting, then the echo effects could not be heard. - Thanks to madec@mclink.it for the bug report and freeze file that made it - easy to find the problem. -- DOS port was always using stereo sound setting, if sound card - supported it, regardless of the user preference. -- Linux port X11 port could crash if window was resized while transparency - effects were enabled. -- The colour subtraction accelerator look-up table was slightly wrong, causing - one bit of red, green blue values to 'spill' into the next field. -- Allowed colour window to cut a hole in the main-screen and show the sub- - screen underneath. The effect is used by Illusion of Gaia. -- Added support for colour subtraction, with the halve-the-result flag - set. -- Included DSP1 code from _Demo_. Now you can see the track in Mario Kart and - the ground in Pilot Wings - still can't play the games though due to other - missing commands. -- Added an NMI hack to work around a code bug in Battle Toads: BATTLEMANIACS, - its only by chance that the game works on a real SNES - And disabled it - again because it causes problems for Chrono Trigger. -- A frame skip of zero was actually still skipping one frame. Thanks to - Marius Fodor for the info. -- And yet more X-OR window bug fixes - now the effects during some of the more - 'posh' spells look correct in Chrono Trigger. -- Yet another window area inversion bug - off by one pixel on right-hand edge. -- Forgot to put dummy start and end points for XOR window combination modes - - now Uniracers looks correct and Sailor Moon looks like it does on a real - SNES. -- Window clip code was using wrong index into a 2-dimensional array when - the whole of the main or sub-screens were clipped. -1.05 -- The master volume disable code was looking that the wrong variable! -- Fixed crash bug in newer sound code if a ROM tried to start a sample - playing who's data went past the end of SPC700 memory. (Cannon Fodder) -1.04 -- Fixed DSP1 ROM header detection bug. -- More DSP1 work; still nothing works, although I know the multiply command - is correct because I've compared the results against a real DSP1. -1.03 -- Oops, the multi-player 5 disable code change broke the multi-player 5 being - the default controller. -- Implemented the colour window on the main screen - now Zelda's oval zoom - window displays correctly and Krusty's Super Fun House clips the left-most - 8 pixels as it does on the real SNES. -- TERRANIGMA didn't like me returning a random value when it attempted to - read a channel's the current sample byte. -- Hacked in initial support for mode 7 priority-per-pixel - the priority bit - doesn't actually change the priority of the pixel but the two games that I - know of that use the feature look OK. (Winter Extreme Skiing and the - intro of Tiny Toons Adventures). -- Colour addition/subtraction code now uses RGB565 rather than RGB555 - calculations - helps a little with the loss of the bottom bit of SNES - colour data. -- DSP1 emulation started - nothing works yet. -1.02 -- Switched to adding back drop colour rather than fixed colour when - sub-screen addition is enabled but there's nothing on the sub-screen. - Uniracers seems to need it. - DISABLED it again. Causes problems for - other ROMs and Uniracers itself on later screens. -- Fixed XOR window logic combination mode and area inversion code, now - Uniracers works correctly. -- Oops, if colour window and half colour addition/subtraction were both - switched on, area outside colour window was still being halved, it shouldn't. - Hacky fix at the moment until I implement the correct fix. -- Fixed several bugs with the mosaic effect and 16x16 tiles and a few - possible background scroll offset bugs and the mosaic effect. -- Optimised the sound sample generation code for cases when the SNES - sample playback frequency was higher than the sound card playback rate. -- Fixed possible click sound when a sample was first started to be played. -1.01 -- Corrected scan-line count for PAL games - should be 312 lines verses 262 for - NTSC. Was causing slow music on PAL games. -- Added error correction code to the SPC700 timer update code - the - SPC700 timers are updated using the emulated h-blank handler which is - called every emulated 63.6 microseconds (15.720KHz) but the SPC700 timers - need to be updated at multiples of 8KHz, hence the error. Was causing - music to be played slightly too fast. -- Switched back to using C SPC700 code - the old SPC700 asm code was lacking - several optimisations that the C version had. It also had multiple - speed hack cycle skipping bugs. Plus I hadn't even finished optimising - all the code from the last time I converted the C compiler output. -- Optimised SPC700 memory access routines a little. -- Disabled code that prevented ROMs updating SPC700 timer values while the - timer was running - it seems like it is allowed, even though docs on the - 'net I've seen say its not. -1.0 -- Fixed SuperScope support. -- Added hi-res. option to my DOS port. -- Fixed 4, 6, and 8 button standard PC joystick support. -- Changed some types the source code was using BYTE -> uint8, WORD -> uint16, - DWORD -> uint32 and BOOL -> bool8, types were clashing Windows typedefs - but sizes didn't always match. -0.99 -- 8-bit double height and/or width tile rendering was missing every other - group of 4 pixels - screen pointer advance count was wrong. -- Asm SPC700 emulation was ignoring the Shutdown flag - the result is its - not possible to turn off cycle skipping for the SPC700 emulation. -0.98 -- CPU to ROM address decoding code rewritten - used by Game Genie cheat codes, - orginal code might have been the cause of some Game Genie codes not working. -- Started to remove printf calls and replace them with calls to S9xMessage, - port code can then dicide what to do with message. -0.97 -- Re-enabled decompressed sample caching, still has a possible click problem - but the sound code is a lot faster with it enabled. Added command line option - to disable it if required. -- Added '7' key support to rotate through available controller options, in - the order multi-player5, mouse on #1, mouse on #2, superscope, - standard controller and then back to multi-player5. -- Hi-res. (512x448) support fixed. -- Mouse support completed - Lemmings 2 and Mario Paint working a treat. -- More colour window fixes. -- Fixed freeze game problem when ZSNES SuperFX code is being used - - ZSNES 'FX state was not being saved and restored. -- ZSNES SuperFX asm emulation code plugged in to Snes9x. -0.96 -- Looks like if the colour window is not enabled at all and the colour - window selector is defined to only allow colour effects inside the colour - window, then no effects should be visible. -- Offset-per-tile rendering code didn't support width 64 screen size, which - Chrono Trigger used on its title screen. -- Contra 3 seems to prove that defining the clip window area to be 'outside' - a window that covers the whole screen is not an area with no range. - - No it doesn't. It proves that I shouldn't have initialised the right - window edges to 255! Contra 3 enables clipping windows without first - defining their range. -- Debug frame advance feature was being prevented from forcing the next - frame to be rendered by SyncSpeed which was being called after the - debugger returned to the main loop. -- H-DMA code was allowing ROMs to manually start H-DMA during the v-blank - period, ROMs shouldn't be allowed to do this. -- Asm code would not push the correct CPU status onto the emulated stack if - returning from an NMI immediately triggered an IRQ - fixes Mortal Kombat 1 - and War of the Gems. -- 'd' dump memory debug command was not preserving the CYCLES count. -- C versions of SNES memory access code had same problem as asm code on the DOS - port except it didn't cause a crash just ROMs failed to work correctly. -- Asm i386 code was using signed compares to check for special case memory - areas - it was causing crash problems on the DOS port which was sometimes - returning valid address values with the top bit set - i.e. they seemed - like negative values! -- Changed event reschedule code to always allow h-blank start events, used to - disable them during v-blank period. -- Added code to HDMA when end of visible lines reached. -- Changed register 4212 code not to always return h-blank when in v-blank. -- Clipping fixed colour addition to background area was off by one pixel on - the right-hand edge. -- HDMA: Finally worked out how the real SNES operates when ROMs manual - start H-DMA during the frame - ROMs must set up the H-DMA line count - and address values before H-DMA is started. -- Fixed the asm code to remove all hard-wired structure offsets - one offset - into the IPPU structure was wrong in the code because the structure had - changed size. -- Added colour window support and allowed graphic window settings to be - different on the main screen and sub screen, just like a real SNES. -- SuperFX LJMP instruction had bank and address values swapped. -- Fixed possible memory overwrite problem because OBJList array was one - element too short. -- Added AND multi-graphic window combo support. -- ROM image memory allocation allocates an extra 32K of RAM, then moves the - pointer forward by that amount - stops the SuperFX emulation from accessing - unallocated memory, possibly causing a crash. -- SuperFX emulation now stores sign and zero flags in separate variables so - the MERGE instruction can set flags correctly. -- Added 65c816 instruction skipping to i386 asm code when 65c816 waiting in - a simple loop for some 'event' to happen e.g. end of frame NMI. -- Finally fixed the APU instruction skipping problem with the i386 asm - code when the WAI instruction is used - caused slow music on some ROMs. -- Offset-per-tile modes don't seem to support screen size - Mario All Stars - Super Mario 2 requires this on title screen. Doesn't seem to effect - Tetris Attack or Puzzle Bobble. -- Changed SNES select and start keys from shift and control to space and - enter - allows shift-fn key to save game positions without the SNES ROM - also getting a select joypad button press. -- Multiplayer5 support for controllers 3+ was broken for ROMs that used - automatic hardware joypad reading rather than reading joypads serially. -- ResetPPU was not clearing tile caches and marking OBJ as need recomputing. -- Cached OBJ positions and sizes were not being recomputed if ROM changed - global OBJ sizes during frame. -- Fixed brightness multiplication problem on 16-bit code for green. -- SPC700 emulation now uses one variable to store ZERO and NEGATIVE flags. -- SPC700 emulation now only increments PC once at end of instruction. -- New ROM type and interleaved detection code. -- Reading sound DSP register ENDX also clears the value. The docs on the - 'net said that only writing to the register cleared its value. Fixes - sound in Zoop. -- Fixed mode 4 colour palette problem on background #2 in tile-based graphics - code. -- Fixed graphics mode 4, offset-per-tile support. Only one set of offset data - that is switchable between horizontal and vertical, unlike modes 2 and 6 - which allow separate horizontal and vertical offsets per tile. -- Modified the APU timer code again, if the timer is enabled, a write to the - timer target register is only allowed if a value hasn't been written yet. - Fixed Donkey Kong Country 1 and Earth Worm Jim 1 & 2. -- Attack rate of 0ms changed from 1ms back to 0ms because of a group of ROMs - that change from attack mode to decay mode in real-time. Will change back - when I've added better SPC700 CPU and sound generation sync code. -- Added support for ROMs set a new sound timer value while the timer is - enabled (EWJ 1 & 2). -- Added support for ROMs that read the sound envelope height (MK1, MK2, etc). -- ROMs writing to the H-DMA enable register during visible scan-lines were - restarting H-DMA for that frame causing random screen effect corruption. -- Echo feedback seems to be after the FIR filter, not before as a diagram I've - seen suggests. -- Sound pitch modulation added. -- Memory access routines changed to pass a single 24-bit address rather than - the previous separate 8-bit bank and 16-bit address parameters. -0.3 -- Updates to A-Bus address during a frame must not update H-DMA address. - Fixes Actraiser 2 and Pacman 2. -- Removed sound volume mangling - with echo support enabled it doesn't seem to - be required. -- Attack rate of 0ms changed to 1ms to help prevent click sound with sudden - start of a sample playing. -- Sample caching of samples that looped using part of the original sample - created a click on the sound output. Caching disabled for the moment. Would - require 512K of cache RAM to fix sample caching. -- Colour addition/subtraction support added - but still a little buggy in - places and very slow. -- 16-bit colour support added. -- Sustain sound volume was not being set if a sample using ADSR was started - with both the attack rate and decay rate set to zero - resulted in missing - sound samples on with some games. -- Sound echo support added. -- Sound channel mixing code was not completely clearing a channel's sound - buffer when a channel finished playing a sample. -- Sound mixing code rewritten to use one buffer, rather than writing each - channel into a separate buffer then combining them into one buffer. -- Memory access routines rewritten to use an 8K block lookup table rather than - dedicated code for each ROM memory map - it was getting difficult to support - the new types of SNES ROM memory maps becoming apparent. -- Sound sample decoding wasn't decoding sound samples correctly if a - previously cached sample was only partially overwritten by the ROM as - opposed to being completely replaced. -- Sound sample decoding wasn't clipping generated sample values correctly. -- Changed H-DMA to start in the current frame only if enable register is - written to during v-blank, h-blank or while the screen is blanked. -- The SPC700 seems to start executing instructions before the 65c816 - - shorter reset pulse? (NO - forgot the SPC700 executes instructions while DMA - is taking place). -- ROMs that reset the H-IRQ position so another IRQ would be triggered on the - same scan-line where not supported - Super Off-Road: The Baj needs it. -- $4212 bit 7 needs to go high at the end of h-blank at line 224 not at the - start of h-blank - Bubsy needs it. -- Sample decoding routine could write to memory outside sample cache area if - address of block to decode was greater than $0x10000 - 9. -- Walking mario can be seen on map screen of MarioWorld - needed sprite - priority rotation working. ROM sets bit 7 of $2103 then sets rotation in - $2102. Reset rotation at start of v-blank not at end. -0.24 -- Fixed reading of DMA register values - now Ms Pacman works. -- Saved sprite memory address being restored on the wrong scan-line - caused - corrupt sprites on at least one game (GANBARE GOEMON 2). -- Screen colour palette not being updated if ROM only wrote to low byte of - palette register. -- Possible memory corruption fixed if a ROM tried to write to an invalid - sprite address via PPU registers. -- X11 port support quick load and save by pressing function keys to load or - shift + function keys to save. -0.23 -- Added option to disable graphic window effects - T2: The Arcade Game doesn't - seem to like them. -- Mode 7 "outside screen area" register interpretation fixed - now the - Actraiser map screen looks a lot better. -- Old DMA code hack for Battle Toads: Double Dragon removed as it was no - longer required and it was causing problems for Ys III. -- Lowered max volume level of 16-bit sound mixing code to help with sound - clipping problems is lots of SNES sound channels are playing. -0.22 -- Crash bug fixed in mode 7 graphics windows code -0.21 -- Fixed a noise channel volume bug - noise waveform was getting clipped. -- Fixed 24bit X Window System server support on the Solaris port. -- Sprites in priority level 1 on mode 7 were being drawn incorrectly behind - graphics screen. -- BG 3 priority 1 tiles sometimes not drawn dependent on the $2105 bit 3 - setting. -- Added graphic window support the tile redraw code. -- Added mosaic support to tile redraw code. -- Tile redraw code was drawing one line too many on screen-splits. -- Tile-based redraw code made more intelligent about when a background should - be displayed or not. -- Added wrap within bank support to large DMAs just to support Rock 'n' Roll - racing. -0.20 -- DMA routines added lots of special cases and removed most calls to GetByte, - using a pointer instead. -- Multiple using PPU registers is now only computed when first byte of result - is actually read. -- Sound enabled by default if compiled without DEBUGGER defined. -- Tile redraw method made the default. -- Fixed CPU_SHUTDOWN so SPC700 continues to execute even if main CPU is - "skipping" cycles waiting for an event to happen. -- More command line options added. -- Default cycles-per-scan-line to execute lowered to 90% from 100%. -- +/- keys now work even if auto-frame rate adjust was enabled. -- SPC700 emulation partially rewritten in assembler. -- Asm 65c816 code change to use same speed up techniques as the C++ code. -- Minor speed tweaks to the sound decoding and mixing code. -- C++ SPC700 emulation changed to use same method as 65c816 emulation for - computing and storing emulated CPU flags. -- Mode 7 code rewritten and several scrolling offset bugs fixed. -- Lo-ROM S-RAM memory map bug fixed - now Uniracers works. -- Multiple speed ups and changes to the tile and line-based redraw code. -- Tile and line redraw code changed to cache converted tiles between frames. -- Variable cycle length timing made compile-tile switchable. -- C++ 65c816 emulation changed to use several opcode jump tables to avoid - a register size comparison test on most emulated instructions. -- C++ 65c816 emulation changed how is computes and stores emulated CPU flags. -- Fixed high frequency sound playback bug - the sample rate calculation was - blowing the range of an unsigned long. -- Fixed V-RAM reading so DKC3, Addams Family, Aladdin and Pacman all work. -- Fixed sound code so ROMs can change from ADSR mode to decrease mode - fixes - lots of ROMs. -0.12 released -- Added dynamic speed regulation. -- TCALL vector calculation change from n to 15 - n. -- Fixed crash bug if ROM writes to sound DSP register numbers greater than - 127. -- Fixed DOS memory locked for interrupt code. -- Added long name versions of command line switches. -- Added command line switch for SPC700_SHUTDOWN code and WAI cycle skipping - code. -0.1 released -- All DOS memory is now locked from being swapped. -- Fixed DOS port keyboard polling code - could get confused if a keyboard - interrupt happened while keys were being checked. -- SPC700 ADC instruction never cleared Overflow or Carry flags! -- Changed selection of playback speeds for Solaris port. -- Sample caching code was broken - cached samples were never used. -- Added code speed ups for ROMs that use a lot of DMA to VRAM. -- More cpu code asm speed up. -- Fixed 16x16 size tiles on tile-based redraw code. -- Fixed sound gain-mode increase and decrease volume envelopes. -- Added code to support ROMs that reuse sprites in the same frame. -- Fixed processing of negative volume levels. -- Fixed SPC700 EOR1 instruction. -- Added SPC700 shutdown code to stop executing SPC700 instructions if in - a tight loop waiting for a timer or for the 65C816 to respond. -- DOS playback rate was being forced to 16KHz by Allegro - fixed. -- Fixed bug in SPC700 MOV1 C,bit, address. -- Fixed a off-by-one loop sample pointer bug in MixSamples. -- Added command line flags for cached-tile based drawing and sub-screen - background layers priority swapping. -- NOPE, got encoding of the OR1/EOR1,AND1 range of correct originally - - got duff information from an "SPC700" programmer. -- More SPC700 fixes: got the encoding of the OR1/EOR1,AND1 range of - instructions wrong - I guessed wrong originally. -- Sample looping bug fix on mono sound mixing code. -- Sound pitch value no-longer clipped to 14 bits - apparently FF3 needs this. -- Followed Paradox's suggestion and changed graphics code to place sub-screen - background layers below main-screen background layers. Helps lots of games - that use sub-screen addition/subtraction - now you don't have to toggle - background layers on and off so often just to see hidden text, characters, - or maps, etc. Made it switchable. - Acts as a good intermediate solution until sub-screen addition/subtraction - is actually implemented. -- Modified sound skipper code to return random values when ROM is stuck - waiting for the SPC700 CPU to respond - helps several ROMs that previously - don't work with the currently selection of APU skippers. -- Improved sound mixing code so volume is not attenuated so much, giving - better results on 8bit sound cards. -- Changed the frequency at which the joystick polling routine is called - now - called every-other frame rather than every 3rd frame. -- Recompiled Linux and DOS ports with the Pentium optimising version of gcc - - gives a few percent speed increase. -- Changed V-RAM increment count from 64 to 128 - apparently Final Fantasy 3 - needs this as well. -- Fixed sprite priority bug with Mode 7 - apparently Final Fantasy 3 needs - this. -- Fixed a screen clipping problem with the S-VGA mode. -- Fixed bug that had crept in with -m 2 S-VGA mode (Linux version). -- Fixed S-VGA Linux version with sound enabled. -- The SPC700 ADC (X),(Y) instruction was broken - with all these SPC700 fixes - now many more ROMs work with sound enabled. -- The SPC700 Pop PSW instruction was not resetting the direct page location. -- The SPC700 instruction MOV A,[DP+X] was incorrectly doing a MOV A,DP+X. -- Got the SPC700 SETx and CLRx instruction encoding swapped around. -- Fixed #define problem that was stopping DOS snapshot saving from working. -0.72 released -- Fixed the DOS filename handling - old Unix code was screwing up with ROM - filenames that contained backslashes (\) - the ROM would load but S-RAM - loading and saving would fail and the default filename for snapshots - wouldn't work. -- This time really fixed Allegro library keyboard handling (DOS port); it - was missing key some presses/releases (was stopping Chrono Trigger - Left + Right + A button combo from working). -- Added code to automatically remove headers off S-RAM save files with - 512 byte headers. -- 32Mbit ROMs in interleaved format are now automatically detected and - converted. -- Added -ss 3 sound skip method support to the asm version - now NBA Live '96 - works again. -- Added support for multi-part ROM images. -0.71 released -- Made libgz.so statically linked (again) on Linux port - sorry. -- Made writing to $4200 also clear any pending IRQs. This finally allows - Battle Toads: Double Dragon, Spawn and Sieken 3 all the work with the same - IRQ logic (but Sieken 3 still gets stuck in sound download code). -- Fixed a H-DMA wobble bug - some frames could randomly miss a line of - H-DMA causing the F-Zero screen to wobble, and slight text character - corruption on games like DKC3. -- Interleaved format ROM images are now swapped in-place, without the need - for a temp 4Mb buffer (saves lots of disk swapping on a 16Mb Windows 95 - machine). -0.7 released -- Fixed Allegro library keyboard handling (DOS port); it was missing key - some presses/releases. -- DOS port had a different MAX_PATH value which moved the location of the - SRAM size variable when using the asm CPU emulation core. This, in turn, - caused the SRAM emulation to fail on the DOS port. Donkey Kong County 2 & 3 - were reporting a ROM copier was connected to the SNES and refused to run. -- Fixed assembler version of XCE - it was always leaving the carry flag - clear - caused Killer Instinct and Super Punchout to think a ROM - copier was fitted to the SNES and they all refused to run. -- Fixed assembler versions of MVN/MVP - they weren't setting the data bank - register to the destination bank of the instruction. -- Fixed joystick detection on MS-DOS port - a single 2 or 4 button joystick in - port 1 was being ignored if a second joystick was not present in port 2. -- Fixed an uninitialised variable in graphics code - was causing random - missing scan lines on Mode 7 screens. -- Joysticks now scanned every 3rd frame (joystick scanning is slow in the PC). -- Double-whoops, Metriod 3 had stopped working in v0.6 - fixed it - (memory map bug). -- Made bit 6 of $4211 set if v-counter == v-timer-position. -- Made reading of $4200 read $4212 instead. -- Adjusted DMA timing to always access ROM memory at slow speed - this seems - to fix Battle Toads. -- Added code to automatically clear pending IRQs when the horizontal line - is no longer equal to the horizontal timer line - this fixes Seiken 3, it - now just gets stuck in the sound CPU wait code - oh well. -- Moved NMI back to its original pre-0.65 behaviour, now Puzzle Bobble works. -- More graphics speed ups - the code to render background tiles with their - priority bits set is only called if there are actual priority-bit tiles. -- Changed default frame skip rate from 1 to 2 - its seems most people don't - bother to read the docs, so I thought I'll help them out a bit! -- Speeded up Mode 7 graphics on games like F-Zero that rewrite the matrix - registers on each scan line using H-DMA. -- Reorganised the graphics code and did a slight speed up - graphics code - will be the next thing to rewrite in assembler. -- Rewrote CPU core in assembler for Intel platforms - gives a very noticeable - speed increase. -- Fixed several problems with the APU sound CPU emulation - its now getting - stable enough to try and implement sound. -- Fixed bug that caused 1 byte of S-RAM to be emulated when ROM didn't - expect any - it was enough to stop Street Fighter 2 and others from - working - thanks Lord ESNES. -- The TXS and TCS instructions shouldn't set the Z and N flags. -- Looks like MVP/MVN instructions should ignore accumulator size - change - code to always use all 16 bits and exit with accumulator set to 0xffff. -- Whoops, accidently left some test code in which was causing the V-BLANK - flag, bit 8 in register $4212, to be miss-calculated. -- Fixed palette in mode 0. -- Speeded up graphics drawing a little by skipping groups of 4 pixels that - were all transparent. -0.65 released -- S-VGA and MS-DOS ports now have a VGA mode command line flag. -- Improved the fading code - should be much more smooth now. -- Fixed second joy-pad support and re-mapped keys and joysticks to actually - make a match between what my docs said and a real SNES (SNES docs I'd - seen were wrong!). -- Fixed a bug in Relative Long CPU addressing mode. -- Ported Snes96 to MS-DOS. -- Snapshot loading and saving no longer uses external gzip binary. -- Added support for registers at $21c2 and $21c3. -- Made reading the software latch for the horizontal and vertical counters also - clear any pending IRQ. -- Added sprite priority rotation. -- Rewrote parts of the graphics routines to fix a sprite-to-sprite priority - bug. -- NMI flag changed again - now back to being reset by reading $4210 but - actual NMI is delayed. -- Made mode 7 background colour 0 transparent - this fixed several sprite - priority problems a few games where having. -- Finally worked out how sprite "Object Name Select" works and emulated it - - this fixes many (if not all) of the corrupted sprites some games - experienced. -- Delayed NMI activation for one instruction to give time for loops that - wait for bit 7 of $4210 to go high. -- Special-cased line count of 128 on H-DMA to mean repeat previous data with - a line count of 128 and not just terminate H-DMA on that channel. -- APU sound CPU emulation added - just need to debug the thing. -- Fixed Overflow flag setting in ADC and SBC instructions - it was never - being set. -- Rewrote how CPU instructions are fetched and how values are pushed and pulled - from the stack - it gave a very large increase in emulation speed. -- H-DMA was being started one scan-line too late. -- Added CG-RAM reading support. -- Added "Full Graphic" V-RAM reading. -- Speeded up C version of CPU emulation quite a bit - could speed it up a - little more before rewriting in assembler. -- Fixed bugs in 16x16 tile drawing on 2bit and 8bit deep screens. -0.6 released -- Speeded up 16x16 tile background rendering by removing a temp tile buffer - it was using. The speed up also fixed a vertical scroll bug. -- Fixed slight window clipping on 16x16 tile backgrounds. -- Added automatic PAL/NTSC mode switching. -- Fixed background and sprites so only visible if on main-screen or - on sub-screen under correct circumstance. -- Fixed lockup bug in DMA. -- Stopped NMI flag from being reset by reading $4210 - was causing a couple - of games to get stuck. -- Whoops, got horizontal and vertical Mode 7 flip bits around the wrong way! -- Fixed MIT shared memory pixmap support for X11 version (it was always turned - off). -- Fixed minor bug - first sprite in priority group was drawn twice. Didn't - cause any visual bugs, it just slowed down redrawing a little. -- Fixed DMA bug - transfer byte count should be 0 after DMA has finished. -- Fixed a scaling bug if width < height. -- Interleaved ROM image support added. -- 16bit and 24bit X11 server support added - with scaling. -- Added window scaling on X11 version. -- Partial clip windows added - the only window overlap option implemented at - the moment is OR, it seems it good enough for all the ROMs I've tested - it with. -- Partial Mosaic effect added (pixels only growing vertically). -- Missing Mode 7 "outside screen area" option added. -- Fixed mode 7 screen wrap "outside screen area" option. -- Used new event processing to finally fix H-IRQ so it triggers at the - correct position on the scan line. -- New event processing added. -- Linux version now statically links libgz.so (sorry). -0.5 released -- Linux S-VGA version changed from using a 320x240 ModeX screen (slow) to a - 256x256 chunky screen (faster) - thanks to Phillip Ezolt (pe28+@andrew.cmu.edu) - for information on how to do this. -- Mode 7 screen flipping added. -- Included Snes97's CPU emulation code into Snes96. Didn't fix any bugs but - slowed down the emulation some what and I couldn't compile it optimised - because it was so large - so I removed it again. -- Added a few extra features available via the keyboard. -- Fixed a H-DMA transfer mode - bad documentation. -- Fixed H-DMA indirect addressing (it was using the wrong CPU memory bank). -- The Linux slow down bug is my crappy laptop enabling battery saving features ! -- Changed graphics code to perform true line-by-line screen updates. -- Fixed sprite drawing bugs. -- Ported Snes97's graphics code to Snes96. -- Fixed memory map for HiROM save RAM area. -- Fixed HiROM memory map - now Killer Instinct and Donkey Kong County work ! -- OK the slow down bug is just actually my laptop trying to save battery - power by slowing the CPU clock! -- The Linux slow down bug shows itself on DOS emulators running under DOSEMU - so it must be a kernel problem (or feature). -- Fixed H-DMA (again) to be complete emulation - all I need now is line-by-line - screen update... -- Fixed DMA to not copy too many bytes if byte count was not a multiple of - the transfer mode quantity (caused corruption on Super Mario World map screen). -- Changed mapping of keyboard to joy-pad buttons and added additional - direction keys for joy-pad one so player one's right hand doesn't have to - obscure player two's keyboard joy-pad buttons. -- Changed joystick button layout to match SNES if using a 6 button joy-pad. -- Changed snapshot format so I can easily use libgz on Linux. -- Added few speed up tweaks that will be lost again when I add line-by-line - screen update. -- First visible scan-line changed from 8 to 1 to match with new docs. -- New SNES information source found; fixed partial H-DMA emulation to include - indirect addressing support. -- Snapshot files are now compressed. -- Compressed ROM images now supported on Linux. -- Snapshot loading and saving added. -- Joystick support for Linux added. One 2, 4 or 6 button joystick, or two 2 - button joysticks supported (PC hardware limitation). -- SVGA full screen support added for Linux. Still has the X11 slow down bug so - can't blame the X11 server any more! Must be a kernel bug or a very odd - emulator bug. -- Added emulation of two joy-pads on the PC/Sun keyboard. -- Removed -i command line flag as it is no longer used. -h value range has also - changed: now 1 - 100 (percentage). -- Actuate cycle counting rather than instruction counting now added including - fast and slow ROM timing - should give much better timing information when - line-by-line screen update added. -- Bug fixed old-style joy-pad access used by some ROMs - Mario All Stars still - gives problems if enabled and I don't know why; but at least Super Bomberman - now works ! -- Looks like if both horizontal and vertical IRQ are enabled then IRQ should - only be triggered once per frame and not once per scan line - looking at the - IRQ handler of a couple of ROMs seems to confirm this. -- Added initial cycle counting - not accurate enough for some ROMs though. -- Finally worked out how the odd VRAM address increments should work but only - found one ROM, so far, that actually uses it. -- Debugged the odd slow down problem with the Linux port - it seems to be a - bug in the X Window System server - starve the X server of keyboard presses - or mouse clicks or movement and the X server slows down, slowing down the - emulator with it ! -0.4 released -- Fixed sprite vertical clipping at top of screen. -- No need to invert the Mode 7 transformation matrix before use - the - ROM coder already had to! -- Fixed Mode 7 scrolling offset when using special effects. -- Added Mode 7 rotation, enlargement and reduction emulation. -- DMA shouldn't zero the byte count value after a DMA has completed. -- Added DMA reading (Addams Family was using it) -- Fixed V-RAM read function - returned data should lag behind the V-RAM - address by one byte/word. -- Added mode 7 graphics only. -0.3 released -- Speeded up the main CPU loop a bit. -- Add more command line options: - -f <frame skip> (default 1) - -i <no instructions between polling X> (default 32768) - -h <number instructions per scan line> (default 45, some games allow a lower - setting resulting in a increased - emulated frame rate) - -t enable CPU tracing - -ss <sound CPU skip wait method> (default 0, more methods to be added) - -H disable H-DMA emulation - -F Force Hi-ROM memory map -- Modified planar to chunky conversion to use look up tables. -- But now Mario All Stars won't start. Made emulation of $4016 optional with - -o command line switch. -- Thanks to Carlos (calb) of ESNES fame, I've added correct $4016 & $4017 - joy-pad register processing - now several more ROMs will start once a - button is pressed and can be controlled. -- DMA wasn't updating DMA registers with the final CPU address used after the - DMA had completed (caused sprite and background corruption with some ROMs). - Still suspect another DMA side effect isn't being emulated correctly though. -- Fixed setting of CPU overflow flag in ADC and SBC instructions in decimal - mode. -- Fixed MVP/MVN CPU instructions to leave X and Y values correct at end of - loop - several more ROMs now work. Still don't know if MVP/MVN instructions - should ignore the accumulator size flag or not. -- Rewrote background drawing code - gives a large increase in speed. -- Flag to only update X Windows colour palette when necessary was missing a - case - caused some ROMs to start with a black screen. -- Code to only update background tiles when changed wasn't working so I - disabled it. -- CPU WAI instruction needed to trigger on hardware IRQ even when interrupt - enable flag was false. -- DMA was not transferring 65536 bytes when byte count was 0. -- Fixed matrix 16bit x 8bit multiplication (old debug code was causing junk - value to be returned). -- Fixed Makefile so version.h header file change recompiles file that shows - version number in window title. -- Added more reporting of used but unimplemented missing hardware features to - debug command. -- New ROM loading code from Jerremy included, can now cope with ROM images - with no 512 byte header. -- Speeded up emulated memory access a little bit. -0.2 released -- Added matrix 16bit x 8bit multiplication for Super Off-Road Racer. -- Added initial H-DMA emulation - visual effects using it will not be seen - correctly until screen is updated line-by-line rather than the whole screen - at end-of-frame. -- Fixed horizontal sprite clipping (vertical clipping still has a problem). -- Integrated large sprite bug fixes and new background drawing code from - Jerremy. -- Fixed large size per-sprite flag; always stayed true after sprite size was - changed to large. -- Rewrote the planar to chunky pixel conversion routines (still need more - work). -- Made registers $4016 & $4017 always return $ff - lots of ROMs that previously - wouldn't go beyond the title screen thought old-style joy-pads were - connected and were waiting for the user to press a button on them. -- Frame skip rate now set to 1 instead of 5 on my P166 laptop! -- Fixed NMI v-blank flag being incorrect set, caused some ROMs to lock. -- X keyboard autorepeat now switched off when emulator has keyboard focus. -- Added number key options to toggle backgrounds 1 to 4 and objs (sprites) on - and off. -- Fixed sprite clipping problems at edge of left hand side of screen. -- Corrected Hi-ROM memory map (I think) (no I didn't) -- Fixed most of the sprite-to-sprite priority problems. -- Added sprite debug command, 'S'. -- Added a debug command to show what missing hardware features a ROM was using. -- Added horizontal and vertical beam position IRQ - horizontal always triggers - at start of line at the moment. -- Fixed SBC instruction to set carry flag the correct way around. -Initial release 0.1 -- Ported Windows 95 version of Snes96 to Linux on a PC and Solaris on a - SparcStation. -- Corrected work RAM memory map. diff --git a/source/cheats.c b/source/cheats.c index 1a5e833..572fd55 100644 --- a/source/cheats.c +++ b/source/cheats.c @@ -22,8 +22,7 @@ static bool S9xAllHex(const char* code, int32_t len) const char* S9xProActionReplayToRaw(const char* code, uint32_t* address, uint8_t* byte) { uint32_t data = 0; - if (strlen(code) != 8 || !S9xAllHex(code, 8) || - sscanf(code, "%x", &data) != 1) + if (strlen(code) != 8 || !S9xAllHex(code, 8) || sscanf(code, "%x", &data) != 1) return "Invalid Pro Action Replay code - should be 8 hex digits in length."; *address = data >> 8; @@ -100,271 +99,3 @@ const char* S9xGameGenieToRaw(const char* code, uint32_t* address, uint8_t* byte return NULL; } - -void S9xStartCheatSearch(SCheatData* d) -{ - // memmove may be required: Source is usually a different malloc, but could be pointed to d->CWRAM [Neb] - memmove(d->CWRAM, d->RAM, 0x20000); - // memmove may be required: Source is usually a different malloc, but could be pointed to d->CSRAM [Neb] - memmove(d->CSRAM, d->SRAM, 0x10000); - // memmove may be required: Source is usually a different malloc, but could be pointed to d->CIRAM [Neb] - memmove(d->CIRAM, &d->FillRAM [0x3000], 0x2000); - memset(d->WRAM_BITS, 0xff, 0x20000 >> 3); - memset(d->SRAM_BITS, 0xff, 0x10000 >> 3); - memset(d->IRAM_BITS, 0xff, 0x2000 >> 3); -} - -#define BIT_CLEAR(a,v) \ -(a)[(v) >> 5] &= ~(1 << ((v) & 31)) - -#define BIT_SET(a,v) \ -(a)[(v) >> 5] |= 1 << ((v) & 31) - -#define TEST_BIT(a,v) \ -((a)[(v) >> 5] & (1 << ((v) & 31))) - -#define CHEATS_C(c,a,b) \ -((c) == S9X_LESS_THAN ? (a) < (b) : \ - (c) == S9X_GREATER_THAN ? (a) > (b) : \ - (c) == S9X_LESS_THAN_OR_EQUAL ? (a) <= (b) : \ - (c) == S9X_GREATER_THAN_OR_EQUAL ? (a) >= (b) : \ - (c) == S9X_EQUAL ? (a) == (b) : \ - (a) != (b)) - -#define _D(s,m,o) \ -((s) == S9X_8_BITS ? (uint8_t) (*((m) + (o))) : \ - (s) == S9X_16_BITS ? ((uint16_t) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ - (s) == S9X_24_BITS ? ((uint32_t) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16))) : \ -((uint32_t) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) - -#define _DS(s,m,o) \ -((s) == S9X_8_BITS ? ((int8_t) *((m) + (o))) : \ - (s) == S9X_16_BITS ? ((int16_t) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ - (s) == S9X_24_BITS ? (((int32_t) ((*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16)) << 8)) >> 8): \ - ((int32_t) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) - -void S9xSearchForChange(SCheatData* d, S9xCheatComparisonType cmp, - S9xCheatDataSize size, bool is_signed, bool update) -{ - int32_t l; - int32_t i; - - switch (size) - { - case S9X_8_BITS: - l = 0; - break; - case S9X_16_BITS: - l = 1; - break; - case S9X_24_BITS: - l = 2; - break; - default: - case S9X_32_BITS: - l = 3; - break; - } - - if (is_signed) - { - for (i = 0; i < 0x20000 - l; i++) - { - if (TEST_BIT(d->WRAM_BITS, i) && - CHEATS_C(cmp, _DS(size, d->RAM, i), _DS(size, d->CWRAM, i))) - { - if (update) - d->CWRAM [i] = d->RAM [i]; - } - else - BIT_CLEAR(d->WRAM_BITS, i); - } - - for (i = 0; i < 0x10000 - l; i++) - { - if (TEST_BIT(d->SRAM_BITS, i) && - CHEATS_C(cmp, _DS(size, d->SRAM, i), _DS(size, d->CSRAM, i))) - { - if (update) - d->CSRAM [i] = d->SRAM [i]; - } - else - BIT_CLEAR(d->SRAM_BITS, i); - } - - for (i = 0; i < 0x2000 - l; i++) - { - if (TEST_BIT(d->IRAM_BITS, i) && - CHEATS_C(cmp, _DS(size, d->FillRAM + 0x3000, i), _DS(size, d->CIRAM, i))) - { - if (update) - d->CIRAM [i] = d->FillRAM [i + 0x3000]; - } - else - BIT_CLEAR(d->IRAM_BITS, i); - } - } - else - { - for (i = 0; i < 0x20000 - l; i++) - { - if (TEST_BIT(d->WRAM_BITS, i) && - CHEATS_C(cmp, _D(size, d->RAM, i), _D(size, d->CWRAM, i))) - { - if (update) - d->CWRAM [i] = d->RAM [i]; - } - else - BIT_CLEAR(d->WRAM_BITS, i); - } - - for (i = 0; i < 0x10000 - l; i++) - { - if (TEST_BIT(d->SRAM_BITS, i) && - CHEATS_C(cmp, _D(size, d->SRAM, i), _D(size, d->CSRAM, i))) - { - if (update) - d->CSRAM [i] = d->SRAM [i]; - } - else - BIT_CLEAR(d->SRAM_BITS, i); - } - - for (i = 0; i < 0x2000 - l; i++) - { - if (TEST_BIT(d->IRAM_BITS, i) && - CHEATS_C(cmp, _D(size, d->FillRAM + 0x3000, i), _D(size, d->CIRAM, i))) - { - if (update) - d->CIRAM [i] = d->FillRAM [i + 0x3000]; - } - else - BIT_CLEAR(d->IRAM_BITS, i); - } - } -} - -void S9xSearchForValue(SCheatData* d, S9xCheatComparisonType cmp, - S9xCheatDataSize size, uint32_t value, - bool is_signed, bool update) -{ - int32_t l; - int32_t i; - - switch (size) - { - case S9X_8_BITS: - l = 0; - break; - case S9X_16_BITS: - l = 1; - break; - case S9X_24_BITS: - l = 2; - break; - default: - case S9X_32_BITS: - l = 3; - break; - } - - - if (is_signed) - { - for (i = 0; i < 0x20000 - l; i++) - { - if (TEST_BIT(d->WRAM_BITS, i) && - CHEATS_C(cmp, _DS(size, d->RAM, i), (int32_t) value)) - { - if (update) - d->CWRAM [i] = d->RAM [i]; - } - else - BIT_CLEAR(d->WRAM_BITS, i); - } - - for (i = 0; i < 0x10000 - l; i++) - { - if (TEST_BIT(d->SRAM_BITS, i) && - CHEATS_C(cmp, _DS(size, d->SRAM, i), (int32_t) value)) - { - if (update) - d->CSRAM [i] = d->SRAM [i]; - } - else - BIT_CLEAR(d->SRAM_BITS, i); - } - - for (i = 0; i < 0x2000 - l; i++) - { - if (TEST_BIT(d->IRAM_BITS, i) && - CHEATS_C(cmp, _DS(size, d->FillRAM + 0x3000, i), (int32_t) value)) - { - if (update) - d->CIRAM [i] = d->FillRAM [i + 0x3000]; - } - else - BIT_CLEAR(d->IRAM_BITS, i); - } - } - else - { - for (i = 0; i < 0x20000 - l; i++) - { - if (TEST_BIT(d->WRAM_BITS, i) && - CHEATS_C(cmp, _D(size, d->RAM, i), value)) - { - if (update) - d->CWRAM [i] = d->RAM [i]; - } - else - BIT_CLEAR(d->WRAM_BITS, i); - } - - for (i = 0; i < 0x10000 - l; i++) - { - if (TEST_BIT(d->SRAM_BITS, i) && - CHEATS_C(cmp, _D(size, d->SRAM, i), value)) - { - if (update) - d->CSRAM [i] = d->SRAM [i]; - } - else - BIT_CLEAR(d->SRAM_BITS, i); - } - - for (i = 0; i < 0x2000 - l; i++) - { - if (TEST_BIT(d->IRAM_BITS, i) && - CHEATS_C(cmp, _D(size, d->FillRAM + 0x3000, i), value)) - { - if (update) - d->CIRAM [i] = d->FillRAM [i + 0x3000]; - } - else - BIT_CLEAR(d->IRAM_BITS, i); - } - } -} - -void S9xOutputCheatSearchResults(SCheatData* d) -{ - int32_t i; - for (i = 0; i < 0x20000; i++) - { - if (TEST_BIT(d->WRAM_BITS, i)) - printf("WRAM: %05x: %02x\n", i, d->RAM [i]); - } - - for (i = 0; i < 0x10000; i++) - { - if (TEST_BIT(d->SRAM_BITS, i)) - printf("SRAM: %04x: %02x\n", i, d->SRAM [i]); - } - - for (i = 0; i < 0x2000; i++) - { - if (TEST_BIT(d->IRAM_BITS, i)) - printf("IRAM: %05x: %02x\n", i, d->FillRAM [i + 0x3000]); - } -} diff --git a/source/cheats.h b/source/cheats.h index 42e2b47..df8a9a6 100644 --- a/source/cheats.h +++ b/source/cheats.h @@ -59,10 +59,4 @@ void S9xDeleteCheats(); void S9xDeleteCheat(uint32_t which1); bool S9xLoadCheatFile(const char* filename); bool S9xSaveCheatFile(const char* filename); - -void S9xStartCheatSearch(SCheatData* cheats); -void S9xSearchForChange(SCheatData* cheats, S9xCheatComparisonType cmp, S9xCheatDataSize size, bool is_signed, bool update); -void S9xSearchForValue(SCheatData* cheats, S9xCheatComparisonType cmp, S9xCheatDataSize size, uint32_t value, bool is_signed, bool update); -void S9xOutputCheatSearchResults(SCheatData* cheats); - #endif diff --git a/source/cheats2.c b/source/cheats2.c index 3d6519e..f113cd9 100644 --- a/source/cheats2.c +++ b/source/cheats2.c @@ -112,11 +112,9 @@ void S9xApplyCheats(void) { uint32_t i; if (Settings.ApplyCheats) - { for (i = 0; i < Cheat.num_cheats; i++) if (Cheat.c [i].enabled) S9xApplyCheat(i); - } } void S9xRemoveCheats(void) @@ -130,27 +128,22 @@ void S9xRemoveCheats(void) bool S9xLoadCheatFile(const char* filename) { uint8_t data [8 + MAX_SFCCHEAT_NAME]; - FILE* fs = NULL; - + FILE* fs = fopen(filename, "rb"); Cheat.num_cheats = 0; - fs = fopen(filename, "rb"); - if (!fs) - return (false); + return false; - while (fread((void*) data, 1, 8 + MAX_SFCCHEAT_NAME, - fs) == 8 + MAX_SFCCHEAT_NAME) + while (fread((void*) data, 1, 8 + MAX_SFCCHEAT_NAME, fs) == 8 + MAX_SFCCHEAT_NAME) { if (data[6] != 254 || data[7] != 252) { fclose(fs); - return (false); + return false; } Cheat.c [Cheat.num_cheats].enabled = (data [0] & 4) == 0; Cheat.c [Cheat.num_cheats].byte = data [1]; - Cheat.c [Cheat.num_cheats].address = data [2] | (data [3] << 8) | - (data [4] << 16); + Cheat.c [Cheat.num_cheats].address = data [2] | (data [3] << 8) | (data [4] << 16); Cheat.c [Cheat.num_cheats].saved_byte = data [5]; Cheat.c [Cheat.num_cheats].saved = (data [0] & 8) != 0; memcpy(Cheat.c [Cheat.num_cheats].name, &data [8], MAX_SFCCHEAT_NAME - 1); @@ -158,25 +151,25 @@ bool S9xLoadCheatFile(const char* filename) } fclose(fs); - return (true); + return true; } bool S9xSaveCheatFile(const char* filename) { uint32_t i; uint8_t data [8 + MAX_SFCCHEAT_NAME]; - FILE* fs = NULL; + FILE* fs; if (Cheat.num_cheats == 0) { (void) remove(filename); - return (true); + return true; } fs = fopen(filename, "wb"); if (!fs) - return (false); + return false; for (i = 0; i < Cheat.num_cheats; i++) { @@ -199,10 +192,10 @@ bool S9xSaveCheatFile(const char* filename) if (fwrite(data, 8 + MAX_SFCCHEAT_NAME, 1, fs) != 1) { fclose(fs); - return (false); + return false; } } fclose(fs); - return (true); + return true; } diff --git a/source/clip.c b/source/clip.c index c579b77..7cafc10 100644 --- a/source/clip.c +++ b/source/clip.c @@ -13,24 +13,27 @@ typedef struct } Band; #define BAND_EMPTY(B) (B.Left >= B.Right) -#define BANDS_INTERSECT(A,B) ((A.Left >= B.Left && A.Left < B.Right) || \ - (B.Left >= A.Left && B.Left < A.Right)) -#define OR_BANDS(R,A,B) {\ +#define BANDS_INTERSECT(A,B) ((A.Left >= B.Left && A.Left < B.Right) || (B.Left >= A.Left && B.Left < A.Right)) +#define OR_BANDS(R,A,B) \ +{ \ R.Left = MIN(A.Left, B.Left); \ - R.Right = MAX(A.Right, B.Right);} + R.Right = MAX(A.Right, B.Right); \ +} -#define AND_BANDS(R,A,B) {\ +#define AND_BANDS(R,A,B) \ +{ \ R.Left = MAX(A.Left, B.Left); \ - R.Right = MIN(A.Right, B.Right);} + R.Right = MIN(A.Right, B.Right); \ +} static int32_t IntCompare(const void* d1, const void* d2) { - return (*(uint32_t*) d1 - * (uint32_t*) d2); + return *(uint32_t*) d1 - *(uint32_t*) d2; } static int32_t BandCompare(const void* d1, const void* d2) { - return (((Band*) d1)->Left - ((Band*) d2)->Left); + return ((Band*) d1)->Left - ((Band*) d2)->Left; } void ComputeClipWindows() @@ -53,8 +56,7 @@ void ComputeClipWindows() { if ((Memory.FillRAM [0x2130] & 0xc0) == 0xc0) { - // The whole of the main screen is switched off, - // completely clip everything. + // The whole of the main screen is switched off, completely clip everything. for (i = 0; i < 6; i++) { IPPU.Clip [c].Count [i] = 1; @@ -66,37 +68,29 @@ void ComputeClipWindows() else if ((Memory.FillRAM [0x2130] & 0xc0) == 0x00) continue; } - else + else if ((Memory.FillRAM [0x2130] & 0x30) == 0x30) // .. colour window on the sub-screen. { - // .. colour window on the sub-screen. - if ((Memory.FillRAM [0x2130] & 0x30) == 0x30) + // The sub-screen is switched off, completely clip everything. + int32_t i; + for (i = 0; i < 6; i++) { - // The sub-screen is switched off, completely - // clip everything. - int32_t i; - for (i = 0; i < 6; i++) - { - IPPU.Clip [1].Count [i] = 1; - IPPU.Clip [1].Left [0][i] = 1; - IPPU.Clip [1].Right [0][i] = 0; - } - return; + IPPU.Clip [1].Count [i] = 1; + IPPU.Clip [1].Left [0][i] = 1; + IPPU.Clip [1].Right [0][i] = 0; } - else if ((Memory.FillRAM [0x2130] & 0x30) == 0x00) - continue; + return; } + else if ((Memory.FillRAM [0x2130] & 0x30) == 0x00) + continue; } - if (w == 5 || pClip->Count [5] || - (Memory.FillRAM [0x212c + c] & Memory.FillRAM [0x212e + c] & (1 << w))) + if (w == 5 || pClip->Count [5] || (Memory.FillRAM [0x212c + c] & Memory.FillRAM [0x212e + c] & (1 << w))) { Band Win1[3]; Band Win2[3]; uint32_t Window1Enabled = 0; uint32_t Window2Enabled = 0; - bool invert = (w == 5 && - ((c == 1 && (Memory.FillRAM [0x2130] & 0x30) == 0x10) || - (c == 0 && (Memory.FillRAM [0x2130] & 0xc0) == 0x40))); + bool invert = (w == 5 && ((c == 1 && (Memory.FillRAM [0x2130] & 0x30) == 0x10) || (c == 0 && (Memory.FillRAM [0x2130] & 0xc0) == 0x40))); if (w == 5 || (Memory.FillRAM [0x212c + c] & Memory.FillRAM [0x212e + c] & (1 << w))) { @@ -107,33 +101,30 @@ void ComputeClipWindows() Win1[Window1Enabled].Left = PPU.Window1Left; Win1[Window1Enabled++].Right = PPU.Window1Right + 1; } - else + else if (PPU.Window1Left <= PPU.Window1Right) { - if (PPU.Window1Left <= PPU.Window1Right) + if (PPU.Window1Left > 0) { - if (PPU.Window1Left > 0) - { - Win1[Window1Enabled].Left = 0; - Win1[Window1Enabled++].Right = PPU.Window1Left; - } - if (PPU.Window1Right < 255) - { - Win1[Window1Enabled].Left = PPU.Window1Right + 1; - Win1[Window1Enabled++].Right = 256; - } - if (Window1Enabled == 0) - { - Win1[Window1Enabled].Left = 1; - Win1[Window1Enabled++].Right = 0; - } + Win1[Window1Enabled].Left = 0; + Win1[Window1Enabled++].Right = PPU.Window1Left; } - else + if (PPU.Window1Right < 255) { - // 'outside' a window with no range - - // appears to be the whole screen. - Win1[Window1Enabled].Left = 0; + Win1[Window1Enabled].Left = PPU.Window1Right + 1; Win1[Window1Enabled++].Right = 256; } + if (Window1Enabled == 0) + { + Win1[Window1Enabled].Left = 1; + Win1[Window1Enabled++].Right = 0; + } + } + else + { + // 'outside' a window with no range - + // appears to be the whole screen. + Win1[Window1Enabled].Left = 0; + Win1[Window1Enabled++].Right = 256; } } if (PPU.ClipWindow2Enable [w]) @@ -198,48 +189,42 @@ void ComputeClipWindows() { if (BAND_EMPTY(Win2[0])) Bands[B++] = Win1[0]; - else - { - if (BANDS_INTERSECT(Win1[0], Win2[0])) - { - OR_BANDS(Bands[0], Win1[0], Win2[0]) - B = 1; - } - else - { - Bands[B++] = Win1[0]; - Bands[B++] = Win2[0]; - } - } - } - else - { - if (BANDS_INTERSECT(Win1[0], Win2[0])) + else if (BANDS_INTERSECT(Win1[0], Win2[0])) { OR_BANDS(Bands[0], Win1[0], Win2[0]) - if (BANDS_INTERSECT(Win1[0], Win2[1])) - OR_BANDS(Bands[1], Win1[0], Win2[1]) - else - Bands[1] = Win2[1]; B = 1; - if (BANDS_INTERSECT(Bands[0], Bands[1])) - OR_BANDS(Bands[0], Bands[0], Bands[1]) - else - B = 2; } - else if (BANDS_INTERSECT(Win1[0], Win2[1])) + else { + Bands[B++] = Win1[0]; Bands[B++] = Win2[0]; - OR_BANDS(Bands[B], Win1[0], Win2[1]); - B++; } + } + else if (BANDS_INTERSECT(Win1[0], Win2[0])) + { + OR_BANDS(Bands[0], Win1[0], Win2[0]) + if (BANDS_INTERSECT(Win1[0], Win2[1])) + OR_BANDS(Bands[1], Win1[0], Win2[1]) else - { - Bands[0] = Win2[0]; - Bands[1] = Win1[0]; - Bands[2] = Win2[1]; - B = 3; - } + Bands[1] = Win2[1]; + B = 1; + if (BANDS_INTERSECT(Bands[0], Bands[1])) + OR_BANDS(Bands[0], Bands[0], Bands[1]) + else + B = 2; + } + else if (BANDS_INTERSECT(Win1[0], Win2[1])) + { + Bands[B++] = Win2[0]; + OR_BANDS(Bands[B], Win1[0], Win2[1]); + B++; + } + else + { + Bands[0] = Win2[0]; + Bands[1] = Win1[0]; + Bands[2] = Win2[1]; + B = 3; } } } @@ -426,7 +411,6 @@ void ComputeClipWindows() { j = 0; // Easy case to deal with, so special case it. - if (Bands[0].Left > 0) { pClip->Left[j][w] = 0; @@ -500,7 +484,6 @@ void ComputeClipWindows() { // Only one window enabled so no need to perform // complex overlap logic... - if (Window1Enabled) { if (invert) diff --git a/source/cpuaddr.h b/source/cpuaddr.h index 4c0fb84..bdeb242 100644 --- a/source/cpuaddr.h +++ b/source/cpuaddr.h @@ -13,13 +13,13 @@ static INLINE void Immediate8(void) CPU.PC++; } -static INLINE void Immediate16() +static INLINE void Immediate16(void) { OpAddress = ICPU.ShiftedPB + CPU.PC - CPU.PCBase; CPU.PC += 2; } -static INLINE void Relative() +static INLINE void Relative(void) { int8_t Int8 = *CPU.PC++; #ifndef SA1_OPCODES @@ -28,7 +28,7 @@ static INLINE void Relative() OpAddress = ((int32_t)(CPU.PC - CPU.PCBase) + Int8) & 0xffff; } -static INLINE void RelativeLong() +static INLINE void RelativeLong(void) { #ifdef FAST_LSB_WORD_ACCESS OpAddress = *(uint16_t*) CPU.PC; @@ -152,9 +152,6 @@ static INLINE void DirectIndirectIndexed(bool read) if (read) OpenBus = (uint8_t)(OpAddress >> 8); OpAddress += ICPU.ShiftedDB + ICPU.Registers.Y.W; - - // XXX: always add one if STA - // XXX: else Add one cycle if crosses page boundary } static INLINE void DirectIndirectIndexedLong(bool read) @@ -221,8 +218,6 @@ static INLINE void AbsoluteIndexedX(bool read) #ifndef SA1_OPCODES CPU.Cycles += CPU.MemSpeedx2; #endif - // XXX: always add one cycle for ROL, LSR, etc - // XXX: else is cross page boundary add one cycle } static INLINE void AbsoluteIndexedY(bool read) @@ -238,8 +233,6 @@ static INLINE void AbsoluteIndexedY(bool read) #ifndef SA1_OPCODES CPU.Cycles += CPU.MemSpeedx2; #endif - // XXX: always add cycle for STA - // XXX: else is cross page boundary add one cycle } static INLINE void AbsoluteLongIndexedX(bool read) diff --git a/source/cpuexec.c b/source/cpuexec.c index ef96339..fedb318 100644 --- a/source/cpuexec.c +++ b/source/cpuexec.c @@ -367,7 +367,6 @@ void S9xDoHBlankProcessing_SFX() if (!PPU.ForcedBlanking) { uint8_t tmp = 0; - PPU.OAMAddr = PPU.SavedOAMAddr; if (PPU.OAMPriorityRotation) @@ -399,45 +398,42 @@ void S9xDoHBlankProcessing_SFX() CPU.Flags &= ~NMI_FLAG; S9xStartScreenRefresh(); } - if (CPU.V_Counter >= FIRST_VISIBLE_LINE && - CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) + if (CPU.V_Counter >= FIRST_VISIBLE_LINE && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) RenderLine(CPU.V_Counter - FIRST_VISIBLE_LINE); #ifndef USE_BLARGG_APU + if (APU.TimerEnabled [2]) { - if (APU.TimerEnabled [2]) + APU.Timer [2] += 4; + while (APU.Timer [2] >= APU.TimerTarget [2]) { - APU.Timer [2] += 4; - while (APU.Timer [2] >= APU.TimerTarget [2]) + IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf; + APU.Timer [2] -= APU.TimerTarget [2]; + IAPU.WaitCounter++; + IAPU.APUExecuting = true; + } + } + if (CPU.V_Counter & 1) + { + if (APU.TimerEnabled [0]) + { + APU.Timer [0]++; + if (APU.Timer [0] >= APU.TimerTarget [0]) { - IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf; - APU.Timer [2] -= APU.TimerTarget [2]; + IAPU.RAM [0xfd] = (IAPU.RAM [0xfd] + 1) & 0xf; + APU.Timer [0] = 0; IAPU.WaitCounter++; IAPU.APUExecuting = true; } } - if (CPU.V_Counter & 1) + if (APU.TimerEnabled [1]) { - if (APU.TimerEnabled [0]) + APU.Timer [1]++; + if (APU.Timer [1] >= APU.TimerTarget [1]) { - APU.Timer [0]++; - if (APU.Timer [0] >= APU.TimerTarget [0]) - { - IAPU.RAM [0xfd] = (IAPU.RAM [0xfd] + 1) & 0xf; - APU.Timer [0] = 0; - IAPU.WaitCounter++; - IAPU.APUExecuting = true; - } - } - if (APU.TimerEnabled [1]) - { - APU.Timer [1]++; - if (APU.Timer [1] >= APU.TimerTarget [1]) - { - IAPU.RAM [0xfe] = (IAPU.RAM [0xfe] + 1) & 0xf; - APU.Timer [1] = 0; - IAPU.WaitCounter++; - IAPU.APUExecuting = true; - } + IAPU.RAM [0xfe] = (IAPU.RAM [0xfe] + 1) & 0xf; + APU.Timer [1] = 0; + IAPU.WaitCounter++; + IAPU.APUExecuting = true; } } } @@ -501,7 +497,6 @@ void S9xDoHBlankProcessing_NoSFX() if (!PPU.ForcedBlanking) { uint8_t tmp = 0; - PPU.OAMAddr = PPU.SavedOAMAddr; if (PPU.OAMPriorityRotation) @@ -533,45 +528,42 @@ void S9xDoHBlankProcessing_NoSFX() CPU.Flags &= ~NMI_FLAG; S9xStartScreenRefresh(); } - if (CPU.V_Counter >= FIRST_VISIBLE_LINE && - CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) + if (CPU.V_Counter >= FIRST_VISIBLE_LINE && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) RenderLine(CPU.V_Counter - FIRST_VISIBLE_LINE); #ifndef USE_BLARGG_APU + if (APU.TimerEnabled [2]) { - if (APU.TimerEnabled [2]) + APU.Timer [2] += 4; + while (APU.Timer [2] >= APU.TimerTarget [2]) { - APU.Timer [2] += 4; - while (APU.Timer [2] >= APU.TimerTarget [2]) + IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf; + APU.Timer [2] -= APU.TimerTarget [2]; + IAPU.WaitCounter++; + IAPU.APUExecuting = true; + } + } + if (CPU.V_Counter & 1) + { + if (APU.TimerEnabled [0]) + { + APU.Timer [0]++; + if (APU.Timer [0] >= APU.TimerTarget [0]) { - IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf; - APU.Timer [2] -= APU.TimerTarget [2]; + IAPU.RAM [0xfd] = (IAPU.RAM [0xfd] + 1) & 0xf; + APU.Timer [0] = 0; IAPU.WaitCounter++; IAPU.APUExecuting = true; } } - if (CPU.V_Counter & 1) + if (APU.TimerEnabled [1]) { - if (APU.TimerEnabled [0]) + APU.Timer [1]++; + if (APU.Timer [1] >= APU.TimerTarget [1]) { - APU.Timer [0]++; - if (APU.Timer [0] >= APU.TimerTarget [0]) - { - IAPU.RAM [0xfd] = (IAPU.RAM [0xfd] + 1) & 0xf; - APU.Timer [0] = 0; - IAPU.WaitCounter++; - IAPU.APUExecuting = true; - } - } - if (APU.TimerEnabled [1]) - { - APU.Timer [1]++; - if (APU.Timer [1] >= APU.TimerTarget [1]) - { - IAPU.RAM [0xfe] = (IAPU.RAM [0xfe] + 1) & 0xf; - APU.Timer [1] = 0; - IAPU.WaitCounter++; - IAPU.APUExecuting = true; - } + IAPU.RAM [0xfe] = (IAPU.RAM [0xfe] + 1) & 0xf; + APU.Timer [1] = 0; + IAPU.WaitCounter++; + IAPU.APUExecuting = true; } } } diff --git a/source/cpuexec.h b/source/cpuexec.h index 9654d86..3a5075b 100644 --- a/source/cpuexec.h +++ b/source/cpuexec.h @@ -116,10 +116,8 @@ static INLINE void S9xReschedule(void) } if (PPU.HTimerEnabled && - (int32_t) PPU.HTimerPosition < max && - (int32_t) PPU.HTimerPosition > CPU.NextEvent && - (!PPU.VTimerEnabled || - (PPU.VTimerEnabled && CPU.V_Counter == PPU.IRQVBeamPos))) + (int32_t) PPU.HTimerPosition < max && (int32_t) PPU.HTimerPosition > CPU.NextEvent && + (!PPU.VTimerEnabled || (PPU.VTimerEnabled && CPU.V_Counter == PPU.IRQVBeamPos))) { which = (int32_t) PPU.HTimerPosition < Settings.HBlankStart ? HTIMER_BEFORE_EVENT : HTIMER_AFTER_EVENT; max = PPU.HTimerPosition; @@ -127,5 +125,4 @@ static INLINE void S9xReschedule(void) CPU.NextEvent = max; CPU.WhichEvent = which; } - #endif diff --git a/source/cpumacro.h b/source/cpumacro.h index 313e920..77d569f 100644 --- a/source/cpumacro.h +++ b/source/cpumacro.h @@ -19,7 +19,7 @@ static INLINE void SetZN8(uint8_t Work) ICPU._Negative = Work; } -static INLINE void ADC8() +static INLINE void ADC8(void) { uint8_t Work8 = S9xGetByte(OpAddress); @@ -67,7 +67,7 @@ static INLINE void ADC8() SetZN8(ICPU.Registers.AL); } -static INLINE void ADC16() +static INLINE void ADC16(void) { uint16_t Work16 = S9xGetWord(OpAddress); @@ -134,19 +134,19 @@ static INLINE void ADC16() SetZN16(ICPU.Registers.A.W); } -static INLINE void AND16() +static INLINE void AND16(void) { ICPU.Registers.A.W &= S9xGetWord(OpAddress); SetZN16(ICPU.Registers.A.W); } -static INLINE void AND8() +static INLINE void AND8(void) { ICPU.Registers.AL &= S9xGetByte(OpAddress); SetZN8(ICPU.Registers.AL); } -static INLINE void A_ASL16() +static INLINE void A_ASL16(void) { #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; @@ -156,7 +156,7 @@ static INLINE void A_ASL16() SetZN16(ICPU.Registers.A.W); } -static INLINE void A_ASL8() +static INLINE void A_ASL8(void) { #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; @@ -166,7 +166,7 @@ static INLINE void A_ASL8() SetZN8(ICPU.Registers.AL); } -static INLINE void ASL16() +static INLINE void ASL16(void) { uint16_t Work16; #ifndef SA1_OPCODES @@ -180,7 +180,7 @@ static INLINE void ASL16() SetZN16(Work16); } -static INLINE void ASL8() +static INLINE void ASL8(void) { uint8_t Work8; #ifndef SA1_OPCODES @@ -193,7 +193,7 @@ static INLINE void ASL8() SetZN8(Work8); } -static INLINE void BIT16() +static INLINE void BIT16(void) { uint16_t Work16 = S9xGetWord(OpAddress); ICPU._Overflow = (Work16 & 0x4000) != 0; @@ -201,7 +201,7 @@ static INLINE void BIT16() ICPU._Zero = (Work16 & ICPU.Registers.A.W) != 0; } -static INLINE void BIT8() +static INLINE void BIT8(void) { uint8_t Work8 = S9xGetByte(OpAddress); ICPU._Overflow = (Work8 & 0x40) != 0; @@ -209,49 +209,49 @@ static INLINE void BIT8() ICPU._Zero = Work8 & ICPU.Registers.AL; } -static INLINE void CMP16() +static INLINE void CMP16(void) { int32_t Int32 = (int32_t) ICPU.Registers.A.W - (int32_t) S9xGetWord(OpAddress); ICPU._Carry = Int32 >= 0; SetZN16((uint16_t) Int32); } -static INLINE void CMP8() +static INLINE void CMP8(void) { int16_t Int16 = (int16_t) ICPU.Registers.AL - (int16_t) S9xGetByte(OpAddress); ICPU._Carry = Int16 >= 0; SetZN8((uint8_t) Int16); } -static INLINE void CMX16() +static INLINE void CMX16(void) { int32_t Int32 = (int32_t) ICPU.Registers.X.W - (int32_t) S9xGetWord(OpAddress); ICPU._Carry = Int32 >= 0; SetZN16((uint16_t) Int32); } -static INLINE void CMX8() +static INLINE void CMX8(void) { int16_t Int16 = (int16_t) ICPU.Registers.XL - (int16_t) S9xGetByte(OpAddress); ICPU._Carry = Int16 >= 0; SetZN8((uint8_t) Int16); } -static INLINE void CMY16() +static INLINE void CMY16(void) { int32_t Int32 = (int32_t) ICPU.Registers.Y.W - (int32_t) S9xGetWord(OpAddress); ICPU._Carry = Int32 >= 0; SetZN16((uint16_t) Int32); } -static INLINE void CMY8() +static INLINE void CMY8(void) { int16_t Int16 = (int16_t) ICPU.Registers.YL - (int16_t) S9xGetByte(OpAddress); ICPU._Carry = Int16 >= 0; SetZN8((uint8_t) Int16); } -static INLINE void A_DEC16() +static INLINE void A_DEC16(void) { #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; @@ -261,7 +261,7 @@ static INLINE void A_DEC16() SetZN16(ICPU.Registers.A.W); } -static INLINE void A_DEC8() +static INLINE void A_DEC8(void) { #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; @@ -271,10 +271,9 @@ static INLINE void A_DEC8() SetZN8(ICPU.Registers.AL); } -static INLINE void DEC16() +static INLINE void DEC16(void) { uint16_t Work16; - #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; #endif @@ -285,10 +284,9 @@ static INLINE void DEC16() SetZN16(Work16); } -static INLINE void DEC8() +static INLINE void DEC8(void) { uint8_t Work8; - #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; #endif @@ -298,19 +296,19 @@ static INLINE void DEC8() SetZN8(Work8); } -static INLINE void EOR16() +static INLINE void EOR16(void) { ICPU.Registers.A.W ^= S9xGetWord(OpAddress); SetZN16(ICPU.Registers.A.W); } -static INLINE void EOR8() +static INLINE void EOR8(void) { ICPU.Registers.AL ^= S9xGetByte(OpAddress); SetZN8(ICPU.Registers.AL); } -static INLINE void A_INC16() +static INLINE void A_INC16(void) { #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; @@ -320,7 +318,7 @@ static INLINE void A_INC16() SetZN16(ICPU.Registers.A.W); } -static INLINE void A_INC8() +static INLINE void A_INC8(void) { #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; @@ -330,7 +328,7 @@ static INLINE void A_INC8() SetZN8(ICPU.Registers.AL); } -static INLINE void INC16() +static INLINE void INC16(void) { uint16_t Work16; #ifndef SA1_OPCODES @@ -343,10 +341,9 @@ static INLINE void INC16() SetZN16(Work16); } -static INLINE void INC8() +static INLINE void INC8(void) { uint8_t Work8; - #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; #endif @@ -356,43 +353,43 @@ static INLINE void INC8() SetZN8(Work8); } -static INLINE void LDA16() +static INLINE void LDA16(void) { ICPU.Registers.A.W = S9xGetWord(OpAddress); SetZN16(ICPU.Registers.A.W); } -static INLINE void LDA8() +static INLINE void LDA8(void) { ICPU.Registers.AL = S9xGetByte(OpAddress); SetZN8(ICPU.Registers.AL); } -static INLINE void LDX16() +static INLINE void LDX16(void) { ICPU.Registers.X.W = S9xGetWord(OpAddress); SetZN16(ICPU.Registers.X.W); } -static INLINE void LDX8() +static INLINE void LDX8(void) { ICPU.Registers.XL = S9xGetByte(OpAddress); SetZN8(ICPU.Registers.XL); } -static INLINE void LDY16() +static INLINE void LDY16(void) { ICPU.Registers.Y.W = S9xGetWord(OpAddress); SetZN16(ICPU.Registers.Y.W); } -static INLINE void LDY8() +static INLINE void LDY8(void) { ICPU.Registers.YL = S9xGetByte(OpAddress); SetZN8(ICPU.Registers.YL); } -static INLINE void A_LSR16() +static INLINE void A_LSR16(void) { #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; @@ -402,7 +399,7 @@ static INLINE void A_LSR16() SetZN16(ICPU.Registers.A.W); } -static INLINE void A_LSR8() +static INLINE void A_LSR8(void) { #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; @@ -412,10 +409,9 @@ static INLINE void A_LSR8() SetZN8(ICPU.Registers.AL); } -static INLINE void LSR16() +static INLINE void LSR16(void) { uint16_t Work16; - #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; #endif @@ -427,10 +423,9 @@ static INLINE void LSR16() SetZN16(Work16); } -static INLINE void LSR8() +static INLINE void LSR8(void) { uint8_t Work8; - #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; #endif @@ -441,19 +436,19 @@ static INLINE void LSR8() SetZN8(Work8); } -static INLINE void ORA16() +static INLINE void ORA16(void) { ICPU.Registers.A.W |= S9xGetWord(OpAddress); SetZN16(ICPU.Registers.A.W); } -static INLINE void ORA8() +static INLINE void ORA8(void) { ICPU.Registers.AL |= S9xGetByte(OpAddress); SetZN8(ICPU.Registers.AL); } -static INLINE void A_ROL16() +static INLINE void A_ROL16(void) { uint32_t Work32; #ifndef SA1_OPCODES @@ -465,7 +460,7 @@ static INLINE void A_ROL16() SetZN16((uint16_t) Work32); } -static INLINE void A_ROL8() +static INLINE void A_ROL8(void) { uint16_t Work16; #ifndef SA1_OPCODES @@ -479,10 +474,9 @@ static INLINE void A_ROL8() SetZN8((uint8_t) Work16); } -static INLINE void ROL16() +static INLINE void ROL16(void) { uint32_t Work32; - #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; #endif @@ -495,7 +489,7 @@ static INLINE void ROL16() SetZN16((uint16_t) Work32); } -static INLINE void ROL8() +static INLINE void ROL8(void) { uint16_t Work16; #ifndef SA1_OPCODES @@ -509,7 +503,7 @@ static INLINE void ROL8() SetZN8((uint8_t) Work16); } -static INLINE void A_ROR16() +static INLINE void A_ROR16(void) { uint32_t Work32; #ifndef SA1_OPCODES @@ -523,7 +517,7 @@ static INLINE void A_ROR16() SetZN16((uint16_t) Work32); } -static INLINE void A_ROR8() +static INLINE void A_ROR8(void) { uint16_t Work16; #ifndef SA1_OPCODES @@ -536,10 +530,9 @@ static INLINE void A_ROR8() SetZN8((uint8_t) Work16); } -static INLINE void ROR16() +static INLINE void ROR16(void) { uint32_t Work32; - #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; #endif @@ -552,7 +545,7 @@ static INLINE void ROR16() SetZN16((uint16_t) Work32); } -static INLINE void ROR8() +static INLINE void ROR8(void) { uint16_t Work16; #ifndef SA1_OPCODES @@ -566,7 +559,7 @@ static INLINE void ROR8() SetZN8((uint8_t) Work16); } -static INLINE void SBC16() +static INLINE void SBC16(void) { uint16_t Work16 = S9xGetWord(OpAddress); @@ -633,7 +626,7 @@ static INLINE void SBC16() SetZN16(ICPU.Registers.A.W); } -static INLINE void SBC8() +static INLINE void SBC8(void) { uint8_t Work8 = S9xGetByte(OpAddress); if (CheckDecimal()) @@ -681,50 +674,49 @@ static INLINE void SBC8() SetZN8(ICPU.Registers.AL); } -static INLINE void STA16() +static INLINE void STA16(void) { S9xSetWord(ICPU.Registers.A.W, OpAddress); } -static INLINE void STA8() +static INLINE void STA8(void) { S9xSetByte(ICPU.Registers.AL, OpAddress); } -static INLINE void STX16() +static INLINE void STX16(void) { S9xSetWord(ICPU.Registers.X.W, OpAddress); } -static INLINE void STX8() +static INLINE void STX8(void) { S9xSetByte(ICPU.Registers.XL, OpAddress); } -static INLINE void STY16() +static INLINE void STY16(void) { S9xSetWord(ICPU.Registers.Y.W, OpAddress); } -static INLINE void STY8() +static INLINE void STY8(void) { S9xSetByte(ICPU.Registers.YL, OpAddress); } -static INLINE void STZ16() +static INLINE void STZ16(void) { S9xSetWord(0, OpAddress); } -static INLINE void STZ8() +static INLINE void STZ8(void) { S9xSetByte(0, OpAddress); } -static INLINE void TSB16() +static INLINE void TSB16(void) { uint16_t Work16; - #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; #endif @@ -735,7 +727,7 @@ static INLINE void TSB16() S9xSetByte(Work16 & 0xFF, OpAddress); } -static INLINE void TSB8() +static INLINE void TSB8(void) { uint8_t Work8; #ifndef SA1_OPCODES @@ -747,7 +739,7 @@ static INLINE void TSB8() S9xSetByte(Work8, OpAddress); } -static INLINE void TRB16() +static INLINE void TRB16(void) { uint16_t Work16; #ifndef SA1_OPCODES @@ -760,7 +752,7 @@ static INLINE void TRB16() S9xSetByte(Work16 & 0xFF, OpAddress); } -static INLINE void TRB8() +static INLINE void TRB8(void) { uint8_t Work8; #ifndef SA1_OPCODES diff --git a/source/cpuops.c b/source/cpuops.c index 2254713..9a15852 100644 --- a/source/cpuops.c +++ b/source/cpuops.c @@ -20,7 +20,7 @@ int32_t OpAddress; -/* ADC *************************************************************************************** */ +/* ADC */ static void Op69M1(void) { Immediate8(); @@ -201,9 +201,7 @@ static void Op73M0(void) ADC16(); } -/**********************************************************************************************/ - -/* AND *************************************************************************************** */ +/* AND */ static void Op29M1(void) { ICPU.Registers.AL &= *CPU.PC++; @@ -394,9 +392,8 @@ static void Op33M0(void) StackRelativeIndirectIndexed(true); AND16(); } -/**********************************************************************************************/ -/* ASL *************************************************************************************** */ +/* ASL */ static void Op0AM1(void) { A_ASL8(); @@ -454,9 +451,8 @@ static void Op1EM0(void) AbsoluteIndexedX(false); ASL16(); } -/**********************************************************************************************/ -/* BIT *************************************************************************************** */ +/* BIT */ static void Op89M1(void) { ICPU._Zero = ICPU.Registers.AL & *CPU.PC++; @@ -525,9 +521,8 @@ static void Op3CM0(void) AbsoluteIndexedX(true); BIT16(); } -/**********************************************************************************************/ -/* CMP *************************************************************************************** */ +/* CMP */ static void OpC9M1(void) { int32_t Int32 = (int32_t) ICPU.Registers.AL - (int32_t) *CPU.PC++; @@ -721,9 +716,7 @@ static void OpD3M0(void) CMP16(); } -/**********************************************************************************************/ - -/* CMX *************************************************************************************** */ +/* CMX */ static void OpE0X1(void) { int32_t Int32 = (int32_t) ICPU.Registers.XL - (int32_t) *CPU.PC++; @@ -773,9 +766,7 @@ static void OpECX0(void) CMX16(); } -/**********************************************************************************************/ - -/* CMY *************************************************************************************** */ +/* CMY */ static void OpC0X1(void) { int32_t Int32 = (int32_t) ICPU.Registers.YL - (int32_t) *CPU.PC++; @@ -825,9 +816,7 @@ static void OpCCX0(void) CMY16(); } -/**********************************************************************************************/ - -/* DEC *************************************************************************************** */ +/* DEC */ static void Op3AM1(void) { A_DEC8(); @@ -886,9 +875,7 @@ static void OpDEM0(void) DEC16(); } -/**********************************************************************************************/ - -/* EOR *************************************************************************************** */ +/* EOR */ static void Op49M1(void) { ICPU.Registers.AL ^= *CPU.PC++; @@ -1080,9 +1067,7 @@ static void Op53M0(void) EOR16(); } -/**********************************************************************************************/ - -/* INC *************************************************************************************** */ +/* INC */ static void Op1AM1(void) { A_INC8(); @@ -1141,8 +1126,7 @@ static void OpFEM0(void) INC16(); } -/**********************************************************************************************/ -/* LDA *************************************************************************************** */ +/* LDA */ static void OpA9M1(void) { ICPU.Registers.AL = *CPU.PC++; @@ -1335,9 +1319,7 @@ static void OpB3M0(void) LDA16(); } -/**********************************************************************************************/ - -/* LDX *************************************************************************************** */ +/* LDX */ static void OpA2X1(void) { ICPU.Registers.XL = *CPU.PC++; @@ -1408,9 +1390,8 @@ static void OpBEX0(void) AbsoluteIndexedY(true); LDX16(); } -/**********************************************************************************************/ -/* LDY *************************************************************************************** */ +/* LDY */ static void OpA0X1(void) { ICPU.Registers.YL = *CPU.PC++; @@ -1482,9 +1463,8 @@ static void OpBCX0(void) AbsoluteIndexedX(true); LDY16(); } -/**********************************************************************************************/ -/* LSR *************************************************************************************** */ +/* LSR */ static void Op4AM1(void) { A_LSR8(); @@ -1543,9 +1523,7 @@ static void Op5EM0(void) LSR16(); } -/**********************************************************************************************/ - -/* ORA *************************************************************************************** */ +/* ORA */ static void Op09M1(void) { ICPU.Registers.AL |= *CPU.PC++; @@ -1737,9 +1715,7 @@ static void Op13M0(void) ORA16(); } -/**********************************************************************************************/ - -/* ROL *************************************************************************************** */ +/* ROL */ static void Op2AM1(void) { A_ROL8(); @@ -1797,9 +1773,8 @@ static void Op3EM0(void) AbsoluteIndexedX(false); ROL16(); } -/**********************************************************************************************/ -/* ROR *************************************************************************************** */ +/* ROR */ static void Op6AM1(void) { A_ROR8(); @@ -1857,9 +1832,8 @@ static void Op7EM0(void) AbsoluteIndexedX(false); ROR16(); } -/**********************************************************************************************/ -/* SBC *************************************************************************************** */ +/* SBC */ static void OpE9M1(void) { Immediate8(); @@ -2039,9 +2013,8 @@ static void OpF3M0(void) StackRelativeIndirectIndexed(true); SBC16(); } -/**********************************************************************************************/ -/* STA *************************************************************************************** */ +/* STA */ static void Op85M1(void) { Direct(false); @@ -2217,9 +2190,8 @@ static void Op93M0(void) StackRelativeIndirectIndexed(false); STA16(); } -/**********************************************************************************************/ -/* STX *************************************************************************************** */ +/* STX */ static void Op86X1(void) { Direct(false); @@ -2255,9 +2227,8 @@ static void Op8EX0(void) Absolute(false); STX16(); } -/**********************************************************************************************/ -/* STY *************************************************************************************** */ +/* STY */ static void Op84X1(void) { Direct(false); @@ -2293,9 +2264,8 @@ static void Op8CX0(void) Absolute(false); STY16(); } -/**********************************************************************************************/ -/* STZ *************************************************************************************** */ +/* STZ */ static void Op64M1(void) { Direct(false); @@ -2344,9 +2314,7 @@ static void Op9EM0(void) STZ16(); } -/**********************************************************************************************/ - -/* TRB *************************************************************************************** */ +/* TRB */ static void Op14M1(void) { Direct(false); @@ -2370,9 +2338,8 @@ static void Op1CM0(void) Absolute(false); TRB16(); } -/**********************************************************************************************/ -/* TSB *************************************************************************************** */ +/* TSB */ static void Op04M1(void) { Direct(false); @@ -2397,9 +2364,7 @@ static void Op0CM0(void) TSB16(); } -/**********************************************************************************************/ - -/* Branch Instructions *********************************************************************** */ +/* Branch Instructions */ #ifndef SA1_OPCODES #define BranchCheck() \ if(CPU.BranchSkip) \ @@ -2421,7 +2386,6 @@ static INLINE void CPUShutdown(void) // interrupt. Interrupts are delayed for a few cycles already, but // the delay could allow the shutdown code to cycle skip again. // Was causing screen flashing on Top Gear 3000. - if (CPU.WaitCounter == 0 && !(CPU.Flags & (IRQ_PENDING_FLAG | NMI_FLAG))) { CPU.WaitAddress = NULL; @@ -2433,8 +2397,7 @@ static INLINE void CPUShutdown(void) do { APU_EXECUTE1(); - } - while (APU.Cycles < CPU.NextEvent); + } while (APU.Cycles < CPU.NextEvent); ICPU.CPUExecuting = true; } #endif @@ -2474,8 +2437,7 @@ static INLINE void ForceShutdown(void) do { APU_EXECUTE1(); - } - while (APU.Cycles < CPU.NextEvent); + } while (APU.Cycles < CPU.NextEvent); ICPU.CPUExecuting = true; } #endif @@ -2615,9 +2577,8 @@ static void Op70(void) CPUShutdown(); } } -/**********************************************************************************************/ -/* ClearFlag Instructions ******************************************************************** */ +/* ClearFlag Instructions */ /* CLC */ static void Op18(void) { @@ -2643,7 +2604,6 @@ static void Op58(void) #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; #endif - /* CHECK_FOR_IRQ(); */ } /* CLV */ @@ -2654,9 +2614,8 @@ static void OpB8(void) CPU.Cycles += ONE_CYCLE; #endif } -/**********************************************************************************************/ -/* DEX/DEY *********************************************************************************** */ +/* DEX/DEY */ static void OpCAX1(void) { #ifndef SA1_OPCODES @@ -2696,9 +2655,8 @@ static void Op88X0(void) ICPU.Registers.Y.W--; SetZN16(ICPU.Registers.Y.W); } -/**********************************************************************************************/ -/* INX/INY *********************************************************************************** */ +/* INX/INY */ static void OpE8X1(void) { #ifndef SA1_OPCODES @@ -2739,35 +2697,32 @@ static void OpC8X0(void) SetZN16(ICPU.Registers.Y.W); } -/**********************************************************************************************/ - -/* NOP *************************************************************************************** */ +/* NOP */ static void OpEA(void) { #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; #endif } -/**********************************************************************************************/ -/* PUSH Instructions ************************************************************************* */ +/* PUSH Instructions */ #define PushB(b)\ S9xSetByte(b, ICPU.Registers.S.W--); #define PushBE(b)\ PushB(b);\ - ICPU.Registers.SH = 0x01; + ICPU.Registers.SH = 0x01 #define PushW(w)\ S9xSetByte((w) >> 8, ICPU.Registers.S.W);\ S9xSetByte((w) & 0xff, (ICPU.Registers.S.W - 1) & 0xffff);\ - ICPU.Registers.S.W -= 2; + ICPU.Registers.S.W -= 2 #define PushWE(w)\ PushW(w); \ - ICPU.Registers.SH = 0x01; + ICPU.Registers.SH = 0x01 -//PEA NL +/* PEA NL */ static void OpF4E1(void) { Absolute(false); @@ -2780,7 +2735,7 @@ static void OpF4(void) PushW((uint16_t)OpAddress); } -//PEI NL +/* PEI NL */ static void OpD4E1(void) { DirectIndirect(false); @@ -2793,20 +2748,20 @@ static void OpD4(void) PushW((uint16_t)OpAddress); } -//PER NL +/* PER NL */ static void Op62E1(void) { - RelativeLong(false); + RelativeLong(); PushWE((uint16_t)OpAddress); } static void Op62(void) { - RelativeLong(false); + RelativeLong(); PushW((uint16_t)OpAddress); } -//PHA +/* PHA */ static void Op48E1(void) { PushBE(ICPU.Registers.AL); @@ -2831,7 +2786,7 @@ static void Op48M0(void) #endif } -//PHB +/* PHB */ static void Op8BE1(void) { PushBE(ICPU.Registers.DB); @@ -2848,7 +2803,7 @@ static void Op8B(void) #endif } -//PHD NL +/* PHD NL */ static void Op0BE1(void) { PushWE(ICPU.Registers.D.W); @@ -2865,7 +2820,7 @@ static void Op0B(void) #endif } -//PHK +/* PHK */ static void Op4BE1(void) { PushBE(ICPU.Registers.PB); @@ -2882,7 +2837,7 @@ static void Op4B(void) #endif } -//PHP +/* PHP */ static void Op08E1(void) { S9xPackStatus(); @@ -2901,7 +2856,7 @@ static void Op08(void) #endif } -//PHX +/* PHX */ static void OpDAE1(void) { PushBE(ICPU.Registers.XL); @@ -2926,7 +2881,7 @@ static void OpDAX0(void) #endif } -//PHY +/* PHY */ static void Op5AE1(void) { PushBE(ICPU.Registers.YL); @@ -2950,25 +2905,24 @@ static void Op5AX0(void) CPU.Cycles += ONE_CYCLE; #endif } -/**********************************************************************************************/ -/* PULL Instructions ************************************************************************* */ +/* PULL Instructions */ #define PullB(b)\ - b = S9xGetByte (++ICPU.Registers.S.W); + b = S9xGetByte (++ICPU.Registers.S.W) #define PullBE(b)\ PullB(b);\ - ICPU.Registers.SH = 0x01; + ICPU.Registers.SH = 0x01 #define PullW(w)\ w = S9xGetByte(++ICPU.Registers.S.W);\ - w |= (S9xGetByte(++ICPU.Registers.S.W) << 8); + w |= (S9xGetByte(++ICPU.Registers.S.W) << 8) #define PullWE(w)\ PullW(w);\ - ICPU.Registers.SH = 0x01; + ICPU.Registers.SH = 0x01 -//PLA +/* PLA */ static void Op68E1(void) { #ifndef SA1_OPCODES @@ -2996,7 +2950,7 @@ static void Op68M0(void) SetZN16(ICPU.Registers.A.W); } -//PLB +/* PLB */ static void OpABE1(void) { #ifndef SA1_OPCODES @@ -3017,8 +2971,7 @@ static void OpAB(void) ICPU.ShiftedDB = ICPU.Registers.DB << 16; } -/* PHP */ -//PLD NL +/* PLD NL */ static void Op2BE1(void) { #ifndef SA1_OPCODES @@ -3070,7 +3023,7 @@ static void Op28(void) S9xFixCycles(); } -//PLX +/* PLX */ static void OpFAE1(void) { #ifndef SA1_OPCODES @@ -3098,7 +3051,7 @@ static void OpFAX0(void) SetZN16(ICPU.Registers.X.W); } -//PLY +/* PLY */ static void Op7AE1(void) { #ifndef SA1_OPCODES @@ -3126,9 +3079,6 @@ static void Op7AX0(void) SetZN16(ICPU.Registers.Y.W); } -/**********************************************************************************************/ - -/* SetFlag Instructions ********************************************************************** */ /* SEC */ static void Op38(void) { @@ -3155,9 +3105,7 @@ static void Op78(void) CPU.Cycles += ONE_CYCLE; #endif } -/**********************************************************************************************/ -/* Transfer Instructions ********************************************************************* */ /* TAX8 */ static void OpAAX1(void) { @@ -3335,9 +3283,7 @@ static void OpBBX0(void) SetZN16(ICPU.Registers.X.W); } -/**********************************************************************************************/ - -/* XCE *************************************************************************************** */ +/* XCE */ static void OpFB(void) { uint8_t A1, A2; @@ -3361,9 +3307,8 @@ static void OpFB(void) } S9xFixCycles(); } -/**********************************************************************************************/ -/* BRK *************************************************************************************** */ +/* BRK */ static void Op00(void) { if (!CheckEmulation()) @@ -3400,17 +3345,15 @@ static void Op00(void) #endif } } -/**********************************************************************************************/ -/* BRL ************************************************************************************** */ +/* BRL */ static void Op82(void) { RelativeLong(); S9xSetPCBase(ICPU.ShiftedPB + OpAddress); } -/**********************************************************************************************/ -/* IRQ *************************************************************************************** */ +/* IRQ */ void S9xOpcode_IRQ(void) { if (!CheckEmulation()) @@ -3426,16 +3369,12 @@ void S9xOpcode_IRQ(void) ICPU.Registers.PB = 0; ICPU.ShiftedPB = 0; #ifdef SA1_OPCODES - S9xSA1SetPCBase(Memory.FillRAM [0x2207] | - (Memory.FillRAM [0x2208] << 8)); + S9xSA1SetPCBase(Memory.FillRAM [0x2207] | (Memory.FillRAM [0x2208] << 8)); #else if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) - S9xSetPCBase(Memory.FillRAM [0x220e] | - (Memory.FillRAM [0x220f] << 8)); + S9xSetPCBase(Memory.FillRAM [0x220e] | (Memory.FillRAM [0x220f] << 8)); else S9xSetPCBase(S9xGetWord(0xFFEE)); -#endif -#ifndef SA1_OPCODES CPU.Cycles += TWO_CYCLES; #endif } @@ -3451,24 +3390,18 @@ void S9xOpcode_IRQ(void) ICPU.Registers.PB = 0; ICPU.ShiftedPB = 0; #ifdef SA1_OPCODES - S9xSA1SetPCBase(Memory.FillRAM [0x2207] | - (Memory.FillRAM [0x2208] << 8)); + S9xSA1SetPCBase(Memory.FillRAM [0x2207] | (Memory.FillRAM [0x2208] << 8)); #else if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) - S9xSetPCBase(Memory.FillRAM [0x220e] | - (Memory.FillRAM [0x220f] << 8)); + S9xSetPCBase(Memory.FillRAM [0x220e] | (Memory.FillRAM [0x220f] << 8)); else S9xSetPCBase(S9xGetWord(0xFFFE)); -#endif -#ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; #endif } } -/**********************************************************************************************/ - -/* NMI *************************************************************************************** */ +/* NMI */ void S9xOpcode_NMI(void) { if (!CheckEmulation()) @@ -3484,16 +3417,12 @@ void S9xOpcode_NMI(void) ICPU.Registers.PB = 0; ICPU.ShiftedPB = 0; #ifdef SA1_OPCODES - S9xSA1SetPCBase(Memory.FillRAM [0x2205] | - (Memory.FillRAM [0x2206] << 8)); + S9xSA1SetPCBase(Memory.FillRAM [0x2205] | (Memory.FillRAM [0x2206] << 8)); #else if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) - S9xSetPCBase(Memory.FillRAM [0x220c] | - (Memory.FillRAM [0x220d] << 8)); + S9xSetPCBase(Memory.FillRAM [0x220c] | (Memory.FillRAM [0x220d] << 8)); else S9xSetPCBase(S9xGetWord(0xFFEA)); -#endif -#ifndef SA1_OPCODES CPU.Cycles += TWO_CYCLES; #endif } @@ -3509,23 +3438,18 @@ void S9xOpcode_NMI(void) ICPU.Registers.PB = 0; ICPU.ShiftedPB = 0; #ifdef SA1_OPCODES - S9xSA1SetPCBase(Memory.FillRAM [0x2205] | - (Memory.FillRAM [0x2206] << 8)); + S9xSA1SetPCBase(Memory.FillRAM [0x2205] | (Memory.FillRAM [0x2206] << 8)); #else if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) - S9xSetPCBase(Memory.FillRAM [0x220c] | - (Memory.FillRAM [0x220d] << 8)); + S9xSetPCBase(Memory.FillRAM [0x220c] | (Memory.FillRAM [0x220d] << 8)); else S9xSetPCBase(S9xGetWord(0xFFFA)); -#endif -#ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; #endif } } -/**********************************************************************************************/ -/* COP *************************************************************************************** */ +/* COP */ static void Op02(void) { if (!CheckEmulation()) @@ -3562,9 +3486,8 @@ static void Op02(void) #endif } } -/**********************************************************************************************/ -/* JML *************************************************************************************** */ +/* JML */ static void OpDC(void) { AbsoluteIndirectLong(false); @@ -3583,9 +3506,8 @@ static void Op5C(void) ICPU.ShiftedPB = OpAddress & 0xff0000; S9xSetPCBase(OpAddress); } -/**********************************************************************************************/ -/* JMP *************************************************************************************** */ +/* JMP */ static void Op4C(void) { Absolute(false); @@ -3609,9 +3531,8 @@ static void Op7C(void) CPU.Cycles += ONE_CYCLE; #endif } -/**********************************************************************************************/ -/* JSL/RTL *********************************************************************************** */ +/* JSL/RTL */ static void Op22E1(void) { AbsoluteLong(false); @@ -3653,9 +3574,8 @@ static void Op6B(void) CPU.Cycles += TWO_CYCLES; #endif } -/**********************************************************************************************/ -/* JSR/RTS *********************************************************************************** */ +/* JSR/RTS */ static void Op20(void) { Absolute(false); @@ -3696,9 +3616,7 @@ static void Op60(void) #endif } -/**********************************************************************************************/ - -/* MVN/MVP *********************************************************************************** */ +/* MVN/MVP */ static void Op54X1(void) { #ifndef SA1_OPCODES @@ -3771,9 +3689,7 @@ static void Op44X0(void) CPU.PC -= 3; } -/**********************************************************************************************/ - -/* REP/SEP *********************************************************************************** */ +/* REP/SEP */ static void OpC2(void) { uint8_t Work8 = ~*CPU.PC++; @@ -3817,9 +3733,8 @@ static void OpE2(void) } S9xFixCycles(); } -/**********************************************************************************************/ -/* XBA *************************************************************************************** */ +/* XBA */ static void OpEB(void) { uint8_t Work8 = ICPU.Registers.AL; @@ -3830,9 +3745,8 @@ static void OpEB(void) CPU.Cycles += TWO_CYCLES; #endif } -/**********************************************************************************************/ -/* RTI *************************************************************************************** */ +/* RTI */ static void Op40(void) { PullB(ICPU.Registers.PL); @@ -3857,10 +3771,7 @@ static void Op40(void) S9xFixCycles(); } -/**********************************************************************************************/ - -/* STP/WAI/DB ******************************************************************************** */ -// WAI +/* WAI */ static void OpCB(void) { #ifdef SA1_OPCODES @@ -3888,8 +3799,7 @@ static void OpCB(void) #endif } -// Usually an STP opcode -// SNESAdvance speed hack, not implemented in Snes9xTYL | Snes9x-Euphoria (from the speed-hacks branch of CatSFC) +// Usually an STP opcode; SNESAdvance speed hack, not implemented in Snes9xTYL | Snes9x-Euphoria (from the speed-hacks branch of CatSFC) static void OpDB(void) { #ifndef NO_SPEEDHACKS @@ -3911,10 +3821,6 @@ static void OpDB(void) CPU.PC = CPU.PCBase + OpAddress; #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif #endif CPUShutdown (); } @@ -3926,10 +3832,6 @@ static void OpDB(void) CPU.PC = CPU.PCBase + OpAddress; #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif #endif CPUShutdown (); } @@ -3962,10 +3864,6 @@ static void Op42(void) CPU.PC = CPU.PCBase + OpAddress; #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif #endif CPUShutdown (); } @@ -3977,10 +3875,6 @@ static void Op42(void) CPU.PC = CPU.PCBase + OpAddress; #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif #endif CPUShutdown (); } @@ -3992,10 +3886,6 @@ static void Op42(void) CPU.PC = CPU.PCBase + OpAddress; #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif #endif CPUShutdown (); } @@ -4007,10 +3897,6 @@ static void Op42(void) CPU.PC = CPU.PCBase + OpAddress; #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif #endif CPUShutdown (); } @@ -4019,10 +3905,6 @@ static void Op42(void) CPU.PC = CPU.PCBase + OpAddress; #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif #endif CPUShutdown (); return; @@ -4033,10 +3915,6 @@ static void Op42(void) CPU.PC = CPU.PCBase + OpAddress; #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif #endif CPUShutdown (); } @@ -4048,10 +3926,6 @@ static void Op42(void) CPU.PC = CPU.PCBase + OpAddress; #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif #endif CPUShutdown (); } @@ -4063,10 +3937,6 @@ static void Op42(void) CPU.PC = CPU.PCBase + OpAddress; #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif #endif CPUShutdown (); } @@ -4078,10 +3948,6 @@ static void Op42(void) CPU.PC = CPU.PCBase + OpAddress; #ifndef SA1_OPCODES CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif #endif CPUShutdown (); } @@ -4090,11 +3956,7 @@ static void Op42(void) #endif } -/*****************************************************************************/ - -/*****************************************************************************/ -/* CPU-S9xOpcodes Definitions */ -/*****************************************************************************/ +/* CPU-S9xOpcodes Definitions */ SOpcodes S9xOpcodesM1X1[256] = { {Op00}, {Op01M1}, {Op02}, {Op03M1}, {Op04M1}, diff --git a/source/display.h b/source/display.h index e7732bc..e43b80c 100644 --- a/source/display.h +++ b/source/display.h @@ -14,5 +14,4 @@ void S9xToggleSoundChannel(int32_t channel); void S9xNextController(void); const char* S9xGetFilename(const char* extension); - #endif diff --git a/source/dma.c b/source/dma.c index 63aab98..6bc7922 100644 --- a/source/dma.c +++ b/source/dma.c @@ -48,7 +48,7 @@ void S9xDoDMA(uint8_t Channel) if ((d->ABank == 0x7E || d->ABank == 0x7F) && d->BAddress == 0x80 && !d->TransferDirection) { d->AAddress += d->TransferBytes; - //does an invalid DMA actually take time? + // Does an invalid DMA actually take time? // I'd say yes, since 'invalid' is probably just the WRAM chip // not being able to read and write itself at the same time CPU.Cycles += (d->TransferBytes + 1) * SLOW_ONE_CYCLE; @@ -67,7 +67,6 @@ void S9xDoDMA(uint8_t Channel) if (d->AAddressFixed && Memory.FillRAM [0x4801] > 0) { uint8_t* in_ptr; - // XXX: Should probably verify that we're DMAing from ROM? // And somewhere we should make sure we're not running across a mapping boundary too. inc = !d->AAddressDecrement ? 1 : -1; @@ -102,7 +101,6 @@ void S9xDoDMA(uint8_t Channel) int32_t i; int32_t num_chars = 1 << ((Memory.FillRAM [0x2231] >> 2) & 7); int32_t depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 : (Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2; - int32_t bytes_per_char = 8 * depth; int32_t bytes_per_line = depth * num_chars; int32_t char_line_bytes = bytes_per_char * num_chars; @@ -112,7 +110,6 @@ void S9xDoDMA(uint8_t Channel) uint8_t* p = buffer; uint32_t inc = char_line_bytes - (d->AAddress % char_line_bytes); uint32_t char_count = inc / bytes_per_char; - in_sa1_dma = true; switch (depth) @@ -210,7 +207,6 @@ void S9xDoDMA(uint8_t Channel) { uint8_t* base; uint16_t p; - /* XXX: DMA is potentially broken here for cases where we DMA across * XXX: memmap boundries. A possible solution would be to re-call * XXX: GetBasePointer whenever we cross a boundry, and when @@ -237,7 +233,6 @@ void S9xDoDMA(uint8_t Channel) base = &Memory.ROM [MAX_ROM_SIZE - 0x10000]; p = 0; } - if (in_sdd1_dma) { base = in_sdd1_dma; @@ -572,7 +567,7 @@ update_address: CPU.InDMA = false; } -void S9xStartHDMA() +void S9xStartHDMA(void) { uint8_t i; IPPU.HDMA = Memory.FillRAM [0x420c]; @@ -600,7 +595,6 @@ uint8_t S9xDoHDMA(uint8_t byte) uint8_t mask; SDMA* p = &DMA [0]; int32_t d = 0; - CPU.InDMA = true; CPU.Cycles += ONE_CYCLE * 3; @@ -611,7 +605,6 @@ uint8_t S9xDoHDMA(uint8_t byte) if (!p->LineCount) { uint8_t line; - //remember, InDMA is set. //Get/Set incur no charges! CPU.Cycles += SLOW_ONE_CYCLE; @@ -743,7 +736,7 @@ uint8_t S9xDoHDMA(uint8_t byte) return byte; } -void S9xResetDMA() +void S9xResetDMA(void) { int32_t c, d; for (d = 0; d < 8; d++) diff --git a/source/dsp1.c b/source/dsp1.c index 6a7a6b6..e0ffa99 100644 --- a/source/dsp1.c +++ b/source/dsp1.c @@ -9,7 +9,7 @@ void (*SetDSP)(uint8_t, uint16_t) = &DSP1SetByte; uint8_t(*GetDSP)(uint16_t) = &DSP1GetByte; -void S9xResetDSP1() +void S9xResetDSP1(void) { DSP1.waiting4command = true; DSP1.in_count = 0; @@ -155,7 +155,6 @@ void DSP1SetByte(uint8_t byte, uint16_t address) { if (--DSP1.in_count == 0) { - // Actually execute the command DSP1.waiting4command = true; DSP1.out_index = 0; switch (DSP1.command) @@ -163,33 +162,27 @@ void DSP1SetByte(uint8_t byte, uint16_t address) case 0x1f: DSP1.out_count = 2048; break; - case 0x00: // Multiple + case 0x00: // Multiple Op00Multiplicand = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op00Multiplier = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); - DSPOp00(); - DSP1.out_count = 2; DSP1.output [0] = Op00Result & 0xFF; DSP1.output [1] = (Op00Result >> 8) & 0xFF; break; - case 0x20: // Multiple + case 0x20: // Multiple Op20Multiplicand = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op20Multiplier = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); - DSPOp20(); - DSP1.out_count = 2; DSP1.output [0] = Op20Result & 0xFF; DSP1.output [1] = (Op20Result >> 8) & 0xFF; break; case 0x30: - case 0x10: // Inverse + case 0x10: // Inverse Op10Coefficient = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op10Exponent = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); - DSPOp10(); - DSP1.out_count = 4; DSP1.output [0] = (uint8_t)(((int16_t) Op10CoefficientR) & 0xFF); DSP1.output [1] = (uint8_t)((((int16_t) Op10CoefficientR) >> 8) & 0xFF); @@ -197,74 +190,62 @@ void DSP1SetByte(uint8_t byte, uint16_t address) DSP1.output [3] = (uint8_t)((((int16_t) Op10ExponentR) >> 8) & 0xff); break; case 0x24: - case 0x04: // Sin and Cos of angle + case 0x04: // Sin and Cos of angle Op04Angle = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op04Radius = (uint16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); - DSPOp04(); - DSP1.out_count = 4; DSP1.output [0] = (uint8_t)(Op04Sin & 0xFF); DSP1.output [1] = (uint8_t)((Op04Sin >> 8) & 0xFF); DSP1.output [2] = (uint8_t)(Op04Cos & 0xFF); DSP1.output [3] = (uint8_t)((Op04Cos >> 8) & 0xFF); break; - case 0x08: // Radius + case 0x08: // Radius Op08X = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op08Y = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op08Z = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); - DSPOp08(); - DSP1.out_count = 4; DSP1.output [0] = (uint8_t)(((int16_t) Op08Ll) & 0xFF); DSP1.output [1] = (uint8_t)((((int16_t) Op08Ll) >> 8) & 0xFF); DSP1.output [2] = (uint8_t)(((int16_t) Op08Lh) & 0xFF); DSP1.output [3] = (uint8_t)((((int16_t) Op08Lh) >> 8) & 0xFF); break; - case 0x18: // Range + case 0x18: // Range Op18X = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op18Y = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op18Z = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); Op18R = (int16_t)(DSP1.parameters [6] | (DSP1.parameters[7] << 8)); - DSPOp18(); - DSP1.out_count = 2; DSP1.output [0] = (uint8_t)(Op18D & 0xFF); DSP1.output [1] = (uint8_t)((Op18D >> 8) & 0xFF); break; - case 0x38: // Range + case 0x38: // Range Op38X = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op38Y = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op38Z = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); Op38R = (int16_t)(DSP1.parameters [6] | (DSP1.parameters[7] << 8)); - DSPOp38(); - DSP1.out_count = 2; DSP1.output [0] = (uint8_t)(Op38D & 0xFF); DSP1.output [1] = (uint8_t)((Op38D >> 8) & 0xFF); break; - case 0x28: // Distance (vector length) + case 0x28: // Distance (vector length) Op28X = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op28Y = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op28Z = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); - DSPOp28(); - DSP1.out_count = 2; DSP1.output [0] = (uint8_t)(Op28R & 0xFF); DSP1.output [1] = (uint8_t)((Op28R >> 8) & 0xFF); break; case 0x2c: - case 0x0c: // Rotate (2D rotate) + case 0x0c: // Rotate (2D rotate) Op0CA = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op0CX1 = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op0CY1 = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); - DSPOp0C(); - DSP1.out_count = 4; DSP1.output [0] = (uint8_t)(Op0CX2 & 0xFF); DSP1.output [1] = (uint8_t)((Op0CX2 >> 8) & 0xFF); @@ -272,17 +253,14 @@ void DSP1SetByte(uint8_t byte, uint16_t address) DSP1.output [3] = (uint8_t)((Op0CY2 >> 8) & 0xFF); break; case 0x3c: - case 0x1c: // Polar (3D rotate) + case 0x1c: // Polar (3D rotate) Op1CZ = (DSP1.parameters [0] | (DSP1.parameters[1] << 8)); - //MK: reversed X and Y on neviksti and John's advice. Op1CY = (DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op1CX = (DSP1.parameters [4] | (DSP1.parameters[5] << 8)); Op1CXBR = (DSP1.parameters [6] | (DSP1.parameters[7] << 8)); Op1CYBR = (DSP1.parameters [8] | (DSP1.parameters[9] << 8)); Op1CZBR = (DSP1.parameters [10] | (DSP1.parameters[11] << 8)); - DSPOp1C(); - DSP1.out_count = 6; DSP1.output [0] = (uint8_t)(Op1CXAR & 0xFF); DSP1.output [1] = (uint8_t)((Op1CXAR >> 8) & 0xFF); @@ -294,7 +272,7 @@ void DSP1SetByte(uint8_t byte, uint16_t address) case 0x32: case 0x22: case 0x12: - case 0x02: // Parameter (Projection) + case 0x02: // Parameter (Projection) Op02FX = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op02FY = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op02FZ = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); @@ -302,9 +280,7 @@ void DSP1SetByte(uint8_t byte, uint16_t address) Op02LES = (int16_t)(DSP1.parameters [8] | (DSP1.parameters[9] << 8)); Op02AAS = (uint16_t)(DSP1.parameters [10] | (DSP1.parameters[11] << 8)); Op02AZS = (uint16_t)(DSP1.parameters [12] | (DSP1.parameters[13] << 8)); - DSPOp02(); - DSP1.out_count = 8; DSP1.output [0] = (uint8_t)(Op02VOF & 0xFF); DSP1.output [1] = (uint8_t)((Op02VOF >> 8) & 0xFF); @@ -315,14 +291,12 @@ void DSP1SetByte(uint8_t byte, uint16_t address) DSP1.output [6] = (uint8_t)(Op02CY & 0xFF); DSP1.output [7] = (uint8_t)((Op02CY >> 8) & 0xFF); break; - case 0x3a: //1a Mirror - case 0x2a: //1a Mirror - case 0x1a: // Raster mode 7 matrix data + case 0x3a: //1a Mirror + case 0x2a: //1a Mirror + case 0x1a: // Raster mode 7 matrix data case 0x0a: Op0AVS = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); - DSPOp0A(); - DSP1.out_count = 8; DSP1.output [0] = (uint8_t)(Op0AA & 0xFF); DSP1.output [2] = (uint8_t)(Op0AB & 0xFF); @@ -337,13 +311,11 @@ void DSP1SetByte(uint8_t byte, uint16_t address) case 0x16: case 0x26: case 0x36: - case 0x06: // Project object + case 0x06: // Project object Op06X = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op06Y = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op06Z = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); - DSPOp06(); - DSP1.out_count = 6; DSP1.output [0] = (uint8_t)(Op06H & 0xff); DSP1.output [1] = (uint8_t)((Op06H >> 8) & 0xFF); @@ -355,20 +327,17 @@ void DSP1SetByte(uint8_t byte, uint16_t address) case 0x1e: case 0x2e: case 0x3e: - case 0x0e: // Target + case 0x0e: // Target Op0EH = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op0EV = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); - DSPOp0E(); - DSP1.out_count = 4; DSP1.output [0] = (uint8_t)(Op0EX & 0xFF); DSP1.output [1] = (uint8_t)((Op0EX >> 8) & 0xFF); DSP1.output [2] = (uint8_t)(Op0EY & 0xFF); DSP1.output [3] = (uint8_t)((Op0EY >> 8) & 0xFF); break; - // Extra commands used by Pilot Wings - case 0x05: + case 0x05: // Extra commands used by Pilot Wings case 0x35: case 0x31: case 0x01: // Set attitude matrix A @@ -376,37 +345,32 @@ void DSP1SetByte(uint8_t byte, uint16_t address) Op01Zr = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op01Yr = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); Op01Xr = (int16_t)(DSP1.parameters [6] | (DSP1.parameters[7] << 8)); - DSPOp01(); break; case 0x15: - case 0x11: // Set attitude matrix B + case 0x11: // Set attitude matrix B Op11m = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op11Zr = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op11Yr = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); Op11Xr = (int16_t)(DSP1.parameters [7] | (DSP1.parameters[7] << 8)); - DSPOp11(); break; case 0x25: - case 0x21: // Set attitude matrix C + case 0x21: // Set attitude matrix C Op21m = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op21Zr = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op21Yr = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); Op21Xr = (int16_t)(DSP1.parameters [6] | (DSP1.parameters[7] << 8)); - DSPOp21(); break; case 0x09: case 0x39: case 0x3d: - case 0x0d: // Objective matrix A + case 0x0d: // Objective matrix A Op0DX = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op0DY = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op0DZ = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); - DSPOp0D(); - DSP1.out_count = 6; DSP1.output [0] = (uint8_t)(Op0DF & 0xFF); DSP1.output [1] = (uint8_t)((Op0DF >> 8) & 0xFF); @@ -416,13 +380,11 @@ void DSP1SetByte(uint8_t byte, uint16_t address) DSP1.output [5] = (uint8_t)((Op0DU >> 8) & 0xFF); break; case 0x19: - case 0x1d: // Objective matrix B + case 0x1d: // Objective matrix B Op1DX = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op1DY = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op1DZ = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); - DSPOp1D(); - DSP1.out_count = 6; DSP1.output [0] = (uint8_t)(Op1DF & 0xFF); DSP1.output [1] = (uint8_t)((Op1DF >> 8) & 0xFF); @@ -432,13 +394,11 @@ void DSP1SetByte(uint8_t byte, uint16_t address) DSP1.output [5] = (uint8_t)((Op1DU >> 8) & 0xFF); break; case 0x29: - case 0x2d: // Objective matrix C + case 0x2d: // Objective matrix C Op2DX = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op2DY = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op2DZ = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); - DSPOp2D(); - DSP1.out_count = 6; DSP1.output [0] = (uint8_t)(Op2DF & 0xFF); DSP1.output [1] = (uint8_t)((Op2DF >> 8) & 0xFF); @@ -448,13 +408,11 @@ void DSP1SetByte(uint8_t byte, uint16_t address) DSP1.output [5] = (uint8_t)((Op2DU >> 8) & 0xFF); break; case 0x33: - case 0x03: // Subjective matrix A + case 0x03: // Subjective matrix A Op03F = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op03L = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op03U = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); - DSPOp03(); - DSP1.out_count = 6; DSP1.output [0] = (uint8_t)(Op03X & 0xFF); DSP1.output [1] = (uint8_t)((Op03X >> 8) & 0xFF); @@ -463,13 +421,11 @@ void DSP1SetByte(uint8_t byte, uint16_t address) DSP1.output [4] = (uint8_t)(Op03Z & 0xFF); DSP1.output [5] = (uint8_t)((Op03Z >> 8) & 0xFF); break; - case 0x13: // Subjective matrix B + case 0x13: // Subjective matrix B Op13F = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op13L = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op13U = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); - DSPOp13(); - DSP1.out_count = 6; DSP1.output [0] = (uint8_t)(Op13X & 0xFF); DSP1.output [1] = (uint8_t)((Op13X >> 8) & 0xFF); @@ -478,13 +434,11 @@ void DSP1SetByte(uint8_t byte, uint16_t address) DSP1.output [4] = (uint8_t)(Op13Z & 0xFF); DSP1.output [5] = (uint8_t)((Op13Z >> 8) & 0xFF); break; - case 0x23: // Subjective matrix C + case 0x23: // Subjective matrix C Op23F = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op23L = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op23U = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); - DSPOp23(); - DSP1.out_count = 6; DSP1.output [0] = (uint8_t)(Op23X & 0xFF); DSP1.output [1] = (uint8_t)((Op23X >> 8) & 0xFF); @@ -498,9 +452,7 @@ void DSP1SetByte(uint8_t byte, uint16_t address) Op0BX = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op0BY = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op0BZ = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); - DSPOp0B(); - DSP1.out_count = 2; DSP1.output [0] = (uint8_t)(Op0BS & 0xFF); DSP1.output [1] = (uint8_t)((Op0BS >> 8) & 0xFF); @@ -509,9 +461,7 @@ void DSP1SetByte(uint8_t byte, uint16_t address) Op1BX = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op1BY = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op1BZ = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); - DSPOp1B(); - DSP1.out_count = 2; DSP1.output [0] = (uint8_t)(Op1BS & 0xFF); DSP1.output [1] = (uint8_t)((Op1BS >> 8) & 0xFF); @@ -520,9 +470,7 @@ void DSP1SetByte(uint8_t byte, uint16_t address) Op2BX = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); Op2BY = (int16_t)(DSP1.parameters [2] | (DSP1.parameters[3] << 8)); Op2BZ = (int16_t)(DSP1.parameters [4] | (DSP1.parameters[5] << 8)); - DSPOp2B(); - DSP1.out_count = 2; DSP1.output [0] = (uint8_t)(Op2BS & 0xFF); DSP1.output [1] = (uint8_t)((Op2BS >> 8) & 0xFF); @@ -535,9 +483,7 @@ void DSP1SetByte(uint8_t byte, uint16_t address) Op14U = (int16_t)(DSP1.parameters [6] | (DSP1.parameters[7] << 8)); Op14F = (int16_t)(DSP1.parameters [8] | (DSP1.parameters[9] << 8)); Op14L = (int16_t)(DSP1.parameters [10] | (DSP1.parameters[11] << 8)); - DSPOp14(); - DSP1.out_count = 6; DSP1.output [0] = (uint8_t)(Op14Zrr & 0xFF); DSP1.output [1] = (uint8_t)((Op14Zrr >> 8) & 0xFF); @@ -549,9 +495,7 @@ void DSP1SetByte(uint8_t byte, uint16_t address) case 0x27: case 0x2F: Op2FUnknown = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); - DSPOp2F(); - DSP1.out_count = 2; DSP1.output [0] = (uint8_t)(Op2FSize & 0xFF); DSP1.output [1] = (uint8_t)((Op2FSize >> 8) & 0xFF); @@ -559,9 +503,7 @@ void DSP1SetByte(uint8_t byte, uint16_t address) case 0x07: case 0x0F: Op0FRamsize = (int16_t)(DSP1.parameters [0] | (DSP1.parameters[1] << 8)); - DSPOp0F(); - DSP1.out_count = 2; DSP1.output [0] = (uint8_t)(Op0FPass & 0xFF); DSP1.output [1] = (uint8_t)((Op0FPass >> 8) & 0xFF); @@ -660,7 +602,6 @@ void DSP2SetByte(uint8_t byte, uint16_t address) if (DSP1.in_count == DSP1.in_index) { - // Actually execute the command DSP1.waiting4command = true; DSP1.out_index = 0; switch (DSP1.command) @@ -670,7 +611,6 @@ void DSP2SetByte(uint8_t byte, uint16_t address) { DSP2Op0DHasLen = false; DSP1.out_count = DSP2Op0DOutLen; - //execute Op5 DSP2_Op0D(); } else @@ -689,7 +629,6 @@ void DSP2SetByte(uint8_t byte, uint16_t address) { DSP2Op06HasLen = false; DSP1.out_count = DSP2Op06Len; - //execute Op5 DSP2_Op06(); } else @@ -706,8 +645,7 @@ void DSP2SetByte(uint8_t byte, uint16_t address) DSP1.out_count = 32; DSP2_Op01(); break; - case 0x09: - // Multiply - don't yet know if this is signed or unsigned + case 0x09: // Multiply - don't yet know if this is signed or unsigned DSP2Op09Word1 = DSP1.parameters[0] | (DSP1.parameters[1] << 8); DSP2Op09Word2 = DSP1.parameters[2] | (DSP1.parameters[3] << 8); DSP1.out_count = 4; @@ -726,7 +664,6 @@ void DSP2SetByte(uint8_t byte, uint16_t address) { DSP2Op05HasLen = false; DSP1.out_count = DSP2Op05Len; - //execute Op5 DSP2_Op05(); } else @@ -792,9 +729,8 @@ bool DSP4_init = false; void DSP4SetByte(uint8_t byte, uint16_t address) { - if (!DSP4_init) + if (!DSP4_init) // bootup { - // bootup DSP4.waiting4command = 1; DSP4_init = true; } @@ -871,76 +807,59 @@ void DSP4SetByte(uint8_t byte, uint16_t address) if (!DSP4.waiting4command && DSP4.in_count == DSP4.in_index) { - // Actually execute the command DSP4.waiting4command = true; DSP4.out_index = 0; DSP4.in_index = 0; switch (DSP4.command) { - // 16-bit multiplication - case 0x0000: + case 0x0000: // 16-bit multiplication { int16_t multiplier, multiplicand; int32_t product; - multiplier = DSP4_READ_WORD(0); multiplicand = DSP4_READ_WORD(2); - product = DSP4_Multiply(multiplicand, multiplier); - DSP4.out_count = 4; DSP4_WRITE_WORD(0, product); DSP4_WRITE_WORD(2, product >> 16); break; } - // unknown: horizontal mapping command - case 0x0011: + case 0x0011: // unknown: horizontal mapping command { int16_t a, b, c, d, m; - a = DSP4_READ_WORD(6); b = DSP4_READ_WORD(4); c = DSP4_READ_WORD(2); d = DSP4_READ_WORD(0); - m = DSP4_UnknownOP11(a, b, c, d); - DSP4.out_count = 2; DSP4_WRITE_WORD(0, m); break; } - // track projection - case 0x0001: + case 0x0001: // track projection DSP4_Op01(); break; - // track projection (pass 2) - case 0x0007: + case 0x0007: // track projection (pass 2) DSP4_Op07(); break; - // zone projections (fuel/repair/lap/teleport/...) - case 0x0008: + case 0x0008: // zone projections (fuel/repair/lap/teleport/...) DSP4_Op08(); break; - // sprite transformation - case 0x0009: + case 0x0009: // sprite transformation DSP4_Op09(); break; - // fast track projection - case 0x000D: + case 0x000D: // fast track projection DSP4_Op0D(); break; - // internal memory management (01) - case 0x0003: + case 0x0003: // internal memory management (01) { // reset op09 data op09_mode = false; break; } - // internal memory management (06) - case 0x0005: + case 0x0005: // internal memory management (06) { int32_t lcv; - // clear OAM tables op06_index = 0; op06_offset = 0; @@ -948,49 +867,39 @@ void DSP4SetByte(uint8_t byte, uint16_t address) op06_OAM[lcv] = 0; break; } - // internal memory management (0D) - case 0x000E: + case 0x000E: // internal memory management (0D) { // reset op09 data op09_mode = true; break; } - // sprite OAM post-table data - case 0x0006: + case 0x0006: // sprite OAM post-table data { int32_t lcv; - DSP4.out_count = 32; for (lcv = 0; lcv < 32; lcv++) DSP4.output[lcv] = op06_OAM[lcv]; + break; } - break; - // unknown - case 0x000A: + case 0x000A: // unknown { int16_t out1a, out2a; - out1a = (int16_t)0xff40; out2a = (int16_t)0x00c0; - DSP4.out_count = 8; - DSP4_WRITE_WORD(0, out1a); DSP4_WRITE_WORD(2, out2a); DSP4_WRITE_WORD(4, out1a); DSP4_WRITE_WORD(6, out2a); + break; } - break; - - // render player positions around track - case 0x000B: + case 0x000B: // render player positions around track { int16_t sp_x = DSP4_READ_WORD(0); int16_t sp_y = DSP4_READ_WORD(2); int16_t oam = DSP4_READ_WORD(4); - // Only allow 1p/1p-split to yield output (???) - if (!op09_mode) + if (!op09_mode) // Only allow 1p/1p-split to yield output (???) { // yield OAM output DSP4.out_count = 6; @@ -1004,8 +913,7 @@ void DSP4SetByte(uint8_t byte, uint16_t address) // OAM: size,msb data DSP4_Op06(false, false); } - // 4p mode - else + else // 4p mode { // no OAM available DSP4.out_count = 0; @@ -1023,8 +931,7 @@ void DSP4SetByte(uint8_t byte, uint16_t address) uint8_t DSP4GetByte(uint16_t address) { uint8_t t; - if ((address & 0xf000) == 0x6000 || - (address >= 0x8000 && address < 0xc000)) + if ((address & 0xf000) == 0x6000 || (address >= 0x8000 && address < 0xc000)) { if (DSP4.out_count) { diff --git a/source/dsp1.h b/source/dsp1.h index 4cc2eca..63306c8 100644 --- a/source/dsp1.h +++ b/source/dsp1.h @@ -35,5 +35,4 @@ void S9xResetDSP1(void); uint8_t S9xGetDSP(uint16_t Address); void S9xSetDSP(uint8_t Byte, uint16_t Address); extern SDSP1 DSP1; - #endif diff --git a/source/dsp1emu.c b/source/dsp1emu.c index 6ed470c..1a78e5f 100644 --- a/source/dsp1emu.c +++ b/source/dsp1emu.c @@ -146,7 +146,7 @@ int16_t Op00Multiplicand; int16_t Op00Multiplier; int16_t Op00Result; -void DSPOp00() +void DSPOp00(void) { Op00Result = Op00Multiplicand * Op00Multiplier >> 15; } @@ -155,7 +155,7 @@ int16_t Op20Multiplicand; int16_t Op20Multiplier; int16_t Op20Result; -void DSPOp20() +void DSPOp20(void) { Op20Result = Op20Multiplicand * Op20Multiplier >> 15; Op20Result++; @@ -181,7 +181,8 @@ void DSP1_Inverse(int16_t Coefficient, int16_t Exponent, int16_t* iCoefficient, // Step Two: Remove Sign if (Coefficient < 0) { - if (Coefficient < -32767) Coefficient = -32767; + if (Coefficient < -32767) + Coefficient = -32767; Coefficient = -Coefficient; Sign = -1; } @@ -195,12 +196,15 @@ void DSP1_Inverse(int16_t Coefficient, int16_t Exponent, int16_t* iCoefficient, // Step Four: Special Case if (Coefficient == 0x4000) - if (Sign == 1) *iCoefficient = 0x7fff; + { + if (Sign == 1) + *iCoefficient = 0x7fff; else { *iCoefficient = -0x4000; Exponent--; } + } else { // Step Five: Initial Guess @@ -217,7 +221,7 @@ void DSP1_Inverse(int16_t Coefficient, int16_t Exponent, int16_t* iCoefficient, } } -void DSPOp10() +void DSPOp10(void) { DSP1_Inverse(Op10Coefficient, Op10Exponent, &Op10CoefficientR, &Op10ExponentR); } @@ -305,11 +309,13 @@ int16_t DSP1_Sin(int16_t Angle) if (Angle < 0) { - if (Angle == -32768) return 0; + if (Angle == -32768) + return 0; return -DSP1_Sin(-Angle); } S = DSP1_SinTable[Angle >> 8] + (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[0x40 + (Angle >> 8)] >> 15); - if (S > 32767) S = 32767; + if (S > 32767) + S = 32767; return (int16_t) S; } @@ -319,11 +325,13 @@ int16_t DSP1_Cos(int16_t Angle) if (Angle < 0) { - if (Angle == -32768) return -32768; + if (Angle == -32768) + return -32768; Angle = -Angle; } S = DSP1_SinTable[0x40 + (Angle >> 8)] - (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[Angle >> 8] >> 15); - if (S < -32768) S = -32767; + if (S < -32768) + S = -32767; return (int16_t) S; } @@ -333,17 +341,21 @@ void DSP1_Normalize(int16_t m, int16_t* Coefficient, int16_t* Exponent) int16_t e = 0; if (m < 0) + { while ((m & i) && i) { i >>= 1; e++; } + } else + { while (!(m & i) && i) { i >>= 1; e++; } + } if (e > 0) *Coefficient = m * DSP1ROM[0x21 + e] << 1; @@ -361,17 +373,21 @@ void DSP1_NormalizeDouble(int32_t Product, int16_t* Coefficient, int16_t* Expone int16_t e = 0; if (m < 0) + { while ((m & i) && i) { i >>= 1; e++; } + } else + { while (!(m & i) && i) { i >>= 1; e++; } + } if (e > 0) { @@ -384,17 +400,21 @@ void DSP1_NormalizeDouble(int32_t Product, int16_t* Coefficient, int16_t* Expone i = 0x4000; if (m < 0) + { while ((n & i) && i) { i >>= 1; e++; } + } else + { while (!(n & i) && i) { i >>= 1; e++; } + } if (e > 15) *Coefficient = n * DSP1ROM[0x0012 + e] << 1; @@ -412,17 +432,17 @@ int16_t DSP1_Truncate(int16_t C, int16_t E) { if (E > 0) { - if (C > 0) return 32767; - else if (C < 0) return -32767; - } - else - { - if (E < 0) return C * DSP1ROM[0x0031 + E] >> 15; + if (C > 0) + return 32767; + else if (C < 0) + return -32767; } + else if (E < 0) + return C * DSP1ROM[0x0031 + E] >> 15; return C; } -void DSPOp04() +void DSPOp04(void) { Op04Sin = DSP1_Sin(Op04Angle) * Op04Radius >> 15; Op04Cos = DSP1_Cos(Op04Angle) * Op04Radius >> 15; @@ -434,7 +454,7 @@ int16_t Op0CY1; int16_t Op0CX2; int16_t Op0CY2; -void DSPOp0C() +void DSPOp0C(void) { Op0CX2 = (Op0CY1 * DSP1_Sin(Op0CA) >> 15) + (Op0CX1 * DSP1_Cos(Op0CA) >> 15); Op0CY2 = (Op0CY1 * DSP1_Cos(Op0CA) >> 15) - (Op0CX1 * DSP1_Sin(Op0CA) >> 15); @@ -524,7 +544,8 @@ void DSP1_Parameter(int16_t Fx, int16_t Fy, int16_t Fz, int16_t Lfe, int16_t Les if (AZS < 0) { MaxAZS = -MaxAZS; - if (AZS < MaxAZS + 1) AZS = MaxAZS + 1; + if (AZS < MaxAZS + 1) + AZS = MaxAZS + 1; } else if (AZS > MaxAZS) AZS = MaxAZS; @@ -550,10 +571,11 @@ void DSP1_Parameter(int16_t Fx, int16_t Fy, int16_t Fz, int16_t Lfe, int16_t Les if ((Azs != AZS) || (Azs == MaxAZS)) { - if (Azs == -32768) Azs = -32767; - + if (Azs == -32768) + Azs = -32767; C = Azs - MaxAZS; - if (C >= 0) C--; + if (C >= 0) + C--; Aux = ~(C << 2); C = Aux * DSP1ROM[0x0328] >> 15; @@ -620,7 +642,7 @@ int16_t Op02VVA; int16_t Op02CX; int16_t Op02CY; -void DSPOp02() +void DSPOp02(void) { DSP1_Parameter(Op02FX, Op02FY, Op02FZ, Op02LFE, Op02LES, Op02AAS, Op02AZS, &Op02VOF, &Op02VVA, &Op02CX, &Op02CY); } @@ -631,7 +653,7 @@ int16_t Op0AB; int16_t Op0AC; int16_t Op0AD; -void DSPOp0A() +void DSPOp0A(void) { DSP1_Raster(Op0AVS, &Op0AA, &Op0AB, &Op0AC, &Op0AD); Op0AVS++; @@ -639,7 +661,7 @@ void DSPOp0A() int16_t DSP1_ShiftR(int16_t C, int16_t E) { - return (C * DSP1ROM[0x0031 + E] >> 15); + return C * DSP1ROM[0x0031 + E] >> 15; } void DSP1_Project(int16_t X, int16_t Y, int16_t Z, int16_t *H, int16_t *V, int16_t *M) @@ -661,17 +683,17 @@ void DSP1_Project(int16_t X, int16_t Y, int16_t Z, int16_t *H, int16_t *V, int16 Pz>>=1; E3--; - refE = MIN(E, E3); - refE = MIN(refE, E4); + refE = MIN(E, E3); + refE = MIN(refE, E4); - Px = DSP1_ShiftR(Px, E4 - refE); // normalize them to the same exponent - Py = DSP1_ShiftR(Py, E - refE); - Pz = DSP1_ShiftR(Pz, E3 - refE); + Px = DSP1_ShiftR(Px, E4 - refE); // normalize them to the same exponent + Py = DSP1_ShiftR(Py, E - refE); + Pz = DSP1_ShiftR(Pz, E3 - refE); - C11 = -(Px * Nx >> 15); - C8 = -(Py * Ny >> 15); - C9 = -(Pz * Nz >> 15); - C12 = C11 + C8 + C9; // this cannot overflow! + C11 = -(Px * Nx >> 15); + C8 = -(Py * Ny >> 15); + C9 = -(Pz * Nz >> 15); + C12 = C11 + C8 + C9; // this cannot overflow! aux4 = C12; // de-normalization with 32-bit arithmetic refE = 16 - refE; // refE can be up to 3 @@ -723,7 +745,7 @@ int16_t Op06H; int16_t Op06V; int16_t Op06M; -void DSPOp06() +void DSPOp06(void) { DSP1_Project(Op06X, Op06Y, Op06Z, &Op06H, &Op06V, &Op06M); } @@ -745,7 +767,7 @@ int16_t Op21Zr; int16_t Op21Xr; int16_t Op21Yr; -void DSPOp01() +void DSPOp01(void) { int16_t SinAz = DSP1_Sin(Op01Zr); int16_t CosAz = DSP1_Cos(Op01Zr); @@ -769,7 +791,7 @@ void DSPOp01() matrixA[2][2] = (Op01m * CosAx >> 15) * CosAy >> 15; } -void DSPOp11() +void DSPOp11(void) { int16_t SinAz = DSP1_Sin(Op11Zr); int16_t CosAz = DSP1_Cos(Op11Zr); @@ -793,7 +815,7 @@ void DSPOp11() matrixB[2][2] = (Op11m * CosAx >> 15) * CosAy >> 15; } -void DSPOp21() +void DSPOp21(void) { int16_t SinAz = DSP1_Sin(Op21Zr); int16_t CosAz = DSP1_Cos(Op21Zr); @@ -836,21 +858,21 @@ int16_t Op2DF; int16_t Op2DL; int16_t Op2DU; -void DSPOp0D() +void DSPOp0D(void) { Op0DF = (Op0DX * matrixA[0][0] >> 15) + (Op0DY * matrixA[0][1] >> 15) + (Op0DZ * matrixA[0][2] >> 15); Op0DL = (Op0DX * matrixA[1][0] >> 15) + (Op0DY * matrixA[1][1] >> 15) + (Op0DZ * matrixA[1][2] >> 15); Op0DU = (Op0DX * matrixA[2][0] >> 15) + (Op0DY * matrixA[2][1] >> 15) + (Op0DZ * matrixA[2][2] >> 15); } -void DSPOp1D() +void DSPOp1D(void) { Op1DF = (Op1DX * matrixB[0][0] >> 15) + (Op1DY * matrixB[0][1] >> 15) + (Op1DZ * matrixB[0][2] >> 15); Op1DL = (Op1DX * matrixB[1][0] >> 15) + (Op1DY * matrixB[1][1] >> 15) + (Op1DZ * matrixB[1][2] >> 15); Op1DU = (Op1DX * matrixB[2][0] >> 15) + (Op1DY * matrixB[2][1] >> 15) + (Op1DZ * matrixB[2][2] >> 15); } -void DSPOp2D() +void DSPOp2D(void) { Op2DF = (Op2DX * matrixC[0][0] >> 15) + (Op2DY * matrixC[0][1] >> 15) + (Op2DZ * matrixC[0][2] >> 15); Op2DL = (Op2DX * matrixC[1][0] >> 15) + (Op2DY * matrixC[1][1] >> 15) + (Op2DZ * matrixC[1][2] >> 15); @@ -876,21 +898,21 @@ int16_t Op23X; int16_t Op23Y; int16_t Op23Z; -void DSPOp03() +void DSPOp03(void) { Op03X = (Op03F * matrixA[0][0] >> 15) + (Op03L * matrixA[1][0] >> 15) + (Op03U * matrixA[2][0] >> 15); Op03Y = (Op03F * matrixA[0][1] >> 15) + (Op03L * matrixA[1][1] >> 15) + (Op03U * matrixA[2][1] >> 15); Op03Z = (Op03F * matrixA[0][2] >> 15) + (Op03L * matrixA[1][2] >> 15) + (Op03U * matrixA[2][2] >> 15); } -void DSPOp13() +void DSPOp13(void) { Op13X = (Op13F * matrixB[0][0] >> 15) + (Op13L * matrixB[1][0] >> 15) + (Op13U * matrixB[2][0] >> 15); Op13Y = (Op13F * matrixB[0][1] >> 15) + (Op13L * matrixB[1][1] >> 15) + (Op13U * matrixB[2][1] >> 15); Op13Z = (Op13F * matrixB[0][2] >> 15) + (Op13L * matrixB[1][2] >> 15) + (Op13U * matrixB[2][2] >> 15); } -void DSPOp23() +void DSPOp23(void) { Op23X = (Op23F * matrixC[0][0] >> 15) + (Op23L * matrixC[1][0] >> 15) + (Op23U * matrixC[2][0] >> 15); Op23Y = (Op23F * matrixC[0][1] >> 15) + (Op23L * matrixC[1][1] >> 15) + (Op23U * matrixC[2][1] >> 15); @@ -907,7 +929,7 @@ int16_t Op14Zrr; int16_t Op14Xrr; int16_t Op14Yrr; -void DSPOp14() +void DSPOp14(void) { int16_t CSec, ESec, CTan, CSin, C, E; @@ -973,7 +995,7 @@ int16_t Op0EV; int16_t Op0EX; int16_t Op0EY; -void DSPOp0E() +void DSPOp0E(void) { DSP1_Target(Op0EH, Op0EV, &Op0EX, &Op0EY); } @@ -991,24 +1013,24 @@ int16_t Op2BY; int16_t Op2BZ; int16_t Op2BS; -void DSPOp0B() +void DSPOp0B(void) { Op0BS = (Op0BX * matrixA[0][0] + Op0BY * matrixA[0][1] + Op0BZ * matrixA[0][2]) >> 15; } -void DSPOp1B() +void DSPOp1B(void) { Op1BS = (Op1BX * matrixB[0][0] + Op1BY * matrixB[0][1] + Op1BZ * matrixB[0][2]) >> 15; } -void DSPOp2B() +void DSPOp2B(void) { Op2BS = (Op2BX * matrixC[0][0] + Op2BY * matrixC[0][1] + Op2BZ * matrixC[0][2]) >> 15; } int16_t Op08X, Op08Y, Op08Z, Op08Ll, Op08Lh; -void DSPOp08() +void DSPOp08(void) { int32_t Op08Size = (Op08X * Op08X + Op08Y * Op08Y + Op08Z * Op08Z) << 1; Op08Ll = Op08Size & 0xffff; @@ -1017,14 +1039,14 @@ void DSPOp08() int16_t Op18X, Op18Y, Op18Z, Op18R, Op18D; -void DSPOp18() +void DSPOp18(void) { Op18D = (Op18X * Op18X + Op18Y * Op18Y + Op18Z * Op18Z - Op18R * Op18R) >> 15; } int16_t Op38X, Op38Y, Op38Z, Op38R, Op38D; -void DSPOp38() +void DSPOp38(void) { Op38D = (Op38X * Op38X + Op38Y * Op38Y + Op38Z * Op38Z - Op38R * Op38R) >> 15; Op38D++; @@ -1035,16 +1057,18 @@ int16_t Op28Y; int16_t Op28Z; int16_t Op28R; -void DSPOp28() +void DSPOp28(void) { int32_t Radius = Op28X * Op28X + Op28Y * Op28Y + Op28Z * Op28Z; - if (Radius == 0) Op28R = 0; + if (Radius == 0) + Op28R = 0; else { int16_t C, E, Pos, Node1, Node2; DSP1_NormalizeDouble(Radius, &C, &E); - if (E & 1) C = C * 0x4000 >> 15; + if (E & 1) + C = C * 0x4000 >> 15; Pos = C * 0x0040 >> 15; @@ -1065,7 +1089,7 @@ int16_t Op1CX2; int16_t Op1CY2; int16_t Op1CZ2; -void DSPOp1C() +void DSPOp1C(void) { // Rotate Around Op1CZ1 Op1CX1 = (Op1CYBR * DSP1_Sin(Op1CZ) >> 15) + (Op1CXBR * DSP1_Cos(Op1CZ) >> 15); @@ -1089,7 +1113,7 @@ void DSPOp1C() uint16_t Op0FRamsize; uint16_t Op0FPass; -void DSPOp0F() +void DSPOp0F(void) { Op0FPass = 0x0000; } @@ -1097,7 +1121,7 @@ void DSPOp0F() int16_t Op2FUnknown; int16_t Op2FSize; -void DSPOp2F() +void DSPOp2F(void) { Op2FSize = 0x100; } diff --git a/source/dsp2emu.c b/source/dsp2emu.c index 9e3e137..4e22d54 100644 --- a/source/dsp2emu.c +++ b/source/dsp2emu.c @@ -8,7 +8,7 @@ bool DSP2Op06HasLen = false; int32_t DSP2Op06Len = 0; uint8_t DSP2Op05Transparent = 0; -void DSP2_Op05() +void DSP2_Op05(void) { uint8_t color; // Overlay bitmap with transparency. @@ -49,16 +49,14 @@ void DSP2_Op05() { c1 = *p1++; c2 = *p2++; - *p3++ = (((c2 >> 4) == color) ? c1 & 0xf0 : c2 & 0xf0) | - (((c2 & 0x0f) == color) ? c1 & 0x0f : c2 & 0x0f); + *p3++ = (((c2 >> 4) == color) ? c1 & 0xf0 : c2 & 0xf0) | (((c2 & 0x0f) == color) ? c1 & 0x0f : c2 & 0x0f); } } -void DSP2_Op01() +void DSP2_Op01(void) { // Op01 size is always 32 bytes input and output. // The hardware does strange things if you vary the size. - int32_t j; uint8_t c0, c1, c2, c3; uint8_t* p1 = DSP1.parameters; @@ -66,55 +64,20 @@ void DSP2_Op01() uint8_t* p2b = &DSP1.output[16]; // halfway // Process 8 blocks of 4 bytes each - for (j = 0; j < 8; j++) { c0 = *p1++; c1 = *p1++; c2 = *p1++; c3 = *p1++; - - *p2a++ = (c0 & 0x10) << 3 | - (c0 & 0x01) << 6 | - (c1 & 0x10) << 1 | - (c1 & 0x01) << 4 | - (c2 & 0x10) >> 1 | - (c2 & 0x01) << 2 | - (c3 & 0x10) >> 3 | - (c3 & 0x01); - - *p2a++ = (c0 & 0x20) << 2 | - (c0 & 0x02) << 5 | - (c1 & 0x20) | - (c1 & 0x02) << 3 | - (c2 & 0x20) >> 2 | - (c2 & 0x02) << 1 | - (c3 & 0x20) >> 4 | - (c3 & 0x02) >> 1; - - *p2b++ = (c0 & 0x40) << 1 | - (c0 & 0x04) << 4 | - (c1 & 0x40) >> 1 | - (c1 & 0x04) << 2 | - (c2 & 0x40) >> 3 | - (c2 & 0x04) | - (c3 & 0x40) >> 5 | - (c3 & 0x04) >> 2; - - - *p2b++ = (c0 & 0x80) | - (c0 & 0x08) << 3 | - (c1 & 0x80) >> 2 | - (c1 & 0x08) << 1 | - (c2 & 0x80) >> 4 | - (c2 & 0x08) >> 1 | - (c3 & 0x80) >> 6 | - (c3 & 0x08) >> 3; + *p2a++ = (c0 & 0x10) << 3 | (c0 & 0x01) << 6 | (c1 & 0x10) << 1 | (c1 & 0x01) << 4 | (c2 & 0x10) >> 1 | (c2 & 0x01) << 2 | (c3 & 0x10) >> 3 | (c3 & 0x01); + *p2a++ = (c0 & 0x20) << 2 | (c0 & 0x02) << 5 | (c1 & 0x20) | (c1 & 0x02) << 3 | (c2 & 0x20) >> 2 | (c2 & 0x02) << 1 | (c3 & 0x20) >> 4 | (c3 & 0x02) >> 1; + *p2b++ = (c0 & 0x40) << 1 | (c0 & 0x04) << 4 | (c1 & 0x40) >> 1 | (c1 & 0x04) << 2 | (c2 & 0x40) >> 3 | (c2 & 0x04) | (c3 & 0x40) >> 5 | (c3 & 0x04) >> 2; + *p2b++ = (c0 & 0x80) | (c0 & 0x08) << 3 | (c1 & 0x80) >> 2 | (c1 & 0x08) << 1 | (c2 & 0x80) >> 4 | (c2 & 0x08) >> 1 | (c3 & 0x80) >> 6 | (c3 & 0x08) >> 3; } - return; } -void DSP2_Op06() +void DSP2_Op06(void) { // Input: // size @@ -131,13 +94,10 @@ int32_t DSP2Op0DOutLen = 0; int32_t DSP2Op0DInLen = 0; // Scale bitmap based on input length out output length - -void DSP2_Op0D() +void DSP2_Op0D(void) { // (Modified) Overload's algorithm - int32_t i; - for(i = 0 ; i < DSP2Op0DOutLen ; i++) { int32_t j = i << 1; diff --git a/source/dsp4.h b/source/dsp4.h index 760891c..53ff365 100644 --- a/source/dsp4.h +++ b/source/dsp4.h @@ -3,85 +3,80 @@ #ifndef _DSP4_H_ #define _DSP4_H_ -// debug -int32_t block; // current block number -extern int32_t c; - // op control -int8_t DSP4_Logic; // controls op flow +int8_t DSP4_Logic; // controls op flow // projection format -const int16_t PLANE_START = 0x7fff; // starting distance +const int16_t PLANE_START = 0x7fff; // starting distance -int16_t view_plane; // viewer location -int16_t far_plane; // next milestone into screen -int16_t segments; // # raster segments to draw -int16_t raster; // current raster line +int16_t view_plane; // viewer location +int16_t far_plane; // next milestone into screen +int16_t segments; // # raster segments to draw +int16_t raster; // current raster line -int16_t project_x; // current x-position -int16_t project_y; // current y-position +int16_t project_x; // current x-position +int16_t project_y; // current y-position -int16_t project_centerx; // x-target of projection -int16_t project_centery; // y-target of projection +int16_t project_centerx; // x-target of projection +int16_t project_centery; // y-target of projection -int16_t project_x1; // current x-distance -int16_t project_x1low; // lower 16-bits -int16_t project_y1; // current y-distance -int16_t project_y1low; // lower 16-bits +int16_t project_x1; // current x-distance +int16_t project_x1low; // lower 16-bits +int16_t project_y1; // current y-distance +int16_t project_y1low; // lower 16-bits -int16_t project_x2; // next projected x-distance -int16_t project_y2; // next projected y-distance +int16_t project_x2; // next projected x-distance +int16_t project_y2; // next projected y-distance -int16_t project_pitchx; // delta center -int16_t project_pitchxlow; // lower 16-bits -int16_t project_pitchy; // delta center -int16_t project_pitchylow; // lower 16-bits +int16_t project_pitchx; // delta center +int16_t project_pitchxlow; // lower 16-bits +int16_t project_pitchy; // delta center +int16_t project_pitchylow; // lower 16-bits -int16_t project_focalx; // x-point of projection at viewer plane -int16_t project_focaly; // y-point of projection at viewer plane +int16_t project_focalx; // x-point of projection at viewer plane +int16_t project_focaly; // y-point of projection at viewer plane -int16_t project_ptr; // data structure pointer +int16_t project_ptr; // data structure pointer // render window -int16_t center_x; // x-center of viewport -int16_t center_y; // y-center of viewport -int16_t viewport_left; // x-left of viewport -int16_t viewport_right; // x-right of viewport -int16_t viewport_top; // y-top of viewport -int16_t viewport_bottom; // y-bottom of viewport +int16_t center_x; // x-center of viewport +int16_t center_y; // y-center of viewport +int16_t viewport_left; // x-left of viewport +int16_t viewport_right; // x-right of viewport +int16_t viewport_top; // y-top of viewport +int16_t viewport_bottom; // y-bottom of viewport // sprite structure -int16_t sprite_x; // projected x-pos of sprite -int16_t sprite_y; // projected y-pos of sprite -int16_t sprite_offset; // data pointer offset -int8_t sprite_type; // vehicle, terrain -bool sprite_size; // sprite size: 8x8 or 16x16 +int16_t sprite_x; // projected x-pos of sprite +int16_t sprite_y; // projected y-pos of sprite +int16_t sprite_offset; // data pointer offset +int8_t sprite_type; // vehicle, terrain +bool sprite_size; // sprite size: 8x8 or 16x16 // path strips -int16_t path_clipRight[4]; // value to clip to for x>b -int16_t path_clipLeft[4]; // value to clip to for x<a -int16_t path_pos[4]; // x-positions of lanes -int16_t path_ptr[4]; // data structure pointers -int16_t path_raster[4]; // current raster -int16_t path_top[4]; // viewport_top +int16_t path_clipRight[4]; // value to clip to for x>b +int16_t path_clipLeft[4]; // value to clip to for x<a +int16_t path_pos[4]; // x-positions of lanes +int16_t path_ptr[4]; // data structure pointers +int16_t path_raster[4]; // current raster +int16_t path_top[4]; // viewport_top -int16_t path_y[2]; // current y-position -int16_t path_x[2]; // current focals -int16_t path_plane[2]; // previous plane +int16_t path_y[2]; // current y-position +int16_t path_x[2]; // current focals +int16_t path_plane[2]; // previous plane // op09 window sorting -int16_t multi_index1; // index counter -int16_t multi_index2; // index counter -bool op09_mode; // window mode +int16_t multi_index1; // index counter +int16_t multi_index2; // index counter +bool op09_mode; // window mode // multi-op storage -int16_t multi_focaly[64]; // focal_y values -int16_t multi_farplane[4]; // farthest drawn distance -int16_t multi_raster[4]; // line where track stops +int16_t multi_focaly[64]; // focal_y values +int16_t multi_farplane[4]; // farthest drawn distance +int16_t multi_raster[4]; // line where track stops // OAM -int8_t op06_OAM[32]; // OAM (size,MSB) data -int8_t op06_index; // index into OAM table -int8_t op06_offset; // offset into OAM table - +int8_t op06_OAM[32]; // OAM (size,MSB) data +int8_t op06_index; // index into OAM table +int8_t op06_offset; // offset into OAM table #endif diff --git a/source/dsp4emu.c b/source/dsp4emu.c index b2fcebf..921f896 100644 --- a/source/dsp4emu.c +++ b/source/dsp4emu.c @@ -11,10 +11,8 @@ // used to wait for dsp i/o #define DSP4_WAIT(x) \ - DSP4_Logic = x; return; - -////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////// + DSP4_Logic = x; \ + return int32_t DSP4_Multiply(int16_t Multiplicand, int16_t Multiplier) { @@ -23,13 +21,9 @@ int32_t DSP4_Multiply(int16_t Multiplicand, int16_t Multiplier) int16_t DSP4_UnknownOP11(int16_t A, int16_t B, int16_t C, int16_t D) { - return ((A * 0x0155 >> 2) & 0xf000) | ((B * 0x0155 >> 6) & 0x0f00) | - ((C * 0x0155 >> 10) & 0x00f0) | ((D * 0x0155 >> 14) & 0x000f); + return ((A * 0x0155 >> 2) & 0xf000) | ((B * 0x0155 >> 6) & 0x0f00) | ((C * 0x0155 >> 10) & 0x00f0) | ((D * 0x0155 >> 14) & 0x000f); } -////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////// - void DSP4_Op06(bool size, bool msb) { // save post-oam table data for future retrieval @@ -45,19 +39,16 @@ void DSP4_Op06(bool size, bool msb) } } -void DSP4_Op01() +void DSP4_Op01(void) { int16_t plane; - int16_t index, lcv; int16_t py_dy, px_dx; int16_t y_out, x_out; uint16_t command; - DSP4.waiting4command = false; - // op flow control - switch (DSP4_Logic) + switch (DSP4_Logic) // op flow control { case 1: goto resume1; @@ -99,9 +90,6 @@ void DSP4_Op01() multi_index1 = 0; multi_index2 = 0; - // debug - block = 0; - //////////////////////////////////////////////////// // command check @@ -109,20 +97,20 @@ void DSP4_Op01() { // scan next command DSP4.in_count = 2; + DSP4_WAIT(1); -DSP4_WAIT(1) resume1: - +resume1: // inspect input command = DSP4_READ_WORD(0); // check for termination - if (command == 0x8000) break; + if(command == 0x8000) + break; // already have 2 bytes in queue DSP4.in_index = 2; DSP4.in_count = 8; - - DSP4_WAIT(2) + DSP4_WAIT(2); //////////////////////////////////////////////////// // process one iteration of projection @@ -134,7 +122,8 @@ resume2: px_dx = 0; // ignore invalid data - if ((uint16_t) plane == 0x8001) continue; + if((uint16_t) plane == 0x8001) + continue; // one-time init if (far_plane) @@ -153,31 +142,26 @@ resume2: // quadratic regression (rough) if (project_focaly >= -0x0f) - py_dy = (int16_t)(project_focaly * project_focaly * -0.20533553 - - 1.08330005 * project_focaly - 69.61094639); + py_dy = (int16_t)(project_focaly * project_focaly * -0.20533553 - 1.08330005 * project_focaly - 69.61094639); else - py_dy = (int16_t)(project_focaly * project_focaly * -0.000657035759 - - 1.07629051 * project_focaly - 65.69315963); + py_dy = (int16_t)(project_focaly * project_focaly * -0.000657035759 - 1.07629051 * project_focaly - 65.69315963); // approximate # of raster lines segments = ABS(project_y2 - project_y1); // prevent overdraw - if (project_y2 >= raster) segments = 0; - else raster = project_y2; + if(project_y2 >= raster) + segments = 0; + else + raster = project_y2; // don't draw outside the window - if (project_y2 < viewport_top) segments = 0; + if(project_y2 < viewport_top) + segments = 0; // project new positions if (segments > 0) - { - // interpolate between projected points - px_dx = ((project_x2 - project_x1) << 8) / segments; - } - - // debug - ++block; + px_dx = ((project_x2 - project_x1) << 8) / segments; // interpolate between projected points // prepare output DSP4.out_count = 8 + 2 + 6 * segments; @@ -191,8 +175,7 @@ resume2: index = 10; - // iterate through each point - for (lcv = 0; lcv < segments; lcv++) + for (lcv = 0; lcv < segments; lcv++) // iterate through each point { // step through the projected line y_out = project_y + ((py_dy * lcv) >> 8); @@ -212,8 +195,7 @@ resume2: project_y += ((py_dy * lcv) >> 8); project_x += ((px_dx * lcv) >> 8); - // new positions - if (segments > 0) + if (segments > 0) // new positions { project_x1 = project_x2; project_y1 = project_y2; @@ -230,15 +212,14 @@ resume2: project_focaly += project_pitchy; project_focalx += project_pitchx; - } - while (1); + } while (1); // terminate op DSP4.waiting4command = true; DSP4.out_count = 0; } -void DSP4_Op07() +void DSP4_Op07(void) { uint16_t command; int16_t plane; @@ -262,7 +243,6 @@ void DSP4_Op07() //////////////////////////////////////////////////// // sort inputs - // 0x00 = DSP4_READ_WORD(0x00); project_focaly = DSP4_READ_WORD(0x02); raster = DSP4_READ_WORD(0x04); viewport_top = DSP4_READ_WORD(0x06); @@ -272,7 +252,6 @@ void DSP4_Op07() project_x1 = DSP4_READ_WORD(0x0e); project_centerx = DSP4_READ_WORD(0x10); project_ptr = DSP4_READ_WORD(0x12); - // (envelope?) 0xc0 = DSP4_READ_WORD(0x14); // pre-compute view_plane = PLANE_START; @@ -285,9 +264,6 @@ void DSP4_Op07() // multi-op storage multi_index2 = 0; - // debug - block = 0; - //////////////////////////////////////////////////// // command check @@ -295,20 +271,20 @@ void DSP4_Op07() { // scan next command DSP4.in_count = 2; + DSP4_WAIT(1); -DSP4_WAIT(1) resume1: - +resume1: // inspect input command = DSP4_READ_WORD(0); // check for opcode termination - if (command == 0x8000) break; + if(command == 0x8000) + break; // already have 2 bytes in queue DSP4.in_index = 2; DSP4.in_count = 12; - - DSP4_WAIT(2) + DSP4_WAIT(2); //////////////////////////////////////////////////// // process one loop of projection @@ -316,38 +292,36 @@ DSP4_WAIT(1) resume1: resume2: px_dx = 0; - // debug - ++block; - // inspect inputs plane = DSP4_READ_WORD(0); project_y2 = DSP4_READ_WORD(2); - // ? = DSP4_READ_WORD(4); project_x2 = DSP4_READ_WORD(6); // ignore invalid data - if ((uint16_t) plane == 0x8001) continue; + if((uint16_t) plane == 0x8001) + continue; // multi-op storage project_focaly = multi_focaly[multi_index2]; // quadratic regression (rough) if (project_focaly >= -0x0f) - py_dy = (int16_t)(project_focaly * project_focaly * -0.20533553 - - 1.08330005 * project_focaly - 69.61094639); + py_dy = (int16_t)(project_focaly * project_focaly * -0.20533553 - 1.08330005 * project_focaly - 69.61094639); else - py_dy = (int16_t)(project_focaly * project_focaly * -0.000657035759 - - 1.07629051 * project_focaly - 65.69315963); + py_dy = (int16_t)(project_focaly * project_focaly * -0.000657035759 - 1.07629051 * project_focaly - 65.69315963); // approximate # of raster lines segments = ABS(project_y2 - project_y1); // prevent overdraw - if (project_y2 >= raster) segments = 0; - else raster = project_y2; + if(project_y2 >= raster) + segments = 0; + else + raster = project_y2; // don't draw outside the window - if (project_y2 < viewport_top) segments = 0; + if(project_y2 < viewport_top) + segments = 0; // project new positions if (segments > 0) @@ -393,14 +367,13 @@ resume2: // multi-op storage multi_index2++; } - } - while (1); + } while (1); DSP4.waiting4command = true; DSP4.out_count = 0; } -void DSP4_Op08() +void DSP4_Op08(void) { uint16_t command; // used in envelope shaping @@ -408,7 +381,6 @@ void DSP4_Op08() int16_t x2_final; int16_t plane, x_left, y_left, x_right, y_right; int16_t envelope1, envelope2; - DSP4.waiting4command = false; // op flow control @@ -436,9 +408,6 @@ void DSP4_Op08() path_clipLeft[2] = DSP4_READ_WORD(0x0c); path_clipLeft[3] = DSP4_READ_WORD(0x0e); - // unknown (constant) - // unknown (constant) - // path positions path_pos[0] = DSP4_READ_WORD(0x20); path_pos[1] = DSP4_READ_WORD(0x22); @@ -467,9 +436,6 @@ void DSP4_Op08() view_plane = PLANE_START; - // debug - block = 0; - //////////////////////////////////////////////////// // command check @@ -477,27 +443,25 @@ void DSP4_Op08() { // scan next command DSP4.in_count = 2; + DSP4_WAIT(1); -DSP4_WAIT(1) resume1: - +resume1: // inspect input command = DSP4_READ_WORD(0); // terminate op - if (command == 0x8000) break; + if(command == 0x8000) + break; // already have 2 bytes in queue DSP4.in_index = 2; DSP4.in_count = 18; + DSP4_WAIT(2); -DSP4_WAIT(2) resume2: - +resume2: //////////////////////////////////////////////////// // projection begins - // debug - ++block; - // look at guidelines plane = DSP4_READ_WORD(0x00); x_left = DSP4_READ_WORD(0x02); @@ -510,7 +474,8 @@ DSP4_WAIT(2) resume2: envelope2 = DSP4_READ_WORD(0x0c); // ignore invalid data - if ((uint16_t) plane == 0x8001) continue; + if((uint16_t) plane == 0x8001) + continue; // first init if (plane == 0x7fff) @@ -534,10 +499,14 @@ DSP4_WAIT(2) resume2: pos2 = path_pos[1] + envelope2; // clip offscreen data - if (pos1 < path_clipLeft[0]) pos1 = path_clipLeft[0]; - if (pos1 > path_clipRight[0]) pos1 = path_clipRight[0]; - if (pos2 < path_clipLeft[1]) pos2 = path_clipLeft[1]; - if (pos2 > path_clipRight[1]) pos2 = path_clipRight[1]; + if(pos1 < path_clipLeft[0]) + pos1 = path_clipLeft[0]; + if(pos1 > path_clipRight[0]) + pos1 = path_clipRight[0]; + if(pos2 < path_clipLeft[1]) + pos2 = path_clipLeft[1]; + if(pos2 > path_clipRight[1]) + pos2 = path_clipRight[1]; path_plane[0] = plane; path_plane[1] = plane; @@ -558,11 +527,14 @@ DSP4_WAIT(2) resume2: segments = ABS(y_left - path_y[0]); // prevent overdraw - if (y_left >= path_raster[0]) segments = 0; - else path_raster[0] = y_left; + if(y_left >= path_raster[0]) + segments = 0; + else + path_raster[0] = y_left; // don't draw outside the window - if (path_raster[0] < path_top[0]) segments = 0; + if(path_raster[0] < path_top[0]) + segments = 0; // proceed if visibility rules apply if (segments > 0) @@ -588,7 +560,6 @@ DSP4_WAIT(2) resume2: // interpolate between projected points with shaping right_inc = ((x2_final - x1_final) << 8) / segments; - path_plane[0] = plane; } @@ -606,10 +577,14 @@ DSP4_WAIT(2) resume2: pos2 = path_pos[1] + ((right_inc * lcv) >> 8) + dx2; // clip offscreen data - if (pos1 < path_clipLeft[0]) pos1 = path_clipLeft[0]; - if (pos1 > path_clipRight[0]) pos1 = path_clipRight[0]; - if (pos2 < path_clipLeft[1]) pos2 = path_clipLeft[1]; - if (pos2 > path_clipRight[1]) pos2 = path_clipRight[1]; + if(pos1 < path_clipLeft[0]) + pos1 = path_clipLeft[0]; + if(pos1 > path_clipRight[0]) + pos1 = path_clipRight[0]; + if(pos2 < path_clipLeft[1]) + pos2 = path_clipLeft[1]; + if(pos2 > path_clipRight[1]) + pos2 = path_clipRight[1]; // data DSP4_WRITE_WORD(index, path_ptr[0]); @@ -641,11 +616,13 @@ DSP4_WAIT(2) resume2: segments = ABS(y_right - path_y[1]); // prevent overdraw - if (y_right >= path_raster[2]) segments = 0; + if(y_right >= path_raster[2]) + segments = 0; else path_raster[2] = y_right; // don't draw outside the window - if (path_raster[2] < path_top[2]) segments = 0; + if(path_raster[2] < path_top[2]) + segments = 0; // proceed if visibility rules apply if (segments > 0) @@ -689,10 +666,14 @@ DSP4_WAIT(2) resume2: pos2 = path_pos[3] + ((right_inc * lcv) >> 8) + dx2; // clip offscreen data - if (pos1 < path_clipLeft[2]) pos1 = path_clipLeft[2]; - if (pos1 > path_clipRight[2]) pos1 = path_clipRight[2]; - if (pos2 < path_clipLeft[3]) pos2 = path_clipLeft[3]; - if (pos2 > path_clipRight[3]) pos2 = path_clipRight[3]; + if(pos1 < path_clipLeft[2]) + pos1 = path_clipLeft[2]; + if(pos1 > path_clipRight[2]) + pos1 = path_clipRight[2]; + if(pos2 < path_clipLeft[3]) + pos2 = path_clipLeft[3]; + if(pos2 > path_clipRight[3]) + pos2 = path_clipRight[3]; // data DSP4_WRITE_WORD(index, path_ptr[2]); @@ -719,15 +700,14 @@ DSP4_WAIT(2) resume2: path_y[1] = y_right; } } - } - while (1); + } while (1); DSP4.waiting4command = true; DSP4.out_count = 2; DSP4_WRITE_WORD(0, 0); } -void DSP4_Op0D() +void DSP4_Op0D(void) { uint16_t command; // inspect inputs @@ -801,9 +781,6 @@ void DSP4_Op0D() project_y -= viewport_bottom; project_x = project_centerx + project_x1; - // debug - block = 0; - //////////////////////////////////////////////////// // command check @@ -811,39 +788,37 @@ void DSP4_Op0D() { // scan next command DSP4.in_count = 2; + DSP4_WAIT(1); -DSP4_WAIT(1) resume1: - +resume1: // inspect input command = DSP4_READ_WORD(0); // terminate op - if (command == 0x8000) break; + if(command == 0x8000) + break; // already have 2 bytes in queue DSP4.in_index = 2; DSP4.in_count = 8; - - DSP4_WAIT(2) + DSP4_WAIT(2); //////////////////////////////////////////////////// // project section of the track - resume2: - plane = DSP4_READ_WORD(0); px_dx = 0; // ignore invalid data - if ((uint16_t) plane == 0x8001) continue; + if((uint16_t) plane == 0x8001) + continue; // one-time init if (far_plane) { // setup final data - // low16=plane project_x1 = project_focalx; project_y1 = project_focaly; plane = far_plane; @@ -856,21 +831,22 @@ resume2: // quadratic regression (rough) if (project_focaly >= -0x0f) - py_dy = (int16_t)(project_focaly * project_focaly * -0.20533553 - - 1.08330005 * project_focaly - 69.61094639); + py_dy = (int16_t)(project_focaly * project_focaly * -0.20533553 - 1.08330005 * project_focaly - 69.61094639); else - py_dy = (int16_t)(project_focaly * project_focaly * -0.000657035759 - - 1.07629051 * project_focaly - 65.69315963); + py_dy = (int16_t)(project_focaly * project_focaly * -0.000657035759 - 1.07629051 * project_focaly - 65.69315963); // approximate # of raster lines segments = ABS(project_y2 - project_y1); // prevent overdraw - if (project_y2 >= raster) segments = 0; - else raster = project_y2; + if(project_y2 >= raster) + segments = 0; + else + raster = project_y2; // don't draw outside the window - if (project_y2 < viewport_top) segments = 0; + if(project_y2 < viewport_top) + segments = 0; // project new positions if (segments > 0) @@ -879,22 +855,16 @@ resume2: px_dx = ((project_x2 - project_x1) << 8) / segments; } - // debug - ++block; - // prepare output DSP4.out_count = 8 + 2 + 6 * segments; - DSP4_WRITE_WORD(0, project_focalx); DSP4_WRITE_WORD(2, project_x2); DSP4_WRITE_WORD(4, project_focaly); DSP4_WRITE_WORD(6, project_y2); DSP4_WRITE_WORD(8, segments); - index = 10; - // iterate through each point - for (lcv = 0; lcv < segments; lcv++) + for (lcv = 0; lcv < segments; lcv++) // iterate through each point { // step through the projected line y_out = project_y + ((py_dy * lcv) >> 8); @@ -930,14 +900,13 @@ resume2: project_focaly += project_pitchy; project_focalx += project_pitchx; - } - while (1); + } while (1); DSP4.waiting4command = true; DSP4.out_count = 0; } -void DSP4_Op09() +void DSP4_Op09(void) { uint16_t command; bool clip; @@ -975,9 +944,6 @@ void DSP4_Op09() //////////////////////////////////////////////////// // process initial inputs - // debug - block = 0; - // grab screen information view_plane = PLANE_START; center_x = DSP4_READ_WORD(0x00); @@ -995,8 +961,7 @@ void DSP4_Op09() multi_index1 %= 4; // convert track line to the window region - project_y2 = center_y + multi_raster[multi_index1] * - (viewport_bottom - center_y) / (0x33 - 0); + project_y2 = center_y + multi_raster[multi_index1] * (viewport_bottom - center_y) / (0x33 - 0); if (!op09_mode) project_y2 -= 2; @@ -1006,21 +971,21 @@ void DSP4_Op09() { //////////////////////////////////////////////////// // check for new sprites - do { uint16_t second; DSP4.in_count = 4; DSP4.in_index = 2; + DSP4_WAIT(1); -DSP4_WAIT(1) resume1: - +resume1: // try to classify sprite second = DSP4_READ_WORD(2); // op termination - if (second == 0x8000) goto terminate; + if(second == 0x8000) + goto terminate; second >>= 8; sprite_type = 0; @@ -1040,13 +1005,11 @@ DSP4_WAIT(1) resume1: no_sprite: // no sprite. try again - DSP4.in_count = 2; + DSP4_WAIT(2); -DSP4_WAIT(2) resume2: - ; - } - while (1); +resume2:; + } while (1); //////////////////////////////////////////////////// // process projection information @@ -1063,9 +1026,9 @@ sprite_found: // we already have 4 bytes we want DSP4.in_count = 6 + 12; DSP4.in_index = 4; + DSP4_WAIT(3); -DSP4_WAIT(3) resume3: - +resume3: // filter inputs project_y1 = DSP4_READ_WORD(0x00); focal_back = DSP4_READ_WORD(0x06); @@ -1087,9 +1050,6 @@ DSP4_WAIT(3) resume3: sprite_y = viewport_bottom - segments; far_plane = plane; - // debug - ++block; - // make the car's x-center available DSP4.out_count = 2; DSP4_WRITE_WORD(0, project_focalx); @@ -1097,28 +1057,25 @@ DSP4_WAIT(3) resume3: // grab a few remaining vehicle values DSP4.in_count = 4; - DSP4_WAIT(4) + DSP4_WAIT(4); - // store final values - -resume4: +resume4: // store final values height = DSP4_READ_WORD(0); sprite_offset = DSP4_READ_WORD(2); // vertical lift factor sprite_y += height; } - // terrain sprite - else if (sprite_type == 2) + else if (sprite_type == 2) // terrain sprite { int16_t plane; // we already have 4 bytes we want DSP4.in_count = 6 + 6 + 2; DSP4.in_index = 4; + DSP4_WAIT(5); -DSP4_WAIT(5) resume5: - +resume5: // sort loop inputs project_y1 = DSP4_READ_WORD(0x00); plane = DSP4_READ_WORD(0x02); @@ -1136,9 +1093,6 @@ DSP4_WAIT(5) resume5: sprite_x = center_x + project_x - project_centerx; sprite_y = viewport_bottom - segments + project_y; far_plane = plane; - - // debug - ++block; } // default sprite size: 16x16 @@ -1149,13 +1103,14 @@ DSP4_WAIT(5) resume5: do { DSP4.in_count = 2; + DSP4_WAIT(6); -DSP4_WAIT(6) resume6: - +resume6: command = DSP4_READ_WORD(0); // opcode termination - if (command == 0x8000) goto terminate; + if(command == 0x8000) + goto terminate; // toggle sprite size if (command == 0x0000) @@ -1166,21 +1121,17 @@ DSP4_WAIT(6) resume6: // new sprite information command >>= 8; - if (command != 0x20 && command != 0x40 && - command != 0x60 && command != 0xa0 && - command != 0xc0 && command != 0xe0) + if (command != 0x20 && command != 0x40 && command != 0x60 && command != 0xa0 && command != 0xc0 && command != 0xe0) break; DSP4.in_count = 6; DSP4.in_index = 2; - - DSP4_WAIT(7) + DSP4_WAIT(7); ///////////////////////////////////// // process tile data resume7: - // sprite deltas sp_dy = DSP4_READ_WORD(2); sp_dx = DSP4_READ_WORD(4); @@ -1191,12 +1142,14 @@ resume7: // reject points outside the clipping window clip = false; - if (sp_x < viewport_left || sp_x > viewport_right) clip = true; - if (sp_y < viewport_top || sp_y > viewport_bottom) clip = true; + if(sp_x < viewport_left || sp_x > viewport_right) + clip = true; + if(sp_y < viewport_top || sp_y > viewport_bottom) + clip = true; // track depth sorting - if (far_plane <= multi_farplane[multi_index1] && - sp_y >= project_y2) clip = true; + if(far_plane <= multi_farplane[multi_index1] && sp_y >= project_y2) + clip = true; // don't draw offscreen coordinates DSP4.out_count = 0; @@ -1210,11 +1163,7 @@ resume7: sp_msb = (sp_x < 0 || sp_x > 255); // emit transparency information - if ( - (sprite_offset & 0x08) && - ((sprite_type == 1 && sp_y >= 0xcc) || - (sprite_type == 2 && sp_y >= 0xbb)) - ) + if((sprite_offset & 0x08) && ((sprite_type == 1 && sp_y >= 0xcc) || (sprite_type == 2 && sp_y >= 0xbb))) { DSP4.out_count = 6; @@ -1225,7 +1174,6 @@ resume7: DSP4.output[2] = sp_x & 0xFF; DSP4.output[3] = (sp_y + 6) & 0xFF; DSP4_WRITE_WORD(4, 0xEE); - out_index = 6; // OAM: size,msb data @@ -1256,8 +1204,7 @@ resume7: DSP4.out_count = 2; DSP4_WRITE_WORD(0, 0); } - } - while (1); + } while (1); ///////////////////////////////////// // special cases: plane == 0x0000 @@ -1275,8 +1222,7 @@ resume7: goto sprite_found; } - // special terrain case - else if (command != 0x00 && command != 0xff) + else if (command != 0x00 && command != 0xff) // special terrain case { sprite_type = 2; @@ -1288,8 +1234,7 @@ resume7: goto sprite_found; } - } - while (1); + } while (1); terminate: DSP4.waiting4command = true; diff --git a/source/fxemu.c b/source/fxemu.c index 4bdc0b0..1a6ca7b 100644 --- a/source/fxemu.c +++ b/source/fxemu.c @@ -9,26 +9,17 @@ /* The FxChip Emulator's internal variables */ FxRegs_s GSU; /* This will be initialized when loading a ROM */ -void FxCacheWriteAccess(uint16_t vAddress) -{ - if ((vAddress & 0x00f) == 0x00f) - GSU.vCacheFlags |= 1 << ((vAddress & 0x1f0) >> 4); -} - void FxFlushCache(void) { - GSU.vCacheFlags = 0; GSU.vCacheBaseReg = 0; GSU.bCacheActive = false; } void fx_flushCache(void) { - GSU.vCacheFlags = 0; GSU.bCacheActive = false; } - void fx_updateRamBank(uint8_t Byte) { // Update BankReg and Bank pointer @@ -52,8 +43,6 @@ static void fx_readRegisterSpaceForUse(void) int32_t i; uint8_t* p = GSU.pvRegisters; - GSU.vErrorCode = 0; - /* Update R0 - R14 */ for (i = 0; i < 15; i++) { @@ -90,10 +79,7 @@ static void fx_readRegisterSpaceForUse(void) else GSU.vScreenSize = (GSU.vScreenHeight / 8) * (256 / 8) * avMult[GSU.vMode]; if (GSU.vPlotOptionReg & 0x10) - { - /* OBJ Mode (for drawing into sprites) */ - GSU.vScreenHeight = 256; - } + GSU.vScreenHeight = 256; /* OBJ Mode (for drawing into sprites) */ if (GSU.pvScreenBase + GSU.vScreenSize > GSU.pvRam + (GSU.nRamBanks * 65536)) GSU.pvScreenBase = GSU.pvRam + (GSU.nRamBanks * 65536) - GSU.vScreenSize; GSU.pfPlot = fx_apfPlotTable[GSU.vMode]; @@ -117,7 +103,6 @@ void fx_computeScreenPointers(void) if (GSU.vMode != GSU.vPrevMode || GSU.vPrevScreenHeight != GSU.vScreenHeight || GSU.vSCBRDirty) { int32_t i; - GSU.vSCBRDirty = false; /* Make a list of pointers to the start of each screen column */ @@ -285,7 +270,6 @@ static void fx_writeRegisterSpaceAfterUse(void) void FxReset(FxInit_s* psFxInfo) { int32_t i; - /* Clear all internal variables */ memset(&GSU, 0, sizeof(FxRegs_s)); @@ -341,9 +325,6 @@ void FxReset(FxInit_s* psFxInfo) /* Start with a nop in the pipe */ GSU.vPipe = 0x01; - /* Set pointer to GSU cache */ - GSU.pvCache = &GSU.pvRegisters[0x100]; - fx_readRegisterSpaceForCheck(); fx_readRegisterSpaceForUse(); } @@ -399,45 +380,5 @@ int32_t FxEmulate(uint32_t nInstructions) fx_writeRegisterSpaceAfterUse(); /* Check for error code */ - if (GSU.vErrorCode) - return GSU.vErrorCode; - else - return vCount; -} - -/* Errors */ -int32_t FxGetErrorCode(void) -{ - return GSU.vErrorCode; -} - -int32_t FxGetIllegalAddress(void) -{ - return GSU.vIllegalAddress; -} - -/* Access to internal registers */ -uint32_t FxGetColorRegister(void) -{ - return GSU.vColorReg & 0xff; -} - -uint32_t FxGetPlotOptionRegister(void) -{ - return GSU.vPlotOptionReg & 0x1f; -} - -uint32_t FxGetSourceRegisterIndex(void) -{ - return GSU.pvSreg - GSU.avReg; -} - -uint32_t FxGetDestinationRegisterIndex(void) -{ - return GSU.pvDreg - GSU.avReg; -} - -uint8_t FxPipe(void) -{ - return GSU.vPipe; + return vCount; } diff --git a/source/fxemu.h b/source/fxemu.h index 3161ebd..66e64e4 100644 --- a/source/fxemu.h +++ b/source/fxemu.h @@ -22,39 +22,13 @@ extern void FxReset(FxInit_s* psFxInfo); extern int32_t FxEmulate(uint32_t nInstructions); /* Write access to the cache */ -extern void FxCacheWriteAccess(uint16_t vAddress); extern void FxFlushCache(void); /* Called when the G flag in SFR is set to zero */ -/* Errors */ -extern int32_t FxGetErrorCode(void); -extern int32_t FxGetIllegalAddress(void); - -/* Access to internal registers */ -extern uint32_t FxGetColorRegister(void); -extern uint32_t FxGetPlotOptionRegister(void); -extern uint32_t FxGetSourceRegisterIndex(void); -extern uint32_t FxGetDestinationRegisterIndex(void); - -/* Get the byte currently in the pipe */ -extern uint8_t FxPipe(void); - /* SCBR write seen. We need to update our cached screen pointers */ extern void fx_dirtySCBR(void); /* Update RamBankReg and RAM Bank pointer */ extern void fx_updateRamBank(uint8_t Byte); -/* Option flags */ -#define FX_FLAG_ADDRESS_CHECKING 0x01 -#define FX_FLAG_ROM_BUFFER 0x02 - -/* Return codes from FxEmulate(), FxStepInto() or FxStepOver() */ -#define FX_BREAKPOINT -1 -#define FX_ERROR_ILLEGAL_ADDRESS -2 - -/* Return the number of bytes in an opcode */ -#define OPCODE_BYTES(op) ((((op) >= 0x05 && (op) <= 0xf) || ((op) >= 0xa0 && (op) <= 0xaf)) ? 2 : (((op) >= 0xf0) ? 3 : 1)) - extern void fx_computeScreenPointers(void); - #endif diff --git a/source/fxinst.c b/source/fxinst.c index 1023e82..d48631d 100644 --- a/source/fxinst.c +++ b/source/fxinst.c @@ -1,7 +1,5 @@ #include "../copyright" -#define FX_DO_ROMBUFFER - #include "fxemu.h" #include "fxinst.h" #include <string.h> @@ -10,7 +8,6 @@ #include <retro_inline.h> extern FxRegs_s GSU; -int32_t gsu_bank [512] = {0}; /* Codes used: * @@ -20,7 +17,6 @@ int32_t gsu_bank [512] = {0}; * (yy) = 8 bit word address (0x0000 - 0x01fe) * #xx = 16 bit immediate value * (xx) = 16 bit address (0x0000 - 0xffff) - * */ /* 00 - stop - stop GSU execution (and maybe generate an IRQ) */ @@ -2967,12 +2963,7 @@ static INLINE void fx_inc_r14(void) /* df - getc - transfer ROM buffer to color register */ static INLINE void fx_getc(void) { -#ifndef FX_DO_ROMBUFFER - uint8_t c; - c = ROM(R14); -#else uint8_t c = GSU.vRomBuffer; -#endif if (GSU.vPlotOptionReg & 0x04) c = (c & 0xf0) | (c >> 4); if (GSU.vPlotOptionReg & 0x08) @@ -3077,12 +3068,7 @@ static INLINE void fx_dec_r14(void) /* ef - getb - get byte from ROM at address R14 */ static INLINE void fx_getb(void) { - uint32_t v; -#ifndef FX_DO_ROMBUFFER - v = (uint32_t)ROM(R14); -#else - v = (uint32_t)GSU.vRomBuffer; -#endif + uint32_t v = (uint32_t)GSU.vRomBuffer; R15++; DREG = v; TESTR14; @@ -3092,14 +3078,8 @@ static INLINE void fx_getb(void) /* ef(ALT1) - getbh - get high-byte from ROM at address R14 */ static INLINE void fx_getbh(void) { - uint32_t v; -#ifndef FX_DO_ROMBUFFER - uint32_t c; - c = (uint32_t)ROM(R14); -#else uint32_t c = USEX8(GSU.vRomBuffer); -#endif - v = USEX8(SREG) | (c << 8); + uint32_t v = USEX8(SREG) | (c << 8); R15++; DREG = v; TESTR14; @@ -3109,13 +3089,8 @@ static INLINE void fx_getbh(void) /* ef(ALT2) - getbl - get low-byte from ROM at address R14 */ static INLINE void fx_getbl(void) { - uint32_t v; -#ifndef FX_DO_ROMBUFFER - uint32_t c = (uint32_t)ROM(R14); -#else uint32_t c = USEX8(GSU.vRomBuffer); -#endif - v = (SREG & 0xff00) | c; + uint32_t v = (SREG & 0xff00) | c; R15++; DREG = v; TESTR14; @@ -3125,14 +3100,7 @@ static INLINE void fx_getbl(void) /* ef(ALT3) - getbs - get sign extended byte from ROM at address R14 */ static INLINE void fx_getbs(void) { - uint32_t v; -#ifndef FX_DO_ROMBUFFER - int8_t c; - c = ROM(R14); - v = SEX8(c); -#else - v = SEX8(GSU.vRomBuffer); -#endif + uint32_t v = SEX8(GSU.vRomBuffer); R15++; DREG = v; TESTR14; @@ -3384,7 +3352,7 @@ uint32_t fx_run(uint32_t nInstructions) READR14; while (TF(G) && (GSU.vCounter-- > 0)) FX_STEP; - return (nInstructions - GSU.vInstCount); + return nInstructions - GSU.vInstCount; } /*** Special table for the different plot configurations ***/ @@ -3448,11 +3416,9 @@ void (*fx_apfOpcodeTable[])(void) = /* f0 - ff */ &fx_iwt_r0, &fx_iwt_r1, &fx_iwt_r2, &fx_iwt_r3, &fx_iwt_r4, &fx_iwt_r5, &fx_iwt_r6, &fx_iwt_r7, &fx_iwt_r8, &fx_iwt_r9, &fx_iwt_r10, &fx_iwt_r11, &fx_iwt_r12, &fx_iwt_r13, &fx_iwt_r14, &fx_iwt_r15, - /* * ALT1 Table */ - /* 00 - 0f */ &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, @@ -3501,11 +3467,9 @@ void (*fx_apfOpcodeTable[])(void) = /* f0 - ff */ &fx_lm_r0, &fx_lm_r1, &fx_lm_r2, &fx_lm_r3, &fx_lm_r4, &fx_lm_r5, &fx_lm_r6, &fx_lm_r7, &fx_lm_r8, &fx_lm_r9, &fx_lm_r10, &fx_lm_r11, &fx_lm_r12, &fx_lm_r13, &fx_lm_r14, &fx_lm_r15, - /* * ALT2 Table */ - /* 00 - 0f */ &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, @@ -3554,11 +3518,9 @@ void (*fx_apfOpcodeTable[])(void) = /* f0 - ff */ &fx_sm_r0, &fx_sm_r1, &fx_sm_r2, &fx_sm_r3, &fx_sm_r4, &fx_sm_r5, &fx_sm_r6, &fx_sm_r7, &fx_sm_r8, &fx_sm_r9, &fx_sm_r10, &fx_sm_r11, &fx_sm_r12, &fx_sm_r13, &fx_sm_r14, &fx_sm_r15, - /* * ALT3 Table */ - /* 00 - 0f */ &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, diff --git a/source/fxinst.h b/source/fxinst.h index 68555b2..e1acd0d 100644 --- a/source/fxinst.h +++ b/source/fxinst.h @@ -135,13 +135,11 @@ typedef struct uint32_t vRomBankReg; /* Rom bank index register */ uint32_t vRamBankReg; /* Ram bank index register */ uint32_t vCacheBaseReg; /* Cache base address register */ - uint32_t vCacheFlags; /* Saying what parts of the cache was written to */ uint32_t vLastRamAdr; /* Last RAM address accessed */ uint32_t* pvDreg; /* Pointer to current destination register */ uint32_t* pvSreg; /* Pointer to current source register */ uint8_t vRomBuffer; /* Current byte read by R14 */ uint8_t vPipe; /* Instructionset pipe */ - uint32_t vPipeAdr; /* The address of where the pipe was read from */ /* status register optimization stuff */ uint32_t vSign; /* v & 0x8000 */ @@ -150,11 +148,6 @@ typedef struct int32_t vOverflow; /* (v >= 0x8000 || v < -0x8000) */ /* Other emulator variables */ - int32_t vErrorCode; - uint32_t vIllegalAddress; - uint8_t bBreakPoint; - uint32_t vBreakPoint; - uint32_t vStepPoint; uint8_t* pvRegisters; /* 768 bytes located in the memory at address 0x3000 */ uint32_t nRamBanks; /* Number of 64kb-banks in FxRam (Don't confuse it with SNES-Ram!!!) */ uint8_t* pvRam; /* Pointer to FxRam */ @@ -177,30 +170,12 @@ typedef struct uint8_t* apvRamBank[FX_RAM_BANKS]; /* Ram bank table (max 256kb) */ uint8_t* apvRomBank[256]; /* Rom bank table */ uint8_t bCacheActive; - uint8_t* pvCache; /* Pointer to the GSU cache */ - uint8_t avCacheBackup[512]; /* Backup of ROM when the cache has replaced it */ uint32_t vCounter; uint32_t vInstCount; uint32_t vSCBRDirty; /* if SCBR is written, our cached screen pointers need updating */ } FxRegs_s; /* GSU registers */ -#define GSU_R0 0x000 -#define GSU_R1 0x002 -#define GSU_R2 0x004 -#define GSU_R3 0x006 -#define GSU_R4 0x008 -#define GSU_R5 0x00a -#define GSU_R6 0x00c -#define GSU_R7 0x00e -#define GSU_R8 0x010 -#define GSU_R9 0x012 -#define GSU_R10 0x014 -#define GSU_R11 0x016 -#define GSU_R12 0x018 -#define GSU_R13 0x01a -#define GSU_R14 0x01c -#define GSU_R15 0x01e #define GSU_SFR 0x030 #define GSU_BRAMR 0x033 #define GSU_PBR 0x034 @@ -212,7 +187,6 @@ typedef struct #define GSU_VCR 0x03b #define GSU_RAMBR 0x03c #define GSU_CBR 0x03e -#define GSU_CACHERAM 0x100 /* SFR flags */ #define FLG_Z (1 << 1) @@ -234,7 +208,7 @@ typedef struct #define SF(a) (GSU.vStatusReg |= FLG_##a ) /* Test and set flag if condition, clear if not */ -#define TS(a,b) GSU.vStatusReg = ((GSU.vStatusReg & (~FLG_##a)) | ((!!(##b)) * FLG_##a )) +#define TS(a, b) (GSU.vStatusReg = ((GSU.vStatusReg & (~FLG_##a)) | ((!!(##b)) * FLG_##a))) /* Testing ALT1 & ALT2 bits */ #define ALT0 (!TF(ALT1) && !TF(ALT2)) @@ -263,7 +237,7 @@ typedef struct GSU.pvDreg = GSU.pvSreg = &R0; /* Read current RAM-Bank */ -#define RAM(adr) GSU.pvRamBank[USEX16(adr)] +#define RAM(adr) (GSU.pvRamBank[USEX16(adr)]) /* Read current ROM-Bank */ #define ROM(idx) (GSU.pvRomBank[USEX16(idx)]) @@ -283,23 +257,14 @@ typedef struct /* Access destination register */ #define DREG (*GSU.pvDreg) -#ifndef FX_DO_ROMBUFFER - -/* Don't read R14 */ -#define READR14 - -/* Don't test and/or read R14 */ -#define TESTR14 - -#else - /* Read R14 */ -#define READR14 GSU.vRomBuffer = ROM(R14) +#define READR14 \ + GSU.vRomBuffer = ROM(R14) /* Test and/or read R14 */ -#define TESTR14 if(GSU.pvDreg == &R14) READR14 - -#endif +#define TESTR14 \ + if(GSU.pvDreg == &R14) \ + READR14 /* Access to registers */ #define R0 GSU.avReg[0] @@ -337,16 +302,11 @@ typedef struct { \ uint32_t vOpcode = (uint32_t) PIPE; \ FETCHPIPE; \ - (*fx_apfOpcodeTable[ (GSU.vStatusReg & 0x300) | vOpcode ])(); \ + (*fx_apfOpcodeTable[(GSU.vStatusReg & 0x300) | vOpcode])(); \ } extern void (*fx_apfOpcodeTable[])(void); extern void (*fx_apfPlotTable[])(void); uint32_t fx_run(uint32_t nInstructions); - -/* Set this define if branches are relative to the instruction in the delay slot */ -/* (I think they are) */ -#define BRANCH_DELAY_RELATIVE - #endif diff --git a/source/getset.h b/source/getset.h index ab2186d..c7f4950 100644 --- a/source/getset.h +++ b/source/getset.h @@ -25,29 +25,29 @@ inline uint8_t S9xGetByte(uint32_t Address) { if (Memory.BlockIsRAM [block]) CPU.WaitAddress = CPU.PCAtOpcodeStart; - return (*(GetAddress + (Address & 0xffff))); + return GetAddress[Address & 0xffff]; } switch ((intptr_t) GetAddress) { case MAP_PPU: - return (S9xGetPPU(Address & 0xffff)); + return S9xGetPPU(Address & 0xffff); case MAP_CPU: - return (S9xGetCPU(Address & 0xffff)); + return S9xGetCPU(Address & 0xffff); case MAP_DSP: - return (S9xGetDSP(Address & 0xffff)); + return S9xGetDSP(Address & 0xffff); case MAP_SA1RAM: case MAP_LOROM_SRAM: - //Address &0x7FFF -offset into bank - //Address&0xFF0000 -bank - //bank>>1 | offset = s-ram address, unbound + //Address & 0x7FFF - offset into bank + //Address & 0xFF0000 - bank + //bank >> 1 | offset = s-ram address, unbound //unbound & SRAMMask = Sram offset - return (*(Memory.SRAM + ((((Address & 0xFF0000) >> 1) | (Address & 0x7FFF)) &Memory.SRAMMask))); + return Memory.SRAM[(((Address & 0xFF0000) >> 1) | (Address & 0x7FFF)) &Memory.SRAMMask]; case MAP_RONLY_SRAM: case MAP_HIROM_SRAM: - return (*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask))); + return Memory.SRAM[((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask]; case MAP_BWRAM: - return (*(Memory.BWRAM + ((Address & 0x7fff) - 0x6000))); + return Memory.BWRAM[(Address & 0x7fff) - 0x6000]; case MAP_C4: return S9xGetC4(Address & 0xffff); case MAP_SPC7110_ROM: @@ -70,7 +70,7 @@ inline uint16_t S9xGetWord(uint32_t Address) if ((Address & 0x0fff) == 0x0fff) { OpenBus = S9xGetByte(Address); - return (OpenBus | (S9xGetByte(Address + 1) << 8)); + return OpenBus | (S9xGetByte(Address + 1) << 8); } int32_t block; uint8_t* GetAddress = Memory.Map [block = (Address >> MEMMAP_SHIFT) & MEMMAP_MASK]; @@ -83,53 +83,46 @@ inline uint16_t S9xGetWord(uint32_t Address) if (Memory.BlockIsRAM [block]) CPU.WaitAddress = CPU.PCAtOpcodeStart; #ifdef FAST_LSB_WORD_ACCESS - return (*(uint16_t*)(GetAddress + (Address & 0xffff))); + return *(uint16_t*) (GetAddress + (Address & 0xffff)); #else - return (*(GetAddress + (Address & 0xffff)) | (*(GetAddress + (Address & 0xffff) + 1) << 8)); + return *(GetAddress + (Address & 0xffff)) | (*(GetAddress + (Address & 0xffff) + 1) << 8); #endif } switch ((intptr_t) GetAddress) { case MAP_PPU: - return (S9xGetPPU(Address & 0xffff) | (S9xGetPPU((Address + 1) & 0xffff) << 8)); + return S9xGetPPU(Address & 0xffff) | (S9xGetPPU((Address + 1) & 0xffff) << 8); case MAP_CPU: - return (S9xGetCPU(Address & 0xffff) | (S9xGetCPU((Address + 1) & 0xffff) << 8)); + return S9xGetCPU(Address & 0xffff) | (S9xGetCPU((Address + 1) & 0xffff) << 8); case MAP_DSP: - return (S9xGetDSP(Address & 0xffff) | (S9xGetDSP((Address + 1) & 0xffff) << 8)); + return S9xGetDSP(Address & 0xffff) | (S9xGetDSP((Address + 1) & 0xffff) << 8); case MAP_SA1RAM: case MAP_LOROM_SRAM: - //Address &0x7FFF -offset into bank - //Address&0xFF0000 -bank - //bank>>1 | offset = s-ram address, unbound + //Address & 0x7FFF - offset into bank + //Address & 0xFF0000 - bank + //bank >> 1 | offset = s-ram address, unbound //unbound & SRAMMask = Sram offset /* BJ: no FAST_LSB_WORD_ACCESS here, since if Memory.SRAMMask=0x7ff * then the high byte doesn't follow the low byte. */ - return - (*(Memory.SRAM + ((((Address & 0xFF0000) >> 1) | (Address & 0x7FFF)) & Memory.SRAMMask))) | - ((*(Memory.SRAM + (((((Address + 1) & 0xFF0000) >> 1) | ((Address + 1) & 0x7FFF)) & Memory.SRAMMask))) << 8); + return *(Memory.SRAM + ((((Address & 0xFF0000) >> 1) | (Address & 0x7FFF)) & Memory.SRAMMask)) | ((*(Memory.SRAM + (((((Address + 1) & 0xFF0000) >> 1) | ((Address + 1) & 0x7FFF)) & Memory.SRAMMask))) << 8); case MAP_RONLY_SRAM: case MAP_HIROM_SRAM: /* BJ: no FAST_LSB_WORD_ACCESS here, since if Memory.SRAMMask=0x7ff * then the high byte doesn't follow the low byte. */ - return (*(Memory.SRAM + - (((Address & 0x7fff) - 0x6000 + - ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) | - (*(Memory.SRAM + - ((((Address + 1) & 0x7fff) - 0x6000 + - (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) << 8)); + return *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) | (*(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) << 8); case MAP_BWRAM: #ifdef FAST_LSB_WORD_ACCESS - return (*(uint16_t*)(Memory.BWRAM + ((Address & 0x7fff) - 0x6000))); + return *(uint16_t*) (Memory.BWRAM + ((Address & 0x7fff) - 0x6000)); #else - return (*(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) | (*(Memory.BWRAM + (((Address + 1) & 0x7fff) - 0x6000)) << 8)); + return *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) | (*(Memory.BWRAM + (((Address + 1) & 0x7fff) - 0x6000)) << 8); #endif case MAP_C4: - return (S9xGetC4(Address & 0xffff) | (S9xGetC4((Address + 1) & 0xffff) << 8)); + return S9xGetC4(Address & 0xffff) | (S9xGetC4((Address + 1) & 0xffff) << 8); case MAP_SPC7110_ROM: - return (S9xGetSPC7110Byte(Address) | (S9xGetSPC7110Byte(Address + 1)) << 8); + return S9xGetSPC7110Byte(Address) | (S9xGetSPC7110Byte(Address + 1)) << 8; case MAP_SPC7110_DRAM: - return (S9xGetSPC7110(0x4800) | (S9xGetSPC7110(0x4800) << 8)); + return S9xGetSPC7110(0x4800) | (S9xGetSPC7110(0x4800) << 8); case MAP_OBC_RAM: return GetOBC1(Address & 0xFFFF) | (GetOBC1((Address + 1) & 0xFFFF) << 8); case MAP_SETA_DSP: @@ -137,7 +130,7 @@ inline uint16_t S9xGetWord(uint32_t Address) case MAP_SETA_RISC: return S9xGetST018(Address) | (S9xGetST018((Address + 1)) << 8); default: - return (OpenBus | (OpenBus << 8)); + return OpenBus | (OpenBus << 8); } } @@ -153,8 +146,7 @@ inline void S9xSetByte(uint8_t Byte, uint32_t Address) if (SetAddress >= (uint8_t*) MAP_LAST) { SetAddress += Address & 0xffff; - if (SetAddress == SA1.WaitByteAddress1 || - SetAddress == SA1.WaitByteAddress2) + if (SetAddress == SA1.WaitByteAddress1 || SetAddress == SA1.WaitByteAddress2) { SA1.Executing = SA1.S9xOpcodes != NULL; SA1.WaitCounter = 0; @@ -232,8 +224,7 @@ inline void S9xSetWord(uint16_t Word, uint32_t Address) if (SetAddress >= (uint8_t*) MAP_LAST) { SetAddress += Address & 0xffff; - if (SetAddress == SA1.WaitByteAddress1 || - SetAddress == SA1.WaitByteAddress2) + if (SetAddress == SA1.WaitByteAddress1 || SetAddress == SA1.WaitByteAddress2) { SA1.Executing = SA1.S9xOpcodes != NULL; SA1.WaitCounter = 0; @@ -276,12 +267,8 @@ inline void S9xSetWord(uint16_t Word, uint32_t Address) { /* BJ: no FAST_LSB_WORD_ACCESS here, since if Memory.SRAMMask=0x7ff * then the high byte doesn't follow the low byte. */ - *(Memory.SRAM + - (((((Address & 0x7fff) - 0x6000) + - ((Address & 0xf0000) >> 3)) & Memory.SRAMMask))) = (uint8_t) Word; - *(Memory.SRAM + - ((((((Address + 1) & 0x7fff) - 0x6000) + - (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask))) = (uint8_t)(Word >> 8); + *(Memory.SRAM + (((((Address & 0x7fff) - 0x6000) + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask))) = (uint8_t) Word; + *(Memory.SRAM + ((((((Address + 1) & 0x7fff) - 0x6000) + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask))) = (uint8_t)(Word >> 8); CPU.SRAMModified = true; } return; @@ -324,7 +311,7 @@ inline uint8_t* GetBasePointer(uint32_t Address) { uint8_t* GetAddress = Memory.Map [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK]; if (GetAddress >= (uint8_t*) MAP_LAST) - return (GetAddress); + return GetAddress; if (Settings.SPC7110 && ((Address & 0x7FFFFF) == 0x4800)) return s7r.bank50; switch ((intptr_t) GetAddress) @@ -338,17 +325,17 @@ inline uint8_t* GetBasePointer(uint32_t Address) case MAP_OBC_RAM: return Memory.FillRAM; case MAP_DSP: - return (Memory.FillRAM - 0x6000); + return Memory.FillRAM - 0x6000; case MAP_SA1RAM: case MAP_LOROM_SRAM: case MAP_SETA_DSP: return Memory.SRAM; case MAP_BWRAM: - return (Memory.BWRAM - 0x6000); + return Memory.BWRAM - 0x6000; case MAP_HIROM_SRAM: - return (Memory.SRAM - 0x6000); + return Memory.SRAM - 0x6000; case MAP_C4: - return (Memory.C4RAM - 0x6000); + return Memory.C4RAM - 0x6000; default: return NULL; } @@ -358,7 +345,7 @@ inline uint8_t* S9xGetMemPointer(uint32_t Address) { uint8_t* GetAddress = Memory.Map [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK]; if (GetAddress >= (uint8_t*) MAP_LAST) - return (GetAddress + (Address & 0xffff)); + return GetAddress + (Address & 0xffff); if (Settings.SPC7110 && ((Address & 0x7FFFFF) == 0x4800)) return s7r.bank50; @@ -368,20 +355,20 @@ inline uint8_t* S9xGetMemPointer(uint32_t Address) case MAP_SPC7110_DRAM: return &s7r.bank50[Address & 0xffff]; case MAP_PPU: - return (Memory.FillRAM + (Address & 0xffff)); + return Memory.FillRAM + (Address & 0xffff); case MAP_CPU: - return (Memory.FillRAM + (Address & 0xffff)); + return Memory.FillRAM + (Address & 0xffff); case MAP_DSP: - return (Memory.FillRAM - 0x6000 + (Address & 0xffff)); + return Memory.FillRAM - 0x6000 + (Address & 0xffff); case MAP_SA1RAM: case MAP_LOROM_SRAM: - return (Memory.SRAM + (Address & 0xffff)); + return Memory.SRAM + (Address & 0xffff); case MAP_BWRAM: - return (Memory.BWRAM - 0x6000 + (Address & 0xffff)); + return Memory.BWRAM - 0x6000 + (Address & 0xffff); case MAP_HIROM_SRAM: - return (Memory.SRAM - 0x6000 + (Address & 0xffff)); + return Memory.SRAM - 0x6000 + (Address & 0xffff); case MAP_C4: - return (Memory.C4RAM - 0x6000 + (Address & 0xffff)); + return Memory.C4RAM - 0x6000 + (Address & 0xffff); case MAP_OBC_RAM: return GetMemPointerOBC1(Address); case MAP_SETA_DSP: diff --git a/source/gfx.c b/source/gfx.c index e28c4f3..cc946aa 100644 --- a/source/gfx.c +++ b/source/gfx.c @@ -14,20 +14,20 @@ #define M7 19 -void ComputeClipWindows(); +void ComputeClipWindows(void); -extern uint8_t BitShifts[8][4]; -extern uint8_t TileShifts[8][4]; +extern uint8_t BitShifts [8][4]; +extern uint8_t TileShifts [8][4]; extern uint8_t PaletteShifts[8][4]; -extern uint8_t PaletteMasks[8][4]; -extern uint8_t Depths[8][4]; -extern uint8_t BGSizes [2]; +extern uint8_t PaletteMasks [8][4]; +extern uint8_t Depths [8][4]; +extern uint8_t BGSizes [2]; -extern NormalTileRenderer DrawTilePtr; +extern NormalTileRenderer DrawTilePtr; extern ClippedTileRenderer DrawClippedTilePtr; -extern NormalTileRenderer DrawHiResTilePtr; +extern NormalTileRenderer DrawHiResTilePtr; extern ClippedTileRenderer DrawHiResClippedTilePtr; -extern LargePixelRenderer DrawLargePixelPtr; +extern LargePixelRenderer DrawLargePixelPtr; extern SBG BG; @@ -77,100 +77,40 @@ extern uint8_t Mode7Depths [2]; } \ } - #define BLACK BUILD_PIXEL(0,0,0) -void DrawTile16(uint32_t Tile, int32_t Offset, uint32_t StartLine, - uint32_t LineCount); -void DrawClippedTile16(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Width, - uint32_t StartLine, uint32_t LineCount); -void DrawTile16HalfWidth(uint32_t Tile, int32_t Offset, uint32_t StartLine, - uint32_t LineCount); -void DrawClippedTile16HalfWidth(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Width, - uint32_t StartLine, uint32_t LineCount); -void DrawTile16x2(uint32_t Tile, int32_t Offset, uint32_t StartLine, - uint32_t LineCount); -void DrawClippedTile16x2(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Width, - uint32_t StartLine, uint32_t LineCount); -void DrawTile16x2x2(uint32_t Tile, int32_t Offset, uint32_t StartLine, - uint32_t LineCount); -void DrawClippedTile16x2x2(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Width, - uint32_t StartLine, uint32_t LineCount); -void DrawLargePixel16(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Pixels, - uint32_t StartLine, uint32_t LineCount); -void DrawLargePixel16HalfWidth(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Pixels, - uint32_t StartLine, uint32_t LineCount); - -void DrawTile16Add(uint32_t Tile, int32_t Offset, uint32_t StartLine, - uint32_t LineCount); - -void DrawClippedTile16Add(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Width, - uint32_t StartLine, uint32_t LineCount); - -void DrawTile16Add1_2(uint32_t Tile, int32_t Offset, uint32_t StartLine, - uint32_t LineCount); - -void DrawClippedTile16Add1_2(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Width, - uint32_t StartLine, uint32_t LineCount); - -void DrawTile16FixedAdd1_2(uint32_t Tile, int32_t Offset, uint32_t StartLine, - uint32_t LineCount); - -void DrawClippedTile16FixedAdd1_2(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Width, - uint32_t StartLine, uint32_t LineCount); - -void DrawTile16Sub(uint32_t Tile, int32_t Offset, uint32_t StartLine, - uint32_t LineCount); - -void DrawClippedTile16Sub(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Width, - uint32_t StartLine, uint32_t LineCount); - -void DrawTile16Sub1_2(uint32_t Tile, int32_t Offset, uint32_t StartLine, - uint32_t LineCount); - -void DrawClippedTile16Sub1_2(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Width, - uint32_t StartLine, uint32_t LineCount); - -void DrawTile16FixedSub1_2(uint32_t Tile, int32_t Offset, uint32_t StartLine, - uint32_t LineCount); - -void DrawClippedTile16FixedSub1_2(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Width, - uint32_t StartLine, uint32_t LineCount); - -void DrawLargePixel16Add(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Pixels, - uint32_t StartLine, uint32_t LineCount); - -void DrawLargePixel16Add1_2(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Pixels, - uint32_t StartLine, uint32_t LineCount); - -void DrawLargePixel16Sub(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Pixels, - uint32_t StartLine, uint32_t LineCount); - -void DrawLargePixel16Sub1_2(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Pixels, - uint32_t StartLine, uint32_t LineCount); - -bool S9xInitGFX() +void DrawTile16(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount); +void DrawClippedTile16(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount); +void DrawTile16HalfWidth(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount); +void DrawClippedTile16HalfWidth(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount); +void DrawTile16x2(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount); +void DrawClippedTile16x2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount); +void DrawTile16x2x2(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount); +void DrawClippedTile16x2x2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount); +void DrawLargePixel16(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Pixels, uint32_t StartLine, uint32_t LineCount); +void DrawLargePixel16HalfWidth(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Pixels, uint32_t StartLine, uint32_t LineCount); +void DrawTile16Add(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount); +void DrawClippedTile16Add(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount); +void DrawTile16Add1_2(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount); +void DrawClippedTile16Add1_2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount); +void DrawTile16FixedAdd1_2(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount); +void DrawClippedTile16FixedAdd1_2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount); +void DrawTile16Sub(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount); +void DrawClippedTile16Sub(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount); +void DrawTile16Sub1_2(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount); +void DrawClippedTile16Sub1_2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount); +void DrawTile16FixedSub1_2(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount); +void DrawClippedTile16FixedSub1_2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount); +void DrawLargePixel16Add(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Pixels, uint32_t StartLine, uint32_t LineCount); +void DrawLargePixel16Add1_2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Pixels, uint32_t StartLine, uint32_t LineCount); +void DrawLargePixel16Sub(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Pixels, uint32_t StartLine, uint32_t LineCount); +void DrawLargePixel16Sub1_2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Pixels, uint32_t StartLine, uint32_t LineCount); + +bool S9xInitGFX(void) { uint32_t r, g, b; uint32_t PixelOdd = 1; uint32_t PixelEven = 2; - uint8_t bitshift; for (bitshift = 0; bitshift < 4; bitshift++) { @@ -283,10 +223,9 @@ bool S9xInitGFX() S9xFixColourBrightness(); if (!(GFX.X2 = (uint16_t*) malloc(sizeof(uint16_t) * 0x10000))) - return (false); + return false; - if (!(GFX.ZERO_OR_X2 = (uint16_t*) malloc(sizeof(uint16_t) * 0x10000)) || - !(GFX.ZERO = (uint16_t*) malloc(sizeof(uint16_t) * 0x10000))) + if (!(GFX.ZERO_OR_X2 = (uint16_t*) malloc(sizeof(uint16_t) * 0x10000)) || !(GFX.ZERO = (uint16_t*) malloc(sizeof(uint16_t) * 0x10000))) { if (GFX.ZERO_OR_X2) { @@ -298,7 +237,7 @@ bool S9xInitGFX() free(GFX.X2); GFX.X2 = NULL; } - return (false); + return false; } // Build a lookup table that multiplies a packed RGB value by 2 with @@ -328,7 +267,6 @@ bool S9xInitGFX() // Build a lookup table that if the top bit of the color value is zero // then the value is zero, otherwise multiply the value by 2. Used by // the color subtraction code. - for (r = 0; r <= MAX_RED; r++) { uint32_t r2 = r; @@ -389,10 +327,10 @@ bool S9xInitGFX() } } } - return (true); + return true; } -void S9xDeinitGFX() +void S9xDeinitGFX(void) { // Free any memory allocated in S9xInitGFX if (GFX.X2) @@ -412,32 +350,19 @@ void S9xDeinitGFX() } } -void S9xBuildDirectColourMaps() +void S9xBuildDirectColourMaps(void) { uint32_t p, c; for (p = 0; p < 8; p++) - { for (c = 0; c < 256; c++) - { - // XXX: Brightness - DirectColourMaps [p][c] = BUILD_PIXEL(((c & 7) << 2) | ((p & 1) << 1), - ((c & 0x38) >> 1) | (p & 2), - ((c & 0xc0) >> 3) | (p & 4)); - } - } + DirectColourMaps [p][c] = BUILD_PIXEL(((c & 7) << 2) | ((p & 1) << 1), ((c & 0x38) >> 1) | (p & 2), ((c & 0xc0) >> 3) | (p & 4)); // XXX: Brightness IPPU.DirectColourMapsNeedRebuild = false; } -void S9xStartScreenRefresh() +void S9xStartScreenRefresh(void) { if (IPPU.RenderThisFrame) { - if (!S9xInitUpdate()) - { - IPPU.RenderThisFrame = false; - return; - } - IPPU.PreviousLine = IPPU.CurrentLine = 0; if (PPU.BGMode == 5 || PPU.BGMode == 6) @@ -510,8 +435,7 @@ void RenderLine(uint8_t C) } else { - if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 && - PPU.BG[2].HOffset == 0xe000) + if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 && PPU.BG[2].HOffset == 0xe000) { LineData[C].BG[2].VOffset = 0xe1; LineData[C].BG[2].HOffset = 0; @@ -536,7 +460,7 @@ void RenderLine(uint8_t C) } } -void S9xEndScreenRefresh() +void S9xEndScreenRefresh(void) { if (IPPU.RenderThisFrame) { @@ -621,11 +545,10 @@ static INLINE void SelectTileRenderer(bool normal) } } -void S9xSetupOBJ() +void S9xSetupOBJ(void) { int32_t Height; uint8_t S; - int32_t SmallWidth, SmallHeight; int32_t LargeWidth, LargeHeight; @@ -679,7 +602,6 @@ void S9xSetupOBJ() uint8_t FirstSprite; /* normal case */ uint8_t LineOBJ[SNES_HEIGHT_EXTENDED]; - memset(LineOBJ, 0, sizeof(LineOBJ)); for (i = 0; i < SNES_HEIGHT_EXTENDED; i++) { @@ -702,7 +624,8 @@ void S9xSetupOBJ() Height = SmallHeight; } HPos = PPU.OBJ[S].HPos; - if (HPos == -256) HPos = 256; + if (HPos == -256) + HPos = 256; if (HPos > -GFX.OBJWidths[S] && HPos <= 256) { uint8_t line, Y; @@ -714,19 +637,21 @@ void S9xSetupOBJ() GFX.OBJVisibleTiles[S] = GFX.OBJWidths[S] >> 3; for (line = 0, Y = (uint8_t)(PPU.OBJ[S].VPos & 0xff); line < Height; Y++, line++) { - if (Y >= SNES_HEIGHT_EXTENDED) continue; + if (Y >= SNES_HEIGHT_EXTENDED) + continue; if (LineOBJ[Y] >= 32) { GFX.OBJLines[Y].RTOFlags |= 0x40; continue; } GFX.OBJLines[Y].Tiles -= GFX.OBJVisibleTiles[S]; - if (GFX.OBJLines[Y].Tiles < 0) GFX.OBJLines[Y].RTOFlags |= 0x80; + if (GFX.OBJLines[Y].Tiles < 0) + GFX.OBJLines[Y].RTOFlags |= 0x80; GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Sprite = S; if (PPU.OBJ[S].VFlip) { // Yes, Width not Height. It so happens that the - // sprites with H=2*W flip as two WxW sprites. + // sprites with H = 2 * W flip as two W * W sprites. GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Line = line ^ (GFX.OBJWidths[S] - 1); } else @@ -735,14 +660,11 @@ void S9xSetupOBJ() } } S = (S + 1) & 0x7F; - } - while (S != FirstSprite); + } while (S != FirstSprite); for (Y = 0; Y < SNES_HEIGHT_EXTENDED; Y++) - { if (LineOBJ[Y] < 32) // Add the sentinel GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Sprite = -1; - } for (Y = 1; Y < SNES_HEIGHT_EXTENDED; Y++) GFX.OBJLines[Y].RTOFlags |= GFX.OBJLines[Y - 1].RTOFlags; } @@ -750,12 +672,10 @@ void S9xSetupOBJ() { int32_t j, Y; /* evil FirstSprite+Y case */ - /* First, find out which sprites are on which lines */ uint8_t OBJOnLine[SNES_HEIGHT_EXTENDED][128]; /* We only initialise this per line, as needed. [Neb] - * Bonus: We can quickly avoid looping if a line has no OBJs. - */ + * Bonus: We can quickly avoid looping if a line has no OBJs. */ bool AnyOBJOnLine[SNES_HEIGHT_EXTENDED]; memset(AnyOBJOnLine, false, sizeof(AnyOBJOnLine)); @@ -773,7 +693,8 @@ void S9xSetupOBJ() Height = SmallHeight; } HPos = PPU.OBJ[S].HPos; - if (HPos == -256) HPos = 256; + if (HPos == -256) + HPos = 256; if (HPos > -GFX.OBJWidths[S] && HPos <= 256) { uint8_t line, Y; @@ -785,7 +706,8 @@ void S9xSetupOBJ() GFX.OBJVisibleTiles[S] = GFX.OBJWidths[S] >> 3; for (line = 0, Y = (uint8_t)(PPU.OBJ[S].VPos & 0xff); line < Height; Y++, line++) { - if (Y >= SNES_HEIGHT_EXTENDED) continue; + if (Y >= SNES_HEIGHT_EXTENDED) + continue; if (!AnyOBJOnLine[Y]) { memset(OBJOnLine[Y], 0, 128); @@ -807,7 +729,6 @@ void S9xSetupOBJ() for (Y = 0; Y < SNES_HEIGHT_EXTENDED; Y++) { GFX.OBJLines[Y].RTOFlags = Y ? GFX.OBJLines[Y - 1].RTOFlags : 0; - GFX.OBJLines[Y].Tiles = 34; j = 0; if (AnyOBJOnLine[Y]) @@ -824,15 +745,16 @@ void S9xSetupOBJ() break; } GFX.OBJLines[Y].Tiles -= GFX.OBJVisibleTiles[S]; - if (GFX.OBJLines[Y].Tiles < 0) GFX.OBJLines[Y].RTOFlags |= 0x80; + if (GFX.OBJLines[Y].Tiles < 0) + GFX.OBJLines[Y].RTOFlags |= 0x80; GFX.OBJLines[Y].OBJ[j].Sprite = S; GFX.OBJLines[Y].OBJ[j++].Line = OBJOnLine[Y][S] & ~0x80; } S = (S + 1) & 0x7F; - } - while (S != FirstSprite); + } while (S != FirstSprite); } - if (j < 32) GFX.OBJLines[Y].OBJ[j].Sprite = -1; + if (j < 32) + GFX.OBJLines[Y].OBJ[j].Sprite = -1; } } @@ -841,14 +763,14 @@ void S9xSetupOBJ() static void DrawOBJS(bool OnMain, uint8_t D) { - int32_t clipcount; struct { uint16_t Pos; bool Value; } Windows[7]; - uint32_t Y, Offset; + int32_t clipcount; + uint32_t Y, Offset; BG.BitShift = 4; BG.TileShift = 5; BG.TileAddress = PPU.OBJNameBase; @@ -859,10 +781,9 @@ static void DrawOBJS(bool OnMain, uint8_t D) BG.Buffered = IPPU.TileCached [TILE_4BIT]; BG.NameSelect = PPU.OBJNameSelect; BG.DirectColourMode = false; - GFX.PixSize = 1; - clipcount = GFX.pCurrentClip->Count [4]; + if (!clipcount) { Windows[0].Pos = 0; @@ -888,7 +809,8 @@ static void DrawOBJS(bool OnMain, uint8_t D) else { // memmove required: Overlapping addresses [Neb] - if (j < i) memmove(&Windows[j + 1], &Windows[j], sizeof(Windows[0]) * (i - j)); + if (j < i) + memmove(&Windows[j + 1], &Windows[j], sizeof(Windows[0]) * (i - j)); Windows[j].Pos = GFX.pCurrentClip->Left[clip][4]; Windows[j].Value = true; i++; @@ -897,7 +819,8 @@ static void DrawOBJS(bool OnMain, uint8_t D) if (j >= i || Windows[j].Pos != GFX.pCurrentClip->Right[clip][4]) { // memmove required: Overlapping addresses [Neb] - if (j < i) memmove(&Windows[j + 1], &Windows[j], sizeof(Windows[0]) * (i - j)); + if (j < i) + memmove(&Windows[j + 1], &Windows[j], sizeof(Windows[0]) * (i - j)); Windows[j].Pos = GFX.pCurrentClip->Right[clip][4]; Windows[j].Value = false; i++; @@ -932,14 +855,12 @@ static void DrawOBJS(bool OnMain, uint8_t D) GFX.Z1 = D + 2; - for (Y = GFX.StartY, Offset = Y * GFX.PPL; Y <= GFX.EndY; - Y++, Offset += GFX.PPL) + for (Y = GFX.StartY, Offset = Y * GFX.PPL; Y <= GFX.EndY; Y++, Offset += GFX.PPL) { int32_t I = 0; int32_t tiles = GFX.OBJLines[Y].Tiles; int32_t S; - for (S = GFX.OBJLines[Y].OBJ[I].Sprite; S >= 0 - && I < 32; S = GFX.OBJLines[Y].OBJ[++I].Sprite) + for (S = GFX.OBJLines[Y].OBJ[I].Sprite; S >= 0 && I < 32; S = GFX.OBJLines[Y].OBJ[++I].Sprite) { int32_t TileInc = 1; int32_t TileLine; @@ -957,8 +878,7 @@ static void DrawOBJS(bool OnMain, uint8_t D) if (OnMain && SUB_OR_ADD(4)) SelectTileRenderer(!GFX.Pseudo && PPU.OBJ [S].Palette < 4); - BaseTile = (((GFX.OBJLines[Y].OBJ[I].Line << 1) + (PPU.OBJ[S].Name & 0xf0)) - & 0xf0) | (PPU.OBJ[S].Name & 0x100) | (PPU.OBJ[S].Palette << 10); + BaseTile = (((GFX.OBJLines[Y].OBJ[I].Line << 1) + (PPU.OBJ[S].Name & 0xf0)) & 0xf0) | (PPU.OBJ[S].Name & 0x100) | (PPU.OBJ[S].Palette << 10); TileX = PPU.OBJ[S].Name & 0x0f; TileLine = (GFX.OBJLines[Y].OBJ[I].Line & 7) * 8; @@ -972,37 +892,43 @@ static void DrawOBJS(bool OnMain, uint8_t D) GFX.Z2 = (PPU.OBJ[S].Priority + 1) * 4 + D; X = PPU.OBJ[S].HPos; - if (X == -256) X = 256; - for (t = tiles, O = Offset + X * GFX.PixSize; X <= 256 - && X < PPU.OBJ[S].HPos + GFX.OBJWidths[S]; - TileX = (TileX + TileInc) & 0x0f, X += 8, O += 8 * GFX.PixSize) + if (X == -256) + X = 256; + for (t = tiles, O = Offset + X * GFX.PixSize; X <= 256 && X < PPU.OBJ[S].HPos + GFX.OBJWidths[S]; TileX = (TileX + TileInc) & 0x0f, X += 8, O += 8 * GFX.PixSize) { - if (X < -7 || --t < 0 || X == 256) continue; + if (X < -7 || --t < 0 || X == 256) + continue; if (X >= NextPos) { for (; WinIdx < 7 && Windows[WinIdx].Pos <= X; WinIdx++); - if (WinIdx == 0) WinStat = false; - else WinStat = Windows[WinIdx - 1].Value; + if (WinIdx == 0) + WinStat = false; + else + WinStat = Windows[WinIdx - 1].Value; NextPos = (WinIdx < 7) ? Windows[WinIdx].Pos : 1000; } if (X + 8 < NextPos) { - if (WinStat)(*DrawTilePtr)(BaseTile | TileX, O, TileLine, 1); + if (WinStat) + (*DrawTilePtr)(BaseTile | TileX, O, TileLine, 1); } else { int32_t x = X; while (x < X + 8) { - if (WinStat)(*DrawClippedTilePtr)(BaseTile | TileX, O, x - X, NextPos - x, - TileLine, 1); + if (WinStat) + (*DrawClippedTilePtr)(BaseTile | TileX, O, x - X, NextPos - x, TileLine, 1); x = NextPos; for (; WinIdx < 7 && Windows[WinIdx].Pos <= x; WinIdx++); - if (WinIdx == 0) WinStat = false; - else WinStat = Windows[WinIdx - 1].Value; + if (WinIdx == 0) + WinStat = false; + else + WinStat = Windows[WinIdx - 1].Value; NextPos = (WinIdx < 7) ? Windows[WinIdx].Pos : 1000; - if (NextPos > X + 8) NextPos = X + 8; + if (NextPos > X + 8) + NextPos = X + 8; } } } @@ -1017,14 +943,12 @@ static void DrawBackgroundMosaic(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8 uint32_t OffsetShift; uint32_t Y; int32_t m5; - uint32_t Tile; uint16_t* SC0; uint16_t* SC1; uint16_t* SC2; uint16_t* SC3; uint8_t depths [2]; - depths[0] = Z1; depths[1] = Z2; @@ -1091,16 +1015,15 @@ static void DrawBackgroundMosaic(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8 uint32_t MosaicOffset = Y % PPU.Mosaic; for (Lines = 1; Lines < PPU.Mosaic - MosaicOffset; Lines++) - if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || - (HOffset != LineData [Y + Lines].BG[bg].HOffset)) + if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || (HOffset != LineData [Y + Lines].BG[bg].HOffset)) break; MosaicLine = VOffset + Y - MosaicOffset; if (Y + Lines > GFX.EndY) Lines = GFX.EndY + 1 - Y; - VirtAlign = (MosaicLine & 7) << 3; + VirtAlign = (MosaicLine & 7) << 3; ScreenLine = MosaicLine >> OffsetShift; Rem16 = MosaicLine & 15; @@ -1136,9 +1059,7 @@ static void DrawBackgroundMosaic(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8 PixWidth = (PPU.Mosaic << m5) - r; } s = Y * GFX.PPL + Left * GFX.PixSize; - for (x = Left; x < Right; x += PixWidth, - s += (IPPU.HalfWidthPixels ? PixWidth >> 1 : PixWidth) * GFX.PixSize, - HPos += PixWidth, PixWidth = (PPU.Mosaic << m5)) + for (x = Left; x < Right; x += PixWidth, s += (IPPU.HalfWidthPixels ? PixWidth >> 1 : PixWidth) * GFX.PixSize, HPos += PixWidth, PixWidth = (PPU.Mosaic << m5)) { uint32_t Quot = (HPos & OffsetMask) >> 3; @@ -1173,33 +1094,17 @@ static void DrawBackgroundMosaic(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8 { // Both horzontal & vertical flip if (Rem16 < 8) - { - (*DrawLargePixelPtr)(Tile + 17 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } + (*DrawLargePixelPtr)(Tile + 17 - (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); else - { - (*DrawLargePixelPtr)(Tile + 1 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } + (*DrawLargePixelPtr)(Tile + 1 - (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); } else { // Horizontal flip only if (Rem16 > 7) - { - (*DrawLargePixelPtr)(Tile + 17 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } + (*DrawLargePixelPtr)(Tile + 17 - (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); else - { - (*DrawLargePixelPtr)(Tile + 1 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } + (*DrawLargePixelPtr)(Tile + 1 - (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); } } else @@ -1209,39 +1114,22 @@ static void DrawBackgroundMosaic(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8 { // Vertical flip only if (Rem16 < 8) - { - (*DrawLargePixelPtr)(Tile + 16 + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } + (*DrawLargePixelPtr)(Tile + 16 + (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); else - { - (*DrawLargePixelPtr)(Tile + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } + (*DrawLargePixelPtr)(Tile + (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); } else { // Normal unflipped if (Rem16 > 7) - { - (*DrawLargePixelPtr)(Tile + 16 + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } + (*DrawLargePixelPtr)(Tile + 16 + (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); else - { - (*DrawLargePixelPtr)(Tile + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } + (*DrawLargePixelPtr)(Tile + (Quot & 1), s, HPos & 7, PixWidth, VirtAlign, Lines); } } } else - (*DrawLargePixelPtr)(Tile + (Quot & 1) * m5, s, HPos & 7, PixWidth, - VirtAlign, Lines); + (*DrawLargePixelPtr)(Tile + (Quot & 1) * m5, s, HPos & 7, PixWidth, VirtAlign, Lines); } } } @@ -1268,7 +1156,6 @@ static void DrawBackgroundOffset(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8 uint8_t depths [2] = {Z1, Z2}; BG.StartPalette = 0; - BPS0 = (uint16_t*) &Memory.VRAM[PPU.BG[2].SCBase << 1]; if (PPU.BG[2].SCSize & 1) @@ -1331,7 +1218,6 @@ static void DrawBackgroundOffset(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8 { uint32_t VOff = LineData [Y].BG[2].VOffset - 1; uint32_t HOff = LineData [Y].BG[2].HOffset; - int32_t VirtAlign; int32_t ScreenLine = VOff >> 3; int32_t t1; @@ -1521,33 +1407,17 @@ static void DrawBackgroundOffset(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8 (*DrawClippedTilePtr)(Tile, s, Offset, Count, VirtAlign, Lines); else { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawClippedTilePtr)(Tile + t1 + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } + if (!(Tile & (V_FLIP | H_FLIP))) // Normal, unflipped + (*DrawClippedTilePtr)(Tile + t1 + (Quot & 1), s, Offset, Count, VirtAlign, Lines); else if (Tile & H_FLIP) { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawClippedTilePtr)(Tile + t2 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawClippedTilePtr)(Tile + t1 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawClippedTilePtr)(Tile + t2 + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); + if (Tile & V_FLIP) // H & V flip + (*DrawClippedTilePtr)(Tile + t2 + 1 - (Quot & 1), s, Offset, Count, VirtAlign, Lines); + else // H flip only + (*DrawClippedTilePtr)(Tile + t1 + 1 - (Quot & 1), s, Offset, Count, VirtAlign, Lines); } + else // V flip only + (*DrawClippedTilePtr)(Tile + t2 + (Quot & 1), s, Offset, Count, VirtAlign, Lines); } Left += Count; @@ -1578,9 +1448,8 @@ static void DrawBackgroundMode5(uint32_t bg, uint8_t Z1, uint8_t Z2) GFX.Pitch = GFX.RealPitch; GFX.PPL = GFX.PPLx2 >> 1; } - GFX.PixSize = 1; - + GFX.PixSize = 1; depths[0] = Z1; depths[1] = Z2; BG.StartPalette = 0; @@ -1597,7 +1466,8 @@ static void DrawBackgroundMode5(uint32_t bg, uint8_t Z1, uint8_t Z2) if ((PPU.BG[bg].SCSize & 2)) SC2 = SC1 + 1024; - else SC2 = SC0; + else + SC2 = SC0; if (((uint8_t*)SC2 - Memory.VRAM) >= 0x10000) SC2 -= 0x08000; @@ -1624,25 +1494,21 @@ static void DrawBackgroundMode5(uint32_t bg, uint8_t Z1, uint8_t Z2) int32_t t2; uint16_t* b1; uint16_t* b2; - int32_t clipcount; int32_t clip; - int32_t y = IPPU.Interlace ? (Y >> 1) : Y; uint32_t VOffset = LineData [y].BG[bg].VOffset; uint32_t HOffset = LineData [y].BG[bg].HOffset; int32_t VirtAlign = (Y + VOffset) & 7; for (Lines = 1; Lines < 8 - VirtAlign; Lines++) - if ((VOffset != LineData [y + Lines].BG[bg].VOffset) || - (HOffset != LineData [y + Lines].BG[bg].HOffset)) + if ((VOffset != LineData [y + Lines].BG[bg].VOffset) || (HOffset != LineData [y + Lines].BG[bg].HOffset)) break; HOffset <<= 1; if (Y + Lines > endy) Lines = endy + 1 - Y; VirtAlign <<= 3; - ScreenLine = (VOffset + Y) >> VOffsetShift; if (((VOffset + Y) & 15) > 7) @@ -1695,7 +1561,6 @@ static void DrawBackgroundMode5(uint32_t bg, uint8_t Z1, uint8_t Z2) s = (IPPU.HalfWidthPixels ? Left >> 1 : Left) * GFX.PixSize + Y * GFX.PPL; HPos = (HOffset + Left * GFX.PixSize) & 0x3ff; - Quot = HPos >> 3; if (Quot > 63) @@ -1717,48 +1582,24 @@ static void DrawBackgroundMode5(uint32_t bg, uint8_t Z1, uint8_t Z2) if (BG.TileSize == 8) { - if (!(Tile & H_FLIP)) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr)(Tile + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - { - // H flip - (*DrawHiResClippedTilePtr)(Tile + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } + if (!(Tile & H_FLIP)) // Normal, unflipped + (*DrawHiResClippedTilePtr)(Tile + (Quot & 1), s, Offset, Count, VirtAlign, Lines); + else // H flip + (*DrawHiResClippedTilePtr)(Tile + 1 - (Quot & 1), s, Offset, Count, VirtAlign, Lines); } else { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr)(Tile + t1 + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } + if (!(Tile & (V_FLIP | H_FLIP))) // Normal, unflipped + (*DrawHiResClippedTilePtr)(Tile + t1 + (Quot & 1), s, Offset, Count, VirtAlign, Lines); else if (Tile & H_FLIP) { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawHiResClippedTilePtr)(Tile + t2 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawHiResClippedTilePtr)(Tile + t1 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawHiResClippedTilePtr)(Tile + t2 + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); + if (Tile & V_FLIP) // H & V flip + (*DrawHiResClippedTilePtr)(Tile + t2 + 1 - (Quot & 1), s, Offset, Count, VirtAlign, Lines); + else // H flip only + (*DrawHiResClippedTilePtr)(Tile + t1 + 1 - (Quot & 1), s, Offset, Count, VirtAlign, Lines); } + else // V flip only + (*DrawHiResClippedTilePtr)(Tile + t2 + (Quot & 1), s, Offset, Count, VirtAlign, Lines); } t += Quot & 1; @@ -1781,48 +1622,24 @@ static void DrawBackgroundMode5(uint32_t bg, uint8_t Z1, uint8_t Z2) GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; if (BG.TileSize == 8) { - if (!(Tile & H_FLIP)) - { - // Normal, unflipped - (*DrawHiResTilePtr)(Tile + (Quot & 1), - s, VirtAlign, Lines); - } - else - { - // H flip - (*DrawHiResTilePtr)(Tile + 1 - (Quot & 1), - s, VirtAlign, Lines); - } + if (!(Tile & H_FLIP)) // Normal, unflipped + (*DrawHiResTilePtr)(Tile + (Quot & 1), s, VirtAlign, Lines); + else // H flip + (*DrawHiResTilePtr)(Tile + 1 - (Quot & 1), s, VirtAlign, Lines); } else { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawHiResTilePtr)(Tile + t1 + (Quot & 1), - s, VirtAlign, Lines); - } + if (!(Tile & (V_FLIP | H_FLIP))) // Normal, unflipped + (*DrawHiResTilePtr)(Tile + t1 + (Quot & 1), s, VirtAlign, Lines); else if (Tile & H_FLIP) { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawHiResTilePtr)(Tile + t2 + 1 - (Quot & 1), - s, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawHiResTilePtr)(Tile + t1 + 1 - (Quot & 1), - s, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawHiResTilePtr)(Tile + t2 + (Quot & 1), - s, VirtAlign, Lines); + if (Tile & V_FLIP) // H & V flip + (*DrawHiResTilePtr)(Tile + t2 + 1 - (Quot & 1), s, VirtAlign, Lines); + else // H flip only + (*DrawHiResTilePtr)(Tile + t1 + 1 - (Quot & 1), s, VirtAlign, Lines); } + else // V flip only + (*DrawHiResTilePtr)(Tile + t2 + (Quot & 1), s, VirtAlign, Lines); } t += Quot & 1; @@ -1839,48 +1656,24 @@ static void DrawBackgroundMode5(uint32_t bg, uint8_t Z1, uint8_t Z2) GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; if (BG.TileSize == 8) { - if (!(Tile & H_FLIP)) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr)(Tile + (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - else - { - // H flip - (*DrawHiResClippedTilePtr)(Tile + 1 - (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } + if (!(Tile & H_FLIP)) // Normal, unflipped + (*DrawHiResClippedTilePtr)(Tile + (Quot & 1), s, 0, Count, VirtAlign, Lines); + else // H flip + (*DrawHiResClippedTilePtr)(Tile + 1 - (Quot & 1), s, 0, Count, VirtAlign, Lines); } else { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr)(Tile + t1 + (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } + if (!(Tile & (V_FLIP | H_FLIP))) // Normal, unflipped + (*DrawHiResClippedTilePtr)(Tile + t1 + (Quot & 1), s, 0, Count, VirtAlign, Lines); else if (Tile & H_FLIP) { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawHiResClippedTilePtr)(Tile + t2 + 1 - (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawHiResClippedTilePtr)(Tile + t1 + 1 - (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawHiResClippedTilePtr)(Tile + t2 + (Quot & 1), - s, 0, Count, VirtAlign, Lines); + if (Tile & V_FLIP) // H & V flip + (*DrawHiResClippedTilePtr)(Tile + t2 + 1 - (Quot & 1), s, 0, Count, VirtAlign, Lines); + else // H flip only + (*DrawHiResClippedTilePtr)(Tile + t1 + 1 - (Quot & 1), s, 0, Count, VirtAlign, Lines); } + else // V flip only + (*DrawHiResClippedTilePtr)(Tile + t2 + (Quot & 1), s, 0, Count, VirtAlign, Lines); } } } @@ -1902,8 +1695,6 @@ static void DrawBackground(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8_t Z2) int32_t Lines; int32_t OffsetMask; int32_t OffsetShift; - - GFX.PixSize = 1; BG.TileSize = BGSizes [PPU.BG[bg].BGSize]; @@ -1915,8 +1706,7 @@ static void DrawBackground(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8_t Z2) BG.Buffered = IPPU.TileCached [Depths [BGMode][bg]]; BG.PaletteShift = PaletteShifts[BGMode][bg]; BG.PaletteMask = PaletteMasks[BGMode][bg]; - BG.DirectColourMode = (BGMode == 3 || BGMode == 4) && bg == 0 && - (GFX.r2130 & 1); + BG.DirectColourMode = (BGMode == 3 || BGMode == 4) && bg == 0 && (GFX.r2130 & 1); if (PPU.BGMosaic [bg] && PPU.Mosaic > 1) { @@ -1941,7 +1731,8 @@ static void DrawBackground(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8_t Z2) if (BGMode == 0) BG.StartPalette = bg << 5; - else BG.StartPalette = 0; + else + BG.StartPalette = 0; SC0 = (uint16_t*) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; @@ -1994,15 +1785,13 @@ static void DrawBackground(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8_t Z2) int32_t VirtAlign = (Y + VOffset) & 7; for (Lines = 1; Lines < 8 - VirtAlign; Lines++) - if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || - (HOffset != LineData [Y + Lines].BG[bg].HOffset)) + if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || (HOffset != LineData [Y + Lines].BG[bg].HOffset)) break; if (Y + Lines > GFX.EndY) Lines = GFX.EndY + 1 - Y; VirtAlign <<= 3; - ScreenLine = (VOffset + Y) >> OffsetShift; if (((VOffset + Y) & 15) > 7) @@ -2051,10 +1840,8 @@ static void DrawBackground(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8_t Z2) continue; } - s = Left * GFX.PixSize + Y * GFX.PPL; HPos = (HOffset + Left) & OffsetMask; - Quot = HPos >> 3; if (BG.TileSize == 8) @@ -2085,40 +1872,18 @@ static void DrawBackground(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8_t Z2) GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; if (BG.TileSize == 8) + (*DrawClippedTilePtr)(Tile, s, Offset, Count, VirtAlign, Lines); + else if (!(Tile & (V_FLIP | H_FLIP))) // Normal, unflipped + (*DrawClippedTilePtr)(Tile + t1 + (Quot & 1), s, Offset, Count, VirtAlign, Lines); + else if (Tile & H_FLIP) { - (*DrawClippedTilePtr)(Tile, s, Offset, Count, VirtAlign, - Lines); - } - else - { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawClippedTilePtr)(Tile + t1 + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else if (Tile & H_FLIP) - { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawClippedTilePtr)(Tile + t2 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawClippedTilePtr)(Tile + t1 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawClippedTilePtr)(Tile + t2 + (Quot & 1), s, - Offset, Count, VirtAlign, Lines); - } + if (Tile & V_FLIP) // H & V flip + (*DrawClippedTilePtr)(Tile + t2 + 1 - (Quot & 1), s, Offset, Count, VirtAlign, Lines); + else // H flip only + (*DrawClippedTilePtr)(Tile + t1 + 1 - (Quot & 1), s, Offset, Count, VirtAlign, Lines); } + else // V flip only + (*DrawClippedTilePtr)(Tile + t2 + (Quot & 1), s, Offset, Count, VirtAlign, Lines); if (BG.TileSize == 8) { @@ -2144,46 +1909,25 @@ static void DrawBackground(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8_t Z2) Count = Width - Count; Middle = Count >> 3; Count &= 7; - for (C = Middle; C > 0; - s += (IPPU.HalfWidthPixels ? 4 : 8) * GFX.PixSize, Quot++, C--) + + for (C = Middle; C > 0; s += (IPPU.HalfWidthPixels ? 4 : 8) * GFX.PixSize, Quot++, C--) { Tile = READ_2BYTES(t); GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; if (BG.TileSize != 8) { - if (Tile & H_FLIP) + if (Tile & H_FLIP) // Horizontal flip, but what about vertical flip? { - // Horizontal flip, but what about vertical flip ? - if (Tile & V_FLIP) - { - // Both horzontal & vertical flip - (*DrawTilePtr)(Tile + t2 + 1 - (Quot & 1), s, - VirtAlign, Lines); - } - else - { - // Horizontal flip only - (*DrawTilePtr)(Tile + t1 + 1 - (Quot & 1), s, - VirtAlign, Lines); - } - } - else - { - // No horizontal flip, but is there a vertical flip ? - if (Tile & V_FLIP) - { - // Vertical flip only - (*DrawTilePtr)(Tile + t2 + (Quot & 1), s, - VirtAlign, Lines); - } - else - { - // Normal unflipped - (*DrawTilePtr)(Tile + t1 + (Quot & 1), s, - VirtAlign, Lines); - } + if (Tile & V_FLIP) // Both horzontal & vertical flip + (*DrawTilePtr)(Tile + t2 + 1 - (Quot & 1), s, VirtAlign, Lines); + else // Horizontal flip only + (*DrawTilePtr)(Tile + t1 + 1 - (Quot & 1), s, VirtAlign, Lines); } + else if (Tile & V_FLIP) // Vertical flip only + (*DrawTilePtr)(Tile + t2 + (Quot & 1), s, VirtAlign, Lines); + else // Normal unflipped + (*DrawTilePtr)(Tile + t1 + (Quot & 1), s, VirtAlign, Lines); } else (*DrawTilePtr)(Tile, s, VirtAlign, Lines); @@ -2212,40 +1956,20 @@ static void DrawBackground(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8_t Z2) GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; if (BG.TileSize == 8) - (*DrawClippedTilePtr)(Tile, s, 0, Count, VirtAlign, - Lines); + (*DrawClippedTilePtr)(Tile, s, 0, Count, VirtAlign, Lines); else { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawClippedTilePtr)(Tile + t1 + (Quot & 1), s, 0, - Count, VirtAlign, Lines); - } + if (!(Tile & (V_FLIP | H_FLIP))) // Normal, unflipped + (*DrawClippedTilePtr)(Tile + t1 + (Quot & 1), s, 0, Count, VirtAlign, Lines); else if (Tile & H_FLIP) { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawClippedTilePtr)(Tile + t2 + 1 - (Quot & 1), - s, 0, Count, VirtAlign, - Lines); - } - else - { - // H flip only - (*DrawClippedTilePtr)(Tile + t1 + 1 - (Quot & 1), - s, 0, Count, VirtAlign, - Lines); - } - } - else - { - // V flip only - (*DrawClippedTilePtr)(Tile + t2 + (Quot & 1), - s, 0, Count, VirtAlign, - Lines); + if (Tile & V_FLIP) // H & V flip + (*DrawClippedTilePtr)(Tile + t2 + 1 - (Quot & 1), s, 0, Count, VirtAlign, Lines); + else // H flip only + (*DrawClippedTilePtr)(Tile + t1 + 1 - (Quot & 1), s, 0, Count, VirtAlign, Lines); } + else // V flip only + (*DrawClippedTilePtr)(Tile + t2 + (Quot & 1), s, 0, Count, VirtAlign, Lines); } } } @@ -2253,26 +1977,26 @@ static void DrawBackground(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8_t Z2) } #define RENDER_BACKGROUND_MODE7(TYPE,FUNC) \ - uint32_t clip; \ + uint32_t clip; \ int32_t aa, cc; \ int32_t dir; \ int32_t startx, endx; \ uint32_t Left = 0; \ uint32_t Right = 256; \ uint32_t ClipCount; \ - uint16_t *ScreenColors = IPPU.ScreenColors; \ - uint8_t *VRAM1; \ + uint16_t* ScreenColors = IPPU.ScreenColors; \ + uint8_t* VRAM1; \ uint32_t Line; \ - uint8_t *Depth; \ - SLineMatrixData *l; \ + uint8_t* Depth; \ + SLineMatrixData* l; \ (void)ScreenColors; \ \ VRAM1 = Memory.VRAM + 1; \ if (GFX.r2130 & 1) \ { \ - if (IPPU.DirectColourMapsNeedRebuild) \ + if (IPPU.DirectColourMapsNeedRebuild) \ S9xBuildDirectColourMaps (); \ - ScreenColors = DirectColourMaps [0]; \ + ScreenColors = DirectColourMaps [0]; \ } \ \ ClipCount = GFX.pCurrentClip->Count [bg]; \ @@ -2286,30 +2010,30 @@ static void DrawBackground(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8_t Z2) \ for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX.Pitch, Depth += GFX.PPL, l++) \ { \ - int32_t yy; \ - int32_t BB,DD; \ + int32_t yy; \ + int32_t BB,DD; \ \ - int32_t HOffset = ((int32_t) LineData [Line].BG[0].HOffset << M7) >> M7; \ - int32_t VOffset = ((int32_t) LineData [Line].BG[0].VOffset << M7) >> M7; \ + int32_t HOffset = ((int32_t) LineData [Line].BG[0].HOffset << M7) >> M7; \ + int32_t VOffset = ((int32_t) LineData [Line].BG[0].VOffset << M7) >> M7; \ \ - int32_t CentreX = ((int32_t) l->CentreX << M7) >> M7; \ - int32_t CentreY = ((int32_t) l->CentreY << M7) >> M7; \ + int32_t CentreX = ((int32_t) l->CentreX << M7) >> M7; \ + int32_t CentreY = ((int32_t) l->CentreY << M7) >> M7; \ \ - if (PPU.Mode7VFlip) \ + if (PPU.Mode7VFlip) \ yy = 255 - (int32_t) Line; \ - else \ + else \ yy = Line; \ \ yy += CLIP_10_BIT_SIGNED(VOffset - CentreY); \ \ - BB = l->MatrixB * yy + (CentreX << 8); \ - DD = l->MatrixD * yy + (CentreY << 8); \ + BB = l->MatrixB * yy + (CentreX << 8); \ + DD = l->MatrixD * yy + (CentreY << 8); \ \ - for (clip = 0; clip < ClipCount; clip++) \ - { \ - TYPE *p; \ - uint8_t *d; \ - int32_t xx, AA, CC; \ + for (clip = 0; clip < ClipCount; clip++) \ + { \ + TYPE *p; \ + uint8_t *d; \ + int32_t xx, AA, CC; \ if (GFX.pCurrentClip->Count [bg]) \ { \ Left = GFX.pCurrentClip->Left [clip][bg]; \ @@ -2400,7 +2124,7 @@ static void DrawBackground(uint32_t BGMode, uint32_t bg, uint8_t Z1, uint8_t Z2) static void DrawBGMode7Background(uint8_t* Screen, int32_t bg) { - RENDER_BACKGROUND_MODE7(uint8_t, (uint8_t)(b & GFX.Mode7Mask)) + RENDER_BACKGROUND_MODE7(uint8_t, (uint8_t) (b & GFX.Mode7Mask)) } static void DrawBGMode7Background16(uint8_t* Screen, int32_t bg) @@ -2408,48 +2132,24 @@ static void DrawBGMode7Background16(uint8_t* Screen, int32_t bg) RENDER_BACKGROUND_MODE7(uint16_t, ScreenColors [b & GFX.Mode7Mask]); } -static void DrawBGMode7Background16Add(uint8_t* Screen, int32_t bg) +static void DrawBGMode7Background16Add(uint8_t * Screen, int32_t bg) { - RENDER_BACKGROUND_MODE7(uint16_t, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_ADD(ScreenColors [b & GFX.Mode7Mask], - p [GFX.Delta]) : - COLOR_ADD(ScreenColors [b & GFX.Mode7Mask], - GFX.FixedColour)) : - ScreenColors [b & GFX.Mode7Mask]); + RENDER_BACKGROUND_MODE7(uint16_t, *(d + GFX.DepthDelta) ? (*(d + GFX.DepthDelta) != 1 ? COLOR_ADD(ScreenColors[b & GFX.Mode7Mask], p[GFX.Delta]) : COLOR_ADD(ScreenColors[b & GFX.Mode7Mask], GFX.FixedColour)) : ScreenColors[b & GFX.Mode7Mask]); } -static void DrawBGMode7Background16Add1_2(uint8_t* Screen, int32_t bg) +static void DrawBGMode7Background16Add1_2(uint8_t * Screen, int32_t bg) { - RENDER_BACKGROUND_MODE7(uint16_t, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_ADD1_2(ScreenColors [b & GFX.Mode7Mask], - p [GFX.Delta]) : - COLOR_ADD(ScreenColors [b & GFX.Mode7Mask], - GFX.FixedColour)) : - ScreenColors [b & GFX.Mode7Mask]); + RENDER_BACKGROUND_MODE7(uint16_t, *(d + GFX.DepthDelta) ? (*(d + GFX.DepthDelta) != 1 ? COLOR_ADD1_2(ScreenColors[b & GFX.Mode7Mask], p[GFX.Delta]) : COLOR_ADD(ScreenColors[b & GFX.Mode7Mask], GFX.FixedColour)) : ScreenColors[b & GFX.Mode7Mask]); } -static void DrawBGMode7Background16Sub(uint8_t* Screen, int32_t bg) +static void DrawBGMode7Background16Sub(uint8_t * Screen, int32_t bg) { - RENDER_BACKGROUND_MODE7(uint16_t, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_SUB(ScreenColors [b & GFX.Mode7Mask], - p [GFX.Delta]) : - COLOR_SUB(ScreenColors [b & GFX.Mode7Mask], - GFX.FixedColour)) : - ScreenColors [b & GFX.Mode7Mask]); + RENDER_BACKGROUND_MODE7(uint16_t, *(d + GFX.DepthDelta) ? (*(d + GFX.DepthDelta) != 1 ? COLOR_SUB(ScreenColors[b & GFX.Mode7Mask], p[GFX.Delta]) : COLOR_SUB(ScreenColors[b & GFX.Mode7Mask], GFX.FixedColour)) : ScreenColors[b & GFX.Mode7Mask]); } -static void DrawBGMode7Background16Sub1_2(uint8_t* Screen, int32_t bg) +static void DrawBGMode7Background16Sub1_2(uint8_t * Screen, int32_t bg) { - RENDER_BACKGROUND_MODE7(uint16_t, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_SUB1_2(ScreenColors [b & GFX.Mode7Mask], - p [GFX.Delta]) : - COLOR_SUB(ScreenColors [b & GFX.Mode7Mask], - GFX.FixedColour)) : - ScreenColors [b & GFX.Mode7Mask]); + RENDER_BACKGROUND_MODE7(uint16_t, *(d + GFX.DepthDelta) ? (*(d + GFX.DepthDelta) != 1 ? COLOR_SUB1_2(ScreenColors[b & GFX.Mode7Mask], p[GFX.Delta]) : COLOR_SUB(ScreenColors[b & GFX.Mode7Mask], GFX.FixedColour)) : ScreenColors[b & GFX.Mode7Mask]); } #define RENDER_BACKGROUND_MODE7_i(TYPE,FUNC,COLORFUNC) \ @@ -2842,14 +2542,8 @@ static void DrawBGMode7Background16Sub1_2(uint8_t* Screen, int32_t bg) static uint32_t Q_INTERPOLATE(uint32_t A, uint32_t B, uint32_t C, uint32_t D) { - uint32_t x = ((A >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) + - ((B >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) + - ((C >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) + - ((D >> 2) & HIGH_BITS_SHIFTED_TWO_MASK); - uint32_t y = (A & TWO_LOW_BITS_MASK) + - (B & TWO_LOW_BITS_MASK) + - (C & TWO_LOW_BITS_MASK) + - (D & TWO_LOW_BITS_MASK); + uint32_t x = ((A >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) + ((B >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) + ((C >> 2) & HIGH_BITS_SHIFTED_TWO_MASK) + ((D >> 2) & HIGH_BITS_SHIFTED_TWO_MASK); + uint32_t y = (A & TWO_LOW_BITS_MASK) + (B & TWO_LOW_BITS_MASK) + (C & TWO_LOW_BITS_MASK) + (D & TWO_LOW_BITS_MASK); y = (y >> 2) & TWO_LOW_BITS_MASK; return x + y; } @@ -2861,46 +2555,22 @@ static void DrawBGMode7Background16_i(uint8_t* Screen, int32_t bg) static void DrawBGMode7Background16Add_i(uint8_t* Screen, int32_t bg) { - RENDER_BACKGROUND_MODE7_i(uint16_t, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - (COLOR_ADD(theColor, - p [GFX.Delta])) : - (COLOR_ADD(theColor, - GFX.FixedColour))) : - theColor, (ScreenColors[b & GFX.Mode7Mask])); + RENDER_BACKGROUND_MODE7_i(uint16_t, *(d + GFX.DepthDelta) ? (*(d + GFX.DepthDelta) != 1 ? (COLOR_ADD(theColor, p[GFX.Delta])) : (COLOR_ADD(theColor, GFX.FixedColour))) : theColor, (ScreenColors[b & GFX.Mode7Mask])); } static void DrawBGMode7Background16Add1_2_i(uint8_t* Screen, int32_t bg) { - RENDER_BACKGROUND_MODE7_i(uint16_t, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_ADD1_2(theColor, - p [GFX.Delta]) : - COLOR_ADD(theColor, - GFX.FixedColour)) : - theColor, (ScreenColors[b & GFX.Mode7Mask])); + RENDER_BACKGROUND_MODE7_i(uint16_t, *(d + GFX.DepthDelta) ? (*(d + GFX.DepthDelta) != 1 ? COLOR_ADD1_2(theColor, p[GFX.Delta]) : COLOR_ADD(theColor, GFX.FixedColour)) : theColor, (ScreenColors[b & GFX.Mode7Mask])); } static void DrawBGMode7Background16Sub_i(uint8_t* Screen, int32_t bg) { - RENDER_BACKGROUND_MODE7_i(uint16_t, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_SUB(theColor, - p [GFX.Delta]) : - COLOR_SUB(theColor, - GFX.FixedColour)) : - theColor, (ScreenColors[b & GFX.Mode7Mask])); + RENDER_BACKGROUND_MODE7_i(uint16_t, *(d + GFX.DepthDelta) ? (*(d + GFX.DepthDelta) != 1 ? COLOR_SUB(theColor, p[GFX.Delta]) : COLOR_SUB(theColor, GFX.FixedColour)) : theColor, (ScreenColors[b & GFX.Mode7Mask])); } static void DrawBGMode7Background16Sub1_2_i(uint8_t* Screen, int32_t bg) { - RENDER_BACKGROUND_MODE7_i(uint16_t, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_SUB1_2(theColor, - p [GFX.Delta]) : - COLOR_SUB(theColor, - GFX.FixedColour)) : - theColor, (ScreenColors[b & GFX.Mode7Mask])); + RENDER_BACKGROUND_MODE7_i(uint16_t, *(d + GFX.DepthDelta) ? (*(d + GFX.DepthDelta) != 1 ? COLOR_SUB1_2(theColor, p[GFX.Delta]) : COLOR_SUB(theColor, GFX.FixedColour)) : theColor, (ScreenColors[b & GFX.Mode7Mask])); } static void RenderScreen(uint8_t* Screen, bool sub, bool force_no_add, uint8_t D) @@ -2956,8 +2626,7 @@ static void RenderScreen(uint8_t* Screen, bool sub, bool force_no_add, uint8_t D if (BG2) { SelectTileRenderer(sub || !SUB_OR_ADD(2)); - DrawBackground(PPU.BGMode, 2, D + 3, - PPU.BG3Priority ? D + 17 : D + 6); + DrawBackground(PPU.BGMode, 2, D + 3, PPU.BG3Priority ? D + 17 : D + 6); } if (BG3 && PPU.BGMode == 0) { @@ -3013,69 +2682,40 @@ static void RenderScreen(uint8_t* Screen, bool sub, bool force_no_add, uint8_t D bg = 0; } if (sub || !SUB_OR_ADD(0)) - { - if (!Settings.Mode7Interpolate) - DrawBGMode7Background16(Screen, bg); - else - DrawBGMode7Background16_i(Screen, bg); - } + DrawBGMode7Background16(Screen, bg); else { if (GFX.r2131 & 0x80) { if (GFX.r2131 & 0x40) - { - if (!Settings.Mode7Interpolate) - DrawBGMode7Background16Sub1_2(Screen, bg); - else - DrawBGMode7Background16Sub1_2_i(Screen, bg); - } + DrawBGMode7Background16Sub1_2(Screen, bg); else - { - if (!Settings.Mode7Interpolate) - DrawBGMode7Background16Sub(Screen, bg); - else - DrawBGMode7Background16Sub_i(Screen, bg); - } + DrawBGMode7Background16Sub(Screen, bg); } else { if (GFX.r2131 & 0x40) - { - if (!Settings.Mode7Interpolate) - DrawBGMode7Background16Add1_2(Screen, bg); - else - DrawBGMode7Background16Add1_2_i(Screen, bg); - } + DrawBGMode7Background16Add1_2(Screen, bg); else - { - if (!Settings.Mode7Interpolate) - DrawBGMode7Background16Add(Screen, bg); - else - DrawBGMode7Background16Add_i(Screen, bg); + DrawBGMode7Background16Add(Screen, bg); } } } - } - break; - default: - break; + break; + default: + break; } } -void S9xUpdateScreen() +void S9xUpdateScreen(void) { int32_t x2 = 1; - GFX.S = GFX.Screen; GFX.r2131 = Memory.FillRAM [0x2131]; GFX.r212c = Memory.FillRAM [0x212c]; GFX.r212d = Memory.FillRAM [0x212d]; GFX.r2130 = Memory.FillRAM [0x2130]; - - GFX.Pseudo = (Memory.FillRAM [0x2133] & 8) != 0 && - (GFX.r212c & 15) != (GFX.r212d & 15) && - (GFX.r2131 & 0x3f) == 0; + GFX.Pseudo = (Memory.FillRAM [0x2133] & 8) != 0 && (GFX.r212c & 15) != (GFX.r212d & 15) && (GFX.r2131 & 0x3f) == 0; if (IPPU.OBJChanged) S9xSetupOBJ(); @@ -3146,238 +2786,170 @@ void S9xUpdateScreen() { // memmove converted: Same malloc, different addresses, and identical addresses at line 0 [Neb] // DS2 DMA notes: This code path is unused [Neb] - memcpy(GFX.Screen + y * 2 * GFX.Pitch2, - GFX.Screen + y * GFX.Pitch2, - GFX.Pitch2); + memcpy(GFX.Screen + y * 2 * GFX.Pitch2, GFX.Screen + y * GFX.Pitch2, GFX.Pitch2); // memmove converted: Same malloc, different addresses [Neb] - memcpy(GFX.Screen + (y * 2 + 1) * GFX.Pitch2, - GFX.Screen + y * GFX.Pitch2, - GFX.Pitch2); + memcpy(GFX.Screen + (y * 2 + 1) * GFX.Pitch2, GFX.Screen + y * GFX.Pitch2, GFX.Pitch2); } } } uint32_t black = BLACK | (BLACK << 16); - if (Settings.Transparency) + if (GFX.Pseudo) { - if (GFX.Pseudo) - { - GFX.r2131 = 0x5f; - GFX.r212c &= (Memory.FillRAM [0x212d] | 0xf0); - GFX.r212d |= (Memory.FillRAM [0x212c] & 0x0f); - GFX.r2130 |= 2; - } + GFX.r2131 = 0x5f; + GFX.r212c &= (Memory.FillRAM [0x212d] | 0xf0); + GFX.r212d |= (Memory.FillRAM [0x212c] & 0x0f); + GFX.r2130 |= 2; + } - if (!PPU.ForcedBlanking && ADD_OR_SUB_ON_ANYTHING && - (GFX.r2130 & 0x30) != 0x30 && - !((GFX.r2130 & 0x30) == 0x10 && IPPU.Clip[1].Count[5] == 0)) - { - ClipData* pClip; + if (!PPU.ForcedBlanking && ADD_OR_SUB_ON_ANYTHING && (GFX.r2130 & 0x30) != 0x30 && !((GFX.r2130 & 0x30) == 0x10 && IPPU.Clip[1].Count[5] == 0)) + { + ClipData* pClip; - GFX.FixedColour = BUILD_PIXEL(IPPU.XB [PPU.FixedColourRed], - IPPU.XB [PPU.FixedColourGreen], - IPPU.XB [PPU.FixedColourBlue]); + GFX.FixedColour = BUILD_PIXEL(IPPU.XB [PPU.FixedColourRed], IPPU.XB [PPU.FixedColourGreen], IPPU.XB [PPU.FixedColourBlue]); - // Clear the z-buffer, marking areas 'covered' by the fixed - // colour as depth 1. - pClip = &IPPU.Clip [1]; + // Clear the z-buffer, marking areas 'covered' by the fixed + // colour as depth 1. + pClip = &IPPU.Clip [1]; - // Clear the z-buffer - if (pClip->Count [5]) + // Clear the z-buffer + if (pClip->Count [5]) + { + // Colour window enabled. + uint32_t y; + for (y = starty; y <= endy; y++) { - // Colour window enabled. - uint32_t y; - for (y = starty; y <= endy; y++) + memset(GFX.SubZBuffer + y * GFX.ZPitch, 0, IPPU.RenderedScreenWidth); + memset(GFX.ZBuffer + y * GFX.ZPitch, 0, IPPU.RenderedScreenWidth); + + if (IPPU.Clip [0].Count [5]) { - memset(GFX.SubZBuffer + y * GFX.ZPitch, 0, IPPU.RenderedScreenWidth); - memset(GFX.ZBuffer + y * GFX.ZPitch, 0, IPPU.RenderedScreenWidth); + uint32_t* p = (uint32_t*)(GFX.SubScreen + y * GFX.Pitch2); + uint32_t* q = (uint32_t*)((uint16_t*) p + IPPU.RenderedScreenWidth); + while (p < q) + *p++ = black; + } - if (IPPU.Clip [0].Count [5]) + uint32_t c; + for (c = 0; c < pClip->Count [5]; c++) + { + if (pClip->Right [c][5] > pClip->Left [c][5]) { - uint32_t* p = (uint32_t*)(GFX.SubScreen + y * GFX.Pitch2); - uint32_t* q = (uint32_t*)((uint16_t*) p + IPPU.RenderedScreenWidth); - while (p < q) - *p++ = black; - } + memset(GFX.SubZBuffer + y * GFX.ZPitch + pClip->Left [c][5] * x2, 1, (pClip->Right [c][5] - pClip->Left [c][5]) * x2); - uint32_t c; - for (c = 0; c < pClip->Count [5]; c++) - { - if (pClip->Right [c][5] > pClip->Left [c][5]) + if (IPPU.Clip [0].Count [5]) { - memset(GFX.SubZBuffer + y * GFX.ZPitch + pClip->Left [c][5] * x2, - 1, (pClip->Right [c][5] - pClip->Left [c][5]) * x2); - - if (IPPU.Clip [0].Count [5]) - { - // Blast, have to clear the sub-screen to the fixed-colour - // because there is a colour window in effect clipping - // the main screen that will allow the sub-screen - // 'underneath' to show through. + // Blast, have to clear the sub-screen to the fixed-colour + // because there is a colour window in effect clipping + // the main screen that will allow the sub-screen + // 'underneath' to show through. - uint16_t* p = (uint16_t*)(GFX.SubScreen + y * GFX.Pitch2); - uint16_t* q = p + pClip->Right [c][5] * x2; - p += pClip->Left [c][5] * x2; + uint16_t* p = (uint16_t*)(GFX.SubScreen + y * GFX.Pitch2); + uint16_t* q = p + pClip->Right [c][5] * x2; + p += pClip->Left [c][5] * x2; - while (p < q) - *p++ = (uint16_t) GFX.FixedColour; - } + while (p < q) + *p++ = (uint16_t) GFX.FixedColour; } } } } - else + } + else + { + uint32_t y; + for (y = starty; y <= endy; y++) { - uint32_t y; - for (y = starty; y <= endy; y++) - { - memset(GFX.ZBuffer + y * GFX.ZPitch, 0, IPPU.RenderedScreenWidth); - memset(GFX.SubZBuffer + y * GFX.ZPitch, 1, IPPU.RenderedScreenWidth); + memset(GFX.ZBuffer + y * GFX.ZPitch, 0, IPPU.RenderedScreenWidth); + memset(GFX.SubZBuffer + y * GFX.ZPitch, 1, IPPU.RenderedScreenWidth); - if (IPPU.Clip [0].Count [5]) - { - // Blast, have to clear the sub-screen to the fixed-colour - // because there is a colour window in effect clipping - // the main screen that will allow the sub-screen - // 'underneath' to show through. - uint32_t b = GFX.FixedColour | (GFX.FixedColour << 16); - uint32_t* p = (uint32_t*)(GFX.SubScreen + y * GFX.Pitch2); - uint32_t* q = (uint32_t*)((uint16_t*) p + IPPU.RenderedScreenWidth); + if (IPPU.Clip [0].Count [5]) + { + // Blast, have to clear the sub-screen to the fixed-colour + // because there is a colour window in effect clipping + // the main screen that will allow the sub-screen + // 'underneath' to show through. + uint32_t b = GFX.FixedColour | (GFX.FixedColour << 16); + uint32_t* p = (uint32_t*)(GFX.SubScreen + y * GFX.Pitch2); + uint32_t* q = (uint32_t*)((uint16_t*) p + IPPU.RenderedScreenWidth); - while (p < q) - *p++ = b; - } + while (p < q) + *p++ = b; } } + } - if (ANYTHING_ON_SUB) - { - GFX.DB = GFX.SubZBuffer; - RenderScreen(GFX.SubScreen, true, true, SUB_SCREEN_DEPTH); - } + if (ANYTHING_ON_SUB) + { + GFX.DB = GFX.SubZBuffer; + RenderScreen(GFX.SubScreen, true, true, SUB_SCREEN_DEPTH); + } - if (IPPU.Clip [0].Count [5]) + if (IPPU.Clip [0].Count [5]) + { + uint32_t y; + for (y = starty; y <= endy; y++) { - uint32_t y; - for (y = starty; y <= endy; y++) - { - uint16_t* p = (uint16_t*)(GFX.Screen + y * GFX.Pitch2); - uint8_t* d = GFX.SubZBuffer + y * GFX.ZPitch; - uint8_t* e = d + IPPU.RenderedScreenWidth; + uint16_t* p = (uint16_t*)(GFX.Screen + y * GFX.Pitch2); + uint8_t* d = GFX.SubZBuffer + y * GFX.ZPitch; + uint8_t* e = d + IPPU.RenderedScreenWidth; - while (d < e) - { - if (*d > 1) - *p = *(p + GFX.Delta); - else - *p = BLACK; - d++; - p++; - } + while (d < e) + { + if (*d > 1) + *p = *(p + GFX.Delta); + else + *p = BLACK; + d++; + p++; } } + } - GFX.DB = GFX.ZBuffer; - RenderScreen(GFX.Screen, false, false, MAIN_SCREEN_DEPTH); + GFX.DB = GFX.ZBuffer; + RenderScreen(GFX.Screen, false, false, MAIN_SCREEN_DEPTH); + + if (SUB_OR_ADD(5)) + { + uint32_t back = IPPU.ScreenColors [0]; + uint32_t Left = 0; + uint32_t Right = 256; + uint32_t Count; - if (SUB_OR_ADD(5)) + pClip = &IPPU.Clip [0]; + uint32_t y; + for (y = starty; y <= endy; y++) { - uint32_t back = IPPU.ScreenColors [0]; - uint32_t Left = 0; - uint32_t Right = 256; - uint32_t Count; + if (!(Count = pClip->Count [5])) + { + Left = 0; + Right = 256 * x2; + Count = 1; + } - pClip = &IPPU.Clip [0]; - uint32_t y; - for (y = starty; y <= endy; y++) + uint32_t b; + for (b = 0; b < Count; b++) { - if (!(Count = pClip->Count [5])) + if (pClip->Count [5]) { - Left = 0; - Right = 256 * x2; - Count = 1; + Left = pClip->Left [b][5] * x2; + Right = pClip->Right [b][5] * x2; + if (Right <= Left) + continue; } - uint32_t b; - for (b = 0; b < Count; b++) + if (GFX.r2131 & 0x80) { - if (pClip->Count [5]) - { - Left = pClip->Left [b][5] * x2; - Right = pClip->Right [b][5] * x2; - if (Right <= Left) - continue; - } - - if (GFX.r2131 & 0x80) - { - if (GFX.r2131 & 0x40) - { - /* Subtract, halving the result. */ - uint16_t* p = (uint16_t*)(GFX.Screen + y * GFX.Pitch2) + Left; - uint8_t* d = GFX.ZBuffer + y * GFX.ZPitch; - uint8_t* s = GFX.SubZBuffer + y * GFX.ZPitch + Left; - uint8_t* e = d + Right; - uint16_t back_fixed = COLOR_SUB(back, GFX.FixedColour); - - d += Left; - while (d < e) - { - if (*d == 0) - { - if (*s) - { - if (*s != 1) - *p = COLOR_SUB1_2(back, *(p + GFX.Delta)); - else - *p = back_fixed; - } - else - *p = (uint16_t) back; - } - d++; - p++; - s++; - } - } - else - { - // Subtract - uint16_t* p = (uint16_t*)(GFX.Screen + y * GFX.Pitch2) + Left; - uint8_t* s = GFX.SubZBuffer + y * GFX.ZPitch + Left; - uint8_t* d = GFX.ZBuffer + y * GFX.ZPitch; - uint8_t* e = d + Right; - uint16_t back_fixed = COLOR_SUB(back, GFX.FixedColour); - - d += Left; - while (d < e) - { - if (*d == 0) - { - if (*s) - { - if (*s != 1) - *p = COLOR_SUB(back, *(p + GFX.Delta)); - else - *p = back_fixed; - } - else - *p = (uint16_t) back; - } - d++; - p++; - s++; - } - } - } - else if (GFX.r2131 & 0x40) + if (GFX.r2131 & 0x40) { + /* Subtract, halving the result. */ uint16_t* p = (uint16_t*)(GFX.Screen + y * GFX.Pitch2) + Left; uint8_t* d = GFX.ZBuffer + y * GFX.ZPitch; uint8_t* s = GFX.SubZBuffer + y * GFX.ZPitch + Left; uint8_t* e = d + Right; - uint16_t back_fixed = COLOR_ADD(back, GFX.FixedColour); + uint16_t back_fixed = COLOR_SUB(back, GFX.FixedColour); + d += Left; while (d < e) { @@ -3386,7 +2958,7 @@ void S9xUpdateScreen() if (*s) { if (*s != 1) - *p = COLOR_ADD1_2(back, *(p + GFX.Delta)); + *p = COLOR_SUB1_2(back, *(p + GFX.Delta)); else *p = back_fixed; } @@ -3398,13 +2970,15 @@ void S9xUpdateScreen() s++; } } - else if (back != 0) + else { + // Subtract uint16_t* p = (uint16_t*)(GFX.Screen + y * GFX.Pitch2) + Left; - uint8_t* d = GFX.ZBuffer + y * GFX.ZPitch; uint8_t* s = GFX.SubZBuffer + y * GFX.ZPitch + Left; + uint8_t* d = GFX.ZBuffer + y * GFX.ZPitch; uint8_t* e = d + Right; - uint16_t back_fixed = COLOR_ADD(back, GFX.FixedColour); + uint16_t back_fixed = COLOR_SUB(back, GFX.FixedColour); + d += Left; while (d < e) { @@ -3413,7 +2987,7 @@ void S9xUpdateScreen() if (*s) { if (*s != 1) - *p = COLOR_ADD(back, *(p + GFX.Delta)); + *p = COLOR_SUB(back, *(p + GFX.Delta)); else *p = back_fixed; } @@ -3425,80 +2999,117 @@ void S9xUpdateScreen() s++; } } - else + } + else if (GFX.r2131 & 0x40) + { + uint16_t* p = (uint16_t*)(GFX.Screen + y * GFX.Pitch2) + Left; + uint8_t* d = GFX.ZBuffer + y * GFX.ZPitch; + uint8_t* s = GFX.SubZBuffer + y * GFX.ZPitch + Left; + uint8_t* e = d + Right; + uint16_t back_fixed = COLOR_ADD(back, GFX.FixedColour); + d += Left; + while (d < e) + { + if (*d == 0) + { + if (*s) + { + if (*s != 1) + *p = COLOR_ADD1_2(back, *(p + GFX.Delta)); + else + *p = back_fixed; + } + else + *p = (uint16_t) back; + } + d++; + p++; + s++; + } + } + else if (back != 0) + { + uint16_t* p = (uint16_t*)(GFX.Screen + y * GFX.Pitch2) + Left; + uint8_t* d = GFX.ZBuffer + y * GFX.ZPitch; + uint8_t* s = GFX.SubZBuffer + y * GFX.ZPitch + Left; + uint8_t* e = d + Right; + uint16_t back_fixed = COLOR_ADD(back, GFX.FixedColour); + d += Left; + while (d < e) { - if (!pClip->Count [5]) + if (*d == 0) { - // The backdrop has not been cleared yet - so - // copy the sub-screen to the main screen - // or fill it with the back-drop colour if the - // sub-screen is clear. - uint16_t* p = (uint16_t*)(GFX.Screen + y * GFX.Pitch2) + Left; - uint8_t* d = GFX.ZBuffer + y * GFX.ZPitch; - uint8_t* s = GFX.SubZBuffer + y * GFX.ZPitch + Left; - uint8_t* e = d + Right; - d += Left; - while (d < e) + if (*s) { - if (*d == 0) - { - if (*s) - { - if (*s != 1) - *p = *(p + GFX.Delta); - else - *p = GFX.FixedColour; - } - else - *p = (uint16_t) back; - } - d++; - p++; - s++; + if (*s != 1) + *p = COLOR_ADD(back, *(p + GFX.Delta)); + else + *p = back_fixed; } + else + *p = (uint16_t) back; } + d++; + p++; + s++; } } - } - } // --if (SUB_OR_ADD(5)) - else - { - uint32_t y; - // Subscreen not being added to back - uint32_t back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); - pClip = &IPPU.Clip [0]; - - if (pClip->Count [5]) - { - for (y = starty; y <= endy; y++) + else { - uint32_t b; - for (b = 0; b < pClip->Count [5]; b++) + if (!pClip->Count [5]) { - uint32_t Left = pClip->Left [b][5] * x2; - uint32_t Right = pClip->Right [b][5] * x2; + // The backdrop has not been cleared yet - so + // copy the sub-screen to the main screen + // or fill it with the back-drop colour if the + // sub-screen is clear. uint16_t* p = (uint16_t*)(GFX.Screen + y * GFX.Pitch2) + Left; uint8_t* d = GFX.ZBuffer + y * GFX.ZPitch; + uint8_t* s = GFX.SubZBuffer + y * GFX.ZPitch + Left; uint8_t* e = d + Right; d += Left; - while (d < e) { if (*d == 0) - *p = (int16_t) back; + { + if (*s) + { + if (*s != 1) + *p = *(p + GFX.Delta); + else + *p = GFX.FixedColour; + } + else + *p = (uint16_t) back; + } d++; p++; + s++; } } } } - else + } + } // --if (SUB_OR_ADD(5)) + else + { + uint32_t y; + // Subscreen not being added to back + uint32_t back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); + pClip = &IPPU.Clip [0]; + + if (pClip->Count [5]) + { + for (y = starty; y <= endy; y++) { - for (y = starty; y <= endy; y++) + uint32_t b; + for (b = 0; b < pClip->Count [5]; b++) { - uint16_t* p = (uint16_t*)(GFX.Screen + y * GFX.Pitch2); + uint32_t Left = pClip->Left [b][5] * x2; + uint32_t Right = pClip->Right [b][5] * x2; + uint16_t* p = (uint16_t*)(GFX.Screen + y * GFX.Pitch2) + Left; uint8_t* d = GFX.ZBuffer + y * GFX.ZPitch; - uint8_t* e = d + 256 * x2; + uint8_t* e = d + Right; + d += Left; while (d < e) { @@ -3510,64 +3121,81 @@ void S9xUpdateScreen() } } } - } //force blanking - else - { - // 16bit and transparency but currently no transparency effects in - // operation. - - uint32_t back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); - - if (PPU.ForcedBlanking) - back = black; - - if (IPPU.Clip [0].Count[5]) + else { - uint32_t y; for (y = starty; y <= endy; y++) { - uint32_t* p = (uint32_t*)(GFX.Screen + y * GFX.Pitch2); - uint32_t* q = (uint32_t*)((uint16_t*) p + IPPU.RenderedScreenWidth); - - while (p < q) - *p++ = black; + uint16_t* p = (uint16_t*)(GFX.Screen + y * GFX.Pitch2); + uint8_t* d = GFX.ZBuffer + y * GFX.ZPitch; + uint8_t* e = d + 256 * x2; - uint32_t c; - for (c = 0; c < IPPU.Clip [0].Count [5]; c++) + while (d < e) { - if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5]) - { - uint16_t* p = (uint16_t*)(GFX.Screen + y * GFX.Pitch2); - uint16_t* q = p + IPPU.Clip [0].Right [c][5] * x2; - p += IPPU.Clip [0].Left [c][5] * x2; - - while (p < q) - *p++ = (uint16_t) back; - } + if (*d == 0) + *p = (int16_t) back; + d++; + p++; } } } - else + } + } //force blanking + else + { + // 16bit and transparency but currently no transparency effects in + // operation. + + uint32_t back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); + + if (PPU.ForcedBlanking) + back = black; + + if (IPPU.Clip [0].Count[5]) + { + uint32_t y; + for (y = starty; y <= endy; y++) { - uint32_t y; - for (y = starty; y <= endy; y++) + uint32_t* p = (uint32_t*)(GFX.Screen + y * GFX.Pitch2); + uint32_t* q = (uint32_t*)((uint16_t*) p + IPPU.RenderedScreenWidth); + + while (p < q) + *p++ = black; + + uint32_t c; + for (c = 0; c < IPPU.Clip [0].Count [5]; c++) { - uint32_t* p = (uint32_t*)(GFX.Screen + y * GFX.Pitch2); - uint32_t* q = (uint32_t*)((uint16_t*) p + IPPU.RenderedScreenWidth); - while (p < q) - *p++ = back; + if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5]) + { + uint16_t* p = (uint16_t*)(GFX.Screen + y * GFX.Pitch2); + uint16_t* q = p + IPPU.Clip [0].Right [c][5] * x2; + p += IPPU.Clip [0].Left [c][5] * x2; + + while (p < q) + *p++ = (uint16_t) back; + } } } - - if (!PPU.ForcedBlanking) + } + else + { + uint32_t y; + for (y = starty; y <= endy; y++) { - uint32_t y; - for (y = starty; y <= endy; y++) - memset(GFX.ZBuffer + y * GFX.ZPitch, 0, IPPU.RenderedScreenWidth); - GFX.DB = GFX.ZBuffer; - RenderScreen(GFX.Screen, false, true, SUB_SCREEN_DEPTH); + uint32_t* p = (uint32_t*)(GFX.Screen + y * GFX.Pitch2); + uint32_t* q = (uint32_t*)((uint16_t*) p + IPPU.RenderedScreenWidth); + while (p < q) + *p++ = back; } } + + if (!PPU.ForcedBlanking) + { + uint32_t y; + for (y = starty; y <= endy; y++) + memset(GFX.ZBuffer + y * GFX.ZPitch, 0, IPPU.RenderedScreenWidth); + GFX.DB = GFX.ZBuffer; + RenderScreen(GFX.Screen, false, true, SUB_SCREEN_DEPTH); + } } if (PPU.BGMode != 5 && PPU.BGMode != 6 && IPPU.DoubleWidthPixels) diff --git a/source/gfx.h b/source/gfx.h index 1b4cc6a..5599527 100644 --- a/source/gfx.h +++ b/source/gfx.h @@ -19,7 +19,6 @@ void S9xBuildDirectColourMaps(void); bool S9xInitGFX(void); void S9xDeinitGFX(void); -bool S9xInitUpdate(void); typedef struct { @@ -154,10 +153,7 @@ static INLINE uint16_t COLOR_ADD(uint16_t C1, uint16_t C2) else if (C2 == 0) return C1; else - return GFX.X2 [(((C1 & RGB_REMOVE_LOW_BITS_MASK) + - (C2 & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + - (C1 & C2 & RGB_LOW_BITS_MASK)] | - ((C1 ^ C2) & RGB_LOW_BITS_MASK); + return GFX.X2[(((C1 & RGB_REMOVE_LOW_BITS_MASK) + (C2 & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + (C1 & C2 & RGB_LOW_BITS_MASK)] | ((C1 ^ C2) & RGB_LOW_BITS_MASK); } #define COLOR_ADD1_2(C1, C2) \ @@ -175,13 +171,7 @@ static INLINE uint16_t COLOR_ADD(uint16_t C1, uint16_t C2) GFX.ZERO [(((C1) | RGB_HI_BITS_MASKx2) - \ ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1] -typedef void (*NormalTileRenderer)(uint32_t Tile, int32_t Offset, - uint32_t StartLine, uint32_t LineCount); -typedef void (*ClippedTileRenderer)(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Width, - uint32_t StartLine, uint32_t LineCount); -typedef void (*LargePixelRenderer)(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Pixels, - uint32_t StartLine, uint32_t LineCount); - +typedef void (*NormalTileRenderer)(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount); +typedef void (*ClippedTileRenderer)(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount); +typedef void (*LargePixelRenderer)(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Pixels, uint32_t StartLine, uint32_t LineCount); #endif diff --git a/source/globals.c b/source/globals.c index 830c6ab..36d0e67 100644 --- a/source/globals.c +++ b/source/globals.c @@ -17,7 +17,6 @@ char String[513]; SICPU ICPU; - SCPUState CPU; #ifndef USE_BLARGG_APU @@ -27,9 +26,7 @@ SSoundData SoundData; #endif SSettings Settings; - SDSP1 DSP1; - SSA1 SA1; SnesModel M1SNES = {1, 3, 2}; @@ -40,8 +37,6 @@ int32_t OpAddress = 0; CMemory Memory; -SSNESGameFixes SNESGameFixes; - uint8_t OpenBus = 0; FxInit_s SuperFX; @@ -191,15 +186,14 @@ uint32_t TailMask [5] = uint8_t APUROM [64] = { - 0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0, 0xFC, 0x8F, 0xAA, 0xF4, 0x8F, - 0xBB, 0xF5, 0x78, 0xCC, 0xF4, 0xD0, 0xFB, 0x2F, 0x19, 0xEB, 0xF4, 0xD0, 0xFC, - 0x7E, 0xF4, 0xD0, 0x0B, 0xE4, 0xF5, 0xCB, 0xF4, 0xD7, 0x00, 0xFC, 0xD0, 0xF3, - 0xAB, 0x01, 0x10, 0xEF, 0x7E, 0xF4, 0x10, 0xEB, 0xBA, 0xF6, 0xDA, 0x00, 0xBA, - 0xF4, 0xC4, 0xF4, 0xDD, 0x5D, 0xD0, 0xDB, 0x1F, 0x00, 0x00, 0xC0, 0xFF + 0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0, 0xFC, 0x8F, 0xAA, 0xF4, 0x8F, 0xBB, 0xF5, 0x78, + 0xCC, 0xF4, 0xD0, 0xFB, 0x2F, 0x19, 0xEB, 0xF4, 0xD0, 0xFC, 0x7E, 0xF4, 0xD0, 0x0B, 0xE4, 0xF5, + 0xCB, 0xF4, 0xD7, 0x00, 0xFC, 0xD0, 0xF3, 0xAB, 0x01, 0x10, 0xEF, 0x7E, 0xF4, 0x10, 0xEB, 0xBA, + 0xF6, 0xDA, 0x00, 0xBA, 0xF4, 0xC4, 0xF4, 0xDD, 0x5D, 0xD0, 0xDB, 0x1F, 0x00, 0x00, 0xC0, 0xFF }; // Raw SPC700 instruction cycle lengths -uint16_t S9xAPUCycleLengths [256] = +uint8_t S9xAPUCycleLengths [256] = { /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, */ /* 00 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 6, 8, @@ -222,7 +216,7 @@ uint16_t S9xAPUCycleLengths [256] = // Actual data used by CPU emulation, will be scaled by APUReset routine // to be relative to the 65c816 instruction lengths. -uint16_t S9xAPUCycles [256] = +uint8_t S9xAPUCycles [256] = { /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, */ /* 00 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 6, 8, diff --git a/source/hardware.txt b/source/hardware.txt deleted file mode 100644 index ec6f2e5..0000000 --- a/source/hardware.txt +++ /dev/null @@ -1,502 +0,0 @@ -This document gives a brief description of the known hardware features of the -SNES giving you some idea what SNES emulation authors are up against. - -Quick Overview --------------- - -o 65c816 CPU running at up to 3.58MHz. - -o SPC700 CPU core running at 2.48MHz with built-in custom sound digital - signal processor. - -o Two custom graphics processors used to produce displays of up to 512x478 - pixels with up to 32768 colours, 128 sprites, scaling, rotation, and mosaic - effects, scrolling over a virtual screen, transparency, coloured lens and - window effects and raster effects. - -o 128k work RAM, 64k sound CPU RAM and 64k video RAM. - -Game packs can include: - -o Up to 6MBytes (or more) of ROM containing the game code, graphics and sound - data. - -o Additional, battery-backed RAM (S-RAM) used to save game positions. - -o 10.5/21MHz RISC CPU (Super FX) used to implement some 3D games and add - special effects to games. - -o A maths co-processor (DSP1) used by some games with lots of physics - calculations involved (Pilot Wings) or mainly as a protection device - (Mario Kart). - -o Other custom chips produced by some software companies to help speed up - games, fit more graphics into a given sized ROM or act as a protection - device. - -Users could buy: - -o A five player adapter, allowing up to five people to play at once on games - that supported it. - -o A 2-button mouse, originally supplied with a paint program. - -o A light-gun that looked like riffle; it used infra-red to provide wire-less - communication between the gun and the console unit. About 10 games - supported it. - -o A GameBoy adapter that allowed the owners to play GameBoy games on their - SNES, some in colour. - -o Copier units that plugged into the cartridge slot on the SNES and allowed - game pak ROMs to be downloaded into RAM on the copier and saved onto - disk. The game could then be played without the original ROM being present - - unless the game pack contained additional hardware, or the game ROM code - tried to detect the copier being present and deliberately crashed the game. - -More Detail ------------ - -65c816 ------- - -The 65c816 is an 8/16-bit CPU that is basically an enhanced 6502: it even -has an emulation mode to make it behave almost exactly like a real 6502. No -doubt Nintendo were hoping to provide a compatibility mode for old NES -games, but failed. - -The CPU features a 24-bit address bus and 8-bit data bus allowing a 16Mb -address space. It has an accumulator and two index registers, all can be -switch to either 8 or 16-bit mode. - -The address space is broken up into 256 banks, each bank being 64k in size, -although there are addressing modes to treat the entire address space as one -continuous block. Bank 0 is special in that the stack, a few addressing -modes and the interrupt and reset vectors all reside there. The stack -pointer is 16-bits wide. - -The 6502 has an addressing mode called zero-page, where the 1-byte address -specified in the instruction refers to a location in the first 256 bytes of -memory, allowing for 2-byte instructions and increased execution speed. The -65c816 extends this idea by allowing the 'zero-page' to be moved anywhere -inside bank 0 by use of the 16-bit direct page register. - -There are other addressing modes available that use the bank specified in -the data bank register, again to help reduce code size and speed up -execution. - -Code normally executes in single bank at a time, the current bank number -being specified by the 8-bit program bank register. There are instructions -available to call subroutines in other banks or just jump to code in other -banks. - -The 65c816 internally runs at 3.58MHz, but other SNES hardware can temporarily -slow it down to 2.58MHz or even 1.56MHz when the CPU attempts read from them -or write to them. In particular, there are a mixture of fast and slow ROMs -inside game packs, slow ROMs can only be accessed at 2.58MHz. - -The 65c816 has direct access to 128k of work RAM plus any additional RAM that -might be in the game pack. Video RAM and sound RAM cannot be accessed -directly. - -SPC700 ------- - -The SPC700 is an 8-bit CPU core, similar to a 6502, but with a different -instruction set, some new addressing modes and multiple and divide -instructions, together with a custom sound digital signal processor, all -contained inside one module. - -The SPC700 and the 65c816 communicate via 4 bi-directional, 8-bit I/O ports. -The SPC700 has its own 64k RAM used to store a program downloaded from 65c816 -and sound sample data. - -The CPU has a built-in, small, 64 byte ROM used as boot-strap code to -download a more complex program and sample data from the game ROM via the -65c816. The ROM can be switched off and replaced with 64 bytes of RAM once -the boot-strap code has done its work. - -The sound DSP can only play compresses sound samples, compressed using a -custom fixed-ratio compression algorithm that compresses 16 16-bit samples -into 8 bytes plus a one byte header. The minimum unit of a sample is one -block. The block header byte contains a shift and filter value (algorithm -decompression information) plus a last block flag and a loop flag; the loop -flag is only used if the last block flag is also set. - -There are 8 separate sound channels allowing up to 8 samples to be played -simultaneously. Each sound channel has a left and right volume setting and -frequency setting. A hardware volume envelope can be defined for each -channel, and echo effects can be turned on and off individually for each -channel. The combined echo waveform can be subjected to an 8-tap FIR -digital filter. The wave output of a channel can be used to modulate the -frequency of the next sound channel, in numerical order. - -The DSP also has a white noise source that can played on a sound channel -instead of sample data. All 8 channels, and any echo sound data, are mixed -together and subjected to a left and right master volume control. - -The DSP also provides 3 interval timers, the first two running at 8kHz and -the last at 64kHz; games normally only use one of them to provide a constant -music playback rate. - -Interrupts ----------- - -The 65c816 provides two external interrupt sources: IRQ, which can be masked, -and NMI, which cannot. - -The IRQ line is connected to an output on one of the graphics chips, that, -it turn can be programmed to generate an IRQ at the start of a scanline, at -a particular position on a scanline or at a particular position of every -scanline. The IRQ line also is connected to one of the pins on the ROM -connector, so additional hardware inside the ROM game pak, such as the Super FX -and SA-1 chips, can also generate interrupts. - -The NMI line is connected to another output of one of the graphics chips and -it can be programmed to generate an interrupt when the vertical blank period -starts. - -The SPC700 chip can also generate interrupts, but they are not used on the -SNES and probably physically not connected. - -Joypad Reading --------------- - -Data from the SNES joy-pads is sent serially between the pad and the console. -Games can choose to read each bit in, one at a time or allow hardware inside -one of the custom chips to automatically read the joy-pad values once every -frame. The game can then read the values from registers. - -SNES joy-pads themselves have direction controls and 8 other buttons named -A, B, X, Y, Left, Right, Start and Select. - -Colour Palette --------------- - -The SNES has a 256 entry 15-bit colour palette, allowing for 256 colours on -screen out of a total palette of 32768. However, games can and do change -colour entries during a frame, this combined with hardware colour value -addition and subtraction and an overall brightness setting, can easily boost -the number of colours on screen to several thousand! - -Tiles ------ - -All SNES graphics data is made up of tiles, a tile being an 8x8 block of -pixels, with each pixel made up of 2, 4 or 8 bits, allowing for 4, 16 or 256 -colours per pixel. - -To complicate matters, the SNES hardware stores tile data in planar format, -that is all the bit 1's of all the pixels of a tile are stored together, -then all the bit 2's and so on. Its like a sequence of 1-bit deep 8x8 pixel -blocks. - -When a tile is used as background data, a 3-bit palette start address is -associated with each tile, allowing the programmer to choose a different -block of colours for each tile from the larger SNES colour palette. Sprites -can only use tiles of depth 4 (16 colours), but each sprite has a palette -start address. - -Background Graphic Modes ------------------------- - -The SNES has eight background graphics modes, each mode varies the number of -individual background layers available, the depth of each layer and what -other features are available. Programmers can change the background mode -during a frame. - -The two most commonly used modes are mode 1, which allows two 16-colour -background layers and one 4-colour layer and mode 7, which allows one 256- -colour layer, but the layer can be rotated, stretched, squashed, sheared and -generally messed around with. - -Each background is made up 32x32 8x8 tiles. However, the number of tiles in -each direction can be double as can the individual tile size. This allows for -a virtual background size of 256x256 up to 1024x1024. Switching to 16x16 tile -size actually just groups four 8x8 tiles together, there is no true 16x16 tile -on the SNES. - -Backgrounds have a pre-defined priority order - when pixels from one -background layer overlap on the screen pixels from another background layer, -the pixels from the lower numbered background are displayed. - -Each tile can be flipped horizontally or vertically, has a 3-bit "palette -number" and a priority bit. The priority bit is used to make all the pixels -in the tile appear in front of pixels from another background layer or -sprite that would otherwise normally appear in front of them. Colour 0 from -each tile is special and means "transparent", allowing non-transparent -pixels from background layers or sprites "underneath" to be visible. - -Normally only 256x224 or 256x239 pixels are visible on screen and backgrounds -have a scroll setting that allows the screen to act as a window onto any -portion of their virtual size. - -Two background modes are available that can display up to 512x478 pixels, -but they're not used by many games because the flicker, caused by the -interlace used display the image on a standard television, would give game -players headaches. - -Sprites -------- - -The SNES has 128 hardware sprites, each sprite can be made up of one or -several 16-colour, 8x8 tiles. Each sprite is assigned a number which defines -its pixel priority when two sprites overlap on screen, it also has a separate -sprite-to-background priority value which defines whether the sprite should -appear in front or behind of the various background layers. Each sprite also -has a 3-bit palette number, horizontal and vertical flip flags, a start tile -number and, of course, an X and Y position. - -There's no way to turn off a sprite - if you don't want it to be visible you -have to place the sprite at off-screen position. - -The SNES hardware seems to impose limits on the number of sprites that can -appear on each scanline; there are one or two games out there that rely on -this 'feature' to hide sprites they don't want visible. - -Mosaic ------- - -The SNES has a hardware mosaic effect. The upper left-hand pixel from a block -of pixels up to 16 pixels wide can be made to cover the area of the other -15; the pixel appears up to 16 times its original size. The effect can only -be used on the background layers, not sprites. All backgrounds share the -same size setting but the effect can be turned on and off per background -layer. - -Many ROMs combine the mosaic effect with a brightness fade to zoom out of one -game screen then zoom on to the next. - -Offset Per Tile ---------------- - -Three of the background screen modes reduce the number of visible background -layers by one, and use its screen data as per-tile background scroll data -for the remaining visible layers. - -The background modes vary as to whether the vertical and horizontal scroll -values can both be altered, or just one of them. Tetris Attack uses the -effect to allow different parts of the screen to scroll vertically at -different rates. - -The horizontal per-tile offset feature is very limited and only allows -adjustment in steps of 8 pixels. - -Mode 7 ------- - -Nintendo use this background screen mode to really show off the SNES compared -to the Sega's Mega Drive. - -By specifying a centre of rotation and a 2 by 2 transformation matrix, the -mode 7 screen can be rotated, scaled, stretched, squashed, etc. just by -writing to a few PPU registers. By varying the values on each scanline, some -very interesting effects can be produced, these include a perspective -effect, shears, split-screen zooms, etc. - -Each pixel is 8-bit (256 colours per pixel) and the screen itself has a -virtual screen size of 1024x1024. - -Mode 7 has another feature where the number of colours are reduced to 128 -and the spare bit is used to swap a pixel between background layer 0 and 1, -thus altering the sprite to background priority. This allows some pixels to -be appear in front of sprites and others appear behind. - -Colour Addition / Subtraction ------------------------------ - -The pixels of background layers and sprites can be directed to one of two -places, the main-screen or the sub-screen. The sub-screen is like a virtual -screen that cannot normally be seen, but the SNES has hardware that can add -or subtract the RGB colour palette values of each pixel on the sub-screen to -or from RGB values of pixels on the main-screen. The effect is that -background layers on the on the main-screen appear translucent, allowing the -sub-screen partly to show through. Examples are cloud, mist and water effects. - -The effect can be turned on and off for each background layer on the -main-screen. There's a master switch for sprites as well, but when turned -on, only sprites with certain colour palette numbers actually have their -pixel values added to or subtracted from. - -The SNES also has a separate fixed colour value; if colour addition or -subtraction is enabled and there's nothing on the sub-screen, the fixed -colour is added or subtracted instead. I've seen it used by games to darken -an area of the screen then overlay a menu on top, to implement a -fade-to-white effect and to tint an area of the screen a particular colour. - -Windows -------- - -The SNES provides two "clip windows". Each window is just an area defined by -a left and right position. A background layer or all sprites can be selected -to appear only inside or outside the window. - -If both windows are enabled on the same background layer or for all sprites, -the areas they define are combined using one of four logical combination -modes: OR, AND, XOR and N-XOR. - -If the left and/or right values are altered on each scanline (normally using -H-DMA), many different shaped windows can be created; I've seen circles, -pentagons, wavy lines, doughnuts, G's, etc. - -There's also the colour window. Each window or both windows can be used to -define the area of the colour window. When the colour window is enabled for -the sub-screen, transparency effects occur only inside or outside the colour -window. When the colour window is enabled for the main-screen, it acts like -a master clip window, clipping all background layers and sprites and even -the back-drop colour to the area either inside or outside the colour window; -in the clipped areas, the sub-screen is displayed or just black. - -Direct Colour Mode ------------------- - -On the 256 colour background modes, the otherwise unused 3-bit per-tile -colour palette number can be used in combination with the 8-bit tile pixel -data to form an 11-bit colour value (2048 colours) without using the SNES -colour palette registers. - -Mode 7 has the same feature, but since mode 7 uses a different tile layout -with no 3-bit colour palette number, a fixed 256 colours are available -instead, again without using the SNES colour palette registers. - -Interlace ---------- - -The SNES normally generates a non-interlaced picture. Interlace can turned -on and the only thing that happens is that the screen appears to flicker -slightly due to the way a television works. However, in the two hi-res. -background screen modes, if interlace is turned on the vertical resolution -doubles from 512x224 to 512x448 (or 512x478 if the expand vertical flag is -also set). - -Not many games use the feature due to the flicker introduced by the -interlace, so its use is normally limited to title screens. However, one -game I know of, RPM Racing, uses the effect during the game. - -DMA ---- - -The SNES provides 8 DMA (direct-memory-access) channels, although only one can -be active at once. Without any intervention of the 65c816 CPU, up to 64K of -data can be transferred from RAM or ROM to any PPU (picture processing unit) -register. Since V-RAM, colour palette and sprite position and display data can -only be written to via PPU registers, DMA provides a very convenient method of -transferring data faster than the CPU alone could provide. There are PPU -registers to read or write to the 128k work RAM, so DMA could be used to copy -data from ROM to RAM as well. - -There is also a DMA read mode, where data is transferred from PPU registers -to RAM. - -There are various limitations on DMA - if multiple DMA channels are started -at once, they execute in order, the numerically lowest one first, then the -next highest and so on. The 65c816 is stopped while DMA takes place. Each -DMA operation can only access one 64k bank at once. However, the biggest -limitation is that DMA can only take place when the graphics chips aren't -also performing graphics data DMA, i.e. DMA can only be used during the -v-blank period or when the screen is forcible blanked. - -H-DMA ------ - -H-DMA is like DMA in that data is transferred from ROM or RAM to PPU -registers without the intervention of the CPU. However, instead of all the -data being transferred in one block, a few bytes are transferred at a time, -just before the start of the each scanline. - -H-DMA shares the same channels as normal DMA, so each channel can be set up -for DMA or H-DMA, but since normal DMA only occurs during v-blank and H-DMA -is disabled during this time, its actually easy to reuse a channel for both -types of DMA. - -There are various H-DMA modes that define how many bytes should be -transferred each scanline, whether the destination PPU register is 8-bit or -16-bit, should new data be transferred each scanline, or can the same data -be reused if a count value hasn't reached zero, etc. - -H-DMA gives a very powerful weapon to programmers, it allows PPU register -values to be easily changed each scanline, so many games can and do use it -to change screen colours, background scroll values, window shape values, -mode 7 matrix values, transparency effects, etc. during the frame. - -Extra Chips Used by the SNES Inside Some Game Paks -================================================== - -Super FX --------- - -The Super FX is just a fast integer RISC-type processor but with a built-in -plot instruction that can draw a single pixel in the SNES' planar format into -a virtual screen very quickly, very handy for 3d polygon rendering. Its a -strange chip though - no stack, a 512 byte cache and a one stage pipe-line -that causes the instruction following a branch instruction to be executed. -Instructions fetched from the cache often execute in a single cycle. - -Super FX games came with additional RAM inside the game pak that is used as -work RAM for the 'FX chip and as save-game positions, if the ROM supports it. - -The 'FX chip has 16 16-bit registers and built-in fast integer multiply. -Although the Super FX and the 65c816 can run in parallel, the 'FX chip can't -access the game pack ROM or RAM at the same time as the main SNES CPU, so most -games just get the SNES CPU to execute a wait loop in the SNES work RAM. - -The 'FX can't access the SNES custom hardware chips, so if the 'FX has -rendered a screen image in its work RAM, it has to go to sleep while the SNES -CPU copies the screen to video RAM, usually using DMA. The SNES CPU can pass -parameters to 'FX routines either by writing them into the 'FX work RAM or -writing directly into the 'FX registers, which it can be accessed by the CPU -only when the 'FX chip is sleeping. - -There are two versions of the 'FX chip, the original 10MHz chip used in Star -Fox and limited to 1Mb of ROM access and 64K RAM and a newer version used in -Yoshi's Island, Doom, Vortex, Winter Gold, Star Fox 2, etc. which can be -clocked at 21MHz and can access twice as much ROM and RAM. - -DSP1 ----- - -The DSP1 is an early digital signal processor with an on-board ROM, -manufactured by NEC. The on-board ROM was loaded with a program developed -by Nintendo to turn the chip into a 3d maths co-processor, able to perform -most primitive, but time-consuming, calculations required when manipulating -objects in a 3d coordinate system relatively quickly, compared to the -speed of the 65c816 CPU alone, that is. - -Most of the calculations supported seemed to be those required by a simple -flight simulator, i.e. the calculations available were choosen with Pilot -Wings in mind. - -The DSP1 has been used in several other games, may be as many as 20, though -most ignore a lot of the available features. The games include Mario Kart, Top -Gear 3000, Battle Racers, Super Air Diver and Bases Loaded 2. - -SA-1 ----- - -The SA-1 is a fast, custom 65c816 8/16-bit processor, the same as inside the -SNES itself, but clocked at 10MHz compared to a maximum of 3.58MHz for the CPU -inside the SNES. - -The SA-1 isn't just a CPU, it also contains some extra circuits developed by -Nintendo which includes some very fast RAM, a memory mapper, DMA, several -real-time timers, and the region lock-out chip. - -The SNES (or ROM copiers) can only access the ROM inside the game pak via the -SA-1; and the SA-1 only enables access to the ROM once its internal region -lock-out chip has verified it has successfully communicated with a lock-out -chip inside the SNES. This very effectively prevents SNES ROM copiers from -being able to copy the ROM. - -The SA-1 is used in Mario RPG and seems to be used in several other games -that Nintendo released in 1996 and beyond. - -S-DD1 ------ - -Very little is known about this chip. It seems to be another digital signal -processor, possibly made by Texas Instruments, dedicated to decompressing -graphics data. Only two games I know of use the chip, Street Fighter Alpha 2 -and Star Ocean. - -Like the SA-1, the SNES and ROM copiers can only access the ROM via the S-DD1, -again preventing ROM copiers from dumping the ROM image. diff --git a/source/memmap.c b/source/memmap.c index 9011f90..d116330 100644 --- a/source/memmap.c +++ b/source/memmap.c @@ -129,8 +129,7 @@ static int32_t ScoreHiROM(bool skip_header, int32_t romoff) if (Memory.ROM [o + 0xd4] == 0x20) score += 2; - if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) + - Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff) + if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) + Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff) { score += 2; if (0 != (Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8))) @@ -171,8 +170,7 @@ static int32_t ScoreLoROM(bool skip_header, int32_t romoff) if (Memory.ROM [o + 0xd5] == 0x23) score += 2; - if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) + - Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff) + if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) + Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff) { score += 2; if (0 != (Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8))) @@ -188,7 +186,7 @@ static int32_t ScoreLoROM(bool skip_header, int32_t romoff) if (!(Memory.ROM [o + 0xfd] & 0x80)) score -= 6; if ((Memory.ROM [o + 0xfc] | (Memory.ROM [o + 0xfd] << 8)) > 0xFFB0) - score -= 2;//reduced per Cowering suggestion + score -= 2; //reduced per Cowering suggestion if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48) score -= 1; if (!AllASCII(&Memory.ROM [o + 0xb0], 6)) @@ -261,10 +259,7 @@ bool S9xInitMemory(void) IPPU.TileCached [TILE_4BIT] = (uint8_t*) calloc(MAX_4BIT_TILES, 1); IPPU.TileCached [TILE_8BIT] = (uint8_t*) calloc(MAX_8BIT_TILES, 1); - if (!Memory.RAM || !Memory.SRAM || !Memory.VRAM || !Memory.ROM || !Memory.BSRAM || - !IPPU.TileCache [TILE_2BIT] || !IPPU.TileCache [TILE_4BIT] || - !IPPU.TileCache [TILE_8BIT] || !IPPU.TileCached [TILE_2BIT] || - !IPPU.TileCached [TILE_4BIT] || !IPPU.TileCached [TILE_8BIT]) + if (!Memory.RAM || !Memory.SRAM || !Memory.VRAM || !Memory.ROM || !Memory.BSRAM || !IPPU.TileCache [TILE_2BIT] || !IPPU.TileCache [TILE_4BIT] || !IPPU.TileCache [TILE_8BIT] || !IPPU.TileCached [TILE_2BIT] || !IPPU.TileCached [TILE_4BIT] || !IPPU.TileCached [TILE_8BIT]) { S9xDeinitMemory(); return false; @@ -272,15 +267,14 @@ bool S9xInitMemory(void) // FillRAM uses first 32K of ROM image area, otherwise space just // wasted. Might be read by the SuperFX code. - Memory.FillRAM = Memory.ROM; // Add 0x8000 to ROM image pointer to stop SuperFX code accessing // unallocated memory (can cause crash on some ports). - Memory.ROM += 0x8000; // still 32-byte aligned + Memory.ROM += 0x8000; // still 32-byte aligned SuperFX.pvRegisters = &Memory.FillRAM [0x3000]; - SuperFX.nRamBanks = 2; // Most only use 1. 1=64KB, 2=128KB=1024Mb + SuperFX.nRamBanks = 2; // Most only use 1. 1 = 64KB, 2 = 128KB = 1024Mb SuperFX.pvRam = Memory.SRAM; SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024); SuperFX.pvRom = (uint8_t*) Memory.ROM; @@ -440,10 +434,7 @@ static void CheckForIPSPatch(const char* rom_filename, bool header, int32_t* rom // Check if ROM image needs to be truncated ofs = ReadInt(patch_file, 3); if (ofs != -1 && ofs - offset < *rom_size) - { - // Need to truncate ROM image - *rom_size = ofs - offset; - } + *rom_size = ofs - offset; // Need to truncate ROM image fclose(patch_file); return; @@ -485,13 +476,12 @@ static uint32_t FileLoader(uint8_t* buffer, const char* filename, int32_t maxsiz do { + int32_t calc_size; FileSize = fread(ptr, 1, maxsize + 0x200 - (ptr - Memory.ROM), ROMFile); fclose(ROMFile); + calc_size = FileSize & ~0x1FFF; // round to the lower 0x2000 - int32_t calc_size = FileSize & ~0x1FFF; // round to the lower 0x2000 - - if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) || - Settings.ForceHeader) + if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) || Settings.ForceHeader) { // memmove required: Overlapping addresses [Neb] // DS2 DMA notes: Can be split into 512-byte DMA blocks [Neb] @@ -519,8 +509,7 @@ static uint32_t FileLoader(uint8_t* buffer, const char* filename, int32_t maxsiz // check for multi file roms - if ((ptr - Memory.ROM) < (maxsize + 0x200) && - (isdigit(ext [0]) && ext [1] == 0 && ext [0] < '9')) + if ((ptr - Memory.ROM) < (maxsize + 0x200) && (isdigit(ext [0]) && ext [1] == 0 && ext [0] < '9')) { more = true; ext [0]++; @@ -531,11 +520,7 @@ static uint32_t FileLoader(uint8_t* buffer, const char* filename, int32_t maxsiz #endif _makepath(fname, drive, dir, name, ext); } - else if (ptr - Memory.ROM < maxsize + 0x200 && - (((len = strlen(name)) == 7 || len == 8) && - strncasecmp(name, "sf", 2) == 0 && - isdigit(name [2]) && isdigit(name [3]) && isdigit(name [4]) && - isdigit(name [5]) && isalpha(name [len - 1]))) + else if (ptr - Memory.ROM < maxsize + 0x200 && (((len = strlen(name)) == 7 || len == 8) && strncasecmp(name, "sf", 2) == 0 && isdigit(name [2]) && isdigit(name [3]) && isdigit(name [4]) && isdigit(name [5]) && isalpha(name [len - 1]))) { more = true; name [len - 1]++; @@ -580,9 +565,6 @@ bool LoadROM( Del7110Gfx(); - memset(&SNESGameFixes, 0, sizeof(SNESGameFixes)); - SNESGameFixes.SRAMInitialValue = 0x60; - memset(bytes0x2000, 0, 0x2000); CPU.TriedInterleavedMode2 = false; @@ -630,7 +612,8 @@ again: // SNESAdvance speed hacks (from the speed-hacks branch of CatSFC) if (strncmp("YOSHI'S ISLAND", (char *) &Memory.ROM[0x7FC0], 14) == 0) { - Memory.ROM[0x0000F4] = 0x42; Memory.ROM[0x0000F5] = 0x3B; + Memory.ROM[0x0000F4] = 0x42; + Memory.ROM[0x0000F5] = 0x3B; } else if (strncmp("SUPER MARIOWORLD", (char *) &Memory.ROM[0x7FC0], 16) == 0) { @@ -638,33 +621,47 @@ again: } else if (strncmp("ALL_STARS + WORLD", (char *) &Memory.ROM[0x7FC0], 17) == 0) { - Memory.ROM[0x0003D0] = 0x42; Memory.ROM[0x0003D1] = 0x5B; - Memory.ROM[0x018522] = 0x42; Memory.ROM[0x018523] = 0x5B; - Memory.ROM[0x02C804] = 0x42; Memory.ROM[0x02C805] = 0xBA; - Memory.ROM[0x0683B5] = 0x42; Memory.ROM[0x0683B6] = 0x5B; - Memory.ROM[0x0696AC] = 0x42; Memory.ROM[0x0696AD] = 0xBA; - Memory.ROM[0x089233] = 0xDB; Memory.ROM[0x089234] = 0x61; - Memory.ROM[0x0895DF] = 0x42; Memory.ROM[0x0895E0] = 0x5B; - Memory.ROM[0x0A7A9D] = 0x42; Memory.ROM[0x0A7A9E] = 0xBA; - Memory.ROM[0x1072E7] = 0x42; Memory.ROM[0x1072E8] = 0xD9; - Memory.ROM[0x107355] = 0x42; Memory.ROM[0x107356] = 0x5B; - Memory.ROM[0x1073CF] = 0x42; Memory.ROM[0x1073D0] = 0x5B; - Memory.ROM[0x107443] = 0x42; Memory.ROM[0x107444] = 0x5B; - Memory.ROM[0x107498] = 0x42; Memory.ROM[0x107499] = 0x5B; - Memory.ROM[0x107505] = 0x42; Memory.ROM[0x107506] = 0x5B; - Memory.ROM[0x107539] = 0x42; Memory.ROM[0x10753A] = 0x5B; - Memory.ROM[0x107563] = 0x42; Memory.ROM[0x107564] = 0x5B; - Memory.ROM[0x18041D] = 0x42; Memory.ROM[0x18041E] = 0x79; + Memory.ROM[0x0003D0] = 0x42; + Memory.ROM[0x0003D1] = 0x5B; + Memory.ROM[0x018522] = 0x42; + Memory.ROM[0x018523] = 0x5B; + Memory.ROM[0x02C804] = 0x42; + Memory.ROM[0x02C805] = 0xBA; + Memory.ROM[0x0683B5] = 0x42; + Memory.ROM[0x0683B6] = 0x5B; + Memory.ROM[0x0696AC] = 0x42; + Memory.ROM[0x0696AD] = 0xBA; + Memory.ROM[0x089233] = 0xDB; + Memory.ROM[0x089234] = 0x61; + Memory.ROM[0x0895DF] = 0x42; + Memory.ROM[0x0895E0] = 0x5B; + Memory.ROM[0x0A7A9D] = 0x42; + Memory.ROM[0x0A7A9E] = 0xBA; + Memory.ROM[0x1072E7] = 0x42; + Memory.ROM[0x1072E8] = 0xD9; + Memory.ROM[0x107355] = 0x42; + Memory.ROM[0x107356] = 0x5B; + Memory.ROM[0x1073CF] = 0x42; + Memory.ROM[0x1073D0] = 0x5B; + Memory.ROM[0x107443] = 0x42; + Memory.ROM[0x107444] = 0x5B; + Memory.ROM[0x107498] = 0x42; + Memory.ROM[0x107499] = 0x5B; + Memory.ROM[0x107505] = 0x42; + Memory.ROM[0x107506] = 0x5B; + Memory.ROM[0x107539] = 0x42; + Memory.ROM[0x10753A] = 0x5B; + Memory.ROM[0x107563] = 0x42; + Memory.ROM[0x107564] = 0x5B; + Memory.ROM[0x18041D] = 0x42; + Memory.ROM[0x18041E] = 0x79; } #endif hi_score = ScoreHiROM(true, 0); lo_score = ScoreLoROM(true, 0); - if (Memory.HeaderCount == 0 && !Settings.ForceNoHeader && - strncmp((char *) &Memory.ROM [0], "BANDAI SFC-ADX", 14) && - ((hi_score > lo_score && ScoreHiROM(true, 0) > hi_score) || - (hi_score <= lo_score && ScoreLoROM(true, 0) > lo_score))) + if (Memory.HeaderCount == 0 && !Settings.ForceNoHeader && strncmp((char *) &Memory.ROM [0], "BANDAI SFC-ADX", 14) && ((hi_score > lo_score && ScoreHiROM(true, 0) > hi_score) || (hi_score <= lo_score && ScoreLoROM(true, 0) > lo_score))) { #ifdef DS2_DMA __dcache_writeback_all(); @@ -694,11 +691,7 @@ again: //If both vectors are invalid, it's type 1 LoROM - if (Memory.ExtendedFormat == NOPE && - strncmp ((char *) &Memory.ROM [0], "BANDAI SFC-ADX", 14) && - ((Memory.ROM[0x7FFC] | (Memory.ROM[0x7FFD] << 8)) < 0x8000) && - ((Memory.ROM[0xFFFC] | (Memory.ROM[0xFFFD] << 8)) < 0x8000) && - !Settings.ForceInterleaved) + if(Memory.ExtendedFormat == NOPE && strncmp((char *) &Memory.ROM[0], "BANDAI SFC-ADX", 14) && ((Memory.ROM[0x7ffc] | (Memory.ROM[0x7ffd] << 8)) < 0x8000) && ((Memory.ROM[0xfffc] | (Memory.ROM[0xFffd] << 8)) < 0x8000) && !Settings.ForceInterleaved) S9xDeinterleaveType1(TotalFileSize, Memory.ROM); //CalculatedSize is now set, so rescore @@ -714,7 +707,6 @@ again: swappedhirom = ScoreHiROM(false, 0x400000); //set swapped here. - if (MAX(swappedlorom, swappedhirom) >= MAX(loromscore, hiromscore)) { Memory.ExtendedFormat = BIGFIRST; @@ -783,29 +775,24 @@ again: !Settings.ForceC4 && !Settings.ForceNoC4 && !Settings.ForceSDD1 && - !Settings.ForceNoSDD1 && - !Settings.ForceInterleaveGD24) + !Settings.ForceNoSDD1) { /* スーファミターボ BIOS読み込み */ - if ((strncmp((char*) &Memory.ROM [0], "BANDAI SFC-ADX", 14) == 0) && - !(strncmp((char*) &Memory.ROM [0x10], "SFC-ADX BACKUP", 14) == 0)) + if ((strncmp((char*) &Memory.ROM [0], "BANDAI SFC-ADX", 14) == 0) && !(strncmp((char*) &Memory.ROM [0x10], "SFC-ADX BACKUP", 14) == 0)) { Memory.LoROM = true; Memory.HiROM = false; Interleaved = false; Tales = false; } - else if (strncmp ((char *) &Memory.ROM [0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0 || - strncmp ((char *) &Memory.ROM [0x7fc0], "SP MOMOTAROU DENTETSU2", 22) == 0 || - strncmp ((char *) &Memory.ROM [0x7fc0], "SUPER FORMATION SOCCE", 21) == 0) + else if (strncmp ((char *) &Memory.ROM [0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0 || strncmp ((char *) &Memory.ROM [0x7fc0], "SP MOMOTAROU DENTETSU2", 22) == 0 || strncmp ((char *) &Memory.ROM [0x7fc0], "SUPER FORMATION SOCCE", 21) == 0) { Memory.LoROM = true; Memory.HiROM = false; Interleaved = false; } /* BS Zooっと麻雀 */ - else if ((strncmp ((char *) &Memory.ROM [0xffc0], "Zooっと麻雀!", 16) == 0)|| - (strncmp ((char *) &Memory.ROM [0xffc0], "Zooっと麻雀!IVT", 15) == 0)) + else if ((strncmp ((char *) &Memory.ROM [0xffc0], "Zooっと麻雀!", 16) == 0)|| (strncmp ((char *) &Memory.ROM [0xffc0], "Zooっと麻雀!IVT", 15) == 0)) { Memory.LoROM = false; Memory.HiROM = true; @@ -888,7 +875,7 @@ again: } else if (Settings.ForceInterleaved2) S9xDeinterleaveType2(false); - else if (Settings.ForceInterleaveGD24 && Memory.CalculatedSize == 0x300000) + else if (Memory.CalculatedSize == 0x300000) { bool t = Memory.LoROM; @@ -909,8 +896,7 @@ again: hi_score = ScoreHiROM(false, 0); lo_score = ScoreLoROM(false, 0); - if ((Memory.HiROM && (lo_score >= hi_score || hi_score < 0)) || - (Memory.LoROM && (hi_score > lo_score || lo_score < 0))) + if ((Memory.HiROM && (lo_score >= hi_score || hi_score < 0)) || (Memory.LoROM && (hi_score > lo_score || lo_score < 0))) { if (retry_count == 0) { @@ -955,8 +941,7 @@ void S9xDeinterleaveType2(bool reset) for (i = 0; i < nblocks * 2; i++) { - blocks [i] = (i & ~0xF) | ((i & 3) << 2) | - ((i & 12) >> 2); + blocks [i] = (i & ~0xF) | ((i & 3) << 2) | ((i & 12) >> 2); } #ifdef DS2_DMA @@ -979,28 +964,20 @@ void S9xDeinterleaveType2(bool reset) { uint8_t b; #ifdef DS2_DMA - ds2_DMAcopy_32Byte(2 /* channel: emu internal */, tmp, - &Memory.ROM [blocks [j] * 0x10000], 0x10000); + ds2_DMAcopy_32Byte(2 /* channel: emu internal */, tmp, &Memory.ROM [blocks [j] * 0x10000], 0x10000); ds2_DMA_wait(2); ds2_DMA_stop(2); - - ds2_DMAcopy_32Byte(2 /* channel: emu internal */, - &Memory.ROM [blocks [j] * 0x10000], - &Memory.ROM [blocks [i] * 0x10000], 0x10000); + ds2_DMAcopy_32Byte(2 /* channel: emu internal */, &Memory.ROM [blocks [j] * 0x10000], &Memory.ROM [blocks [i] * 0x10000], 0x10000); ds2_DMA_wait(2); ds2_DMA_stop(2); - - ds2_DMAcopy_32Byte(2 /* channel: emu internal */, - &Memory.ROM [blocks [i] * 0x10000], tmp, 0x10000); + ds2_DMAcopy_32Byte(2 /* channel: emu internal */, &Memory.ROM [blocks [i] * 0x10000], tmp, 0x10000); ds2_DMA_wait(2); ds2_DMA_stop(2); #else // memmove converted: Different mallocs [Neb] memcpy(tmp, &Memory.ROM [blocks [j] * 0x10000], 0x10000); - // memmove converted: Different addresses, or identical if blocks[i] == blocks[j] [Neb] - memcpy(&Memory.ROM [blocks [j] * 0x10000], - &Memory.ROM [blocks [i] * 0x10000], 0x10000); + memcpy(&Memory.ROM [blocks [j] * 0x10000], &Memory.ROM [blocks [i] * 0x10000], 0x10000); // memmove converted: Different mallocs [Neb] memcpy(&Memory.ROM [blocks [i] * 0x10000], tmp, 0x10000); #endif @@ -1079,8 +1056,7 @@ void InitROM(bool Interleaved) ParseSNESHeader(RomHeader); - //// Detect and initialize chips - //// detection codes are compatible with NSRT + //// Detect and initialize chips - detection codes are compatible with NSRT // DSP1/2/3/4 if (Memory.ROMType == 0x03) @@ -1161,8 +1137,7 @@ void InitROM(bool Interleaved) Settings.SuperFX = !Settings.ForceNoSuperFX; //OBC1 hack ROM - if (strncmp(Memory.ROMName, "METAL COMBAT", 12) == 0 && - Memory.ROMType == 0x13 && Memory.ROMSpeed == 0x42) + if (strncmp(Memory.ROMName, "METAL COMBAT", 12) == 0 && Memory.ROMType == 0x13 && Memory.ROMSpeed == 0x42) { Settings.OBC1 = true; Settings.SuperFX = Settings.ForceSuperFX; @@ -1176,7 +1151,6 @@ void InitROM(bool Interleaved) if (((Memory.ROMType & 0xF0) == 0xF0) & ((Memory.ROMSpeed & 0x0F) != 5)) { Memory.SRAMSize = 2; - SNESGameFixes.SRAMInitialValue = 0x00; if ((Memory.ROMType & 0x0F) == 6) { if (Memory.ROM[0x7FD7] == 0x09) @@ -1196,9 +1170,7 @@ void InitROM(bool Interleaved) Settings.SETA = ST_018; } Settings.C4 = Settings.ForceC4; - if ((Memory.ROMType & 0xf0) == 0xf0 && - (strncmp(Memory.ROMName, "MEGAMAN X", 9) == 0 || - strncmp(Memory.ROMName, "ROCKMAN X", 9) == 0)) + if ((Memory.ROMType & 0xf0) == 0xf0 && (strncmp(Memory.ROMName, "MEGAMAN X", 9) == 0 || strncmp(Memory.ROMName, "ROCKMAN X", 9) == 0)) Settings.C4 = !Settings.ForceNoC4; if (Settings.SETA && Settings.SETA != ST_018) @@ -1212,9 +1184,7 @@ void InitROM(bool Interleaved) Settings.C4 = false; Settings.SDD1 = false; } - else if (Settings.ForceSA1 || - (!Settings.ForceNoSA1 && (Memory.ROMSpeed & ~0x10) == 0x23 && - (Memory.ROMType & 0xf) > 3 && (Memory.ROMType & 0xf0) == 0x30)) + else if (Settings.ForceSA1 || (!Settings.ForceNoSA1 && (Memory.ROMSpeed & ~0x10) == 0x23 && (Memory.ROMType & 0xf) > 3 && (Memory.ROMType & 0xf0) == 0x30)) { Settings.SA1 = true; Settings.DSP1Master = false; @@ -1226,14 +1196,12 @@ void InitROM(bool Interleaved) TalesROMMap(Interleaved); else if (Memory.ExtendedFormat != NOPE) JumboLoROMMap(Interleaved); - else if (strncmp((char*) &Memory.ROM [0x7fc0], "SOUND NOVEL-TCOOL", 17) == 0 || - strncmp((char*) &Memory.ROM [0x7fc0], "DERBY STALLION 96", 17) == 0) + else if (strncmp((char*) &Memory.ROM [0x7fc0], "SOUND NOVEL-TCOOL", 17) == 0 || strncmp((char*) &Memory.ROM [0x7fc0], "DERBY STALLION 96", 17) == 0) { LoROM24MBSMap(); Settings.DSP1Master = false; } - else if (strncmp((char*) &Memory.ROM [0x7fc0], "THOROUGHBRED BREEDER3", 21) == 0 || - strncmp((char*) &Memory.ROM [0x7fc0], "RPG-TCOOL 2", 11) == 0) + else if (strncmp((char*) &Memory.ROM [0x7fc0], "THOROUGHBRED BREEDER3", 21) == 0 || strncmp((char*) &Memory.ROM [0x7fc0], "RPG-TCOOL 2", 11) == 0) { SRAM512KLoROMMap(); Settings.DSP1Master = false; @@ -1253,13 +1221,9 @@ void InitROM(bool Interleaved) Memory.SRAMSize = 5; SufamiTurboLoROMMap(); } - else if ((strncmp((char *) &Memory.ROM [0x7fc0], "ROCKMAN X ", 11) == 0)|| - (strncmp((char *) &Memory.ROM [0x7fc0], "MEGAMAN X ", 11) == 0)|| - (strncmp((char *) &Memory.ROM [0x7fc0], "demon's blazon", 14) == 0)|| - (strncmp((char *) &Memory.ROM [0x7fc0], "demon's crest", 13) == 0)) + else if ((strncmp((char *) &Memory.ROM [0x7fc0], "ROCKMAN X ", 11) == 0)|| (strncmp((char *) &Memory.ROM [0x7fc0], "MEGAMAN X ", 11) == 0)|| (strncmp((char *) &Memory.ROM [0x7fc0], "demon's blazon", 14) == 0)|| (strncmp((char *) &Memory.ROM [0x7fc0], "demon's crest", 13) == 0)) CapcomProtectLoROMMap(); - else if ((Memory.ROMSpeed & ~0x10) == 0x22 && - strncmp(Memory.ROMName, "Super Street Fighter", 20) != 0) + else if ((Memory.ROMSpeed & ~0x10) == 0x22 && strncmp(Memory.ROMName, "Super Street Fighter", 20) != 0) AlphaROMMap(); else if (strncmp ((char *) &Memory.ROM [0x7fc0], "HITOMI3", 7) == 0) { @@ -1275,7 +1239,7 @@ void InitROM(bool Interleaved) uint32_t sum1 = 0; uint32_t sum2 = 0; - if (0 == Memory.CalculatedChecksum) + if (!Memory.CalculatedChecksum) { int32_t power2 = 0; int32_t size = Memory.CalculatedSize; @@ -1358,7 +1322,7 @@ void InitROM(bool Interleaved) #ifndef USE_BLARGG_APU IAPU.OneCycle = ONE_APU_CYCLE; #endif - Settings.Shutdown = Settings.ShutdownMaster; + Settings.Shutdown = true; ResetSpeedMap(); ApplyROMFixes(); sprintf(Memory.ROMName, "%s", Safe(Memory.ROMName)); @@ -1367,22 +1331,9 @@ void InitROM(bool Interleaved) fprintf(stderr, "\"%s\" [%s] %s, %s, Type: %s, Mode: %s, TV: %s, S-RAM: %s, ROMId: %s Company: %2.2s\n", - Memory.ROMName, - (Memory.ROMChecksum + Memory.ROMComplementChecksum != 0xffff || - Memory.ROMChecksum != Memory.CalculatedChecksum) ? "bad checksum" : "checksum ok", - MapType(), - Size(), - KartContents(), - MapMode(), - TVStandard(), - StaticRAMSize(), - Memory.ROMId, - Memory.CompanyId); - - Settings.ForceHeader = Settings.ForceHiROM = Settings.ForceLoROM = - Settings.ForceInterleaved = Settings.ForceNoHeader = - Settings.ForceNotInterleaved = - Settings.ForceInterleaved2 = false; + Memory.ROMName, (Memory.ROMChecksum + Memory.ROMComplementChecksum != 0xffff || Memory.ROMChecksum != Memory.CalculatedChecksum) ? "bad checksum" : "checksum ok", MapType(), Size(), KartContents(), MapMode(), TVStandard(), StaticRAMSize(), Memory.ROMId, Memory.CompanyId); + + Settings.ForceHeader = Settings.ForceHiROM = Settings.ForceLoROM = Settings.ForceInterleaved = Settings.ForceNoHeader = Settings.ForceNotInterleaved = Settings.ForceInterleaved2 = false; } void FixROMSpeed(void) @@ -1693,8 +1644,7 @@ void SetaDSPMap(void) { for (i = 0; i < 0x08; i++) { - //where does the SETA chip access, anyway? - //please confirm this? + // Where does the SETA chip access, anyway? Please confirm this. Memory.Map[c + 0x80 + i] = (uint8_t*)MAP_SETA_DSP; Memory.BlockIsROM [c + 0x80 + i] = false; Memory.BlockIsRAM [c + 0x80 + i] = true; @@ -1804,14 +1754,12 @@ void TalesROMMap(bool Interleaved) { Memory.Map [c + 6] = Memory.Map [c + 0x806] = MAP_HIROM_SRAM_OR_NONE; Memory.Map [c + 7] = Memory.Map [c + 0x807] = MAP_HIROM_SRAM_OR_NONE; - Memory.BlockIsRAM [6 + c] = Memory.BlockIsRAM [7 + c] = - Memory.BlockIsRAM [0x806 + c] = Memory.BlockIsRAM [0x807 + c] = true; + Memory.BlockIsRAM [6 + c] = Memory.BlockIsRAM [7 + c] = Memory.BlockIsRAM [0x806 + c] = Memory.BlockIsRAM [0x807 + c] = true; } else { Memory.Map [c + 6] = Memory.Map [c + 0x806] = (uint8_t*) MAP_NONE; Memory.Map [c + 7] = Memory.Map [c + 0x807] = (uint8_t*) MAP_NONE; - } for (i = c + 8; i < c + 16; i++) { @@ -1854,7 +1802,6 @@ void TalesROMMap(bool Interleaved) } Memory.CalculatedChecksum = sum & 0xFFFF; - MapRAM(); WriteProtectROM(); } @@ -1979,10 +1926,8 @@ void SuperFXROMMap(void) for (c = 0; c < 64; c++) { #ifdef DS2_DMA - ds2_DMAcopy_32Byte(2 /* channel: emu internal */, &ROM [0x200000 + c * 0x10000], - &ROM [c * 0x8000], 0x8000); - ds2_DMAcopy_32Byte(3 /* channel: emu internal 2 */, - &ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); + ds2_DMAcopy_32Byte(2 /* channel: emu internal */, &ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); + ds2_DMAcopy_32Byte(3 /* channel: emu internal 2 */, &ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); ds2_DMA_wait(2); ds2_DMA_wait(3); ds2_DMA_stop(2); @@ -2407,7 +2352,6 @@ void JumboLoROMMap(bool Interleaved) sum += bank[l]; } Memory.CalculatedChecksum = sum & 0xFFFF; - MapRAM(); WriteProtectROM(); } @@ -2726,38 +2670,15 @@ void ApplyROMFixes(void) #endif //Specific game fixes - - Settings.StarfoxHack = match_na("STAR FOX") || - match_na("STAR WING"); - Settings.WinterGold = match_na("FX SKIING NINTENDO 96") || - match_na("DIRT RACER") || - Settings.StarfoxHack; - - if((match_na("LEGEND") && !Settings.PAL)|| - match_na("King Arthurs World")) - SNESGameFixes.EchoOnlyOutput = true; - + Settings.StarfoxHack = match_na("STAR FOX") || match_na("STAR WING"); + Settings.WinterGold = match_na("FX SKIING NINTENDO 96") || match_na("DIRT RACER") || Settings.StarfoxHack; Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX; - //OAM hacks because we don't fully understand the - //behavior of the SNES. - - if (match_na("\xBD\xB0\xCA\xDF\xB0\xCC\xA7\xD0\xBD\xC0") || //Super Famista - match_na("\xBD\xB0\xCA\xDF\xB0\xCC\xA7\xD0\xBD\xC0 2") || //Super Famista 2 - match_na("ZENKI TENCHIMEIDOU") || - match_na("GANBA LEAGUE")) - SNESGameFixes.APU_OutPorts_ReturnValueFix = true; - else if (match_na("FURAI NO SIREN")) - SNESGameFixes.SoundEnvelopeHeightReading2 = true; - //CPU timing hacks Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * Settings.CyclesPercentage) / 100; // A Couple of HDMA related hacks - Lantus - if ((match_na("SFX SUPERBUTOUDEN2")) || - (match_na("ALIEN vs. PREDATOR")) || - (match_na("STONE PROTECTORS")) || - (match_na("SUPER BATTLETANK 2"))) + if ((match_na("SFX SUPERBUTOUDEN2")) || (match_na("ALIEN vs. PREDATOR")) || (match_na("STONE PROTECTORS")) || (match_na("SUPER BATTLETANK 2"))) Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 130) / 100; else if (match_na("HOME IMPROVEMENT")) Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 200) / 100; @@ -2775,10 +2696,7 @@ void ApplyROMFixes(void) else if (match_na("\x0bd\x0da\x0b2\x0d4\x0b0\x0bd\x0de") && Settings.CyclesPercentage == 100) Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 101) / 100; - else if (match_na("WILD TRAX") || - match_na("STAR FOX 2") || - match_na("YOSSY'S ISLAND") || - match_na("YOSHI'S ISLAND")) + else if (match_na("WILD TRAX") || match_na("STAR FOX 2") || match_na("YOSSY'S ISLAND") || match_na("YOSHI'S ISLAND")) CPU.TriedInterleavedMode2 = true; // Start Trek: Deep Sleep 9 else if (strncmp(Memory.ROMId, "A9D", 3) == 0 && Settings.CyclesPercentage == 100) @@ -2968,15 +2886,8 @@ void ApplyROMFixes(void) bytes0x2000 [0xb18] = 0x4c; bytes0x2000 [0xb19] = 0x4b; bytes0x2000 [0xb1a] = 0xea; - SNESGameFixes.SRAMInitialValue = 0x6b; } - //sram value fixes - if (match_na("SUPER DRIFT OUT") || - match_na("SATAN IS OUR FATHER!") || - match_na("goemon 4")) - SNESGameFixes.SRAMInitialValue = 0x00; - if(Settings.BS && Memory.LoROM && match_na("F-ZERO") && Memory.ROMChecksum == 0xb10d && @@ -3009,7 +2920,7 @@ static bool is_bsx(uint8_t *p) // p == "0xFFC0" or "0x7FC0" ROM offset pointer // Maker ID c = p[0x1a]; - if ((c != 0x33) && (c != 0xff)) // 0x33 = Manufacturer: Nintendo + if ((c != 0x33) && (c != 0xff)) // 0x33 = Manufacturer: Nintendo return false; // Month, Day @@ -3068,16 +2979,12 @@ static bool bs_name(uint8_t* p) return false; } //SJIS single byte char - else if((*p >= 0x20 && *p <= 0x7f) || - (*p >= 0xa0 && *p <= 0xdf)) + else if((*p >= 0x20 && *p <= 0x7f) || (*p >= 0xa0 && *p <= 0xdf)) p++; //SJIS multi byte char else if(lcount >= 2) { - if(((*p >= 0x81 && *p <= 0x9f) || - (*p >= 0xe0 && *p <= 0xfc)) && - ((*(p + 1) >= 0x40 && *(p + 1) <= 0x7e) || - (*(p + 1) >= 0x80 && *(p + 1) <= 0xfc))) + if(((*p >= 0x81 && *p <= 0x9f) || (*p >= 0xe0 && *p <= 0xfc)) && ((*(p + 1) >= 0x40 && *(p + 1) <= 0x7e) || (*(p + 1) >= 0x80 && *(p + 1) <= 0xfc))) { p += 2; lcount--; diff --git a/source/memmap.h b/source/memmap.h index e60cb52..157f4f3 100644 --- a/source/memmap.h +++ b/source/memmap.h @@ -88,7 +88,8 @@ enum MAP_RONLY_SRAM, MAP_OBC_RAM, MAP_SETA_DSP, MAP_SETA_RISC, MAP_LAST }; -enum { +enum +{ MAX_ROM_SIZE = 0x800000 }; @@ -149,5 +150,4 @@ uint8_t* S9xGetMemPointer(uint32_t Address); uint8_t* GetBasePointer(uint32_t Address); extern uint8_t OpenBus; - #endif // _memmap_h_ diff --git a/source/obc1.c b/source/obc1.c index 4263284..3ff2f24 100644 --- a/source/obc1.c +++ b/source/obc1.c @@ -86,6 +86,5 @@ void ResetOBC1() OBC1_BasePtr = 0x1c00; OBC1_Shift = 0; OBC1_RAM = &Memory.FillRAM[0x6000]; - memset(OBC1_RAM, 0x00, 0x2000); } diff --git a/source/obc1.h b/source/obc1.h index e781f5b..3d388f8 100644 --- a/source/obc1.h +++ b/source/obc1.h @@ -6,6 +6,5 @@ uint8_t GetOBC1(uint16_t Address); void SetOBC1(uint8_t Byte, uint16_t Address); uint8_t* GetMemPointerOBC1(uint32_t Address); -void ResetOBC1(); - +void ResetOBC1(void); #endif diff --git a/source/port.h b/source/port.h index 3d96509..dfd08f1 100644 --- a/source/port.h +++ b/source/port.h @@ -54,8 +54,7 @@ void _splitpath(const char* path, char* drive, char* dir, char* fname, char* ext #define SLASH_STR "/" #define SLASH_CHAR '/' -#if defined(__i386__) || defined(__i486__) || defined(__i586__) || \ - defined(__WIN32__) || defined(__alpha__) +#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__WIN32__) || defined(__alpha__) #define FAST_LSB_WORD_ACCESS #elif defined(__MIPSEL__) // On little-endian MIPS, a 16-bit word can be read directly from an address @@ -88,12 +87,12 @@ static INLINE int32_t _isqrt(int32_t val) remainder -= (squaredbit | root); root >>= 1; root |= squaredbit; - } else + } + else root >>= 1; squaredbit >>= 2; } return root; } - #endif diff --git a/source/ppu.c b/source/ppu.c index 167610d..4ef83ad 100644 --- a/source/ppu.c +++ b/source/ppu.c @@ -40,8 +40,7 @@ void S9xUpdateHTimer() if (PPU.HTimerEnabled) { PPU.HTimerPosition = PPU.IRQHBeamPos * Settings.H_Max / SNES_HCOUNTER_MAX; - if (PPU.HTimerPosition == Settings.H_Max || - PPU.HTimerPosition == Settings.HBlankStart) + if (PPU.HTimerPosition == Settings.H_Max || PPU.HTimerPosition == Settings.HBlankStart) PPU.HTimerPosition--; if (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos) @@ -49,8 +48,7 @@ void S9xUpdateHTimer() if (PPU.HTimerPosition < CPU.Cycles) { // Missed the IRQ on this line already - if (CPU.WhichEvent == HBLANK_END_EVENT || - CPU.WhichEvent == HTIMER_AFTER_EVENT) + if (CPU.WhichEvent == HBLANK_END_EVENT || CPU.WhichEvent == HTIMER_AFTER_EVENT) { CPU.WhichEvent = HBLANK_END_EVENT; CPU.NextEvent = Settings.H_Max; @@ -63,13 +61,11 @@ void S9xUpdateHTimer() } else { - if (CPU.WhichEvent == HTIMER_BEFORE_EVENT || - CPU.WhichEvent == HBLANK_START_EVENT) + if (CPU.WhichEvent == HTIMER_BEFORE_EVENT || CPU.WhichEvent == HBLANK_START_EVENT) { if (PPU.HTimerPosition > Settings.HBlankStart) { - // HTimer was to trigger before h-blank start, - // now triggers after start of h-blank + // HTimer was to trigger before h-blank start, now triggers after start of h-blank CPU.NextEvent = Settings.HBlankStart; CPU.WhichEvent = HBLANK_START_EVENT; } @@ -117,21 +113,12 @@ static void S9xSetSuperFX(uint8_t Byte, uint16_t Address) if ((old_fill_ram ^ Byte) & FLG_G) { Memory.FillRAM [Address] = Byte; - // Go flag has been changed - if (Byte & FLG_G) + if (Byte & FLG_G) // Go flag has been changed S9xSuperFXExec(); else FxFlushCache(); } break; - case 0x3031: - case 0x3033: - case 0x3037: - case 0x3039: - case 0x303a: - case 0x303b: - case 0x303f: - break; case 0x3034: case 0x3036: Memory.FillRAM [Address] &= 0x7f; @@ -147,8 +134,6 @@ static void S9xSetSuperFX(uint8_t Byte, uint16_t Address) S9xSuperFXExec(); break; default: - if (Address >= 0x3100) - FxCacheWriteAccess(Address); break; } } @@ -163,8 +148,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) { switch (Address) { - case 0x2100: - // Brightness and screen blank bit + case 0x2100: // Brightness and screen blank bit if (Byte != Memory.FillRAM [0x2100]) { FLUSH_REDRAW(); @@ -182,8 +166,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) } } break; - case 0x2101: - // Sprite (OBJ) tile address + case 0x2101: // Sprite (OBJ) tile address if (Byte != Memory.FillRAM [0x2101]) { FLUSH_REDRAW(); @@ -193,8 +176,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) IPPU.OBJChanged = true; } break; - case 0x2102: - // Sprite write address (low) + case 0x2102: // Sprite write address (low) PPU.OAMAddr = ((Memory.FillRAM[0x2103] & 1) << 8) | Byte; PPU.OAMFlip = 2; PPU.SavedOAMAddr = PPU.OAMAddr; @@ -204,9 +186,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) IPPU.OBJChanged = true; } break; - case 0x2103: - // Sprite register write address (high), sprite priority rotation - // bit. + case 0x2103: // Sprite register write address (high), sprite priority rotation bit. PPU.OAMAddr = ((Byte & 1) << 8) | Memory.FillRAM[0x2102]; PPU.OAMPriorityRotation = (Byte & 0x80) ? 1 : 0; @@ -229,13 +209,10 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.OAMFlip = 0; PPU.SavedOAMAddr = PPU.OAMAddr; break; - case 0x2104: - // Sprite register write + case 0x2104: // Sprite register write REGISTER_2104(Byte); break; - case 0x2105: - // Screen mode (0 - 7), background tile sizes and background 3 - // priority + case 0x2105: // Screen mode (0 - 7), background tile sizes and background 3 priority if (Byte != Memory.FillRAM [0x2105]) { FLUSH_REDRAW(); @@ -250,8 +227,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) IPPU.Interlace = (bool) (Memory.FillRAM[0x2133] & 1); } break; - case 0x2106: - // Mosaic pixel size and enable + case 0x2106: // Mosaic pixel size and enable if (Byte != Memory.FillRAM [0x2106]) { FLUSH_REDRAW(); @@ -262,10 +238,10 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.BGMosaic [3] = (Byte & 8) && PPU.Mosaic > 1; } break; - case 0x2107: // [BG0SC] - case 0x2108: // [BG1SC] - case 0x2109: // [BG2SC] - case 0x210A: // [BG3SC] + case 0x2107: // [BG0SC] + case 0x2108: // [BG1SC] + case 0x2109: // [BG2SC] + case 0x210A: // [BG3SC] if (Byte != Memory.FillRAM [Address]) { FLUSH_REDRAW(); @@ -273,7 +249,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.BG[Address - 0x2107].SCBase = (Byte & 0x7c) << 8; } break; - case 0x210B: // [BG01NBA] + case 0x210B: // [BG01NBA] if (Byte != Memory.FillRAM [0x210b]) { FLUSH_REDRAW(); @@ -281,7 +257,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.BG[1].NameBase = ((Byte >> 4) & 7) << 12; } break; - case 0x210C: // [BG23NBA] + case 0x210C: // [BG23NBA] if (Byte != Memory.FillRAM [0x210c]) { FLUSH_REDRAW(); @@ -321,8 +297,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.BG[3].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; PPU.BGnxOFSbyte = Byte; break; - case 0x2115: - // VRAM byte/word access flag and increment + case 0x2115: // VRAM byte/word access flag and increment PPU.VMA.High = (bool) (Byte & 0x80); switch (Byte & 3) { @@ -349,14 +324,12 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) else PPU.VMA.FullGraphicCount = 0; break; - case 0x2116: - // VRAM read/write address (low) + case 0x2116: // VRAM read/write address (low) PPU.VMA.Address &= 0xFF00; PPU.VMA.Address |= Byte; IPPU.FirstVRAMRead = true; break; - case 0x2117: - // VRAM read/write address (high) + case 0x2117: // VRAM read/write address (high) PPU.VMA.Address &= 0x00FF; PPU.VMA.Address |= Byte << 8; IPPU.FirstVRAMRead = true; @@ -366,13 +339,11 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) IPPU.FirstVRAMRead = true; REGISTER_2118(Byte); break; - case 0x2119: - // VRAM write data (high) + case 0x2119: // VRAM write data (high) IPPU.FirstVRAMRead = true; REGISTER_2119(Byte); break; - case 0x211a: - // Mode 7 outside rotation area display mode and flipping + case 0x211a: // Mode 7 outside rotation area display mode and flipping if (Byte != Memory.FillRAM [0x211a]) { FLUSH_REDRAW(); @@ -383,34 +354,27 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.Mode7HFlip = (bool) (Byte & 1); } break; - case 0x211b: - // Mode 7 matrix A (low & high) + case 0x211b: // Mode 7 matrix A (low & high) PPU.MatrixA = ((PPU.MatrixA >> 8) & 0xff) | (Byte << 8); PPU.Need16x8Multiply = true; break; - case 0x211c: - // Mode 7 matrix B (low & high) + case 0x211c: // Mode 7 matrix B (low & high) PPU.MatrixB = ((PPU.MatrixB >> 8) & 0xff) | (Byte << 8); PPU.Need16x8Multiply = true; break; - case 0x211d: - // Mode 7 matrix C (low & high) + case 0x211d: // Mode 7 matrix C (low & high) PPU.MatrixC = ((PPU.MatrixC >> 8) & 0xff) | (Byte << 8); break; - case 0x211e: - // Mode 7 matrix D (low & high) + case 0x211e: // Mode 7 matrix D (low & high) PPU.MatrixD = ((PPU.MatrixD >> 8) & 0xff) | (Byte << 8); break; - case 0x211f: - // Mode 7 centre of rotation X (low & high) + case 0x211f: // Mode 7 centre of rotation X (low & high) PPU.CentreX = ((PPU.CentreX >> 8) & 0xff) | (Byte << 8); break; - case 0x2120: - // Mode 7 centre of rotation Y (low & high) + case 0x2120: // Mode 7 centre of rotation Y (low & high) PPU.CentreY = ((PPU.CentreY >> 8) & 0xff) | (Byte << 8); break; - case 0x2121: - // CG-RAM address + case 0x2121: // CG-RAM address PPU.CGFLIP = false; PPU.CGFLIPRead = false; PPU.CGADD = Byte; @@ -418,8 +382,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) case 0x2122: REGISTER_2122(Byte); break; - case 0x2123: - // Window 1 and 2 enable for backgrounds 1 and 2 + case 0x2123: // Window 1 and 2 enable for backgrounds 1 and 2 if (Byte != Memory.FillRAM [0x2123]) { FLUSH_REDRAW(); @@ -434,8 +397,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.RecomputeClipWindows = true; } break; - case 0x2124: - // Window 1 and 2 enable for backgrounds 3 and 4 + case 0x2124: // Window 1 and 2 enable for backgrounds 3 and 4 if (Byte != Memory.FillRAM [0x2124]) { FLUSH_REDRAW(); @@ -450,8 +412,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.RecomputeClipWindows = true; } break; - case 0x2125: - // Window 1 and 2 enable for objects and colour window + case 0x2125: // Window 1 and 2 enable for objects and colour window if (Byte != Memory.FillRAM [0x2125]) { FLUSH_REDRAW(); @@ -466,8 +427,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.RecomputeClipWindows = true; } break; - case 0x2126: - // Window 1 left position + case 0x2126: // Window 1 left position if (Byte != Memory.FillRAM [0x2126]) { FLUSH_REDRAW(); @@ -475,8 +435,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.RecomputeClipWindows = true; } break; - case 0x2127: - // Window 1 right position + case 0x2127: // Window 1 right position if (Byte != Memory.FillRAM [0x2127]) { FLUSH_REDRAW(); @@ -484,8 +443,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.RecomputeClipWindows = true; } break; - case 0x2128: - // Window 2 left position + case 0x2128: // Window 2 left position if (Byte != Memory.FillRAM [0x2128]) { FLUSH_REDRAW(); @@ -493,8 +451,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.RecomputeClipWindows = true; } break; - case 0x2129: - // Window 2 right position + case 0x2129: // Window 2 right position if (Byte != Memory.FillRAM [0x2129]) { FLUSH_REDRAW(); @@ -502,8 +459,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.RecomputeClipWindows = true; } break; - case 0x212a: - // Windows 1 & 2 overlap logic for backgrounds 1 - 4 + case 0x212a: // Windows 1 & 2 overlap logic for backgrounds 1 - 4 if (Byte != Memory.FillRAM [0x212a]) { FLUSH_REDRAW(); @@ -514,8 +470,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.RecomputeClipWindows = true; } break; - case 0x212b: - // Windows 1 & 2 overlap logic for objects and colour window + case 0x212b: // Windows 1 & 2 overlap logic for objects and colour window if (Byte != Memory.FillRAM [0x212b]) { FLUSH_REDRAW(); @@ -524,8 +479,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.RecomputeClipWindows = true; } break; - case 0x212c: - // Main screen designation (backgrounds 1 - 4 and objects) + case 0x212c: // Main screen designation (backgrounds 1 - 4 and objects) if (Byte != Memory.FillRAM [0x212c]) { FLUSH_REDRAW(); @@ -534,8 +488,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) return; } break; - case 0x212d: - // Sub-screen designation (backgrounds 1 - 4 and objects) + case 0x212d: // Sub-screen designation (backgrounds 1 - 4 and objects) if (Byte != Memory.FillRAM [0x212d]) { FLUSH_REDRAW(); @@ -574,8 +527,7 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) PPU.FixedColourRed = Byte & 0x1f; } break; - case 0x2133: - // Screen settings + case 0x2133: // Screen settings if (Byte != Memory.FillRAM [0x2133]) { if (Byte & 0x04) @@ -601,31 +553,16 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) break; case 0x2134: case 0x2135: - case 0x2136: - // Matrix 16bit x 8bit multiply result (read-only) - /* fall through */ - case 0x2137: - // Software latch for horizontal and vertical timers (read-only) - /* fall through */ - case 0x2138: - // OAM read data (read-only) - /* fall through */ + case 0x2136: // Matrix 16bit x 8bit multiply result (read-only) + case 0x2137: // Software latch for horizontal and vertical timers (read-only) + case 0x2138: // OAM read data (read-only) case 0x2139: - case 0x213a: - // VRAM read data (read-only) - /* fall through */ - case 0x213b: - // CG-RAM read data (read-only) - /* fall through */ + case 0x213a: // VRAM read data (read-only) + case 0x213b: // CG-RAM read data (read-only) case 0x213c: - case 0x213d: - // Horizontal and vertical (low/high) read counter (read-only) - /* fall through */ - case 0x213e: - // PPU status (time over and range over) - /* fall through */ - case 0x213f: - // NTSC/PAL select and field (read-only) + case 0x213d: // Horizontal and vertical (low/high) read counter (read-only) + case 0x213e: // PPU status (time over and range over) + case 0x213f: // NTSC/PAL select and field (read-only) return; case 0x2140: case 0x2141: @@ -728,15 +665,13 @@ void S9xSetPPU(uint8_t Byte, uint16_t Address) Memory.FillRAM [Address] = Byte; return; } - else - // Dai Kaijyu Monogatari II - if (Address == 0x2801 && Settings.SRTC) - S9xSetSRTC(Byte, Address); - else if (Address >= 0x3000 && Address < 0x3300) - { - S9xSetSuperFX(Byte, Address); - return; - } + else if (Address == 0x2801 && Settings.SRTC) // Dai Kaijyu Monogatari II + S9xSetSRTC(Byte, Address); + else if (Address >= 0x3000 && Address < 0x3300) + { + S9xSetSuperFX(Byte, Address); + return; + } } Memory.FillRAM[Address] = Byte; } @@ -775,8 +710,7 @@ uint8_t S9xGetPPU(uint16_t Address) return PPU.OpenBus1; case 0x2134: case 0x2135: - case 0x2136: - // 16bit x 8bit multiply read result. + case 0x2136: // 16bit x 8bit multiply read result. if (PPU.Need16x8Multiply) { int32_t r = (int32_t) PPU.MatrixA * (int32_t)(PPU.MatrixB >> 8); @@ -785,12 +719,11 @@ uint8_t S9xGetPPU(uint16_t Address) Memory.FillRAM[0x2136] = (uint8_t)(r >> 16); PPU.Need16x8Multiply = false; } - return (PPU.OpenBus1 = Memory.FillRAM[Address]); + return PPU.OpenBus1 = Memory.FillRAM[Address]; case 0x2137: S9xLatchCounters(0); return OpenBus; - case 0x2138: - // Read OAM (sprite) control data + case 0x2138: // Read OAM (sprite) control data if (PPU.OAMAddr & 0x100) { if (!(PPU.OAMFlip & 1)) @@ -823,17 +756,14 @@ uint8_t S9xGetPPU(uint16_t Address) } PPU.OAMFlip ^= 1; return (PPU.OpenBus1 = byte); - case 0x2139: - // Read vram low byte + case 0x2139: // Read vram low byte if (IPPU.FirstVRAMRead) byte = Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]; else if (PPU.VMA.FullGraphicCount) { uint32_t addr = PPU.VMA.Address - 1; uint32_t rem = addr & PPU.VMA.Mask1; - uint32_t address = (addr & ~PPU.VMA.Mask1) + - (rem >> PPU.VMA.Shift) + - ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); byte = Memory.VRAM [((address << 1) - 2) & 0xffff]; } else @@ -845,17 +775,14 @@ uint8_t S9xGetPPU(uint16_t Address) IPPU.FirstVRAMRead = false; } return (PPU.OpenBus1 = byte); - case 0x213A: - // Read vram high byte + case 0x213A: // Read vram high byte if (IPPU.FirstVRAMRead) byte = Memory.VRAM[((PPU.VMA.Address << 1) + 1) & 0xffff]; else if (PPU.VMA.FullGraphicCount) { uint32_t addr = PPU.VMA.Address - 1; uint32_t rem = addr & PPU.VMA.Mask1; - uint32_t address = (addr & ~PPU.VMA.Mask1) + - (rem >> PPU.VMA.Shift) + - ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); byte = Memory.VRAM [((address << 1) - 1) & 0xffff]; } else @@ -866,8 +793,7 @@ uint8_t S9xGetPPU(uint16_t Address) IPPU.FirstVRAMRead = false; } return (PPU.OpenBus1 = byte); - case 0x213B: - // Read palette data + case 0x213B: // Read palette data if (PPU.CGFLIPRead) byte = (PPU.OpenBus2 & 0x80) | ((PPU.CGDATA[PPU.CGADD++] >> 8) & 0x7f); else @@ -875,29 +801,25 @@ uint8_t S9xGetPPU(uint16_t Address) PPU.CGFLIPRead = !PPU.CGFLIPRead; return (PPU.OpenBus2 = byte); - case 0x213C: - // Horizontal counter value 0-339 + case 0x213C: // Horizontal counter value 0-339 if (PPU.HBeamFlip) byte = (PPU.OpenBus2 & 0xfe) | ((PPU.HBeamPosLatched >> 8) & 0x01); else byte = (uint8_t)PPU.HBeamPosLatched; PPU.HBeamFlip ^= 1; return (PPU.OpenBus2 = byte); - case 0x213D: - // Vertical counter value 0-262 + case 0x213D: // Vertical counter value 0-262 if (PPU.VBeamFlip) byte = (PPU.OpenBus2 & 0xfe) | ((PPU.VBeamPosLatched >> 8) & 0x01); else byte = (uint8_t)PPU.VBeamPosLatched; PPU.VBeamFlip ^= 1; return (PPU.OpenBus2 = byte); - case 0x213E: - // PPU time and range over flags + case 0x213E: // PPU time and range over flags FLUSH_REDRAW(); byte = (PPU.OpenBus1 & 0x10) | PPU.RangeTimeOver | Model->_5C77; return (PPU.OpenBus1 = byte); - case 0x213F: - // NTSC/PAL and which field flags + case 0x213F: // NTSC/PAL and which field flags PPU.VBeamFlip = PPU.HBeamFlip = 0; byte = (PPU.OpenBus2 & 0x20) | (Memory.FillRAM[0x213f] & 0xc0) | (Settings.PAL ? 0x10 : 0) | Model->_5C78; Memory.FillRAM[0x213f] &= ~0x40; @@ -971,13 +893,7 @@ uint8_t S9xGetPPU(uint16_t Address) IAPU.WaitCounter++; if (Settings.APUEnabled) - { - if (SNESGameFixes.APU_OutPorts_ReturnValueFix && - Address >= 0x2140 && Address <= 0x2143 && !CPU.V_Counter) - return (uint8_t)((Address & 1) ? ((rand() & 0xff00) >> 8) : (rand() & 0xff)); - - return (APU.OutPorts [Address & 3]); - } + return APU.OutPorts [Address & 3]; CPU.BranchSkip = true; @@ -987,23 +903,22 @@ uint8_t S9xGetPPU(uint16_t Address) if (r & 2) { if (r & 4) - return ((Address & 3) == 1 ? 0xaa : 0xbb); + return (Address & 3) == 1 ? 0xaa : 0xbb; else - return ((r >> 3) & 0xff); + return (r >> 3) & 0xff; } } else { int32_t r = rand(); if (r & 2) - return ((r >> 3) & 0xff); + return (r >> 3) & 0xff; } - return (Memory.FillRAM[Address]); + return Memory.FillRAM[Address]; #else - return (S9xAPUReadPort(Address & 3)); + return S9xAPUReadPort(Address & 3); #endif //#ifndef USE_BLARGG_APU - case 0x2180: - // Read WRAM + case 0x2180: // Read WRAM byte = Memory.RAM [PPU.WRAM++]; PPU.WRAM &= 0x1FFFF; return byte; @@ -1024,11 +939,11 @@ uint8_t S9xGetPPU(uint16_t Address) { case 0x21c2: if (Model->_5C77 == 2) - return (0x20); + return 0x20; return OpenBus; case 0x21c3: if (Model->_5C77 == 2) - return (0); + return 0; return OpenBus; default: return OpenBus; @@ -1065,8 +980,7 @@ void S9xSetCPU(uint8_t byte, uint16_t Address) CPU.Cycles += ONE_CYCLE; switch (Address) { - case 0x4016: - // S9xReset reading of old-style joypads + case 0x4016: // S9xReset reading of old-style joypads if ((byte & 1) && !(Memory.FillRAM [Address] & 1)) { PPU.Joypad1ButtonReadPos = 0; @@ -1083,8 +997,7 @@ void S9xSetCPU(uint8_t byte, uint16_t Address) else switch (Address) { - case 0x4200: - // NMI, V & H IRQ and joypad reading enable flags + case 0x4200: // NMI, V & H IRQ and joypad reading enable flags if (byte & 0x20) { if (!PPU.VTimerEnabled) @@ -1097,9 +1010,7 @@ void S9xSetCPU(uint8_t byte, uint16_t Address) } } else - { PPU.VTimerEnabled = false; - } if (byte & 0x10) { @@ -1139,12 +1050,10 @@ void S9xSetCPU(uint8_t byte, uint16_t Address) S9xLatchCounters(1); Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = byte; break; - case 0x4202: - // Multiplier (for multiply) + case 0x4202: // Multiplier (for multiply) break; - case 0x4203: + case 0x4203: // Multiplicand { - // Multiplicand uint32_t res = Memory.FillRAM[0x4202] * byte; #if defined FAST_LSB_WORD_ACCESS || defined FAST_ALIGNED_LSB_WORD_ACCESS @@ -1157,8 +1066,7 @@ void S9xSetCPU(uint8_t byte, uint16_t Address) break; } case 0x4204: - case 0x4205: - // Low and high muliplier (for divide) + case 0x4205: // Low and high muliplier (for divide) break; case 0x4206: { @@ -1205,11 +1113,8 @@ void S9xSetCPU(uint8_t byte, uint16_t Address) { if (PPU.HTimerEnabled) S9xUpdateHTimer(); - else - { - if (PPU.IRQVBeamPos == CPU.V_Counter) - S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); - } + else if (PPU.IRQVBeamPos == CPU.V_Counter) + S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); } break; case 0x420A: @@ -1219,11 +1124,8 @@ void S9xSetCPU(uint8_t byte, uint16_t Address) { if (PPU.HTimerEnabled) S9xUpdateHTimer(); - else - { - if (PPU.IRQVBeamPos == CPU.V_Counter) - S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); - } + else if (PPU.IRQVBeamPos == CPU.V_Counter) + S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); } break; case 0x420B: @@ -1245,13 +1147,10 @@ void S9xSetCPU(uint8_t byte, uint16_t Address) S9xDoDMA(7); break; case 0x420C: - if (Settings.DisableHDMA) - byte = 0; Memory.FillRAM[0x420c] = byte; IPPU.HDMA = byte; break; - case 0x420d: - // Cycle speed 0 - 2.68Mhz, 1 - 3.58Mhz (banks 0x80 +) + case 0x420d: // Cycle speed 0 - 2.68Mhz, 1 - 3.58Mhz (banks 0x80 +) if ((byte & 1) != (Memory.FillRAM [0x420d] & 1)) { if (byte & 1) @@ -1263,15 +1162,12 @@ void S9xSetCPU(uint8_t byte, uint16_t Address) } break; case 0x420e: - case 0x420f: - // --->>> Unknown + case 0x420f: // --->>> Unknown break; - case 0x4210: - // NMI ocurred flag (reset on read or write) + case 0x4210: // NMI ocurred flag (reset on read or write) Memory.FillRAM[0x4210] = Model->_5A22; return; - case 0x4211: - // IRQ ocurred flag (reset on read or write) + case 0x4211: // IRQ ocurred flag (reset on read or write) CLEAR_IRQ_SOURCE(PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); break; case 0x4212: // v-blank, h-blank and joypad being scanned flags (read-only) @@ -1447,8 +1343,6 @@ void S9xSetCPU(uint8_t byte, uint16_t Address) case 0x437F: Memory.FillRAM [Address | 0xf] = byte; break; - /* fall through */ - //These registers are used by both the S-DD1 and the SPC7110 case 0x4800: case 0x4801: case 0x4802: @@ -1459,13 +1353,12 @@ void S9xSetCPU(uint8_t byte, uint16_t Address) case 0x4804: case 0x4805: case 0x4806: - case 0x4807: + case 0x4807: //These registers are used by both the S-DD1 and the SPC7110 if (Settings.SPC7110) S9xSetSPC7110(byte, Address); else S9xSetSDD1MemoryMap(Address - 0x4804, byte & 7); break; - //these are used by the SPC7110 case 0x4808: case 0x4809: case 0x480A: @@ -1540,10 +1433,8 @@ uint8_t S9xGetCPU(uint16_t Address) { if (Memory.FillRAM [0x4016] & 1) { - // MultiPlayer5 adaptor is only allowed to be plugged into port 2 - if (IPPU.Controller == SNES_MULTIPLAYER5) + if (IPPU.Controller == SNES_MULTIPLAYER5) // MultiPlayer5 adaptor is only allowed to be plugged into port 2 return 2; - return 0; } @@ -1551,17 +1442,15 @@ uint8_t S9xGetCPU(uint16_t Address) { if (Memory.FillRAM [0x4201] & 0x80) { - byte = ((IPPU.Joypads[1] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) | - (((IPPU.Joypads[2] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) << 1); + byte = ((IPPU.Joypads[1] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) | (((IPPU.Joypads[2] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) << 1); PPU.Joypad2ButtonReadPos++; - return (byte); + return byte; } else { - byte = ((IPPU.Joypads[3] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) | - (((IPPU.Joypads[4] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) << 1); + byte = ((IPPU.Joypads[3] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) | (((IPPU.Joypads[4] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) << 1); PPU.Joypad3ButtonReadPos++; - return (byte); + return byte; } } else if (IPPU.Controller == SNES_JUSTIFIER || IPPU.Controller == SNES_JUSTIFIER_2) @@ -1606,28 +1495,20 @@ uint8_t S9xGetCPU(uint16_t Address) CPU.WaitAddress = CPU.PCAtOpcodeStart; byte = Memory.FillRAM[0x4210]; Memory.FillRAM[0x4210] = Model->_5A22; //SNEeSe returns 2 for 5A22 version. - return ((byte & 0x80) | (OpenBus & 0x70) | Model->_5A22); + return (byte & 0x80) | (OpenBus & 0x70) | Model->_5A22; case 0x4211: byte = (CPU.IRQActive & (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE)) ? 0x80 : 0; CLEAR_IRQ_SOURCE(PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); byte |= OpenBus & 0x7f; - return (byte); - case 0x4212: - // V-blank, h-blank and joypads being read flags (read-only) + return byte; + case 0x4212: // V-blank, h-blank and joypads being read flags (read-only) CPU.WaitAddress = CPU.PCAtOpcodeStart; - return (REGISTER_4212() | (OpenBus & 0x3E)); - case 0x4213: - // I/O port input - returns 0 wherever $4201 is 0, and 1 elsewhere - // unless something else pulls it down (i.e. a gun) - /* fall through */ + return REGISTER_4212() | (OpenBus & 0x3E); + case 0x4213: // I/O port input - returns 0 wherever $4201 is 0, and 1 elsewhere unless something else pulls it down (i.e. a gun) case 0x4214: - case 0x4215: - // Quotient of divide result + case 0x4215: // Quotient of divide result case 0x4216: - case 0x4217: - // Multiplcation result (for multiply) or remainder of - // divison. - /* fall through */ + case 0x4217: // Multiplcation result (for multiply) or remainder of divison. case 0x4218: case 0x4219: case 0x421a: @@ -1635,9 +1516,8 @@ uint8_t S9xGetCPU(uint16_t Address) case 0x421c: case 0x421d: case 0x421e: - case 0x421f: - // Joypads 1-4 button and direction state. - return (Memory.FillRAM [Address]); + case 0x421f: // Joypads 1-4 button and direction state. + return Memory.FillRAM [Address]; case 0x4300: case 0x4310: case 0x4320: @@ -1647,12 +1527,9 @@ uint8_t S9xGetCPU(uint16_t Address) case 0x4360: case 0x4370: d = (Address >> 4) & 0x7; - return ((DMA[d].TransferDirection ? 0x80 : 0x00) | - (DMA[d].HDMAIndirectAddressing ? 0x40 : 0x00) | - ((uint8_t) Memory.FillRAM [Address]) | - (DMA[d].AAddressDecrement ? 0x10 : 0x00) | - (DMA[d].AAddressFixed ? 0x08 : 0x00) | - (DMA[d].TransferMode & 7)); + return (DMA[d].TransferDirection ? 0x80 : 0x00) | (DMA[d].HDMAIndirectAddressing ? 0x40 : 0x00) | + ((uint8_t) Memory.FillRAM [Address]) | (DMA[d].AAddressDecrement ? 0x10 : 0x00) | + (DMA[d].AAddressFixed ? 0x08 : 0x00) | (DMA[d].TransferMode & 7); case 0x4301: case 0x4311: case 0x4321: @@ -1670,7 +1547,7 @@ uint8_t S9xGetCPU(uint16_t Address) case 0x4352: case 0x4362: case 0x4372: - return (DMA[((Address >> 4) & 0x7)].AAddress & 0xFF); + return DMA[((Address >> 4) & 0x7)].AAddress & 0xFF; case 0x4303: case 0x4313: case 0x4323: @@ -1679,7 +1556,7 @@ uint8_t S9xGetCPU(uint16_t Address) case 0x4353: case 0x4363: case 0x4373: - return (DMA[((Address >> 4) & 0x7)].AAddress >> 8); + return DMA[((Address >> 4) & 0x7)].AAddress >> 8; case 0x4304: case 0x4314: case 0x4324: @@ -1697,7 +1574,7 @@ uint8_t S9xGetCPU(uint16_t Address) case 0x4355: case 0x4365: case 0x4375: - return (DMA[((Address >> 4) & 0x7)].IndirectAddress & 0xff); + return DMA[((Address >> 4) & 0x7)].IndirectAddress & 0xff; case 0x4306: case 0x4316: case 0x4326: @@ -1706,7 +1583,7 @@ uint8_t S9xGetCPU(uint16_t Address) case 0x4356: case 0x4366: case 0x4376: - return (DMA[((Address >> 4) & 0x7)].IndirectAddress >> 8); + return DMA[((Address >> 4) & 0x7)].IndirectAddress >> 8; case 0x4307: case 0x4317: case 0x4327: @@ -1724,7 +1601,7 @@ uint8_t S9xGetCPU(uint16_t Address) case 0x4358: case 0x4368: case 0x4378: - return (DMA[((Address >> 4) & 0x7)].Address & 0xFF); + return DMA[((Address >> 4) & 0x7)].Address & 0xFF; case 0x4309: case 0x4319: case 0x4329: @@ -1733,7 +1610,7 @@ uint8_t S9xGetCPU(uint16_t Address) case 0x4359: case 0x4369: case 0x4379: - return (DMA[((Address >> 4) & 0x7)].Address >> 8); + return DMA[((Address >> 4) & 0x7)].Address >> 8; case 0x430A: case 0x431A: case 0x432A: @@ -1743,7 +1620,7 @@ uint8_t S9xGetCPU(uint16_t Address) case 0x436A: case 0x437A: d = (Address >> 4) & 0x7; - return (DMA[d].LineCount ^ (DMA[d].Repeat ? 0x00 : 0x80)); + return DMA[d].LineCount ^ (DMA[d].Repeat ? 0x00 : 0x80); case 0x430B: case 0x431B: case 0x432B: @@ -1764,10 +1641,8 @@ uint8_t S9xGetCPU(uint16_t Address) default: if (Address >= 0x4800 && Settings.SPC7110) return S9xGetSPC7110(Address); - if (Address >= 0x4800 && Address <= 0x4807 && Settings.SDD1) return Memory.FillRAM[Address]; - return OpenBus; } } @@ -1933,13 +1808,8 @@ void S9xResetPPU() { if (!Settings.SuperFX) memset(&Memory.FillRAM [c], c >> 8, 0x100); - else if ((uint32_t)c < 0x3000 || (uint32_t)c >= 0x3300) - { - /* Don't overwrite SFX pvRegisters at 0x3000-0x32FF, - * they were set in FxReset. - */ + else if ((uint32_t) c < 0x3000 || (uint32_t) c >= 0x3300) // Don't overwrite SFX pvRegisters at 0x3000-0x32FF, they were set in FxReset. memset(&Memory.FillRAM [c], c >> 8, 0x100); - } } memset(&Memory.FillRAM [0x2100], 0, 0x100); @@ -2033,15 +1903,10 @@ void ProcessSuperScope() int32_t x, y; uint32_t buttons; - if (IPPU.Controller == SNES_SUPERSCOPE && - S9xReadSuperScopePosition(&x, &y, &buttons)) + if (IPPU.Controller == SNES_SUPERSCOPE && S9xReadSuperScopePosition(&x, &y, &buttons)) { #define SUPERSCOPE_SIGNATURE 0x00ff - uint32_t scope; - - scope = SUPERSCOPE_SIGNATURE | ((buttons & 1) << (7 + 8)) | - ((buttons & 2) << (5 + 8)) | ((buttons & 4) << (3 + 8)) | - ((buttons & 8) << (1 + 8)); + uint32_t scope = SUPERSCOPE_SIGNATURE | ((buttons & 1) << (7 + 8)) | ((buttons & 2) << (5 + 8)) | ((buttons & 4) << (3 + 8)) | ((buttons & 8) << (1 + 8)); if (Memory.FillRAM[0x4201] & 0x80) { x += 40; @@ -2141,8 +2006,7 @@ void S9xUpdateJustifiers() { Memory.FillRAM [0x213F] = Model->_5C78; - //process latch as Justifier 2 - if (Settings.SecondJustifier) + if (Settings.SecondJustifier) //process latch as Justifier 2 { if (IPPU.Controller == SNES_JUSTIFIER_2) { @@ -2159,8 +2023,7 @@ void S9xUpdateJustifiers() { Memory.FillRAM [0x213F] = Model->_5C78; - //emulate player 1. - if (IPPU.Controller == SNES_JUSTIFIER) + if (IPPU.Controller == SNES_JUSTIFIER) //emulate player 1. { if (!offscreen) { @@ -2171,11 +2034,9 @@ void S9xUpdateJustifiers() } } - //needs restructure - if (!offscreen) + if (!offscreen) //needs restructure { - if ((!last_p1 && IPPU.Controller == SNES_JUSTIFIER) || (last_p1 - && IPPU.Controller == SNES_JUSTIFIER_2)) + if ((!last_p1 && IPPU.Controller == SNES_JUSTIFIER) || (last_p1 && IPPU.Controller == SNES_JUSTIFIER_2)) { PPU.VBeamPosLatched = (uint16_t)(y + 1); PPU.HBeamPosLatched = (uint16_t) x; @@ -2203,23 +2064,16 @@ void S9xUpdateJoypads() IPPU.Joypads [i] &= ~SNES_DOWN_MASK; } - // BJ: This is correct behavior AFAICT (used to be Touhaiden hack) if (IPPU.Controller == SNES_JOYPAD || IPPU.Controller == SNES_MULTIPLAYER5) - { for (i = 0; i < 5; i++) if (IPPU.Joypads [i]) IPPU.Joypads [i] |= 0xffff0000; - } - // Read mouse position if enabled - if (Settings.MouseMaster) - { + if (Settings.MouseMaster) // Read mouse position if enabled for (i = 0; i < 2; i++) S9xProcessMouse(i); - } - // Read SuperScope if enabled - if (Settings.SuperScopeMaster) + if (Settings.SuperScopeMaster) // Read SuperScope if enabled ProcessSuperScope(); if (Memory.FillRAM [0x4200] & 1) diff --git a/source/ppu.h b/source/ppu.h index ba1a857..fef59d3 100644 --- a/source/ppu.h +++ b/source/ppu.h @@ -257,8 +257,7 @@ static INLINE void REGISTER_2104(uint8_t byte) int32_t addr = ((PPU.OAMAddr & 0x10f) << 1) + (PPU.OAMFlip & 1); if (byte != PPU.OAMData [addr]) { - SOBJ* pObj = NULL; - + SOBJ* pObj; FLUSH_REDRAW(); PPU.OAMData [addr] = byte; IPPU.OBJChanged = true; @@ -301,16 +300,13 @@ static INLINE void REGISTER_2104(uint8_t byte) { int32_t addr; uint8_t lowbyte, highbyte; - PPU.OAMWriteRegister &= 0x00ff; lowbyte = (uint8_t)(PPU.OAMWriteRegister); highbyte = byte; PPU.OAMWriteRegister |= byte << 8; - addr = (PPU.OAMAddr << 1); - if (lowbyte != PPU.OAMData [addr] || - highbyte != PPU.OAMData [addr + 1]) + if (lowbyte != PPU.OAMData [addr] || highbyte != PPU.OAMData [addr + 1]) { FLUSH_REDRAW(); PPU.OAMData [addr] = lowbyte; @@ -355,9 +351,7 @@ static INLINE void REGISTER_2118(uint8_t Byte) if (PPU.VMA.FullGraphicCount) { uint32_t rem = PPU.VMA.Address & PPU.VMA.Mask1; - address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + - (rem >> PPU.VMA.Shift) + - ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff; + address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff; Memory.VRAM [address] = Byte; } else @@ -373,9 +367,7 @@ static INLINE void REGISTER_2118_tile(uint8_t Byte) { uint32_t address; uint32_t rem = PPU.VMA.Address & PPU.VMA.Mask1; - address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + - (rem >> PPU.VMA.Shift) + - ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff; + address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff; Memory.VRAM [address] = Byte; IPPU.TileCached [TILE_2BIT][address >> 4] = false; IPPU.TileCached [TILE_4BIT][address >> 5] = false; @@ -386,8 +378,8 @@ static INLINE void REGISTER_2118_tile(uint8_t Byte) static INLINE void REGISTER_2118_linear(uint8_t Byte) { - uint32_t address; - Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xFFFF] = Byte; + uint32_t address = (PPU.VMA.Address << 1) & 0xFFFF; + Memory.VRAM[address] = Byte; IPPU.TileCached [TILE_2BIT][address >> 4] = false; IPPU.TileCached [TILE_4BIT][address >> 5] = false; IPPU.TileCached [TILE_8BIT][address >> 6] = false; @@ -401,9 +393,7 @@ static INLINE void REGISTER_2119(uint8_t Byte) if (PPU.VMA.FullGraphicCount) { uint32_t rem = PPU.VMA.Address & PPU.VMA.Mask1; - address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + - (rem >> PPU.VMA.Shift) + - ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xFFFF; + address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xFFFF; Memory.VRAM [address] = Byte; } else @@ -418,9 +408,7 @@ static INLINE void REGISTER_2119(uint8_t Byte) static INLINE void REGISTER_2119_tile(uint8_t Byte) { uint32_t rem = PPU.VMA.Address & PPU.VMA.Mask1; - uint32_t address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + - (rem >> PPU.VMA.Shift) + - ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xFFFF; + uint32_t address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xFFFF; Memory.VRAM [address] = Byte; IPPU.TileCached [TILE_2BIT][address >> 4] = false; IPPU.TileCached [TILE_4BIT][address >> 5] = false; @@ -452,9 +440,7 @@ static INLINE void REGISTER_2122(uint8_t Byte) IPPU.ColorsChanged = true; IPPU.Blue [PPU.CGADD] = IPPU.XB [(Byte >> 2) & 0x1f]; IPPU.Green [PPU.CGADD] = IPPU.XB [(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f]; - IPPU.ScreenColors [PPU.CGADD] = (uint16_t) BUILD_PIXEL(IPPU.Red [PPU.CGADD], - IPPU.Green [PPU.CGADD], - IPPU.Blue [PPU.CGADD]); + IPPU.ScreenColors [PPU.CGADD] = (uint16_t) BUILD_PIXEL(IPPU.Red [PPU.CGADD], IPPU.Green [PPU.CGADD], IPPU.Blue [PPU.CGADD]); } PPU.CGADD++; } @@ -481,8 +467,7 @@ static INLINE void REGISTER_2180(uint8_t Byte) static INLINE uint8_t REGISTER_4212(void) { uint8_t GetBank = 0; - if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && - CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE + 3) + if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE + 3) GetBank = 1; GetBank |= CPU.Cycles >= Settings.HBlankStart ? 0x40 : 0; @@ -491,5 +476,4 @@ static INLINE uint8_t REGISTER_4212(void) return GetBank; } - #endif diff --git a/source/problems.txt b/source/problems.txt deleted file mode 100644 index 293df59..0000000 --- a/source/problems.txt +++ /dev/null @@ -1,459 +0,0 @@ -o FIXED: Aladdin: Mode 7 tile 0 corruption. bug in my delay-by-one-word read - V-RAM code. -o FIXED: Missing sprites on Captain Commando (all negative x coords) - only - on asm version, but now... -o FIXED: Flashing screen on Captain Commando. -o FIXED: Super Street Fighter 2 won't respond to joy-pad controls. -o FIXED: Final Fantasy V - text windows are partially hidden - background - priority-per tile problem. - needed dual-windowing AND/OR logic mode. -o FIXED: Tinytoons uses Mode 7 priority per pixel. -o FIXED: Formation Soccer seems to need transparent mode 7 graphics and sprites - behind background. -o FIXED: Super Aleste has corrupted sprites on title screen. -o FIXED: Junk on backgrounds of Battle Clash. sub-screen subtract. -o FIXED: Total Carnage scrolling text is off by a couple of lines, h-dma problem. -o FIXED: Puzzle Bobble says "this ROM is not designed for you snes". -o FIXED: Sensible Soccer Mode 0 problems (colours). -o FIXED: Cannon Fodder shows signs of H-DMA problems when showing mission - title screen. -o FIXED: Alien vs Predator: sprites messed up and screen flashing (screen - flashing done on purpose). -o FIXED: ffmq might require MVN/MVP to always use a 16-bit accumulator. -o FIXED: Battle Toads crashes after player selection. -o Mode 5 graphics on snestest.smc Controller Test are corrupt - offset per - tile not implemented. NO - H-512 mode not implemented! -o FIXED: snestest.smc locked up on Electronics test - IRQ never cleared. -o FIXED: Formation Soccer is doing DMA from a bad area of RAM to V-RAM - - needed SPC700 emulation. -o FIXED: Pacman crashes and problems with sprites on title screen - v-ram - reading problem. -o FIXED: New FF5 graphics problems on title screen. -o FIXED: MS-DOS machine with single joystick doesn't work. -o FIXED: Seiken 3 locks up - first in a IRQ loop (its never cleared) then waiting - for sound CPU. -o FIXED: Metriod 3 has a corrupted screen and locks up. -o FIXED: Mechawarrior 3050 has major problems - corrupt screen, extreamly slow frame - time, etc., etc. - needs SetByte and GetByte CPU push code. - So does - Weapon Lord! -o FIXED: **Weapon Lord uses PCALL and TCALL in SPC-700 code ** -o FIXED: Another World is transfering a lot of data using DAM to VRAM and $2180. -o FIXED: Soulblazer has minor h-dma glitches on vertical background scrolling. -o FIXED: Secret of the Stars no go - Sound cpu wait problem. -o FIXED: With reseting IRQ in place in v-line != h-irq-line Battle Toads: Double - Dragon works, but Spawn doesn't. -o FIXED: Memory map problem with Donald Duck (corrupt ROM image). -o FIXED: Comsmo Puzzle and Yuu Yuu all show "V-RAM increment" type - problems (problem was with reading V-RAM). -o FIXED: Some games rewrite the sprite registers during a frame. -o FIXED: ILLUSION has horrible sound... (sample decode routine had a bug). -o FIXED: Find out why graphics are all squashed up on sensi soccer/ bman with old - old tile drawing code... -o FIXED: IRQ wobble on Aladdin at top of screen - causes occational palette flash. -o FIXED: 7th Saga, Actraiser2 and Addams Family causes a core dump on exit. -o FIXED: aleste.smc has sprite display problems on title screen on tile-based redraw - code. -o INFO: DKC3 crashes itself if V-RAM isn't filled with zeros! -o FIXED:Tazmania has stopped working - missing IRQ. Adding a field to - Settings moved a variable being used in asm code. -o FIXED: Castleviana 5 and Sparkster use DMA address decrement to update sprites. -o FIXED: X-Men has some sprite glitches - but only on tile based redraw code - - it blanks the screen early and then DMAs new spite tile data before the - usual end of frame. -o FIXED: Super Punchout shows corrupt knockout timer when H-DMA is enabled. - (was triggering H-DMA during a frame) - only trigger H-DMA during v-blank or - h-blank, otherwise write to register is ignored. -o SOUND: Clayfighter, Tazmania, Madden 94-97, NHL 96-97, and WeaponLord - all spool sound samples into APU RAM using H-DMA! -o FIXED: ASM version bug: SOUND: Super Punchout has lots of sound repeat problems. -o FIXED: DMA? problems on background 3 in SMW. -o FIXED: Weapon Lord hangs on player selection screen (waiting for SPC700?). -o FIXED: Killer Instinct shows BG3 on title screen when it shouldn't. -o FIXED: Blank screen on Rock 'n' Roll Racing - DMA problem. -o FIXED: SFC Bastard has offset problems on Mode 7 graphics on title screen. -o FIXED: SOUND: SFC Bastard (bastardy.smc) locks with sound enabled. -o FIXED: GANBARE GOEMON 2 (sf16232a.078) requires SavedOAMAddr to be set in - OAMAddr after end of frame (at max v_counter?). -o FIXED: SuperOffroad: The Baj has screen flash/timing problems during game - - skipping IRQs ? - It was reseting the H-IRQ position so another IRQ would - occur on the scanline it was already on. -o FIXED: R-TYPE 3 has missing scrolling "space" background during game. - (location $54 contains $10, needs to contain $11) - not a bug, when run on a - real SNES the background is missing as well. -o FIXED: Toy Story plays sample that walks off end of memory - was causing - emulator crashes. -o FIXED: Bubsy has corrupt graphics - it required register $4210 bit 7 to - trigger at the end of h-blank of line 224, not at the start. -o FIXED: Jurrassic Park locks with sound enabled. (Corrupt ROM image). -o FIXED: Q*Bert 3 has major graphics problems after 3rd level or locks. With -h 120 - and VAR_CYCLES game has corrupt graphics, otherwise it crashes. - ROM image - is corrupt as same thing happens on a real SNES. -o FIXED: Evo - Chapter 1 title page shown on two backgrounds at same time - - not bug just sub-screen addition being used. -o FIXED: Ghosts and Ghouls needs H-DMA to be enabled if register is written after - start of frame - Super Punchout needs the opposite... - - only start H-DMA if enable register written to during v-blank or h-blank. -o Exhaust Heat might require scanline drawing just before H-DMA rather than - at end of h-blank. -o FIXED: Exhaust Heat has mode 7 offset problems. v0.24 accidentally fixed the problem - but now its back again. -o FIXED: Goal locks at start with sound enabled. - The SPC700 seems to need to - start executing instructions before the 65c816 so it has initialised $2140 - to $BBAA before the '816 checks for that value. -o FIXED: Final Fight 3 crashes with BRK instruction. - corrupt ROM. -o FIXED: T2 - has problems with clip windows. -o Robocop v Terminator: screen flashes like Alien vs Predator. -o FIXED:Nhl97 crashes - sound APU problem ? -o FIXED: Nhl97 now doesn't crash, instead the game won't start after the teams have - been chosen. -o FIXED: Shadow Run shows sprite-sprite priority problems. -o Alien vs Predator uses colour subtraction on sprites but only on palettes 6-7? - (Collect cloaking device, second object). -o NMI might need to be delayed to end of line. -o JanjYu Gakuen 2 looks at bit 6 of $4211 - might need to show source of - IRQ - $40 for V-IRQ and $20 for H-IRQ? -o FIXED: Sunset riders has repeated background problems(?) - could be sub-screen - addition/subtraction. Colour palette changes during game. -o Priority on snestest.smc Character Test are incorrect. -o Clay Fighter 2 writes to $3007-8 and reads from $3211-4. -o FIXED: Shien The Blade Chase tests bit 0 of $4200 until it goes 0 - reading - $4200 must reflect joypad reading status. No, actually $4200 is open bus. -o FIXED: NBAJam (not Tournament Edition) has an odd memory map - accesses - code at $3Dxxxx. (corrupt ROM image). -o Super Bases Loaded uses Mode 5 and the background offset mode. -o FIXED: Super Bases Loaded 2 has an odd memory map: writes to $E00000 and reads from - $E04000! (DSP1 chip) -o PilotWings uses a DSP. -o FIXED: Return Of Double Dragon needs -FL -ss 1 -o. -o FIXED: Tazmania is rewriting the colour palette just before the end of the frame. - Shows up a a flashing screen. Uses software not DMA. -o FIXED: Actraiser2 has screen flash/timing problems. Was rewriting H-DMA - start addresses during a frame - real SNES seems to ignore these. -o Actraiser2 uses mode 7 fixed colour palette mode - "32K" mode. -o FIXED: Agmawo locks at start. corrupt ROM - looks to be only first part of a - multi-part ROM on the CD. -o FIXED: Alfred Chicken needs -FL. -o Mighty Max and Addams Family 2 are very slow with sound enabled. -o Williams Arcade Classics plays sound samples by varying the volume level - using the gain control... -o FIXED:Zoop: Sound works initially but then stops during game. -o FIXED:Lion King locks up with sound enabled... -o Sparkster has lots of sound repeat problems. -o FIXED: Killer Instinct shows corruption at top of screen during the actual fight. - Seems to need sub-screen emulation turned on. -o Look into passing mask into StartHDMA so the routine only resets DMA - channels with the bit set in the bit mask. -o FIXED: RPM racing uses mode 5 512x512. -o FIXED: Biker Mice From Mars (sfbiker) needs -N and flipped layering '8'. -o FIXED: Mario and Wario (sfmarwar.smc) needs a mouse. -o Battle Toads: Double Dragon needs the -h parameter set to 100. -o FIXED: SF8752.smc has sprites problems when using tile-redraw code. -o FIXED: NHL '97 does a JMP $4320 in bank $87 - $4320 is a register area in that - bank. -o FIXED: Chuck Rock has corrupted sprites on the title screen. -o FIXED: War of the Gems crashes with a STP instruction - bug in asm version of - CPU core - appears when status register spliting was added. Snap6. - If IRQ pending after returning from an NMI then incorrect status pushed - onto stack. -o Adventures of Batman & Robin (bat.smc) has really slow music on title - screen with SPC700 shutdown enabled. -o Return of the Jedi has lots of sound problems. -o WORMS has vertical offset problems on BG1 when displaying life bar at top - of screen. -o FIXED: Street Racer has corrupt sprites on the player select screen. -o FIXED: Super Bases Loaded 1 uses Mode 5 (512x224) on intro. -o INFO: Batman Forever uses sub-screen addition with bg's being on both the main - screen and sub-screen. -o INFO: Intro of Beavis and Butthead uses sub-screen addition with bg's being on - both the main screen and sub-screen. -o INFO: ebreaker.smc bg's on both main and sub-screen. -o Big Sky Trooper's music is very slow. -o FIXED: Bomberman 4 needs -FH. -o FIXED: Captain Commando is interleaved. -o FIXED: Crystal Bean locks at start and is interleaved. - corrupt ROM image. -o Jim Power (jimp.smc) has scrolling/H-DMA problems on the intro. -o FIXED: Ogre Battle has fixed colour subtract problems on the main screen. -o pacman and Jim Power intro seem to rely on maximum number of sprites on a - scanline at once to hide unwanted sprites. -o FIXED: Pacman 2 has scrolling/H-DMA problems during the game. -o FIXED: Power Drive (snk_powd.smc) uses 512x448 on intro. -o FIXED: SKI PARADISE (skiparad.fig) uses mode 7 priority per pixel -o The Magical Quest (smmouse.smc) has an intro with bad raster glitches - uses - exact CPU timing! -o FIXED: Madden 96 needs -FH and has new Antherox intro. -o FIXED: College Slam (collslam.1 on CD) thinks non-standard controllers are - connected. It writes $12 and $02 to $4016. -o The sound on Speedy Gonzales sounds out of tune - seems to vary the - frequency a lot - first low byte then the high byte. -o Stargate has sound clicks on channels 5 and 6 on title page. -o FIXED: Ranman1/2 Part 1 (ranma121.smc) crashes SPC700 at start up - looks like a - 65c816 addressing mode/instruction bug! - corrupt ROM image. -o Speedy Gonzales starts a long DMA to $2180 at v-line 1 with the screen not - blanked. -o FIXED: acc-elf.smc works on v0.1 but crashes with a STP instruction in v0.24. -o FIXED: FLYING HERO BUGYURU flyhero.smc does not work and image is odd size so code - doesn't detect header and remove it. -o FIXED: Yaiba (lmk_yaib.smc) locks waiting for an interrupt to occur to no interrupts - are enabled. -o CORRUPT ROM: Rise of the Robots does a long DMA to V-RAM during in the NMI handler - - it might require the DMA to automatically stop when H-DMA starts if the - screen is not blanked. -o FIXED: Andrew Agassi Tennis has missing sprites - only writes to low byte - of sprite write address register. Writing to low byte must clear hi-byte as - well. -o FIXED: Bonkers locks sound enabled. SPC700 code expected KOFF DSP register - to return value just written. -o Mario Kart has odd graphic windows settings when first started. -o FIXED: Street Racer has odd size sprites and has missing tiles when displayed. -o FIXED: ASM 65c816, Aladdin keeps warping to other side of screen on first level. -o The Great Circus Mystery (circusmystery.smc) doesn't work. -o James Pond 2 gets stuck waiting for SPC700 to respond after first title - screen. works on v0.24. -o Mario All stars - Super Mario 2 uses mode 2 (offset per tile) but with - height 64 on bg #2. Black screen. -o FIXED: Chrono Trigger uses mode 2 with width 64 for wavey 'Trigger' text. Text - should scroll onto screen, it doesn't. It does if width 64 is disabled, - but it starts on the screen first. - bug with not wrapping Quot variable - with mode 2 width 64. -o Tetris Attack uses screen screen height of 64 on offset-per-tile mode 2. -o Batman forever might show that if OBJs are on both the main and sub-screens - and colour addition is enabled, then only OBjs with palette numbers - 4 or greater take part in colour addition and are not displayed on the - sub-screen. -o FIXED: CPUShutdown causes problems for ROMs that wait for h-blank using $4212 - during the v-blank period - Reschedule doesn't enable HBLANK_START_EVENT - during the v-blank period so the cycle skipping code doesn't wake up the - CPU until h-blank end. -o FIXED: Putty Squad seems to use wrong palette for each tile when mosaic effect - is being used - could be only the ROM so far with 16x16 pixels tiles and - mosaic effect. -o FIXED: Mortal Kombat 1 restarts level when once the 'fight' message has disappeared. - - 0.31 has problems. - - 13-03-98 problems. - - 1-4-98 problems. - Problem with asm code only and intermittent. -o FIXED: Clay fighter has problems with colour window when the game starts and the - game locks up anyway. ... but still sound repeat problems. -o FIXED: VAMPIRES KISS has corrupt, flashing OBJs and some v-ram problems, - no problems in 0.41. Problem not dma, ppu, or cpuexec. - - Problem was H-DMA was being started inside v-blank period. -o FIXED: VAMPIRES KISS has tile glitches on bg#2 during game - not present in - 0.41. H-DMA? -o FIXED: Contra 3 has clip window problems resulting in black screen, only - OBJs can be seen when game first starts. -o FIXED: YUUYUU TOKUBETUHEN (yuyut.smc) has missing OBJs when screen is split - - it enables both clip windows on OBJ and sets the combination mode to - AND but both clip windows only overlap a few pixels so the OBJs are not - displayed. - bug in window code, needed to flip the logic window - combination mode because the window area add already been flipped. -o Multiple colour add/sub and clip window bugs with Killer Instinct. -o T2: Arcade Game displays multi-coloured blocks of tiles when a mode 3 - screen is being displayed. Screen shown when game-over. -o Bomberman 5 flickers on title screen when H-DMA is enabled. -o FIXED: XOR window clip code is producing bands that overlap. -o TOKIMEKI MEMORIAL (tokmemor.smc) uses hi-res., mosasic effect and fixed - colour addition. -o FIXED: TOKIMEKI MEMORIAL (tokmemor.smc) displays corrupted sprites - every other - group of four pixels is missing. -o RPM racing (hi-res. interlace) displays blank screen with 8-bit renderer. -o FIXED: Lufia I locks is shutdown is enabled. Asm only. -o FIXED: The SPC700 in Universal Solider locks if shutdown is enabled. Asm only. -o FIXED: Disabling the Multi Player 5 switches controller 1 to a mouse ! -o FIXED: Top Gear 3000 - DSP1? game, though ROM header doesn't mention it. - Bug in ROM header detection code. -o FIXED: Lost Vikings II locks after title screen - works in 0.24. -o Lost Vikings locks or resets on all versions. -o Uniracers enables sub-screen addition on bg # 2 but with nothing on the - the sub-screen. Should it be either the fixed colour or back-drop - colour get added instead? -o Wile E's Revenge has missing music, and very quite sound. Also displays - rotated mode 7 character picture during titles. -o Pilot Wings tries to set up a V-IRQ to happen on the line its already on, - uses IRQ to switch to mode 7. -h 120 fixes problem. Cycle timing must be - off. -o Top Gear 3000 sits in a loop waiting for the H-DMA line count register - to reach a particular value - it never does because its not emulated yet! -o Theme Park starts a rather crummy tune then crashes. Hacker intro? -o Killer Instinct has a one-pixel wide bright line part way down screen - on orcid practice level - colour window invert bug? -o Killer Instinct bg #1 is hidding some transparency effects and the - fighter's sprite shadows on some levels. -o Batman - revenge of the joker locks at start - waiting for SPC700 which - has hit a stop instruction. -o Eye of the Beholder has strange mouse pointer movement problems when SNES - mouse emulation is enabled. -o FIXED: Daffy duck has lots of scrolling glitches on background parallax effects - - timing problems? Missing NMI - ROM kept turning NMI enable flag on and off. -o Aero the AcroBat 2 might wait until a bit in $420B (h-dma enable) clears - - does reading that register indicate H-DMA channels in progress? -o Ardy Lightfoot and Oblix both flash the sprite of the main character - on and off every other frame, should they do this or is it a bug? -o FIXED: Firemen locks at start waiting for SPC700. Human game, needs -ratio 3. -o Jim Power has a one pixel wide bright line down one side of screen on the - level map screen. -o Lots of missing sound effects in Home Alone 2. -o Missing sound effects in Earth Worm Jim 2. -o Captain America has single pixel high line corruption through some of its - tiles. -o NHL STANLEY CUP locks at start waiting for the SPC700 - works with sound - disabled. -o Sailor Moon has colour window problems during intro of game. -o Sailor Moon R screen flashes black during game. -h 102 fixes. -o Tile corruption on Super Pang on 3rd level+ - only on DOS port. -o Mighty Max uses colour window on main screen to clip background colour - palette changes - except its not working on Snes9x. -o FIXED: Battle Toads: Battlemanics crashes during intro - ROM's NMI handler does not - switch index registers to 16-bit before pushing them onto the stack, but - always switches them to 16-bit mode when restoring them. - NMI timing problem. -o FIXED: Contra 3 has missing fire effects when bomber plane drops bombs - use - freeze-game to see. - Colour window is fully clipping the sub-screen and - the fire effects are only on the sub-screen. - - colour window invert bug. -o FIXED: Illusion of Gaia uses sub-screen subtraction with half flag during game - select. Also, uses colour window to cut a hole in the main-screen, - should the sub-screen be visible at this point? Only two backgrounds are - being displayed, one on the main-screen and one on the sub-screen and - the sub-screen is not being added to the background only the background on - the main-screen. -o FIXED: Gun force uses background #2 to display horizontal bullets fired from - player, but they are displayed offset from the main firing them. H-DMA transfer - size array was not set for the mirrored channels. -o FIXED: Empire Strikes Back needs -ratio 5 to work. -o Empire Strikes Back: The Hoth battle stage uses mode 7, priority per pixel - and part of the graphics are missing. -o FIXED: llusion of Gaia menu on the first screen should be on a dark background. - ZSNES gets it correct. -o DOS port can't load some ROMs from CD. NLKE has same problem. Allegro? - ZSNES loads most of them fine. -o -frametime option is broken. -o Jap version of Tetris Attack might have a scrolling bug on the title screen. -o FIXED: Commodore 64 emulator doesn't work with asm CPU core - works fine with - C code. -o FIXED: Chrono Trigger: crash bug in clipping code - use snapshot F6 and press 's'. - Corrupts stack causing crash. -o FIXED: Toy Story only updates screen every-other frame and woody flashes - continuously. (Woody flashing is due to hacked ROM) - Toy Story requires NMI to happen immediately after a WAI instruction. -o Toy Story has garbled sound output just before game starts. DOS port only. -o FIXED: Tales of Phantasia executes across a 0x8000 boundary and either side of - the boundary are at different offsets into the ROM. Causes a crash. -o RPM Racing doesn't display correctly when interpolation and 16-bit screen - mode. X11 port. Works when full-screen X. -o FIXED: Itchy & Scratchy has sprite corruption on the one of the title screens. - Problem appeared between v0.4 and v0.41. -o Start screen on Chase HQ is corrupt. v0.24 has same problem. -o FIXED: King of the Rally has missing music on the car-feature selection screen. - Works in v1.00. Requires DP+X addresses to wrap in zero page. -o FIXED: (again) Lufia I locks is shutdown is enabled waiting for SPC700. - made the SPC700 wake up if the 65c816 reads from the one of the 4 comm ports. - The SPC700 used to only wake up when the 65c816 wrote to the ports. -o WWF-Arcade crashes - calls a subroutine at address $EE758D which only - contains zeros at that address. Memory map bug? -o WWF-Super Wrestlemania and WWF-Raw both seem to display junk background - layers - the ROM enables the layers but does not set up any background data. -o WWF-Super Wrestlemania crashes just before the game starts. Memory map bug? -o FIXED: Ninja Warriors has missing graphics on the title screen - V-IRQ problem? - Problem appears after v1.16. Didn't like H-IRQ triggering on the same line - if the H-IRQ position register was updated. -o Yoshi's Island might show there's an 'off-by-one' bug in the clip window code - when it pops up a message box. -o Tazmania has ticking on the sound during the initial title music. -o SuperScope 6 has a repeating gun-fire sound on the initial aim screen. - Channel volume is set to gain mode. -o Stargate sometimes has a slight click sound at the end of each rapid soft - beep when the start button is pressed on the title page. Channel 6 is the - problem, has attack rate of 10ms, decay 1200ms, infinate sustain and a - sustain level of 5. -o Kirby Superstar - SA-1 game? YEP! -o The Lion King: under sound test, continue long song contains some odd - sounding notes. Is a particular type of sample not being decoded correctly? -o Clicks on the title music of Madden 98. -o Bugs Bunny has sound repeat problems when Bugs kicks a dog. - not a problem, - just needs -envx. -o Bugs Bunny has junk snow characters on bg #1. -o Airwolf hacker intro is very corrupt - corrupt ROM? -o FIXED:Pac-in-time title music sounds a lot worse with new envelope sound code in - 1.17. The game requires samples to be keyed on without being keyed off first. -o DOREMI Fantasy milon uses decay exponential volume envelope on the notes at - the end of the title music - they seem to take too long to decay. -o Winter Gold causes ZSNES Super FX code to overwrite the static data after its - allocation - was causing the X library to crash since that was the .o after - linked after zsnes.o. -o FIXED: Micromachines 2 has continuing engine noise problem when race is over - - sound channel 7 is in sustain mode with time period set to infinite. - - must have updated ADSR parameters as the it was in progress. -o DONE: Check Micromachines on real SNES - does the Ocean logo shear at the start? - If it doesn't it could be a bug in the mode 7 code - the same problem that - affects battle racers. - Does the same thing on a real SNES. -o FIXED: LAMBORGHINI AMERICAN has lots of missing music notes - - uses bent-line inc with attack rate of infinite? - - S9xSetEnvRate thought that the channel was silent and hence the number of - volume steps was 0 so erate was always being set to 0. -o Slight clicking on the sound of Wild Snake - not sound sync or interpolation - bug. -o FIXED: Zoop locks up at the end of each level playing random sound data on one - channel and the main SNES CPU seems to be waiting for the sound channel to - finish. - ENVX should return zero when channel is in gain mode. -o Battle Racers might have missing music during the race. -o Tactics Ogre has missing music and ROM locks up if you visit the sound menu. -o FIXED: Dragon Quest 5: the monsters disappear during fight sequences when the - fireball is used (freeze file 004). - - H-DMA needs to continue for one extra line, e.g. for screen height of - 239 H-DMA needs to run from line 0 to line 239, inclusive. -o Stargate sound click problem during some music - makes large changes to - channel volume levels while the sound is still playing, but other problems - seem to be causing the click. -o Super Air Diver 2, Pilotwings and SD Racing DSP all suffer from the same - shear DSP1 emulation bug. Bug in op 0x02/0x1a/0x0a to do with viewing angle - and rotation. -o Super Air Diver 1 locks at start waiting for sound CPU. -o FIXED: Ballz generates unknown DSP1 command 2f and 0f then locks up on title - screen. Implemented new Ops -o FIXED: Highway Battle 2 generates unknown DSP1 command 2f and lots of different - unknown DSP1 commands during play. The mode 7 screen is all messed up. Hacked game, - but the DSP routines were inaccurate. -o FIXED: Dungenon Master generates lots of unknown DSP1 commands errors. It's DSP-2. -o F1 Roc 2 isn't a DSP1 - uses some form of custom chip. -o F1 Roc 2 has graphic window clip problems with the clip code. -o Vertical mouse movement on Eye of the Beholder is very erratic. -o BT IN BATTLEMANIACS has slight sound click problems during the opening music. -o Bomberman 5 - sound test, music 22 doesn't sound correct. Sounds different on - three different versions 1.00, 1.16 and 1.18. -o FIXED: Sprite priority bug on title screen of ILLUSION OF GAIA. -o FIXED: James Pond 2 - random horizontal sprite movement between two places, seems - OK in 1.11 (only slight bug with battery level) but broken in 1.16. Sprite code relies - on funky behavior. -o Jigsaw Party objects to multi-player 5 emulation, game won't start with it - enabled. -o FIXED: The ROM load code thinks Eek The Cat is in interleave format, it isn't. -o FIXED: Primal Rage v1.20 - major graphics problem problems, not in v1.19. -o FIXED: Mario Kart - single player mode, pressing select to use rear view mirror - results in corrupt graphics. - inverse of an empty colour window should be - whole screen. -o FIXED:Missing logo from FF5 start up screen. - mode 7 was always using - main-screen z-buffer. -o FIXED: Something is zeroing the ZSNES SfxnRamBanks variable in Yoshi's Island, - allowing the code to set junk values in the ROMBR register which in turn - can cause an illegal memory access when the Super FX tries to access its RAM. - - ZSNES code bug. -o FIXED: Background scrolling glitches on Stargate. - - skipping NMIs. Stopped NMI retriggering in same screen. -o Metal Combat - in the title screen speech the '93 of the 1993 words get cut - off earily -o POWER RANGERS FIGHT during the game the score area breaks up and scrolls when - it shouldn't and there is corruption in the character graphics. -o FIXED: Maui Mallard doesn't show the water background layer correctly. - -o Seiken 3 3dfx type screen breakup bug in windows port with 'sal mode - enabled. -o FIXED: RexRonanExperimentalSurgeonUSA layering problem in title screens. - - wasn't wrapping V-RAM addresses for screen (bg) locations. -o PANIC BOMBER WORLD locks up on title screen -o Doom segfaults after splash screen if i386 core is used on Linux. -o Doom hangs when shooting a barrel if C++ core is used on Linux. -o Cu On Pa locks up at the player select screen - input not handled. Timing? -o Madara 2 menus should have a blue window clipped out - hi-res clipping behavior? -o Shin Megami Tensei fusion screen - corrupt graphics - $2105 seems to be getting set - to 0 instead of 9. -o Dragon Ball Z - Super Butoden 2 (J) 1.1 - flashing graphics at the start of - a fight and then later if the screen gets splitted. diff --git a/source/sa1.c b/source/sa1.c index b19ba11..005a9c7 100644 --- a/source/sa1.c +++ b/source/sa1.c @@ -111,29 +111,29 @@ uint8_t S9xSA1GetByte(uint32_t address) { uint8_t* GetAddress = SA1.Map [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]; if (GetAddress >= (uint8_t*) MAP_LAST) - return (*(GetAddress + (address & 0xffff))); + return GetAddress[address & 0xffff]; switch ((intptr_t) GetAddress) { case MAP_PPU: - return (S9xGetSA1(address & 0xffff)); + return S9xGetSA1(address & 0xffff); case MAP_LOROM_SRAM: case MAP_SA1RAM: - return (*(Memory.SRAM + (address & 0xffff))); + return Memory.SRAM[address & 0xffff]; case MAP_BWRAM: - return (*(SA1.BWRAM + ((address & 0x7fff) - 0x6000))); + return SA1.BWRAM[(address & 0x7fff) - 0x6000]; case MAP_BWRAM_BITMAP: address -= 0x600000; if (SA1.VirtualBitmapFormat == 2) - return ((Memory.SRAM [(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); + return (Memory.SRAM [(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3; else - return ((Memory.SRAM [(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); + return (Memory.SRAM [(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15; case MAP_BWRAM_BITMAP2: address = (address & 0xffff) - 0x6000; if (SA1.VirtualBitmapFormat == 2) - return ((SA1.BWRAM [(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); + return (SA1.BWRAM [(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3; else - return ((SA1.BWRAM [(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); + return (SA1.BWRAM [(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15; default: return OpenBus; } @@ -142,7 +142,7 @@ uint8_t S9xSA1GetByte(uint32_t address) uint16_t S9xSA1GetWord(uint32_t address) { OpenBus = S9xSA1GetByte(address); - return (OpenBus | (S9xSA1GetByte(address + 1) << 8)); + return OpenBus | (S9xSA1GetByte(address + 1) << 8); } void S9xSA1SetByte(uint8_t byte, uint32_t address) @@ -264,9 +264,8 @@ void S9xSetSA1MemMap(uint32_t which1, uint8_t map) for (c = 0; c < 0x200; c += 16) { - /*Code from Snes9x 1.54.1 - * - * This allows Super Mario World VLDC 9 hack to load * - * conversion to int is needed here - map is promoted but which1 is not */ + /*Code from Snes9x 1.54.1 - This allows Super Mario World VLDC 9 hack to load. + Conversion to int is needed here - map is promoted but which1 is not */ int32_t offset = (((map & 0x80) ? map : which1) & 7) * 0x100000 + (c << 11) - 0x8000; block = &Memory.ROM [offset]; for (i = c + 8; i < c + 16; i++) @@ -279,32 +278,30 @@ uint8_t S9xGetSA1(uint32_t address) switch (address) { case 0x2300: - return ((uint8_t)((Memory.FillRAM [0x2209] & 0x5f) | - (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE)))); + return (uint8_t)((Memory.FillRAM [0x2209] & 0x5f) | (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE))); case 0x2301: - return ((Memory.FillRAM [0x2200] & 0xf) | - (Memory.FillRAM [0x2301] & 0xf0)); + return (Memory.FillRAM [0x2200] & 0xf) | (Memory.FillRAM [0x2301] & 0xf0); case 0x2306: - return ((uint8_t) SA1.sum); + return (uint8_t) SA1.sum; case 0x2307: - return ((uint8_t)(SA1.sum >> 8)); + return (uint8_t) (SA1.sum >> 8); case 0x2308: - return ((uint8_t)(SA1.sum >> 16)); + return (uint8_t) (SA1.sum >> 16); case 0x2309: - return ((uint8_t)(SA1.sum >> 24)); + return (uint8_t) (SA1.sum >> 24); case 0x230a: - return ((uint8_t)(SA1.sum >> 32)); + return (uint8_t) (SA1.sum >> 32); case 0x230d: { uint8_t byte = Memory.FillRAM [0x230d]; if (Memory.FillRAM [0x2258] & 0x80) S9xSA1ReadVariableLengthData(true, false); - return (byte); + return byte; } } - return (Memory.FillRAM [address]); + return Memory.FillRAM [address]; } void S9xSetSA1(uint8_t byte, uint32_t address) @@ -333,11 +330,9 @@ void S9xSetSA1(uint8_t byte, uint32_t address) Memory.FillRAM [0x2301] |= 0x10; break; case 0x2201: - if (((byte ^ Memory.FillRAM [0x2201]) & 0x80) && - (Memory.FillRAM [0x2300] & byte & 0x80)) + if (((byte ^ Memory.FillRAM [0x2201]) & 0x80) && (Memory.FillRAM [0x2300] & byte & 0x80)) S9xSetIRQ(SA1_IRQ_SOURCE); - if (((byte ^ Memory.FillRAM [0x2201]) & 0x20) && - (Memory.FillRAM [0x2300] & byte & 0x20)) + if (((byte ^ Memory.FillRAM [0x2201]) & 0x20) && (Memory.FillRAM [0x2300] & byte & 0x20)) S9xSetIRQ(SA1_DMA_IRQ_SOURCE); break; case 0x2202: @@ -361,20 +356,17 @@ void S9xSetSA1(uint8_t byte, uint32_t address) S9xSetIRQ(SA1_IRQ_SOURCE); return; case 0x220a: - if (((byte ^ Memory.FillRAM [0x220a]) & 0x80) && - (Memory.FillRAM [0x2301] & byte & 0x80)) + if (((byte ^ Memory.FillRAM [0x220a]) & 0x80) && (Memory.FillRAM [0x2301] & byte & 0x80)) { SA1.Flags |= IRQ_PENDING_FLAG; SA1.IRQActive |= SNES_IRQ_SOURCE; } - if (((byte ^ Memory.FillRAM [0x220a]) & 0x40) && - (Memory.FillRAM [0x2301] & byte & 0x40)) + if (((byte ^ Memory.FillRAM [0x220a]) & 0x40) && (Memory.FillRAM [0x2301] & byte & 0x40)) { SA1.Flags |= IRQ_PENDING_FLAG; SA1.IRQActive |= TIMER_IRQ_SOURCE; } - if (((byte ^ Memory.FillRAM [0x220a]) & 0x20) && - (Memory.FillRAM [0x2301] & byte & 0x20)) + if (((byte ^ Memory.FillRAM [0x220a]) & 0x20) && (Memory.FillRAM [0x2301] & byte & 0x20)) { SA1.Flags |= IRQ_PENDING_FLAG; SA1.IRQActive |= DMA_IRQ_SOURCE; @@ -444,8 +436,7 @@ void S9xSetSA1(uint8_t byte, uint32_t address) { // Char conversion 2 DMA enabled // memmove converted: Same malloc but constant non-overlapping addresses [Neb] - memcpy(&Memory.ROM [MAX_ROM_SIZE - 0x10000] + (SA1.in_char_dma << 4), - &Memory.FillRAM [0x2240], 16); + memcpy(&Memory.ROM [MAX_ROM_SIZE - 0x10000] + (SA1.in_char_dma << 4), &Memory.FillRAM [0x2240], 16); SA1.in_char_dma = (SA1.in_char_dma + 1) & 7; if ((SA1.in_char_dma & 3) == 0) S9xSA1CharConv2(); @@ -488,15 +479,14 @@ void S9xSetSA1(uint8_t byte, uint32_t address) break; } break; - case 0x2258: // Variable bit-field length/auto inc/start. + case 0x2258: // Variable bit-field length/auto inc/start. Memory.FillRAM [0x2258] = byte; S9xSA1ReadVariableLengthData(true, false); return; case 0x2259: case 0x225a: - case 0x225b: // Variable bit-field start address + case 0x225b: // Variable bit-field start address Memory.FillRAM [address] = byte; - // XXX: ??? SA1.variable_bit_pos = 0; S9xSA1ReadVariableLengthData(false, true); return; @@ -509,8 +499,7 @@ static void S9xSA1CharConv2() { uint32_t dest = Memory.FillRAM [0x2235] | (Memory.FillRAM [0x2236] << 8); uint32_t offset = (SA1.in_char_dma & 7) ? 0 : 1; - int32_t depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 : - (Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2; + int32_t depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 : (Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2; int32_t bytes_per_char = 8 * depth; uint8_t* p = &Memory.FillRAM [0x3000] + dest + offset * bytes_per_char; uint8_t* q = &Memory.ROM [MAX_ROM_SIZE - 0x10000] + offset * 64; @@ -540,15 +529,9 @@ static void S9xSA1CharConv2() static void S9xSA1DMA() { - uint32_t src = Memory.FillRAM [0x2232] | - (Memory.FillRAM [0x2233] << 8) | - (Memory.FillRAM [0x2234] << 16); - uint32_t dst = Memory.FillRAM [0x2235] | - (Memory.FillRAM [0x2236] << 8) | - (Memory.FillRAM [0x2237] << 16); - uint32_t len = Memory.FillRAM [0x2238] | - (Memory.FillRAM [0x2239] << 8); - + uint32_t src = Memory.FillRAM[0x2232] | (Memory.FillRAM[0x2233] << 8) | (Memory.FillRAM[0x2234] << 16); + uint32_t dst = Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8) | (Memory.FillRAM[0x2237] << 16); + uint32_t len = Memory.FillRAM[0x2238] | (Memory.FillRAM[0x2239] << 8); uint8_t* s; uint8_t* d; @@ -598,9 +581,7 @@ static void S9xSA1DMA() void S9xSA1ReadVariableLengthData(bool inc, bool no_shift) { - uint32_t addr = Memory.FillRAM [0x2259] | - (Memory.FillRAM [0x225a] << 8) | - (Memory.FillRAM [0x225b] << 16); + uint32_t addr = Memory.FillRAM[0x2259] | (Memory.FillRAM[0x225a] << 8) | (Memory.FillRAM[0x225b] << 16); uint8_t shift = Memory.FillRAM [0x2258] & 15; if (no_shift) diff --git a/source/sar.h b/source/sar.h index 487cdaa..2fc14d2 100644 --- a/source/sar.h +++ b/source/sar.h @@ -50,7 +50,5 @@ static INLINE int64_t SAR64(const int64_t b, const int32_t n) #endif return b >> n; } - #endif - #endif diff --git a/source/sdd1.c b/source/sdd1.c index 58b934e..3a46ec9 100644 --- a/source/sdd1.c +++ b/source/sdd1.c @@ -9,9 +9,7 @@ void S9xSetSDD1MemoryMap(uint32_t bank, uint32_t value) { bank = 0xc00 + bank * 0x100; value = value * 1024 * 1024; - int32_t c; - for (c = 0; c < 0x100; c += 16) { uint8_t* block = &Memory.ROM [value + (c << 12)]; diff --git a/source/sdd1.h b/source/sdd1.h index 7f1df83..4ade993 100644 --- a/source/sdd1.h +++ b/source/sdd1.h @@ -4,7 +4,6 @@ #define _SDD1_H_ void S9xSetSDD1MemoryMap(uint32_t bank, uint32_t value); -void S9xResetSDD1(); -void S9xSDD1PostLoadState(); - +void S9xResetSDD1(void); +void S9xSDD1PostLoadState(void); #endif diff --git a/source/sdd1emu.c b/source/sdd1emu.c index 25da823..3aa1591 100644 --- a/source/sdd1emu.c +++ b/source/sdd1emu.c @@ -98,7 +98,8 @@ static INLINE uint8_t GetCodeword(int32_t bits) in_stream <<= 1; valid_bits--; in_stream ^= 0x8000; - if (in_stream & 0x8000) return 0x80 + (1 << bits); + if (in_stream & 0x8000) + return 0x80 + (1 << bits); tmp = (in_stream >> 8) | (0x7f >> bits); in_stream <<= bits; valid_bits -= bits; @@ -112,7 +113,8 @@ static INLINE uint8_t GetCodeword(int32_t bits) static INLINE uint8_t GolombGetBit(int32_t code_size) { - if (!bit_ctr[code_size]) bit_ctr[code_size] = GetCodeword(code_size); + if (!bit_ctr[code_size]) + bit_ctr[code_size] = GetCodeword(code_size); bit_ctr[code_size]--; if (bit_ctr[code_size] == 0x80) { @@ -150,12 +152,7 @@ static INLINE uint8_t ProbGetBit(uint8_t context) static INLINE uint8_t GetBit(uint8_t cur_bitplane) { - uint8_t bit; - - bit = ProbGetBit(((cur_bitplane & 1) << 4) - | ((prev_bits[cur_bitplane] & high_context_bits) >> 5) - | (prev_bits[cur_bitplane] & low_context_bits)); - + uint8_t bit = ProbGetBit(((cur_bitplane & 1) << 4) | ((prev_bits[cur_bitplane] & high_context_bits) >> 5) | (prev_bits[cur_bitplane] & low_context_bits)); prev_bits[cur_bitplane] <<= 1; prev_bits[cur_bitplane] |= bit; return bit; @@ -165,9 +162,8 @@ void SDD1_decompress(uint8_t* out, uint8_t* in, int32_t len) { uint8_t bit, i, plane; uint8_t byte1, byte2; - - if (len == 0) len = 0x10000; - + if (len == 0) + len = 0x10000; bitplane_type = in[0] >> 6; switch (in[0] & 0x30) @@ -205,13 +201,17 @@ void SDD1_decompress(uint8_t* out, uint8_t* in, int32_t len) { for (byte1 = byte2 = 0, bit = 0x80; bit; bit >>= 1) { - if (GetBit(0)) byte1 |= bit; - if (GetBit(1)) byte2 |= bit; + if(GetBit(0)) + byte1 |= bit; + if(GetBit(1)) + byte2 |= bit; } *(out++) = byte1; - if (!--len) return; + if(!--len) + return; *(out++) = byte2; - if (!--len) return; + if(!--len) + return; } break; case 1: @@ -220,14 +220,19 @@ void SDD1_decompress(uint8_t* out, uint8_t* in, int32_t len) { for (byte1 = byte2 = 0, bit = 0x80; bit; bit >>= 1) { - if (GetBit(plane)) byte1 |= bit; - if (GetBit(plane + 1)) byte2 |= bit; + if(GetBit(plane)) + byte1 |= bit; + if(GetBit(plane + 1)) + byte2 |= bit; } *(out++) = byte1; - if (!--len) return; + if(!--len) + return; *(out++) = byte2; - if (!--len) return; - if (!(i += 32)) plane = (plane + 2) & 7; + if(!--len) + return; + if(!(i += 32)) + plane = (plane + 2) & 7; } break; case 2: @@ -236,26 +241,29 @@ void SDD1_decompress(uint8_t* out, uint8_t* in, int32_t len) { for (byte1 = byte2 = 0, bit = 0x80; bit; bit >>= 1) { - if (GetBit(plane)) byte1 |= bit; - if (GetBit(plane + 1)) byte2 |= bit; + if(GetBit(plane)) + byte1 |= bit; + if(GetBit(plane + 1)) + byte2 |= bit; } *(out++) = byte1; - if (!--len) return; + if(!--len) + return; *(out++) = byte2; - if (!--len) return; - if (!(i += 32)) plane ^= 2; + if(!--len) + return; + if(!(i += 32)) + plane ^= 2; } break; case 3: do { - for (byte1 = plane = 0, bit = 1; bit; bit <<= 1, plane++) - { - if (GetBit(plane)) byte1 |= bit; - } + for(byte1 = plane = 0, bit = 1; bit; bit <<= 1, plane++) + if(GetBit(plane)) + byte1 |= bit; *(out++) = byte1; - } - while (--len); + } while(--len); break; } } diff --git a/source/sdd1emu.h b/source/sdd1emu.h index 07bdeb6..07162f5 100644 --- a/source/sdd1emu.h +++ b/source/sdd1emu.h @@ -4,5 +4,4 @@ #define SDD1EMU_H void SDD1_decompress(uint8_t* out, uint8_t* in, int32_t output_length); - #endif diff --git a/source/seta.h b/source/seta.h index 339ba05..6244f98 100644 --- a/source/seta.h +++ b/source/seta.h @@ -1,6 +1,5 @@ #include "../copyright" -#ifndef NO_SETA #ifndef _seta_h #define _seta_h @@ -59,6 +58,4 @@ typedef struct uint8_t parameters [512]; uint8_t output [512]; } ST018_Regs; - -#endif #endif diff --git a/source/seta010.c b/source/seta010.c index 4e1a293..ca6f121 100644 --- a/source/seta010.c +++ b/source/seta010.c @@ -36,7 +36,6 @@ uint8_t S9xGetST010(uint32_t Address) { if (!(Address & 0x80000)) return 0x80; - if ((Address & 0xFFF) == 0x20) return ST010.op_reg; if ((Address & 0xFFF) == 0x21) @@ -257,7 +256,8 @@ void ST010_OP01(int16_t x0, int16_t y0, int16_t* x1, int16_t* y1, int16_t* Quadr *y1 >>= 1; } - if (*y1 == 0) *Quadrant += 0x4000; + if(*y1 == 0) + *Quadrant += 0x4000; *Theta = (ST010_ArcTan[*y1][*x1] << 8) ^ *Quadrant; } @@ -284,13 +284,15 @@ void ST010_SortDrivers(uint16_t Positions, uint16_t Places[32], uint16_t Drivers bool Sorted; uint16_t Temp; - if (Positions > 1) + if(Positions > 1) + { do { Sorted = true; int32_t i; - for (i = 0; i < Positions - 1; i++) - if (Places[i] < Places[i + 1]) + for(i = 0; i < Positions - 1; i++) + { + if(Places[i] < Places[i + 1]) { Temp = Places[i + 1]; Places[i + 1] = Places[i]; @@ -302,9 +304,10 @@ void ST010_SortDrivers(uint16_t Positions, uint16_t Places[32], uint16_t Drivers Sorted = false; } + } Positions--; - } - while (!Sorted); + } while(!Sorted); + } } #define ST010_WORD(offset) (Memory.SRAM[offset + 1] << 8) | Memory.SRAM[offset] @@ -321,7 +324,8 @@ void S9xSetST010(uint32_t Address, uint8_t Byte) ST010.op_reg = Byte; if ((Address & 0xFFF) == 0x21 && ST010.control_enable) ST010.execute = Byte; - else Memory.SRAM[Address & Memory.SRAMMask] = Byte; + else + Memory.SRAM[Address & Memory.SRAMMask] = Byte; if (ST010.execute & 0x80) { @@ -462,7 +466,8 @@ void S9xSetST010(uint32_t Address, uint8_t Byte) Memory.SRAM[0x0250 + offset] = (uint8_t)(data); Memory.SRAM[0x0251 + offset] = (uint8_t)(data >> 8); - if (data) data = ~data; + if(data) + data = ~data; Memory.SRAM[0x03b0 + offset] = (uint8_t)(data); Memory.SRAM[0x03b1 + offset] = (uint8_t)(data >> 8); @@ -618,49 +623,45 @@ void S9xSetST010(uint32_t Address, uint8_t Byte) wrap = true; } - uint16_t old_speed; - - old_speed = speed; + uint16_t old_speed = speed; - // special case - if (ABS(o1 - rot) == 0x8000) + if (ABS(o1 - rot) == 0x8000) // special case speed = 0x100; - // slow down for sharp curves - else if (ABS(o1 - rot) >= 0x1000) + else if (ABS(o1 - rot) >= 0x1000) // slow down for sharp curves { uint32_t slow = ABS(o1 - rot); slow >>= 4; // scaling speed -= slow; } - // otherwise accelerate - else + else // otherwise accelerate { speed += accel; if (speed > speed_max) - { - // clip speed - speed = speed_max; - } + speed = speed_max; // clip speed } // prevent negative/positive overflow if (ABS(old_speed - speed) > 0x8000) { - if (old_speed < speed) speed = 0; - else speed = 0xff00; + if(old_speed < speed) + speed = 0; + else + speed = 0xff00; } // adjust direction by so many degrees // be careful of negative adjustments - if ((o1 > rot && (o1 - rot) > 0x80) || - (o1 < rot && (rot - o1) >= 0x80)) + if((o1 > rot && (o1 - rot) > 0x80) || (o1 < rot && (rot - o1) >= 0x80)) { - if (o1 < rot) rot -= 0x280; - else if (o1 > rot) rot += 0x280; + if(o1 < rot) + rot -= 0x280; + else if(o1 > rot) + rot += 0x280; } - // turn off wrapping - if (wrap) rot -= 0x8000; + /* turn off wrapping */ + if(wrap) + rot -= 0x8000; // now check the distances (store for later) dx = (xpos_max << 16) - xpos; @@ -669,8 +670,7 @@ void S9xSetST010(uint32_t Address, uint8_t Byte) dy >>= 16; // if we're in so many units of the target, signal it - if ((system && (dy <= 6 && dy >= -8) && (dx <= 126 && dx >= -128)) || - (!system && (dx <= 6 && dx >= -8) && (dy <= 126 && dy >= -128))) + if ((system && (dy <= 6 && dy >= -8) && (dx <= 126 && dx >= -128)) || (!system && (dx <= 6 && dx >= -8) && (dy <= 126 && dy >= -128))) { // announce our new destination and flag it xpos_max = xpos_new & 0x7FFF; diff --git a/source/seta011.c b/source/seta011.c index a005f98..10cd40b 100644 --- a/source/seta011.c +++ b/source/seta011.c @@ -1,30 +1,19 @@ #include "../copyright" -#include <stdio.h> #include "seta.h" #include "memmap.h" ST011_Regs ST011; - -// shougi playboard -uint8_t board[9][9]; - -// debug -static int32_t line = 0; +uint8_t board[9][9]; // shougi playboard uint8_t S9xGetST011(uint32_t Address) { uint8_t t; uint16_t address = (uint16_t) Address & 0xFFFF; - // line counter - line++; - - // status check - if (address == 0x01) + if (address == 0x01) // status check t = 0xFF; - // read directly from s-ram - else + else // read directly from s-ram t = Memory.SRAM[address]; return t; @@ -35,23 +24,17 @@ void S9xSetST011(uint32_t Address, uint8_t Byte) uint16_t address = (uint16_t) Address & 0xFFFF; static bool reset = false; - // debug - line++; - - if (!reset) + if (!reset) // bootup values { - // bootup values ST011.waiting4command = true; reset = true; } Memory.SRAM[address] = Byte; - // op commands/data goes through this address - if (address == 0x00) + if (address == 0x00) // op commands/data goes through this address { - // check for new commands - if (ST011.waiting4command) + if (ST011.waiting4command) // check for new commands { ST011.waiting4command = false; ST011.command = Byte; @@ -84,15 +67,13 @@ void S9xSetST011(uint32_t Address, uint8_t Byte) } } - if (ST011.in_count == ST011.in_index) + if (ST011.in_count == ST011.in_index) // Actually execute the command { - // Actually execute the command ST011.waiting4command = true; ST011.out_index = 0; switch (ST011.command) { - // unknown: download playboard - case 0x01: + case 0x01: // unknown: download playboard { // 9x9 board data: top to bottom, left to right // Values represent piece types and ownership @@ -101,11 +82,7 @@ void S9xSetST011(uint32_t Address, uint8_t Byte) memcpy(board[lcv], ST011.parameters + lcv * 10, 9 * 1); break; } - // unknown - case 0x02: - break; - // unknown - case 0x04: + case 0x04: // unknown case 0x05: { // outputs @@ -113,18 +90,13 @@ void S9xSetST011(uint32_t Address, uint8_t Byte) Memory.SRAM[0x12E] = 0x00; break; } - // unknown - case 0x06: - case 0x07: - break; - // unknown - case 0x0E: + case 0x0E: // unknown { // outputs Memory.SRAM[0x12C] = 0x00; Memory.SRAM[0x12D] = 0x00; + break; } - break; } } } diff --git a/source/seta018.c b/source/seta018.c index 840e479..a608960 100644 --- a/source/seta018.c +++ b/source/seta018.c @@ -5,15 +5,11 @@ ST018_Regs ST018; -static int32_t line; // line counter - uint8_t S9xGetST018(uint32_t Address) { uint8_t t = 0; // Initialise to some value for the compiler uint16_t address = (uint16_t) Address & 0xFFFF; - line++; - // these roles may be flipped // op output if (address == 0x3804) @@ -28,8 +24,7 @@ uint8_t S9xGetST018(uint32_t Address) else t = 0x81; } - // status register - else if (address == 0x3800) + else if (address == 0x3800) // status register t = ST018.status; return t; @@ -39,26 +34,20 @@ void S9xSetST018(uint8_t Byte, uint32_t Address) { uint16_t address = (uint16_t) Address & 0xFFFF; static bool reset = false; - line++; - if (!reset) + if (!reset) // bootup values { - // bootup values ST018.waiting4command = true; ST018.part_command = 0; reset = true; } Memory.SRAM[address] = Byte; + ST018.status = 0x00; // default status for now - // default status for now - ST018.status = 0x00; - - // op data goes through this address - if (address == 0x3804) + if (address == 0x3804) // op data goes through this address { - // check for new commands: 3 bytes length - if (ST018.waiting4command && ST018.part_command == 2) + if (ST018.waiting4command && ST018.part_command == 2) // check for new commands: 3 bytes length { ST018.waiting4command = false; ST018.command <<= 8; @@ -78,32 +67,28 @@ void S9xSetST018(uint8_t Byte, uint32_t Address) break; } } - else if (ST018.waiting4command) + else if (ST018.waiting4command) // 3-byte commands { - // 3-byte commands ST018.part_command++; ST018.command <<= 8; ST018.command |= Byte; } } - // extra parameters - else if (address == 0x3802) + else if (address == 0x3802) // extra parameters { ST018.parameters[ST018.in_index] = Byte; ST018.in_index++; } - if (ST018.in_count == ST018.in_index) + if (ST018.in_count == ST018.in_index) // Actually execute the command { - // Actually execute the command ST018.waiting4command = true; ST018.in_index = 0; ST018.out_index = 0; switch (ST018.command) { - // hardware check? case 0x0100: - case 0xFF00: + case 0xFF00: // hardware check? ST018.waiting4command = false; ST018.pass++; if (ST018.pass == 1) diff --git a/source/snes9x.h b/source/snes9x.h index 3107494..536642b 100644 --- a/source/snes9x.h +++ b/source/snes9x.h @@ -131,16 +131,6 @@ typedef struct int32_t HBlankStart; int32_t CyclesPercentage; bool DisableIRQ; - bool Paused; - bool ForcedPause; - bool StopEmulation; - - /* Tracing options */ - bool TraceDMA; - bool TraceHDMA; - bool TraceVRAM; - bool TraceUnknownRegisters; - bool TraceDSP; /* Joystick options */ bool JoystickEnabled; @@ -152,7 +142,6 @@ typedef struct uint32_t FrameTimePAL; uint32_t FrameTimeNTSC; uint32_t FrameTime; - uint32_t SkipFrames; /* ROM image options */ bool ForceLoROM; @@ -179,7 +168,6 @@ typedef struct bool SuperScope; bool SRTC; uint32_t ControllerOption; - bool ShutdownMaster; bool MultiPlayer5Master; bool SuperScopeMaster; bool MouseMaster; @@ -212,18 +200,6 @@ typedef struct bool Mute; bool NextAPUEnabled; - /* Graphics options */ - bool Transparency; - bool Mode7Interpolate; - - /* SNES graphics options */ - bool BGLayering; - bool DisableGraphicWindows; - bool ForceTransparency; - bool ForceNoTransparency; - bool DisableHDMA; - bool DisplayFrameRate; - /* Others */ bool ApplyCheats; @@ -231,35 +207,16 @@ typedef struct bool StarfoxHack; bool WinterGold; bool BS; /* Japanese Satellite System games. */ - uint8_t APURAMInitialValue; - bool SampleCatchup; bool JustifierMaster; bool Justifier; bool SecondJustifier; int8_t SETA; - bool TakeScreenshot; - int8_t StretchScreenshots; - uint16_t DisplayColor; - int32_t SoundDriver; - int32_t AIDOShmId; - bool NoPatch; - bool ForceInterleaveGD24; } SSettings; -typedef struct -{ - uint8_t APU_OutPorts_ReturnValueFix; - uint8_t SoundEnvelopeHeightReading2; - uint8_t SRAMInitialValue; - bool EchoOnlyOutput; -} SSNESGameFixes; - extern SSettings Settings; extern SCPUState CPU; -extern SSNESGameFixes SNESGameFixes; extern char String [513]; void S9xSetPause(uint32_t mask); void S9xClearPause(uint32_t mask); - #endif diff --git a/source/soundux.c b/source/soundux.c index 3f1a1fa..f053290 100644 --- a/source/soundux.c +++ b/source/soundux.c @@ -165,7 +165,7 @@ void S9xSetSoundVolume(int32_t channel, int16_t volume_left, int16_t volume_righ void S9xSetMasterVolume(int16_t volume_left, int16_t volume_right) { - if (Settings.DisableMasterVolume || SNESGameFixes.EchoOnlyOutput) + if (Settings.DisableMasterVolume) SoundData.master_volume [0] = SoundData.master_volume [1] = 127; else { diff --git a/source/spc700.c b/source/spc700.c index 6737e30..fed54ff 100644 --- a/source/spc700.c +++ b/source/spc700.c @@ -19,8 +19,8 @@ uint8_t Work8 = 0; uint16_t Work16 = 0; uint32_t Work32 = 0; -#define OP1 (*(IAPU.PC + 1)) -#define OP2 (*(IAPU.PC + 2)) +#define OP1 IAPU.PC[1] +#define OP2 IAPU.PC[2] #define APUShutdown() \ if (Settings.Shutdown && (IAPU.PC == IAPU.WaitAddress1 || IAPU.PC == IAPU.WaitAddress2)) \ @@ -39,19 +39,19 @@ uint32_t Work32 = 0; } #define APUSetZN8(b) \ - IAPU._Zero = (b); + IAPU._Zero = (b) #define APUSetZN16(w) \ - IAPU._Zero = ((w) != 0) | ((w) >> 8); + IAPU._Zero = ((w) != 0) | ((w) >> 8) #define TCALL(n) \ {\ - SPC700_PushW (IAPU.PC - IAPU.RAM + 1); \ + PushW (IAPU.PC - IAPU.RAM + 1); \ IAPU.PC = IAPU.RAM + S9xAPUGetByte(0xffc0 + ((15 - n) << 1)) + \ (S9xAPUGetByte(0xffc1 + ((15 - n) << 1)) << 8); \ } -#define SBC(a,b) \ +#define SBC(a, b) \ Int16 = (int16_t) (a) - (int16_t) (b) + (int16_t) (APUCheckCarry ()) - 1; \ IAPU._Carry = Int16 >= 0; \ if ((((a) ^ (b)) & 0x80) && (((a) ^ (uint8_t) Int16) & 0x80)) \ @@ -80,62 +80,68 @@ uint32_t Work32 = 0; #define CMP(a,b) \ Int16 = (int16_t) (a) - (int16_t) (b); \ IAPU._Carry = Int16 >= 0; \ - APUSetZN8((uint8_t) Int16); + APUSetZN8((uint8_t) Int16) #define ASL(b) \ IAPU._Carry = ((b) & 0x80) != 0; \ (b) <<= 1; \ - APUSetZN8 (b); + APUSetZN8 (b) + #define LSR(b) \ IAPU._Carry = (b) & 1; \ (b) >>= 1; \ - APUSetZN8 (b); + APUSetZN8 (b) + #define ROL(b) \ Work16 = ((b) << 1) | APUCheckCarry (); \ IAPU._Carry = Work16 >= 0x100; \ (b) = (uint8_t) Work16; \ - APUSetZN8 (b); + APUSetZN8 (b) + #define ROR(b) \ Work16 = (b) | ((uint16_t) APUCheckCarry () << 8); \ IAPU._Carry = (uint8_t) Work16 & 1; \ Work16 >>= 1; \ (b) = (uint8_t) Work16; \ - APUSetZN8 (b); + APUSetZN8 (b) #define Push(b) \ - *(IAPU.RAM + 0x100 + IAPU.Registers.S) = b; \ - IAPU.Registers.S--; + IAPU.RAM[0x100 + IAPU.Registers.S] = b; \ + IAPU.Registers.S-- #define Pop(b) \ IAPU.Registers.S++; \ - (b) = *(IAPU.RAM + 0x100 + IAPU.Registers.S); + (b) = *(IAPU.RAM + 0x100 + IAPU.Registers.S) #ifdef FAST_LSB_WORD_ACCESS -#define SPC700_PushW(w) \ - if (IAPU.Registers.S == 0) {\ +#define PushW(w) \ + if (IAPU.Registers.S == 0) \ + {\ *(IAPU.RAM + 0x1ff) = (w); \ *(IAPU.RAM + 0x100) = ((w) >> 8); \ - } else { \ + } \ + else \ *(uint16_t *) (IAPU.RAM + 0xff + IAPU.Registers.S) = w; \ - }\ - IAPU.Registers.S -= 2; + IAPU.Registers.S -= 2 + #define PopW(w) \ IAPU.Registers.S += 2; \ if (IAPU.Registers.S == 0) \ (w) = *(IAPU.RAM + 0x1ff) | (*(IAPU.RAM + 0x100) << 8); \ else \ - (w) = *(uint16_t *) (IAPU.RAM + 0xff + IAPU.Registers.S); + (w) = *(uint16_t *) (IAPU.RAM + 0xff + IAPU.Registers.S) #else -#define SPC700_PushW(w) \ +#define PushW(w) \ *(IAPU.RAM + 0xff + IAPU.Registers.S) = w; \ *(IAPU.RAM + 0x100 + IAPU.Registers.S) = ((w) >> 8); \ - IAPU.Registers.S -= 2; + IAPU.Registers.S -= 2 + #define PopW(w) \ IAPU.Registers.S += 2; \ if(IAPU.Registers.S == 0) \ (w) = *(IAPU.RAM + 0x1ff) | (*(IAPU.RAM + 0x100) << 8); \ else \ - (w) = *(IAPU.RAM + 0xff + IAPU.Registers.S) + (*(IAPU.RAM + 0x100 + IAPU.Registers.S) << 8); + (w) = *(IAPU.RAM + 0xff + IAPU.Registers.S) + (*(IAPU.RAM + 0x100 + IAPU.Registers.S) << 8) #endif #define Relative() \ @@ -170,6 +176,7 @@ uint32_t Work32 = 0; #define IndexedXIndirect() \ IAPU.Address = *(IAPU.DirectPage + ((OP1 + IAPU.Registers.X) & 0xff)) + \ (*(IAPU.DirectPage + ((OP1 + IAPU.Registers.X + 1) & 0xff)) << 8); + #define Absolute() \ IAPU.Address = OP1 + (OP2 << 8); @@ -190,104 +197,103 @@ uint32_t Work32 = 0; IAPU.Registers.YA.B.Y; #endif -void Apu00() +void Apu00(void) // NOP { - // NOP IAPU.PC++; } -void Apu01() +void Apu01(void) { - TCALL(0) + TCALL(0); } -void Apu11() +void Apu11(void) { - TCALL(1) + TCALL(1); } -void Apu21() +void Apu21(void) { - TCALL(2) + TCALL(2); } -void Apu31() +void Apu31(void) { - TCALL(3) + TCALL(3); } -void Apu41() +void Apu41(void) { - TCALL(4) + TCALL(4); } -void Apu51() +void Apu51(void) { - TCALL(5) + TCALL(5); } -void Apu61() +void Apu61(void) { - TCALL(6) + TCALL(6); } -void Apu71() +void Apu71(void) { - TCALL(7) + TCALL(7); } -void Apu81() +void Apu81(void) { - TCALL(8) + TCALL(8); } -void Apu91() +void Apu91(void) { - TCALL(9) + TCALL(9); } -void ApuA1() +void ApuA1(void) { - TCALL(10) + TCALL(10); } -void ApuB1() +void ApuB1(void) { - TCALL(11) + TCALL(11); } -void ApuC1() +void ApuC1(void) { - TCALL(12) + TCALL(12); } -void ApuD1() +void ApuD1(void) { - TCALL(13) + TCALL(13); } -void ApuE1() +void ApuE1(void) { - TCALL(14) + TCALL(14); } -void ApuF1() +void ApuF1(void) { - TCALL(15) + TCALL(15); } -void Apu3F() // CALL absolute +void Apu3F(void) // CALL absolute { Absolute(); // 0xB6f for Star Fox 2 - SPC700_PushW(IAPU.PC + 3 - IAPU.RAM); + PushW(IAPU.PC + 3 - IAPU.RAM); IAPU.PC = IAPU.RAM + IAPU.Address; } -void Apu4F() // PCALL $XX +void Apu4F(void) // PCALL $XX { Work8 = OP1; - SPC700_PushW(IAPU.PC + 2 - IAPU.RAM); + PushW(IAPU.PC + 2 - IAPU.RAM); IAPU.PC = IAPU.RAM + 0xff00 + Work8; } @@ -295,42 +301,42 @@ void Apu4F() // PCALL $XX S9xAPUSetByteZ ((uint8_t) (S9xAPUGetByteZ (OP1 ) | (1 << (b))), OP1); \ IAPU.PC += 2 -void Apu02() +void Apu02(void) { SET(0); } -void Apu22() +void Apu22(void) { SET(1); } -void Apu42() +void Apu42(void) { SET(2); } -void Apu62() +void Apu62(void) { SET(3); } -void Apu82() +void Apu82(void) { SET(4); } -void ApuA2() +void ApuA2(void) { SET(5); } -void ApuC2() +void ApuC2(void) { SET(6); } -void ApuE2() +void ApuE2(void) { SET(7); } @@ -339,42 +345,42 @@ void ApuE2() S9xAPUSetByteZ ((uint8_t) (S9xAPUGetByteZ (OP1) & ~(1 << (b))), OP1); \ IAPU.PC += 2; -void Apu12() +void Apu12(void) { CLR(0); } -void Apu32() +void Apu32(void) { CLR(1); } -void Apu52() +void Apu52(void) { CLR(2); } -void Apu72() +void Apu72(void) { CLR(3); } -void Apu92() +void Apu92(void) { CLR(4); } -void ApuB2() +void ApuB2(void) { CLR(5); } -void ApuD2() +void ApuD2(void) { CLR(6); } -void ApuF2() +void ApuF2(void) { CLR(7); } @@ -390,42 +396,42 @@ if (S9xAPUGetByteZ (Work8) & (1 << (b))) \ else \ IAPU.PC += 3 -void Apu03() +void Apu03(void) { BBS(0); } -void Apu23() +void Apu23(void) { BBS(1); } -void Apu43() +void Apu43(void) { BBS(2); } -void Apu63() +void Apu63(void) { BBS(3); } -void Apu83() +void Apu83(void) { BBS(4); } -void ApuA3() +void ApuA3(void) { BBS(5); } -void ApuC3() +void ApuC3(void) { BBS(6); } -void ApuE3() +void ApuE3(void) { BBS(7); } @@ -441,47 +447,47 @@ if (!(S9xAPUGetByteZ (Work8) & (1 << (b)))) \ else \ IAPU.PC += 3 -void Apu13() +void Apu13(void) { BBC(0); } -void Apu33() +void Apu33(void) { BBC(1); } -void Apu53() +void Apu53(void) { BBC(2); } -void Apu73() +void Apu73(void) { BBC(3); } -void Apu93() +void Apu93(void) { BBC(4); } -void ApuB3() +void ApuB3(void) { BBC(5); } -void ApuD3() +void ApuD3(void) { BBC(6); } -void ApuF3() +void ApuF3(void) { BBC(7); } -void Apu04() +void Apu04(void) { // OR A,dp IAPU.Registers.YA.B.A |= S9xAPUGetByteZ(OP1); @@ -489,7 +495,7 @@ void Apu04() IAPU.PC += 2; } -void Apu05() +void Apu05(void) { // OR A,abs Absolute(); @@ -498,7 +504,7 @@ void Apu05() IAPU.PC += 3; } -void Apu06() +void Apu06(void) { // OR A,(X) IAPU.Registers.YA.B.A |= S9xAPUGetByteZ(IAPU.Registers.X); @@ -506,7 +512,7 @@ void Apu06() IAPU.PC++; } -void Apu07() +void Apu07(void) { // OR A,(dp+X) IndexedXIndirect(); @@ -515,7 +521,7 @@ void Apu07() IAPU.PC += 2; } -void Apu08() +void Apu08(void) { // OR A,#00 IAPU.Registers.YA.B.A |= OP1; @@ -523,7 +529,7 @@ void Apu08() IAPU.PC += 2; } -void Apu09() +void Apu09(void) { // OR dp(dest),dp(src) Work8 = S9xAPUGetByteZ(OP1); @@ -533,7 +539,7 @@ void Apu09() IAPU.PC += 3; } -void Apu14() +void Apu14(void) { // OR A,dp+X IAPU.Registers.YA.B.A |= S9xAPUGetByteZ(OP1 + IAPU.Registers.X); @@ -541,7 +547,7 @@ void Apu14() IAPU.PC += 2; } -void Apu15() +void Apu15(void) { // OR A,abs+X AbsoluteX(); @@ -550,7 +556,7 @@ void Apu15() IAPU.PC += 3; } -void Apu16() +void Apu16(void) { // OR A,abs+Y AbsoluteY(); @@ -559,7 +565,7 @@ void Apu16() IAPU.PC += 3; } -void Apu17() +void Apu17(void) { // OR A,(dp)+Y IndirectIndexedY(); @@ -568,7 +574,7 @@ void Apu17() IAPU.PC += 2; } -void Apu18() +void Apu18(void) { // OR dp,#00 Work8 = OP1; @@ -578,7 +584,7 @@ void Apu18() IAPU.PC += 3; } -void Apu19() +void Apu19(void) { // OR (X),(Y) Work8 = S9xAPUGetByteZ(IAPU.Registers.X) | S9xAPUGetByteZ(IAPU.Registers.YA.B.Y); @@ -587,55 +593,47 @@ void Apu19() IAPU.PC++; } -void Apu0A() +void Apu0A(void) { // OR1 C,membit MemBit(); if (!APUCheckCarry()) - { if (S9xAPUGetByte(IAPU.Address) & (1 << IAPU.Bit)) APUSetCarry(); - } IAPU.PC += 3; } -void Apu2A() +void Apu2A(void) { // OR1 C,not membit MemBit(); if (!APUCheckCarry()) - { if (!(S9xAPUGetByte(IAPU.Address) & (1 << IAPU.Bit))) APUSetCarry(); - } IAPU.PC += 3; } -void Apu4A() +void Apu4A(void) { // AND1 C,membit MemBit(); if (APUCheckCarry()) - { if (!(S9xAPUGetByte(IAPU.Address) & (1 << IAPU.Bit))) APUClearCarry(); - } IAPU.PC += 3; } -void Apu6A() +void Apu6A(void) { // AND1 C, not membit MemBit(); if (APUCheckCarry()) - { if ((S9xAPUGetByte(IAPU.Address) & (1 << IAPU.Bit))) APUClearCarry(); - } IAPU.PC += 3; } -void Apu8A() +void Apu8A(void) { // EOR1 C, membit MemBit(); @@ -649,7 +647,7 @@ void Apu8A() IAPU.PC += 3; } -void ApuAA() +void ApuAA(void) { // MOV1 C,membit MemBit(); @@ -660,7 +658,7 @@ void ApuAA() IAPU.PC += 3; } -void ApuCA() +void ApuCA(void) { // MOV1 membit,C MemBit(); @@ -671,7 +669,7 @@ void ApuCA() IAPU.PC += 3; } -void ApuEA() +void ApuEA(void) { // NOT1 membit MemBit(); @@ -679,7 +677,7 @@ void ApuEA() IAPU.PC += 3; } -void Apu0B() +void Apu0B(void) { // ASL dp Work8 = S9xAPUGetByteZ(OP1); @@ -688,7 +686,7 @@ void Apu0B() IAPU.PC += 2; } -void Apu0C() +void Apu0C(void) { // ASL abs Absolute(); @@ -698,7 +696,7 @@ void Apu0C() IAPU.PC += 3; } -void Apu1B() +void Apu1B(void) { // ASL dp+X Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X); @@ -707,14 +705,14 @@ void Apu1B() IAPU.PC += 2; } -void Apu1C() +void Apu1C(void) { // ASL A ASL(IAPU.Registers.YA.B.A); IAPU.PC++; } -void Apu0D() +void Apu0D(void) { // PUSH PSW S9xAPUPackStatus(); @@ -722,28 +720,28 @@ void Apu0D() IAPU.PC++; } -void Apu2D() +void Apu2D(void) { // PUSH A Push(IAPU.Registers.YA.B.A); IAPU.PC++; } -void Apu4D() +void Apu4D(void) { // PUSH X Push(IAPU.Registers.X); IAPU.PC++; } -void Apu6D() +void Apu6D(void) { // PUSH Y Push(IAPU.Registers.YA.B.Y); IAPU.PC++; } -void Apu8E() +void Apu8E(void) { // POP PSW Pop(IAPU.Registers.P); @@ -755,28 +753,28 @@ void Apu8E() IAPU.PC++; } -void ApuAE() +void ApuAE(void) { // POP A Pop(IAPU.Registers.YA.B.A); IAPU.PC++; } -void ApuCE() +void ApuCE(void) { // POP X Pop(IAPU.Registers.X); IAPU.PC++; } -void ApuEE() +void ApuEE(void) { // POP Y Pop(IAPU.Registers.YA.B.Y); IAPU.PC++; } -void Apu0E() +void Apu0E(void) { // TSET1 abs Absolute(); @@ -787,7 +785,7 @@ void Apu0E() IAPU.PC += 3; } -void Apu4E() +void Apu4E(void) { // TCLR1 abs Absolute(); @@ -798,10 +796,10 @@ void Apu4E() IAPU.PC += 3; } -void Apu0F() +void Apu0F(void) { // BRK - SPC700_PushW(IAPU.PC + 1 - IAPU.RAM); + PushW(IAPU.PC + 1 - IAPU.RAM); S9xAPUPackStatus(); Push(IAPU.Registers.P); APUSetBreak(); @@ -809,14 +807,14 @@ void Apu0F() IAPU.PC = IAPU.RAM + S9xAPUGetByte(0xffde) + (S9xAPUGetByte(0xffdf) << 8); } -void ApuEF() +void ApuEF(void) { // SLEEP APU.TimerEnabled[0] = APU.TimerEnabled[1] = APU.TimerEnabled[2] = false; IAPU.APUExecuting = false; } -void ApuFF() +void ApuFF(void) { // STOP APU.TimerEnabled[0] = APU.TimerEnabled[1] = APU.TimerEnabled[2] = false; @@ -824,7 +822,7 @@ void ApuFF() Settings.APUEnabled = false; // re-enabled on next APU reset } -void Apu10() +void Apu10(void) { // BPL Relative(); @@ -838,7 +836,7 @@ void Apu10() IAPU.PC += 2; } -void Apu30() +void Apu30(void) { // BMI Relative(); @@ -852,7 +850,7 @@ void Apu30() IAPU.PC += 2; } -void Apu90() +void Apu90(void) { // BCC Relative(); @@ -866,7 +864,7 @@ void Apu90() IAPU.PC += 2; } -void ApuB0() +void ApuB0(void) { // BCS Relative(); @@ -880,7 +878,7 @@ void ApuB0() IAPU.PC += 2; } -void ApuD0() +void ApuD0(void) { // BNE Relative(); @@ -894,7 +892,7 @@ void ApuD0() IAPU.PC += 2; } -void ApuF0() +void ApuF0(void) { // BEQ Relative(); @@ -908,7 +906,7 @@ void ApuF0() IAPU.PC += 2; } -void Apu50() +void Apu50(void) { // BVC Relative(); @@ -921,7 +919,7 @@ void Apu50() IAPU.PC += 2; } -void Apu70() +void Apu70(void) { // BVS Relative(); @@ -934,28 +932,28 @@ void Apu70() IAPU.PC += 2; } -void Apu2F() +void Apu2F(void) { // BRA Relative(); IAPU.PC = IAPU.RAM + (uint16_t) Int16; } -void Apu80() +void Apu80(void) { // SETC APUSetCarry(); IAPU.PC++; } -void ApuED() +void ApuED(void) { // NOTC IAPU._Carry ^= 1; IAPU.PC++; } -void Apu40() +void Apu40(void) { // SETP APUSetDirectPage(); @@ -963,7 +961,7 @@ void Apu40() IAPU.PC++; } -void Apu1A() +void Apu1A(void) { // DECW dp Work16 = S9xAPUGetByteZ(OP1) + (S9xAPUGetByteZ(OP1 + 1) << 8) - 1; @@ -973,7 +971,7 @@ void Apu1A() IAPU.PC += 2; } -void Apu5A() +void Apu5A(void) { // CMPW YA,dp Work16 = S9xAPUGetByteZ(OP1) + (S9xAPUGetByteZ(OP1 + 1) << 8); @@ -983,7 +981,7 @@ void Apu5A() IAPU.PC += 2; } -void Apu3A() +void Apu3A(void) { // INCW dp Work16 = S9xAPUGetByteZ(OP1) + (S9xAPUGetByteZ(OP1 + 1) << 8) + 1; @@ -993,7 +991,7 @@ void Apu3A() IAPU.PC += 2; } -void Apu7A() +void Apu7A(void) { // ADDW YA,dp Work16 = S9xAPUGetByteZ(OP1) + (S9xAPUGetByteZ(OP1 + 1) << 8); @@ -1011,15 +1009,14 @@ void Apu7A() IAPU.PC += 2; } -void Apu9A() +void Apu9A(void) { // SUBW YA,dp Work16 = S9xAPUGetByteZ(OP1) + (S9xAPUGetByteZ(OP1 + 1) << 8); Int32 = (int32_t) IAPU.Registers.YA.W - (int32_t) Work16; APUClearHalfCarry(); IAPU._Carry = Int32 >= 0; - if (((IAPU.Registers.YA.W ^ Work16) & 0x8000) && - ((IAPU.Registers.YA.W ^ (uint16_t) Int32) & 0x8000)) + if (((IAPU.Registers.YA.W ^ Work16) & 0x8000) && ((IAPU.Registers.YA.W ^ (uint16_t) Int32) & 0x8000)) APUSetOverflow(); else APUClearOverflow(); @@ -1031,7 +1028,7 @@ void Apu9A() IAPU.PC += 2; } -void ApuBA() +void ApuBA(void) { // MOVW YA,dp IAPU.Registers.YA.B.A = S9xAPUGetByteZ(OP1); @@ -1040,7 +1037,7 @@ void ApuBA() IAPU.PC += 2; } -void ApuDA() +void ApuDA(void) { // MOVW dp,YA S9xAPUSetByteZ(IAPU.Registers.YA.B.A, OP1); @@ -1048,7 +1045,7 @@ void ApuDA() IAPU.PC += 2; } -void Apu64() +void Apu64(void) { // CMP A,dp Work8 = S9xAPUGetByteZ(OP1); @@ -1056,7 +1053,7 @@ void Apu64() IAPU.PC += 2; } -void Apu65() +void Apu65(void) { // CMP A,abs Absolute(); @@ -1065,7 +1062,7 @@ void Apu65() IAPU.PC += 3; } -void Apu66() +void Apu66(void) { // CMP A,(X) Work8 = S9xAPUGetByteZ(IAPU.Registers.X); @@ -1073,7 +1070,7 @@ void Apu66() IAPU.PC++; } -void Apu67() +void Apu67(void) { // CMP A,(dp+X) IndexedXIndirect(); @@ -1082,7 +1079,7 @@ void Apu67() IAPU.PC += 2; } -void Apu68() +void Apu68(void) { // CMP A,#00 Work8 = OP1; @@ -1090,7 +1087,7 @@ void Apu68() IAPU.PC += 2; } -void Apu69() +void Apu69(void) { // CMP dp(dest), dp(src) W1 = S9xAPUGetByteZ(OP1); @@ -1099,7 +1096,7 @@ void Apu69() IAPU.PC += 3; } -void Apu74() +void Apu74(void) { // CMP A, dp+X Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X); @@ -1107,7 +1104,7 @@ void Apu74() IAPU.PC += 2; } -void Apu75() +void Apu75(void) { // CMP A,abs+X AbsoluteX(); @@ -1116,7 +1113,7 @@ void Apu75() IAPU.PC += 3; } -void Apu76() +void Apu76(void) { // CMP A, abs+Y AbsoluteY(); @@ -1125,7 +1122,7 @@ void Apu76() IAPU.PC += 3; } -void Apu77() +void Apu77(void) { // CMP A,(dp)+Y IndirectIndexedY(); @@ -1134,7 +1131,7 @@ void Apu77() IAPU.PC += 2; } -void Apu78() +void Apu78(void) { // CMP dp,#00 Work8 = OP1; @@ -1143,7 +1140,7 @@ void Apu78() IAPU.PC += 3; } -void Apu79() +void Apu79(void) { // CMP (X),(Y) W1 = S9xAPUGetByteZ(IAPU.Registers.X); @@ -1152,7 +1149,7 @@ void Apu79() IAPU.PC++; } -void Apu1E() +void Apu1E(void) { // CMP X,abs Absolute(); @@ -1161,7 +1158,7 @@ void Apu1E() IAPU.PC += 3; } -void Apu3E() +void Apu3E(void) { // CMP X,dp Work8 = S9xAPUGetByteZ(OP1); @@ -1169,14 +1166,14 @@ void Apu3E() IAPU.PC += 2; } -void ApuC8() +void ApuC8(void) { // CMP X,#00 CMP(IAPU.Registers.X, OP1); IAPU.PC += 2; } -void Apu5E() +void Apu5E(void) { // CMP Y,abs Absolute(); @@ -1185,7 +1182,7 @@ void Apu5E() IAPU.PC += 3; } -void Apu7E() +void Apu7E(void) { // CMP Y,dp Work8 = S9xAPUGetByteZ(OP1); @@ -1193,7 +1190,7 @@ void Apu7E() IAPU.PC += 2; } -void ApuAD() +void ApuAD(void) { // CMP Y,#00 Work8 = OP1; @@ -1201,22 +1198,21 @@ void ApuAD() IAPU.PC += 2; } -void Apu1F() +void Apu1F(void) { // JMP (abs+X) Absolute(); - IAPU.PC = IAPU.RAM + S9xAPUGetByte(IAPU.Address + IAPU.Registers.X) + - (S9xAPUGetByte(IAPU.Address + IAPU.Registers.X + 1) << 8); + IAPU.PC = IAPU.RAM + S9xAPUGetByte(IAPU.Address + IAPU.Registers.X) + (S9xAPUGetByte(IAPU.Address + IAPU.Registers.X + 1) << 8); } -void Apu5F() +void Apu5F(void) { // JMP abs Absolute(); IAPU.PC = IAPU.RAM + IAPU.Address; } -void Apu20() +void Apu20(void) { // CLRP APUClearDirectPage(); @@ -1224,14 +1220,14 @@ void Apu20() IAPU.PC++; } -void Apu60() +void Apu60(void) { // CLRC APUClearCarry(); IAPU.PC++; } -void ApuE0() +void ApuE0(void) { // CLRV APUClearHalfCarry(); @@ -1239,7 +1235,7 @@ void ApuE0() IAPU.PC++; } -void Apu24() +void Apu24(void) { // AND A,dp IAPU.Registers.YA.B.A &= S9xAPUGetByteZ(OP1); @@ -1247,7 +1243,7 @@ void Apu24() IAPU.PC += 2; } -void Apu25() +void Apu25(void) { // AND A,abs Absolute(); @@ -1256,7 +1252,7 @@ void Apu25() IAPU.PC += 3; } -void Apu26() +void Apu26(void) { // AND A,(X) IAPU.Registers.YA.B.A &= S9xAPUGetByteZ(IAPU.Registers.X); @@ -1264,7 +1260,7 @@ void Apu26() IAPU.PC++; } -void Apu27() +void Apu27(void) { // AND A,(dp+X) IndexedXIndirect(); @@ -1273,7 +1269,7 @@ void Apu27() IAPU.PC += 2; } -void Apu28() +void Apu28(void) { // AND A,#00 IAPU.Registers.YA.B.A &= OP1; @@ -1281,7 +1277,7 @@ void Apu28() IAPU.PC += 2; } -void Apu29() +void Apu29(void) { // AND dp(dest),dp(src) Work8 = S9xAPUGetByteZ(OP1); @@ -1291,7 +1287,7 @@ void Apu29() IAPU.PC += 3; } -void Apu34() +void Apu34(void) { // AND A,dp+X IAPU.Registers.YA.B.A &= S9xAPUGetByteZ(OP1 + IAPU.Registers.X); @@ -1299,7 +1295,7 @@ void Apu34() IAPU.PC += 2; } -void Apu35() +void Apu35(void) { // AND A,abs+X AbsoluteX(); @@ -1308,7 +1304,7 @@ void Apu35() IAPU.PC += 3; } -void Apu36() +void Apu36(void) { // AND A,abs+Y AbsoluteY(); @@ -1317,7 +1313,7 @@ void Apu36() IAPU.PC += 3; } -void Apu37() +void Apu37(void) { // AND A,(dp)+Y IndirectIndexedY(); @@ -1326,7 +1322,7 @@ void Apu37() IAPU.PC += 2; } -void Apu38() +void Apu38(void) { // AND dp,#00 Work8 = OP1; @@ -1336,7 +1332,7 @@ void Apu38() IAPU.PC += 3; } -void Apu39() +void Apu39(void) { // AND (X),(Y) Work8 = S9xAPUGetByteZ(IAPU.Registers.X) & S9xAPUGetByteZ(IAPU.Registers.YA.B.Y); @@ -1345,7 +1341,7 @@ void Apu39() IAPU.PC++; } -void Apu2B() +void Apu2B(void) { // ROL dp Work8 = S9xAPUGetByteZ(OP1); @@ -1354,7 +1350,7 @@ void Apu2B() IAPU.PC += 2; } -void Apu2C() +void Apu2C(void) { // ROL abs Absolute(); @@ -1364,7 +1360,7 @@ void Apu2C() IAPU.PC += 3; } -void Apu3B() +void Apu3B(void) { // ROL dp+X Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X); @@ -1373,14 +1369,14 @@ void Apu3B() IAPU.PC += 2; } -void Apu3C() +void Apu3C(void) { // ROL A ROL(IAPU.Registers.YA.B.A); IAPU.PC++; } -void Apu2E() +void Apu2E(void) { // CBNE dp,rel Work8 = OP1; @@ -1396,7 +1392,7 @@ void Apu2E() IAPU.PC += 3; } -void ApuDE() +void ApuDE(void) { // CBNE dp+X,rel Work8 = OP1 + IAPU.Registers.X; @@ -1412,7 +1408,7 @@ void ApuDE() IAPU.PC += 3; } -void Apu3D() +void Apu3D(void) { // INC X IAPU.Registers.X++; @@ -1421,7 +1417,7 @@ void Apu3D() IAPU.PC++; } -void ApuFC() +void ApuFC(void) { // INC Y IAPU.Registers.YA.B.Y++; @@ -1430,7 +1426,7 @@ void ApuFC() IAPU.PC++; } -void Apu1D() +void Apu1D(void) { // DEC X IAPU.Registers.X--; @@ -1439,7 +1435,7 @@ void Apu1D() IAPU.PC++; } -void ApuDC() +void ApuDC(void) { // DEC Y IAPU.Registers.YA.B.Y--; @@ -1448,7 +1444,7 @@ void ApuDC() IAPU.PC++; } -void ApuAB() +void ApuAB(void) { // INC dp Work8 = S9xAPUGetByteZ(OP1) + 1; @@ -1458,7 +1454,7 @@ void ApuAB() IAPU.PC += 2; } -void ApuAC() +void ApuAC(void) { // INC abs Absolute(); @@ -1469,7 +1465,7 @@ void ApuAC() IAPU.PC += 3; } -void ApuBB() +void ApuBB(void) { // INC dp+X Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X) + 1; @@ -1479,7 +1475,7 @@ void ApuBB() IAPU.PC += 2; } -void ApuBC() +void ApuBC(void) { // INC A IAPU.Registers.YA.B.A++; @@ -1488,7 +1484,7 @@ void ApuBC() IAPU.PC++; } -void Apu8B() +void Apu8B(void) { // DEC dp Work8 = S9xAPUGetByteZ(OP1) - 1; @@ -1498,7 +1494,7 @@ void Apu8B() IAPU.PC += 2; } -void Apu8C() +void Apu8C(void) { // DEC abs Absolute(); @@ -1509,7 +1505,7 @@ void Apu8C() IAPU.PC += 3; } -void Apu9B() +void Apu9B(void) { // DEC dp+X Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X) - 1; @@ -1519,7 +1515,7 @@ void Apu9B() IAPU.PC += 2; } -void Apu9C() +void Apu9C(void) { // DEC A IAPU.Registers.YA.B.A--; @@ -1528,7 +1524,7 @@ void Apu9C() IAPU.PC++; } -void Apu44() +void Apu44(void) { // EOR A,dp IAPU.Registers.YA.B.A ^= S9xAPUGetByteZ(OP1); @@ -1536,7 +1532,7 @@ void Apu44() IAPU.PC += 2; } -void Apu45() +void Apu45(void) { // EOR A,abs Absolute(); @@ -1545,7 +1541,7 @@ void Apu45() IAPU.PC += 3; } -void Apu46() +void Apu46(void) { // EOR A,(X) IAPU.Registers.YA.B.A ^= S9xAPUGetByteZ(IAPU.Registers.X); @@ -1553,7 +1549,7 @@ void Apu46() IAPU.PC++; } -void Apu47() +void Apu47(void) { // EOR A,(dp+X) IndexedXIndirect(); @@ -1562,7 +1558,7 @@ void Apu47() IAPU.PC += 2; } -void Apu48() +void Apu48(void) { // EOR A,#00 IAPU.Registers.YA.B.A ^= OP1; @@ -1570,7 +1566,7 @@ void Apu48() IAPU.PC += 2; } -void Apu49() +void Apu49(void) { // EOR dp(dest),dp(src) Work8 = S9xAPUGetByteZ(OP1); @@ -1580,7 +1576,7 @@ void Apu49() IAPU.PC += 3; } -void Apu54() +void Apu54(void) { // EOR A,dp+X IAPU.Registers.YA.B.A ^= S9xAPUGetByteZ(OP1 + IAPU.Registers.X); @@ -1588,7 +1584,7 @@ void Apu54() IAPU.PC += 2; } -void Apu55() +void Apu55(void) { // EOR A,abs+X AbsoluteX(); @@ -1597,7 +1593,7 @@ void Apu55() IAPU.PC += 3; } -void Apu56() +void Apu56(void) { // EOR A,abs+Y AbsoluteY(); @@ -1606,7 +1602,7 @@ void Apu56() IAPU.PC += 3; } -void Apu57() +void Apu57(void) { // EOR A,(dp)+Y IndirectIndexedY(); @@ -1615,7 +1611,7 @@ void Apu57() IAPU.PC += 2; } -void Apu58() +void Apu58(void) { // EOR dp,#00 Work8 = OP1; @@ -1625,7 +1621,7 @@ void Apu58() IAPU.PC += 3; } -void Apu59() +void Apu59(void) { // EOR (X),(Y) Work8 = S9xAPUGetByteZ(IAPU.Registers.X) ^ S9xAPUGetByteZ(IAPU.Registers.YA.B.Y); @@ -1634,7 +1630,7 @@ void Apu59() IAPU.PC++; } -void Apu4B() +void Apu4B(void) { // LSR dp Work8 = S9xAPUGetByteZ(OP1); @@ -1643,7 +1639,7 @@ void Apu4B() IAPU.PC += 2; } -void Apu4C() +void Apu4C(void) { // LSR abs Absolute(); @@ -1653,7 +1649,7 @@ void Apu4C() IAPU.PC += 3; } -void Apu5B() +void Apu5B(void) { // LSR dp+X Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X); @@ -1662,14 +1658,14 @@ void Apu5B() IAPU.PC += 2; } -void Apu5C() +void Apu5C(void) { // LSR A LSR(IAPU.Registers.YA.B.A); IAPU.PC++; } -void Apu7D() +void Apu7D(void) { // MOV A,X IAPU.Registers.YA.B.A = IAPU.Registers.X; @@ -1677,7 +1673,7 @@ void Apu7D() IAPU.PC++; } -void ApuDD() +void ApuDD(void) { // MOV A,Y IAPU.Registers.YA.B.A = IAPU.Registers.YA.B.Y; @@ -1685,7 +1681,7 @@ void ApuDD() IAPU.PC++; } -void Apu5D() +void Apu5D(void) { // MOV X,A IAPU.Registers.X = IAPU.Registers.YA.B.A; @@ -1693,7 +1689,7 @@ void Apu5D() IAPU.PC++; } -void ApuFD() +void ApuFD(void) { // MOV Y,A IAPU.Registers.YA.B.Y = IAPU.Registers.YA.B.A; @@ -1701,7 +1697,7 @@ void ApuFD() IAPU.PC++; } -void Apu9D() +void Apu9D(void) { //MOV X,SP IAPU.Registers.X = IAPU.Registers.S; @@ -1709,14 +1705,14 @@ void Apu9D() IAPU.PC++; } -void ApuBD() +void ApuBD(void) { // MOV SP,X IAPU.Registers.S = IAPU.Registers.X; IAPU.PC++; } -void Apu6B() +void Apu6B(void) { // ROR dp Work8 = S9xAPUGetByteZ(OP1); @@ -1725,7 +1721,7 @@ void Apu6B() IAPU.PC += 2; } -void Apu6C() +void Apu6C(void) { // ROR abs Absolute(); @@ -1735,7 +1731,7 @@ void Apu6C() IAPU.PC += 3; } -void Apu7B() +void Apu7B(void) { // ROR dp+X Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X); @@ -1744,14 +1740,14 @@ void Apu7B() IAPU.PC += 2; } -void Apu7C() +void Apu7C(void) { // ROR A ROR(IAPU.Registers.YA.B.A); IAPU.PC++; } -void Apu6E() +void Apu6E(void) { // DBNZ dp,rel Work8 = OP1; @@ -1767,7 +1763,7 @@ void Apu6E() IAPU.PC += 3; } -void ApuFE() +void ApuFE(void) { // DBNZ Y,rel Relative(); @@ -1781,14 +1777,14 @@ void ApuFE() IAPU.PC += 2; } -void Apu6F() +void Apu6F(void) { // RET PopW(IAPU.Registers.PC); IAPU.PC = IAPU.RAM + IAPU.Registers.PC; } -void Apu7F() +void Apu7F(void) { // RETI Pop(IAPU.Registers.P); @@ -1797,7 +1793,7 @@ void Apu7F() IAPU.PC = IAPU.RAM + IAPU.Registers.PC; } -void Apu84() +void Apu84(void) { // ADC A,dp Work8 = S9xAPUGetByteZ(OP1); @@ -1805,7 +1801,7 @@ void Apu84() IAPU.PC += 2; } -void Apu85() +void Apu85(void) { // ADC A, abs Absolute(); @@ -1814,7 +1810,7 @@ void Apu85() IAPU.PC += 3; } -void Apu86() +void Apu86(void) { // ADC A,(X) Work8 = S9xAPUGetByteZ(IAPU.Registers.X); @@ -1822,7 +1818,7 @@ void Apu86() IAPU.PC++; } -void Apu87() +void Apu87(void) { // ADC A,(dp+X) IndexedXIndirect(); @@ -1831,7 +1827,7 @@ void Apu87() IAPU.PC += 2; } -void Apu88() +void Apu88(void) { // ADC A,#00 Work8 = OP1; @@ -1839,7 +1835,7 @@ void Apu88() IAPU.PC += 2; } -void Apu89() +void Apu89(void) { // ADC dp(dest),dp(src) Work8 = S9xAPUGetByteZ(OP1); @@ -1849,7 +1845,7 @@ void Apu89() IAPU.PC += 3; } -void Apu94() +void Apu94(void) { // ADC A,dp+X Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X); @@ -1857,7 +1853,7 @@ void Apu94() IAPU.PC += 2; } -void Apu95() +void Apu95(void) { // ADC A, abs+X AbsoluteX(); @@ -1866,7 +1862,7 @@ void Apu95() IAPU.PC += 3; } -void Apu96() +void Apu96(void) { // ADC A, abs+Y AbsoluteY(); @@ -1875,7 +1871,7 @@ void Apu96() IAPU.PC += 3; } -void Apu97() +void Apu97(void) { // ADC A, (dp)+Y IndirectIndexedY(); @@ -1884,7 +1880,7 @@ void Apu97() IAPU.PC += 2; } -void Apu98() +void Apu98(void) { // ADC dp,#00 Work8 = OP1; @@ -1894,7 +1890,7 @@ void Apu98() IAPU.PC += 3; } -void Apu99() +void Apu99(void) { // ADC (X),(Y) W1 = S9xAPUGetByteZ(IAPU.Registers.X); @@ -1904,7 +1900,7 @@ void Apu99() IAPU.PC++; } -void Apu8D() +void Apu8D(void) { // MOV Y,#00 IAPU.Registers.YA.B.Y = OP1; @@ -1912,7 +1908,7 @@ void Apu8D() IAPU.PC += 2; } -void Apu8F() +void Apu8F(void) { // MOV dp,#00 Work8 = OP1; @@ -1920,7 +1916,7 @@ void Apu8F() IAPU.PC += 3; } -void Apu9E() +void Apu9E(void) { // DIV YA,X if ((IAPU.Registers.X & 0x0f) <= (IAPU.Registers.YA.B.Y & 0x0f)) @@ -1935,13 +1931,10 @@ void Apu9E() for (i = 0 ; i < 9 ; ++i) { yva <<= 1; - if (yva & 0x20000) yva = (yva & 0x1ffff) | 1; - if (yva >= x) yva ^= 1; - if (yva & 1) yva = (yva - x) & 0x1ffff; } @@ -1957,7 +1950,7 @@ void Apu9E() IAPU.PC++; } -void Apu9F() +void Apu9F(void) { // XCN A IAPU.Registers.YA.B.A = (IAPU.Registers.YA.B.A >> 4) | (IAPU.Registers.YA.B.A << 4); @@ -1965,7 +1958,7 @@ void Apu9F() IAPU.PC++; } -void ApuA4() +void ApuA4(void) { // SBC A, dp Work8 = S9xAPUGetByteZ(OP1); @@ -1973,7 +1966,7 @@ void ApuA4() IAPU.PC += 2; } -void ApuA5() +void ApuA5(void) { // SBC A, abs Absolute(); @@ -1982,7 +1975,7 @@ void ApuA5() IAPU.PC += 3; } -void ApuA6() +void ApuA6(void) { // SBC A, (X) Work8 = S9xAPUGetByteZ(IAPU.Registers.X); @@ -1990,7 +1983,7 @@ void ApuA6() IAPU.PC++; } -void ApuA7() +void ApuA7(void) { // SBC A,(dp+X) IndexedXIndirect(); @@ -1999,7 +1992,7 @@ void ApuA7() IAPU.PC += 2; } -void ApuA8() +void ApuA8(void) { // SBC A,#00 Work8 = OP1; @@ -2007,7 +2000,7 @@ void ApuA8() IAPU.PC += 2; } -void ApuA9() +void ApuA9(void) { // SBC dp(dest), dp(src) Work8 = S9xAPUGetByteZ(OP1); @@ -2017,7 +2010,7 @@ void ApuA9() IAPU.PC += 3; } -void ApuB4() +void ApuB4(void) { // SBC A, dp+X Work8 = S9xAPUGetByteZ(OP1 + IAPU.Registers.X); @@ -2025,7 +2018,7 @@ void ApuB4() IAPU.PC += 2; } -void ApuB5() +void ApuB5(void) { // SBC A,abs+X AbsoluteX(); @@ -2034,7 +2027,7 @@ void ApuB5() IAPU.PC += 3; } -void ApuB6() +void ApuB6(void) { // SBC A,abs+Y AbsoluteY(); @@ -2043,7 +2036,7 @@ void ApuB6() IAPU.PC += 3; } -void ApuB7() +void ApuB7(void) { // SBC A,(dp)+Y IndirectIndexedY(); @@ -2052,7 +2045,7 @@ void ApuB7() IAPU.PC += 2; } -void ApuB8() +void ApuB8(void) { // SBC dp,#00 Work8 = OP1; @@ -2062,7 +2055,7 @@ void ApuB8() IAPU.PC += 3; } -void ApuB9() +void ApuB9(void) { // SBC (X),(Y) W1 = S9xAPUGetByteZ(IAPU.Registers.X); @@ -2072,14 +2065,14 @@ void ApuB9() IAPU.PC++; } -void ApuAF() +void ApuAF(void) { // MOV (X)+, A S9xAPUSetByteZ(IAPU.Registers.YA.B.A, IAPU.Registers.X++); IAPU.PC++; } -void ApuBE() +void ApuBE(void) { // DAS if (IAPU.Registers.YA.B.A > 0x99 || !IAPU._Carry) @@ -2097,7 +2090,7 @@ void ApuBE() IAPU.PC++; } -void ApuBF() +void ApuBF(void) { // MOV A,(X)+ IAPU.Registers.YA.B.A = S9xAPUGetByteZ(IAPU.Registers.X++); @@ -2105,28 +2098,28 @@ void ApuBF() IAPU.PC++; } -void ApuC0() +void ApuC0(void) { // DI APUClearInterrupt(); IAPU.PC++; } -void ApuA0() +void ApuA0(void) { // EI APUSetInterrupt(); IAPU.PC++; } -void ApuC4() +void ApuC4(void) { // MOV dp,A S9xAPUSetByteZ(IAPU.Registers.YA.B.A, OP1); IAPU.PC += 2; } -void ApuC5() +void ApuC5(void) { // MOV abs,A Absolute(); @@ -2134,14 +2127,14 @@ void ApuC5() IAPU.PC += 3; } -void ApuC6() +void ApuC6(void) { // MOV (X), A S9xAPUSetByteZ(IAPU.Registers.YA.B.A, IAPU.Registers.X); IAPU.PC++; } -void ApuC7() +void ApuC7(void) { // MOV (dp+X),A IndexedXIndirect(); @@ -2149,7 +2142,7 @@ void ApuC7() IAPU.PC += 2; } -void ApuC9() +void ApuC9(void) { // MOV abs,X Absolute(); @@ -2157,14 +2150,14 @@ void ApuC9() IAPU.PC += 3; } -void ApuCB() +void ApuCB(void) { // MOV dp,Y S9xAPUSetByteZ(IAPU.Registers.YA.B.Y, OP1); IAPU.PC += 2; } -void ApuCC() +void ApuCC(void) { // MOV abs,Y Absolute(); @@ -2172,7 +2165,7 @@ void ApuCC() IAPU.PC += 3; } -void ApuCD() +void ApuCD(void) { // MOV X,#00 IAPU.Registers.X = OP1; @@ -2180,7 +2173,7 @@ void ApuCD() IAPU.PC += 2; } -void ApuCF() +void ApuCF(void) { // MUL YA IAPU.Registers.YA.W = (uint16_t) IAPU.Registers.YA.B.A * IAPU.Registers.YA.B.Y; @@ -2188,14 +2181,14 @@ void ApuCF() IAPU.PC++; } -void ApuD4() +void ApuD4(void) { // MOV dp+X, A S9xAPUSetByteZ(IAPU.Registers.YA.B.A, OP1 + IAPU.Registers.X); IAPU.PC += 2; } -void ApuD5() +void ApuD5(void) { // MOV abs+X,A AbsoluteX(); @@ -2203,7 +2196,7 @@ void ApuD5() IAPU.PC += 3; } -void ApuD6() +void ApuD6(void) { // MOV abs+Y,A AbsoluteY(); @@ -2211,7 +2204,7 @@ void ApuD6() IAPU.PC += 3; } -void ApuD7() +void ApuD7(void) { // MOV (dp)+Y,A IndirectIndexedY(); @@ -2219,28 +2212,28 @@ void ApuD7() IAPU.PC += 2; } -void ApuD8() +void ApuD8(void) { // MOV dp,X S9xAPUSetByteZ(IAPU.Registers.X, OP1); IAPU.PC += 2; } -void ApuD9() +void ApuD9(void) { // MOV dp+Y,X S9xAPUSetByteZ(IAPU.Registers.X, OP1 + IAPU.Registers.YA.B.Y); IAPU.PC += 2; } -void ApuDB() +void ApuDB(void) { // MOV dp+X,Y S9xAPUSetByteZ(IAPU.Registers.YA.B.Y, OP1 + IAPU.Registers.X); IAPU.PC += 2; } -void ApuDF() +void ApuDF(void) { // DAA if (IAPU.Registers.YA.B.A > 0x99 || IAPU._Carry) @@ -2258,7 +2251,7 @@ void ApuDF() IAPU.PC++; } -void ApuE4() +void ApuE4(void) { // MOV A, dp IAPU.Registers.YA.B.A = S9xAPUGetByteZ(OP1); @@ -2266,7 +2259,7 @@ void ApuE4() IAPU.PC += 2; } -void ApuE5() +void ApuE5(void) { // MOV A,abs Absolute(); @@ -2275,7 +2268,7 @@ void ApuE5() IAPU.PC += 3; } -void ApuE6() +void ApuE6(void) { // MOV A,(X) IAPU.Registers.YA.B.A = S9xAPUGetByteZ(IAPU.Registers.X); @@ -2283,7 +2276,7 @@ void ApuE6() IAPU.PC++; } -void ApuE7() +void ApuE7(void) { // MOV A,(dp+X) IndexedXIndirect(); @@ -2292,7 +2285,7 @@ void ApuE7() IAPU.PC += 2; } -void ApuE8() +void ApuE8(void) { // MOV A,#00 IAPU.Registers.YA.B.A = OP1; @@ -2300,7 +2293,7 @@ void ApuE8() IAPU.PC += 2; } -void ApuE9() +void ApuE9(void) { // MOV X, abs Absolute(); @@ -2309,7 +2302,7 @@ void ApuE9() IAPU.PC += 3; } -void ApuEB() +void ApuEB(void) { // MOV Y,dp IAPU.Registers.YA.B.Y = S9xAPUGetByteZ(OP1); @@ -2317,7 +2310,7 @@ void ApuEB() IAPU.PC += 2; } -void ApuEC() +void ApuEC(void) { // MOV Y,abs Absolute(); @@ -2326,7 +2319,7 @@ void ApuEC() IAPU.PC += 3; } -void ApuF4() +void ApuF4(void) { // MOV A, dp+X IAPU.Registers.YA.B.A = S9xAPUGetByteZ(OP1 + IAPU.Registers.X); @@ -2334,7 +2327,7 @@ void ApuF4() IAPU.PC += 2; } -void ApuF5() +void ApuF5(void) { // MOV A, abs+X AbsoluteX(); @@ -2343,7 +2336,7 @@ void ApuF5() IAPU.PC += 3; } -void ApuF6() +void ApuF6(void) { // MOV A, abs+Y AbsoluteY(); @@ -2352,7 +2345,7 @@ void ApuF6() IAPU.PC += 3; } -void ApuF7() +void ApuF7(void) { // MOV A, (dp)+Y IndirectIndexedY(); @@ -2361,7 +2354,7 @@ void ApuF7() IAPU.PC += 2; } -void ApuF8() +void ApuF8(void) { // MOV X,dp IAPU.Registers.X = S9xAPUGetByteZ(OP1); @@ -2369,7 +2362,7 @@ void ApuF8() IAPU.PC += 2; } -void ApuF9() +void ApuF9(void) { // MOV X,dp+Y IAPU.Registers.X = S9xAPUGetByteZ(OP1 + IAPU.Registers.YA.B.Y); @@ -2377,14 +2370,14 @@ void ApuF9() IAPU.PC += 2; } -void ApuFA() +void ApuFA(void) { // MOV dp(dest),dp(src) S9xAPUSetByteZ(S9xAPUGetByteZ(OP1), OP2); IAPU.PC += 3; } -void ApuFB() +void ApuFB(void) { // MOV Y,dp+X IAPU.Registers.YA.B.Y = S9xAPUGetByteZ(OP1 + IAPU.Registers.X); @@ -2392,7 +2385,7 @@ void ApuFB() IAPU.PC += 2; } -void (*S9xApuOpcodes[256])() = +void (*S9xApuOpcodes[256])(void) = { Apu00, Apu01, Apu02, Apu03, Apu04, Apu05, Apu06, Apu07, Apu08, Apu09, Apu0A, Apu0B, Apu0C, Apu0D, Apu0E, Apu0F, diff --git a/source/spc700.h b/source/spc700.h index 8d8740d..3de94ae 100644 --- a/source/spc700.h +++ b/source/spc700.h @@ -70,10 +70,8 @@ typedef struct #define APU_EXECUTE() \ if (IAPU.APUExecuting) \ -{\ while (APU.Cycles <= CPU.Cycles) \ - APU_EXECUTE1(); \ -} + APU_EXECUTE1(); #endif #endif diff --git a/source/spc7110.c b/source/spc7110.c index f2dc0e7..7ed339d 100644 --- a/source/spc7110.c +++ b/source/spc7110.c @@ -7,9 +7,9 @@ const char* S9xGetFilename(const char*); -SPC7110Regs s7r; // SPC7110 registers, about 33KB -S7RTC rtc_f9; // FEOEZ (and Shounen Jump no SHou) RTC -void S9xUpdateRTC(void); // S-RTC function hacked to work with the RTC +SPC7110Regs s7r; // SPC7110 registers, about 33KB +S7RTC rtc_f9; // FEOEZ (and Shounen Jump no SHou) RTC +void S9xUpdateRTC(void); // S-RTC function hacked to work with the RTC void S9xSpc7110Init(void) // Emulate power on state { @@ -82,7 +82,6 @@ uint8_t S9xGetSPC7110(uint16_t Address) case 0x4800: { uint16_t count = s7r.reg4809 | (s7r.reg480A << 8); - if (count > 0) count--; else @@ -909,11 +908,9 @@ void S9xUpdateRTC(void) int32_t month; int32_t year; int32_t temp_days; - int32_t year_tens; int32_t year_ones; - if (time_diff > DAYTICKS) { days = time_diff / DAYTICKS; diff --git a/source/spc7110dec.c b/source/spc7110dec.c index 8a25684..f5dc963 100644 --- a/source/spc7110dec.c +++ b/source/spc7110dec.c @@ -64,7 +64,7 @@ typedef struct SPC7110Decomp decomp; -uint8_t spc7110dec_read() +uint8_t spc7110dec_read(void) { decomp.read_counter++; @@ -87,7 +87,6 @@ uint8_t spc7110dec_read() } uint8_t data = decomp.buffer[decomp.buffer_rdoffset++]; - decomp.buffer_rdoffset &= SPC7110_DECOMP_BUFFER_SIZE - 1; decomp.buffer_length--; return data; @@ -100,10 +99,9 @@ void spc7110dec_write(uint8_t data) decomp.buffer_length++; } -uint8_t spc7110dec_dataread() +uint8_t spc7110dec_dataread(void) { uint32_t size = Memory.CalculatedSize - 0x100000; - while(decomp.offset >= size) decomp.offset -= size; return Memory.ROM[0x100000 + decomp.offset++]; @@ -164,7 +162,6 @@ void spc7110dec_mode0(bool init) while(decomp.buffer_length < (SPC7110_DECOMP_BUFFER_SIZE >> 1)) { uint32_t bit; - for(bit = 0; bit < 8; bit++) { /* Get decomp.context */ @@ -240,7 +237,6 @@ void spc7110dec_mode1(bool init) if(init) { uint32_t i; - for(i = 0; i < 4; i++) pixelorder[i] = i; out = inverts = lps = 0; @@ -501,7 +497,6 @@ void spc7110dec_mode2(bool init) /* Update processing info */ lps = (lps << 1) + flag_lps; uint32_t invertbit = decomp.context[con].invert; - inverts = (inverts << 1) + invertbit; /* Update decomp.context state */ @@ -525,7 +520,6 @@ void spc7110dec_mode2(bool init) /* Convert pixel data into bitplanes */ uint32_t data = spc7110dec_morton_4x8(out0); - spc7110dec_write(data >> 24); spc7110dec_write(data >> 16); bitplanebuffer[buffer_index++] = data >> 8; @@ -534,7 +528,6 @@ void spc7110dec_mode2(bool init) if(buffer_index == 16) { uint32_t i; - for(i = 0; i < 16; i++) spc7110dec_write(bitplanebuffer[i]); buffer_index = 0; @@ -580,7 +573,7 @@ uint32_t spc7110dec_morton_4x8(uint32_t data) return decomp.morton32[0][(data >> 0) & 255] + decomp.morton32[1][(data >> 8) & 255] + decomp.morton32[2][(data >> 16) & 255] + decomp.morton32[3][(data >> 24) & 255]; } -void spc7110dec_reset() +void spc7110dec_reset(void) { /* Mode 3 is invalid; this is treated as a special case to always return 0x00 * set to mode 3 so that reading decomp port before starting first decomp will return 0x00 */ @@ -590,14 +583,13 @@ void spc7110dec_reset() decomp.buffer_length = 0; } -void spc7110dec_init() +void spc7110dec_init(void) { decomp.buffer = malloc(SPC7110_DECOMP_BUFFER_SIZE); spc7110dec_reset(); /* Initialize reverse morton lookup tables */ uint32_t i; - for(i = 0; i < 256; i++) { #define map(x, y) (((i >> x) & 1) << y) @@ -613,7 +605,7 @@ void spc7110dec_init() } } -void spc7110dec_deinit() +void spc7110dec_deinit(void) { free(decomp.buffer); } diff --git a/source/srtc.c b/source/srtc.c index 5de0c8a..6427f0b 100644 --- a/source/srtc.c +++ b/source/srtc.c @@ -68,7 +68,7 @@ void S9xHardResetSRTC(void) } /**********************************************************************************************/ -/* S9xSRTCComputeDayOfWeek(void) */ +/* S9xSRTCComputeDayOfWeek(void) */ /* Return 0-6 for Sunday-Saturday */ /**********************************************************************************************/ uint32_t S9xSRTCComputeDayOfWeek(void) @@ -132,11 +132,6 @@ void S9xUpdateSrtcTime(void) // Keep track of game time by computing the number of seconds that pass on the system // clock and adding the same number of seconds to the S-RTC clock structure. - // I originally tried using mktime and localtime library functions to keep track - // of time but some of the GNU time functions fail when the year goes to 2099 - // (and maybe less) and this would have caused a bug with DKJM2 so I'm doing - // it this way to get around that problem. - // Note: Dai Kaijyu Monogatari II only allows dates in the range 1996-21xx. if (rtc.count_enable && !rtc.needs_init) @@ -250,9 +245,8 @@ void S9xUpdateSrtcTime(void) } } - /**********************************************************************************************/ -/* S9xSetSRTC(void) */ +/* S9xSetSRTC(void) */ /* This function sends data to the S-RTC used in Dai Kaijyu Monogatari II */ /**********************************************************************************************/ void S9xSetSRTC(uint8_t data, uint16_t Address) diff --git a/source/tile.c b/source/tile.c index 7b78c27..e203ee1 100644 --- a/source/tile.c +++ b/source/tile.c @@ -27,42 +27,42 @@ static uint8_t ConvertTile(uint8_t* pCache, uint32_t TileAddr) for (line = 8; line != 0; line--, tp += 2) { p1 = p2 = 0; - if ((pix = *(tp + 0))) + if((pix = tp[0])) { p1 |= odd_high[0][pix >> 4]; p2 |= odd_low[0][pix & 0xf]; } - if ((pix = *(tp + 1))) + if((pix = tp[1])) { p1 |= even_high[0][pix >> 4]; p2 |= even_low[0][pix & 0xf]; } - if ((pix = *(tp + 16))) + if((pix = tp[16])) { p1 |= odd_high[1][pix >> 4]; p2 |= odd_low[1][pix & 0xf]; } - if ((pix = *(tp + 17))) + if((pix = tp[17])) { p1 |= even_high[1][pix >> 4]; p2 |= even_low[1][pix & 0xf]; } - if ((pix = *(tp + 32))) + if((pix = tp[32])) { p1 |= odd_high[2][pix >> 4]; p2 |= odd_low[2][pix & 0xf]; } - if ((pix = *(tp + 33))) + if((pix = tp[33])) { p1 |= even_high[2][pix >> 4]; p2 |= even_low[2][pix & 0xf]; } - if ((pix = *(tp + 48))) + if((pix = tp[48])) { p1 |= odd_high[3][pix >> 4]; p2 |= odd_low[3][pix & 0xf]; } - if ((pix = *(tp + 49))) + if((pix = tp[49])) { p1 |= even_high[3][pix >> 4]; p2 |= even_low[3][pix & 0xf]; @@ -72,27 +72,26 @@ static uint8_t ConvertTile(uint8_t* pCache, uint32_t TileAddr) non_zero |= p1 | p2; } break; - case 4: for (line = 8; line != 0; line--, tp += 2) { p1 = p2 = 0; - if ((pix = *(tp + 0))) + if((pix = tp[0])) { p1 |= odd_high[0][pix >> 4]; p2 |= odd_low[0][pix & 0xf]; } - if ((pix = *(tp + 1))) + if((pix = tp[1])) { p1 |= even_high[0][pix >> 4]; p2 |= even_low[0][pix & 0xf]; } - if ((pix = *(tp + 16))) + if((pix = tp[16])) { p1 |= odd_high[1][pix >> 4]; p2 |= odd_low[1][pix & 0xf]; } - if ((pix = *(tp + 17))) + if((pix = tp[17])) { p1 |= even_high[1][pix >> 4]; p2 |= even_low[1][pix & 0xf]; @@ -102,17 +101,16 @@ static uint8_t ConvertTile(uint8_t* pCache, uint32_t TileAddr) non_zero |= p1 | p2; } break; - case 2: for (line = 8; line != 0; line--, tp += 2) { p1 = p2 = 0; - if ((pix = *(tp + 0))) + if((pix = tp[0])) { p1 |= odd_high[0][pix >> 4]; p2 |= odd_low[0][pix & 0xf]; } - if ((pix = *(tp + 1))) + if((pix = tp[1])) { p1 |= even_high[0][pix >> 4]; p2 |= even_low[0][pix & 0xf]; @@ -123,7 +121,7 @@ static uint8_t ConvertTile(uint8_t* pCache, uint32_t TileAddr) } break; } - return (non_zero ? true : BLANK_TILE); + return non_zero ? 1 : BLANK_TILE; } #define PLOT_PIXEL(screen, pixel) (pixel) @@ -234,10 +232,8 @@ static void WRITE_4PIXELS16x2x2(int32_t Offset, uint8_t* Pixels, uint16_t* Scree { if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[N])) { - Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX.RealPitch >> 1) + N * 2] = - Screen [(GFX.RealPitch >> 1) + N * 2 + 1] = ScreenColors [Pixel]; - Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX.RealPitch >> 1) + N * 2] = - Depth [(GFX.RealPitch >> 1) + N * 2 + 1] = GFX.Z2; + Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX.RealPitch >> 1) + N * 2] = Screen [(GFX.RealPitch >> 1) + N * 2 + 1] = ScreenColors [Pixel]; + Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX.RealPitch >> 1) + N * 2] = Depth [(GFX.RealPitch >> 1) + N * 2 + 1] = GFX.Z2; } } } @@ -252,113 +248,93 @@ static void WRITE_4PIXELS16_FLIPPEDx2x2(int32_t Offset, uint8_t* Pixels, uint16_ { if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) { - Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX.RealPitch >> 1) + N * 2] = - Screen [(GFX.RealPitch >> 1) + N * 2 + 1] = ScreenColors [Pixel]; - Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX.RealPitch >> 1) + N * 2] = - Depth [(GFX.RealPitch >> 1) + N * 2 + 1] = GFX.Z2; + Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX.RealPitch >> 1) + N * 2] = Screen [(GFX.RealPitch >> 1) + N * 2 + 1] = ScreenColors [Pixel]; + Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX.RealPitch >> 1) + N * 2] = Depth [(GFX.RealPitch >> 1) + N * 2 + 1] = GFX.Z2; } } } void DrawTile16(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - RENDER_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4) + RENDER_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4); } void DrawClippedTile16(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4) + TILE_CLIP_PREAMBLE(); + RENDER_CLIPPED_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4); } void DrawTile16HalfWidth(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - RENDER_TILE(WRITE_4PIXELS16_HALFWIDTH, WRITE_4PIXELS16_FLIPPED_HALFWIDTH, 2) + RENDER_TILE(WRITE_4PIXELS16_HALFWIDTH, WRITE_4PIXELS16_FLIPPED_HALFWIDTH, 2); } void DrawClippedTile16HalfWidth(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_HALFWIDTH, WRITE_4PIXELS16_FLIPPED_HALFWIDTH, 2) + TILE_CLIP_PREAMBLE(); + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_HALFWIDTH, WRITE_4PIXELS16_FLIPPED_HALFWIDTH, 2); } void DrawTile16x2(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - RENDER_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8) + RENDER_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8); } void DrawClippedTile16x2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8) + TILE_CLIP_PREAMBLE(); + RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8); } -void DrawTile16x2x2(uint32_t Tile, int32_t Offset, uint32_t StartLine, - uint32_t LineCount) +void DrawTile16x2x2(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - RENDER_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8) + RENDER_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8); } -void DrawClippedTile16x2x2(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Width, - uint32_t StartLine, uint32_t LineCount) +void DrawClippedTile16x2x2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8) + TILE_CLIP_PREAMBLE(); + RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8); } -void DrawLargePixel16(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Pixels, - uint32_t StartLine, uint32_t LineCount) +void DrawLargePixel16(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Pixels, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE - + TILE_PREAMBLE(); uint16_t* sp = (uint16_t*) GFX.S + Offset; uint8_t* Depth = GFX.DB + Offset; uint16_t pixel; - - RENDER_TILE_LARGE(ScreenColors [pixel], PLOT_PIXEL) + RENDER_TILE_LARGE(ScreenColors [pixel], PLOT_PIXEL); } void DrawLargePixel16HalfWidth(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Pixels, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE - + TILE_PREAMBLE(); uint16_t* sp = (uint16_t*) GFX.S + Offset; uint8_t* Depth = GFX.DB + Offset; uint16_t pixel; - - RENDER_TILE_LARGE_HALFWIDTH(ScreenColors [pixel], PLOT_PIXEL) + RENDER_TILE_LARGE_HALFWIDTH(ScreenColors [pixel], PLOT_PIXEL); } static void WRITE_4PIXELS16_ADD(int32_t Offset, uint8_t* Pixels, uint16_t* ScreenColors) { uint8_t Pixel, N; - uint16_t* Screen = (uint16_t*) GFX.S + Offset; uint8_t* Depth = GFX.ZBuffer + Offset; uint8_t* SubDepth = GFX.SubZBuffer + Offset; @@ -387,7 +363,6 @@ static void WRITE_4PIXELS16_ADD(int32_t Offset, uint8_t* Pixels, uint16_t* Scree static void WRITE_4PIXELS16_FLIPPED_ADD(int32_t Offset, uint8_t* Pixels, uint16_t* ScreenColors) { uint8_t Pixel, N; - uint16_t* Screen = (uint16_t*) GFX.S + Offset; uint8_t* Depth = GFX.ZBuffer + Offset; uint8_t* SubDepth = GFX.SubZBuffer + Offset; @@ -433,8 +408,7 @@ static void WRITE_4PIXELS16_ADD1_2(int32_t Offset, uint8_t* Pixels, uint16_t* Sc Screen [N] = COLOR_ADD(ScreenColors [Pixel], GFX.FixedColour); break; default: - Screen [N] = (uint16_t)(COLOR_ADD1_2(ScreenColors [Pixel], - Screen [GFX.Delta + N])); + Screen [N] = (uint16_t)(COLOR_ADD1_2(ScreenColors [Pixel], Screen [GFX.Delta + N])); break; } Depth [N] = GFX.Z2; @@ -462,8 +436,7 @@ static void WRITE_4PIXELS16_FLIPPED_ADD1_2(int32_t Offset, uint8_t* Pixels, uint Screen [N] = COLOR_ADD(ScreenColors [Pixel], GFX.FixedColour); break; default: - Screen [N] = (uint16_t)(COLOR_ADD1_2(ScreenColors [Pixel], - Screen [GFX.Delta + N])); + Screen [N] = (uint16_t)(COLOR_ADD1_2(ScreenColors [Pixel], Screen [GFX.Delta + N])); break; } Depth [N] = GFX.Z2; @@ -575,8 +548,7 @@ static void WRITE_4PIXELS16_FLIPPED_SUB1_2(int32_t Offset, uint8_t* Pixels, uint Screen [N] = (uint16_t) COLOR_SUB(ScreenColors [Pixel], GFX.FixedColour); break; default: - Screen [N] = (uint16_t) COLOR_SUB1_2(ScreenColors [Pixel], - Screen [GFX.Delta + N]); + Screen [N] = (uint16_t) COLOR_SUB1_2(ScreenColors [Pixel], Screen [GFX.Delta + N]); break; } Depth [N] = GFX.Z2; @@ -587,7 +559,7 @@ static void WRITE_4PIXELS16_FLIPPED_SUB1_2(int32_t Offset, uint8_t* Pixels, uint void DrawTile16Add(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; uint8_t Pixel; uint16_t* Screen = (uint16_t*) GFX.S + Offset; @@ -598,8 +570,7 @@ void DrawTile16Add(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t L { case 0: bp = pCache + StartLine; - for (l = LineCount; l != 0; - l--, bp += 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) + for (l = LineCount; l != 0; l--, bp += 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) { uint8_t N; for (N = 0; N < 8; N++) @@ -625,8 +596,7 @@ void DrawTile16Add(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t L break; case H_FLIP: bp = pCache + StartLine; - for (l = LineCount; l != 0; - l--, bp += 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) + for (l = LineCount; l != 0; l--, bp += 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) { uint8_t N; for (N = 0; N < 8; N++) @@ -652,8 +622,7 @@ void DrawTile16Add(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t L break; case H_FLIP | V_FLIP: bp = pCache + 56 - StartLine; - for (l = LineCount; l != 0; - l--, bp -= 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) + for (l = LineCount; l != 0; l--, bp -= 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) { uint8_t N; for (N = 0; N < 8; N++) @@ -679,8 +648,7 @@ void DrawTile16Add(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t L break; case V_FLIP: bp = pCache + 56 - StartLine; - for (l = LineCount; l != 0; - l--, bp -= 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) + for (l = LineCount; l != 0; l--, bp -= 8, Screen += GFX.PPL, Depth += GFX.PPL, SubDepth += GFX.PPL) { uint8_t N; for (N = 0; N < 8; N++) @@ -711,67 +679,55 @@ void DrawTile16Add(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t L void DrawClippedTile16Add(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4) + TILE_CLIP_PREAMBLE(); + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4); } void DrawTile16Add1_2(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - RENDER_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4) + RENDER_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4); } void DrawClippedTile16Add1_2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4) + TILE_CLIP_PREAMBLE(); + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4); } void DrawTile16Sub(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - RENDER_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4) + RENDER_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4); } -void DrawClippedTile16Sub(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Width, - uint32_t StartLine, uint32_t LineCount) +void DrawClippedTile16Sub(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4) + TILE_CLIP_PREAMBLE(); + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4); } -void DrawTile16Sub1_2(uint32_t Tile, int32_t Offset, uint32_t StartLine, - uint32_t LineCount) +void DrawTile16Sub1_2(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - RENDER_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4) + RENDER_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4); } -void DrawClippedTile16Sub1_2(uint32_t Tile, int32_t Offset, - uint32_t StartPixel, uint32_t Width, - uint32_t StartLine, uint32_t LineCount) +void DrawClippedTile16Sub1_2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4) + TILE_CLIP_PREAMBLE(); + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4); } static void WRITE_4PIXELS16_ADDF1_2(int32_t Offset, uint8_t* Pixels, uint16_t* ScreenColors) @@ -852,78 +808,67 @@ static void WRITE_4PIXELS16_FLIPPED_SUBF1_2(int32_t Offset, uint8_t* Pixels, uin void DrawTile16FixedAdd1_2(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - RENDER_TILE(WRITE_4PIXELS16_ADDF1_2, WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4) + RENDER_TILE(WRITE_4PIXELS16_ADDF1_2, WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4); } void DrawClippedTile16FixedAdd1_2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADDF1_2, - WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4) + TILE_CLIP_PREAMBLE(); + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADDF1_2, WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4); } void DrawTile16FixedSub1_2(uint32_t Tile, int32_t Offset, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - RENDER_TILE(WRITE_4PIXELS16_SUBF1_2, WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4) + RENDER_TILE(WRITE_4PIXELS16_SUBF1_2, WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4); } void DrawClippedTile16FixedSub1_2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Width, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE + TILE_PREAMBLE(); uint8_t* bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUBF1_2, - WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4) + TILE_CLIP_PREAMBLE(); + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUBF1_2, WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4); } void DrawLargePixel16Add(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Pixels, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE - + TILE_PREAMBLE(); uint16_t* sp = (uint16_t*) GFX.S + Offset; uint8_t* Depth = GFX.ZBuffer + Offset; uint16_t pixel; #define LARGE_ADD_PIXEL(s, p) \ (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ - COLOR_ADD (p, *(s + GFX.Delta)) : \ - COLOR_ADD (p, GFX.FixedColour)) \ - : p) + COLOR_ADD (p, *(s + GFX.Delta)) : \ + COLOR_ADD (p, GFX.FixedColour)) : p) - RENDER_TILE_LARGE(ScreenColors [pixel], LARGE_ADD_PIXEL) + RENDER_TILE_LARGE(ScreenColors [pixel], LARGE_ADD_PIXEL); } void DrawLargePixel16Add1_2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Pixels, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE - + TILE_PREAMBLE(); uint16_t* sp = (uint16_t*) GFX.S + Offset; uint8_t* Depth = GFX.ZBuffer + Offset; uint16_t pixel; #define LARGE_ADD_PIXEL1_2(s, p) \ ((uint16_t) (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ - COLOR_ADD1_2 (p, *(s + GFX.Delta)) : \ - COLOR_ADD (p, GFX.FixedColour)) \ - : p)) + COLOR_ADD1_2 (p, *(s + GFX.Delta)) : \ + COLOR_ADD (p, GFX.FixedColour)) : p)) - RENDER_TILE_LARGE(ScreenColors [pixel], LARGE_ADD_PIXEL1_2) + RENDER_TILE_LARGE(ScreenColors [pixel], LARGE_ADD_PIXEL1_2); } void DrawLargePixel16Sub(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Pixels, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE - + TILE_PREAMBLE(); uint16_t* sp = (uint16_t*) GFX.S + Offset; uint8_t* Depth = GFX.ZBuffer + Offset; uint16_t pixel; @@ -931,16 +876,14 @@ void DrawLargePixel16Sub(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uin #define LARGE_SUB_PIXEL(s, p) \ (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ COLOR_SUB (p, *(s + GFX.Delta)) : \ - COLOR_SUB (p, GFX.FixedColour)) \ - : p) + COLOR_SUB (p, GFX.FixedColour)) : p) - RENDER_TILE_LARGE(ScreenColors [pixel], LARGE_SUB_PIXEL) + RENDER_TILE_LARGE(ScreenColors [pixel], LARGE_SUB_PIXEL); } void DrawLargePixel16Sub1_2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, uint32_t Pixels, uint32_t StartLine, uint32_t LineCount) { - TILE_PREAMBLE - + TILE_PREAMBLE(); uint16_t* sp = (uint16_t*) GFX.S + Offset; uint8_t* Depth = GFX.ZBuffer + Offset; uint16_t pixel; @@ -948,8 +891,7 @@ void DrawLargePixel16Sub1_2(uint32_t Tile, int32_t Offset, uint32_t StartPixel, #define LARGE_SUB_PIXEL1_2(s, p) \ (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ COLOR_SUB1_2 (p, *(s + GFX.Delta)) : \ - COLOR_SUB (p, GFX.FixedColour)) \ - : p) + COLOR_SUB (p, GFX.FixedColour)) : p) - RENDER_TILE_LARGE(ScreenColors [pixel], LARGE_SUB_PIXEL1_2) + RENDER_TILE_LARGE(ScreenColors [pixel], LARGE_SUB_PIXEL1_2); } diff --git a/source/tile.h b/source/tile.h index 2a273f6..12b294d 100644 --- a/source/tile.h +++ b/source/tile.h @@ -3,24 +3,18 @@ #ifndef _TILE_H_ #define _TILE_H_ -#define TILE_PREAMBLE \ +#define TILE_PREAMBLE() \ uint8_t *pCache; \ -\ uint32_t TileAddr = BG.TileAddress + ((Tile & 0x3ff) << BG.TileShift); \ if ((Tile & 0x1ff) >= 256) \ TileAddr += BG.NameSelect; \ -\ TileAddr &= 0xffff; \ -\ uint32_t TileNumber; \ pCache = &BG.Buffer[(TileNumber = (TileAddr >> BG.TileShift)) << 6]; \ -\ if (!BG.Buffered [TileNumber]) \ BG.Buffered[TileNumber] = ConvertTile (pCache, TileAddr); \ -\ if (BG.Buffered [TileNumber] == BLANK_TILE) \ return; \ -\ uint32_t l; \ uint16_t *ScreenColors; \ if (BG.DirectColourMode) \ @@ -30,7 +24,7 @@ ScreenColors = DirectColourMaps [(Tile >> 10) & BG.PaletteMask]; \ } \ else \ - ScreenColors = &IPPU.ScreenColors [(((Tile >> 10) & BG.PaletteMask) << BG.PaletteShift) + BG.StartPalette]; + ScreenColors = &IPPU.ScreenColors [(((Tile >> 10) & BG.PaletteMask) << BG.PaletteShift) + BG.StartPalette] #define RENDER_TILE(NORMAL, FLIPPED, N) \ switch (Tile & (V_FLIP | H_FLIP)) \ @@ -79,10 +73,9 @@ break; \ } -#define TILE_CLIP_PREAMBLE \ +#define TILE_CLIP_PREAMBLE() \ uint32_t d1; \ uint32_t d2; \ -\ if (StartPixel < 4) \ { \ d1 = HeadMask [StartPixel]; \ @@ -91,18 +84,16 @@ } \ else \ d1 = 0; \ -\ if (StartPixel + Width > 4) \ { \ if (StartPixel > 4) \ d2 = HeadMask [StartPixel - 4]; \ else \ d2 = 0xffffffff; \ -\ d2 &= TailMask [(StartPixel + Width - 4)]; \ } \ else \ - d2 = 0; + d2 = 0 #define RENDER_CLIPPED_TILE(NORMAL, FLIPPED, N) \ uint32_t dd; \ @@ -114,8 +105,7 @@ { \ /* This is perfectly OK, regardless of endianness. The tiles are \ * cached in leftmost-endian order (when not horiz flipped) by \ - * the ConvertTile function. \ - */ \ + * the ConvertTile function. */ \ if ((dd = (*(uint32_t *) bp) & d1)) \ NORMAL (Offset, (uint8_t *) &dd, ScreenColors); \ if ((dd = (*(uint32_t *) (bp + 4)) & d2)) \ @@ -167,7 +157,7 @@ StartPixel = 7 - StartPixel; \ /* fallthrough for no-flip case - above was a horizontal flip */ \ case 0: \ - if ((pixel = *(pCache + StartLine + StartPixel))) \ + if((pixel = pCache[StartLine + StartPixel])) \ { \ pixel = PIXEL; \ for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \ @@ -188,7 +178,7 @@ StartPixel = 7 - StartPixel; \ /* fallthrough for V_FLIP-only case - above was a horizontal flip */ \ case V_FLIP: \ - if ((pixel = *(pCache + 56 - StartLine + StartPixel))) \ + if((pixel = pCache[56 - StartLine + StartPixel])) \ { \ pixel = PIXEL; \ for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \ @@ -216,7 +206,7 @@ StartPixel = 7 - StartPixel; \ /* fallthrough for no-flip case - above was a horizontal flip */ \ case 0: \ - if ((pixel = *(pCache + StartLine + StartPixel))) \ + if((pixel = pCache[StartLine + StartPixel])) \ { \ pixel = PIXEL; \ for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \ @@ -237,7 +227,7 @@ StartPixel = 7 - StartPixel; \ /* fallthrough for V_FLIP-only case - above was a horizontal flip */ \ case V_FLIP: \ - if ((pixel = *(pCache + 56 - StartLine + StartPixel))) \ + if((pixel = pCache[56 - StartLine + StartPixel])) \ { \ pixel = PIXEL; \ for (l = LineCount; l != 0; l--, sp += GFX.PPL, Depth += GFX.PPL) \ |