From 804169dd621a3ad3eec1a32ce30350de667fee80 Mon Sep 17 00:00:00 2001 From: aliaspider Date: Thu, 30 Oct 2014 00:23:30 +0100 Subject: apply a facelift --- source/ppu.c | 5751 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 2924 insertions(+), 2827 deletions(-) (limited to 'source/ppu.c') diff --git a/source/ppu.c b/source/ppu.c index 631039b..a7d58a2 100644 --- a/source/ppu.c +++ b/source/ppu.c @@ -1,6 +1,6 @@ /******************************************************************************* Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and Jerremy Koot (jkoot@snes9x.com) @@ -43,46 +43,46 @@ S-DD1 C emulator code (c) Copyright 2003 Brad Jorsch with research by Andreas Naive and John Weidman - + S-RTC C emulator code (c) Copyright 2001 John Weidman - + ST010 C++ emulator code (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - Super FX C emulator code + Super FX C emulator code (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + - Specific ports contains the works of other authors. See headers in individual files. - + Snes9x homepage: http://www.snes9x.com - + Permission to use, copy, modify and distribute Snes9x in both binary and source form, for non-commercial purposes, is hereby granted without fee, providing that this license information and copyright notice appear with all copies and any derived work. - + This software is provided 'as-is', without any express or implied warranty. In no event shall the authors be held liable for any damages arising from the use of this software. - + Snes9x is freeware for PERSONAL USE only. Commercial users should seek permission of the copyright holders first. Commercial use includes charging money for Snes9x or software derived from Snes9x. - + The copyright holders request that bug fixes and improvements to the code should be forwarded to them so everyone can benefit from the modifications in future versions. - + Super NES and Super Nintendo Entertainment System are trademarks of Nintendo Co., Limited and its subsidiary companies. *******************************************************************************/ @@ -106,103 +106,102 @@ #include "fxinst.h" extern struct FxInit_s SuperFX; #else -void S9xSuperFXWriteReg (uint8, uint32); -uint8 S9xSuperFXReadReg (uint32); +void S9xSuperFXWriteReg(uint8, uint32); +uint8 S9xSuperFXReadReg(uint32); #endif -uint32 justifiers=0xFFFF00AA; -uint8 in_bit=0; +uint32 justifiers = 0xFFFF00AA; +uint8 in_bit = 0; -extern uint8 *HDMAMemPointers [8]; +extern uint8* HDMAMemPointers [8]; -void S9xLatchCounters (bool force) +void S9xLatchCounters(bool force) { - if(!force && !(Memory.FillRAM[0x4213] & 0x80)) return; + if (!force && !(Memory.FillRAM[0x4213] & 0x80)) return; #if 0 # ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PCAtOpcodeStart; + CPU.WaitAddress = CPU.PCAtOpcodeStart; # endif #endif - PPU.HVBeamCounterLatched = 1; - PPU.VBeamPosLatched = (uint16) CPU.V_Counter; - PPU.HBeamPosLatched = (uint16) ((CPU.Cycles * SNES_HCOUNTER_MAX) / Settings.H_Max); + PPU.HVBeamCounterLatched = 1; + PPU.VBeamPosLatched = (uint16) CPU.V_Counter; + PPU.HBeamPosLatched = (uint16)((CPU.Cycles * SNES_HCOUNTER_MAX) / + Settings.H_Max); - // Causes screen flicker for Yoshi's Island if uncommented - //CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + // Causes screen flicker for Yoshi's Island if uncommented + //CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); - Memory.FillRAM [0x213F] |= 0x40; + Memory.FillRAM [0x213F] |= 0x40; } void S9xUpdateJustifiers(); -void S9xUpdateHTimer () +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) - { - PPU.HTimerPosition--; - } - - if (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos) - { - if (PPU.HTimerPosition < CPU.Cycles) - { - // Missed the IRQ on this line already - if (CPU.WhichEvent == HBLANK_END_EVENT || - CPU.WhichEvent == HTIMER_AFTER_EVENT) - { - CPU.WhichEvent = HBLANK_END_EVENT; - CPU.NextEvent = Settings.H_Max; - } - else - { - CPU.WhichEvent = HBLANK_START_EVENT; - CPU.NextEvent = Settings.HBlankStart; - } - } - else - { - 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 - CPU.NextEvent = Settings.HBlankStart; - CPU.WhichEvent = HBLANK_START_EVENT; - } - else - { - CPU.NextEvent = PPU.HTimerPosition; - CPU.WhichEvent = HTIMER_BEFORE_EVENT; - } - } - else - { - CPU.WhichEvent = HTIMER_AFTER_EVENT; - CPU.NextEvent = PPU.HTimerPosition; - } - } - } - } + if (PPU.HTimerEnabled) + { + PPU.HTimerPosition = PPU.IRQHBeamPos * Settings.H_Max / SNES_HCOUNTER_MAX; + if (PPU.HTimerPosition == Settings.H_Max || + PPU.HTimerPosition == Settings.HBlankStart) + PPU.HTimerPosition--; + + if (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos) + { + if (PPU.HTimerPosition < CPU.Cycles) + { + // Missed the IRQ on this line already + if (CPU.WhichEvent == HBLANK_END_EVENT || + CPU.WhichEvent == HTIMER_AFTER_EVENT) + { + CPU.WhichEvent = HBLANK_END_EVENT; + CPU.NextEvent = Settings.H_Max; + } + else + { + CPU.WhichEvent = HBLANK_START_EVENT; + CPU.NextEvent = Settings.HBlankStart; + } + } + else + { + 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 + CPU.NextEvent = Settings.HBlankStart; + CPU.WhichEvent = HBLANK_START_EVENT; + } + else + { + CPU.NextEvent = PPU.HTimerPosition; + CPU.WhichEvent = HTIMER_BEFORE_EVENT; + } + } + else + { + CPU.WhichEvent = HTIMER_AFTER_EVENT; + CPU.NextEvent = PPU.HTimerPosition; + } + } + } + } } -void S9xFixColourBrightness () +void S9xFixColourBrightness() { - IPPU.XB = mul_brightness [PPU.Brightness]; - int i; + IPPU.XB = mul_brightness [PPU.Brightness]; + int i; for (i = 0; i < 256; i++) { IPPU.Red [i] = IPPU.XB [PPU.CGDATA [i] & 0x1f]; IPPU.Green [i] = IPPU.XB [(PPU.CGDATA [i] >> 5) & 0x1f]; IPPU.Blue [i] = IPPU.XB [(PPU.CGDATA [i] >> 10) & 0x1f]; - IPPU.ScreenColors [i] = BUILD_PIXEL (IPPU.Red [i], IPPU.Green [i], - IPPU.Blue [i]); + IPPU.ScreenColors [i] = BUILD_PIXEL(IPPU.Red [i], IPPU.Green [i], + IPPU.Blue [i]); } } @@ -210,695 +209,744 @@ void S9xFixColourBrightness () /* S9xSetPPU() */ /* This function sets a PPU Register to a specific byte */ /******************************************************************************/ -void S9xSetPPU (uint8 Byte, uint16 Address) +void S9xSetPPU(uint8 Byte, uint16 Address) { -// fprintf(stderr, "%03d: %02x to %04x\n", CPU.V_Counter, Byte, Address); - if (Address <= 0x2183) - { - switch (Address) - { - case 0x2100: - // Brightness and screen blank bit - if (Byte != Memory.FillRAM [0x2100]) - { - FLUSH_REDRAW (); - if (PPU.Brightness != (Byte & 0xF)) - { - IPPU.ColorsChanged = TRUE; - IPPU.DirectColourMapsNeedRebuild = TRUE; - PPU.Brightness = Byte & 0xF; - S9xFixColourBrightness (); - if (PPU.Brightness > IPPU.MaxBrightness) - IPPU.MaxBrightness = PPU.Brightness; - } - if ((Memory.FillRAM[0x2100] & 0x80) != (Byte & 0x80)) - { - IPPU.ColorsChanged = TRUE; - PPU.ForcedBlanking = (Byte >> 7) & 1; - } - } - break; - - case 0x2101: - // Sprite (OBJ) tile address - if (Byte != Memory.FillRAM [0x2101]) - { - FLUSH_REDRAW (); - PPU.OBJNameBase = (Byte & 3) << 14; - PPU.OBJNameSelect = ((Byte >> 3) & 3) << 13; - PPU.OBJSizeSelect = (Byte >> 5) & 7; - IPPU.OBJChanged = TRUE; - } - break; - - case 0x2102: - // Sprite write address (low) - PPU.OAMAddr = ((Memory.FillRAM[0x2103]&1)<<8) | Byte; - PPU.OAMFlip = 2; - PPU.OAMReadFlip = 0; - PPU.SavedOAMAddr = PPU.OAMAddr; - if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) - { - PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; - IPPU.OBJChanged = TRUE; - } - break; - - 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; - if (PPU.OAMPriorityRotation) - { - if (PPU.FirstSprite != (PPU.OAMAddr >> 1)) - { - PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; - IPPU.OBJChanged = TRUE; - } - } else { - if (PPU.FirstSprite != 0) - { - PPU.FirstSprite = 0; - IPPU.OBJChanged = TRUE; - } - } - PPU.OAMFlip = 0; - PPU.OAMReadFlip = 0; - PPU.SavedOAMAddr = PPU.OAMAddr; - break; - - case 0x2104: - // Sprite register write - REGISTER_2104(Byte); - break; - - case 0x2105: - // Screen mode (0 - 7), background tile sizes and background 3 - // priority - if (Byte != Memory.FillRAM [0x2105]) - { - FLUSH_REDRAW (); - PPU.BG[0].BGSize = (Byte >> 4) & 1; - PPU.BG[1].BGSize = (Byte >> 5) & 1; - PPU.BG[2].BGSize = (Byte >> 6) & 1; - PPU.BG[3].BGSize = (Byte >> 7) & 1; - PPU.BGMode = Byte & 7; - // BJ: BG3Priority only takes effect if BGMode==1 and the bit is set - PPU.BG3Priority = ((Byte & 0x0f) == 0x09); - if(PPU.BGMode==5||PPU.BGMode==6) - IPPU.Interlace = Memory.FillRAM[0x2133]&1; - } - break; - - case 0x2106: - // Mosaic pixel size and enable - if (Byte != Memory.FillRAM [0x2106]) - { - FLUSH_REDRAW (); - PPU.Mosaic = (Byte >> 4) + 1; - PPU.BGMosaic [0] = (Byte & 1) && PPU.Mosaic > 1; - PPU.BGMosaic [1] = (Byte & 2) && PPU.Mosaic > 1; - PPU.BGMosaic [2] = (Byte & 4) && PPU.Mosaic > 1; - PPU.BGMosaic [3] = (Byte & 8) && PPU.Mosaic > 1; - } - break; - case 0x2107: // [BG0SC] - case 0x2108: // [BG1SC] - case 0x2109: // [BG2SC] - case 0x210A: // [BG3SC] - if (Byte != Memory.FillRAM [Address]) - { - FLUSH_REDRAW (); - PPU.BG[Address - 0x2107].SCSize = Byte & 3; - PPU.BG[Address - 0x2107].SCBase = (Byte & 0x7c) << 8; - } - break; - - case 0x210B: // [BG01NBA] - if (Byte != Memory.FillRAM [0x210b]) - { - FLUSH_REDRAW (); - PPU.BG[0].NameBase = (Byte & 7) << 12; - PPU.BG[1].NameBase = ((Byte >> 4) & 7) << 12; - } - break; - - case 0x210C: // [BG23NBA] - if (Byte != Memory.FillRAM [0x210c]) - { - FLUSH_REDRAW (); - PPU.BG[2].NameBase = (Byte & 7) << 12; - PPU.BG[3].NameBase = ((Byte >> 4) & 7) << 12; - } - break; - - - //This is the Theme Park fix - it appears all these registers - //share a previous byte value for setting them. - - case 0x210D: - //TEST9 if(last_written != 0x210d) PPU.BGnxOFSbyte = 0; - PPU.BG[0].HOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[0].HOffset = %04x %d)\n", Byte, Address, PPU.BG[0].HOffset, CPU.V_Counter); - break; - - case 0x210E: - PPU.BG[0].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[0].VOffset = %04x %d)\n", Byte, Address, PPU.BG[0].VOffset, CPU.V_Counter); - break; - - case 0x210F: - PPU.BG[1].HOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[1].HOffset = %04x %d)\n", Byte, Address, PPU.BG[1].HOffset, CPU.V_Counter); - break; - - case 0x2110: - PPU.BG[1].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[1].VOffset = %04x %d)\n", Byte, Address, PPU.BG[1].VOffset, CPU.V_Counter); - break; - - case 0x2111: - PPU.BG[2].HOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[2].HOffset = %04x %d)\n", Byte, Address, PPU.BG[2].HOffset, CPU.V_Counter); - break; - - case 0x2112: - PPU.BG[2].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[2].VOffset = %04x %d)\n", Byte, Address, PPU.BG[2].VOffset, CPU.V_Counter); - break; - - case 0x2113: - PPU.BG[3].HOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[3].HOffset = %04x %d)\n", Byte, Address, PPU.BG[3].HOffset, CPU.V_Counter); - break; - - case 0x2114: - PPU.BG[3].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; - PPU.BGnxOFSbyte = Byte; - // fprintf(stderr, "%02x to %04x (PPU.BG[3].VOffset = %04x %d)\n", Byte, Address, PPU.BG[3].VOffset, CPU.V_Counter); - break; - - //end Theme Park - - case 0x2115: - // VRAM byte/word access flag and increment - PPU.VMA.High = (Byte & 0x80) == 0 ? FALSE : TRUE; - switch (Byte & 3) - { - case 0: - PPU.VMA.Increment = 1; - break; - case 1: - PPU.VMA.Increment = 32; - break; - case 2: - case 3: - PPU.VMA.Increment = 128; - break; - } - if (Byte & 0x0c) - { - static uint16 IncCount [4] = { 0, 32, 64, 128 }; - static uint16 Shift [4] = { 0, 5, 6, 7 }; -// PPU.VMA.Increment = 1; - uint8 i = (Byte & 0x0c) >> 2; - PPU.VMA.FullGraphicCount = IncCount [i]; - PPU.VMA.Mask1 = IncCount [i] * 8 - 1; - PPU.VMA.Shift = Shift [i]; - } - else - PPU.VMA.FullGraphicCount = 0; - break; - - case 0x2116: - // VRAM read/write address (low) - PPU.VMA.Address &= 0xFF00; - PPU.VMA.Address |= Byte; + // fprintf(stderr, "%03d: %02x to %04x\n", CPU.V_Counter, Byte, Address); + if (Address <= 0x2183) + { + switch (Address) + { + case 0x2100: + // Brightness and screen blank bit + if (Byte != Memory.FillRAM [0x2100]) + { + FLUSH_REDRAW(); + if (PPU.Brightness != (Byte & 0xF)) + { + IPPU.ColorsChanged = TRUE; + IPPU.DirectColourMapsNeedRebuild = TRUE; + PPU.Brightness = Byte & 0xF; + S9xFixColourBrightness(); + if (PPU.Brightness > IPPU.MaxBrightness) + IPPU.MaxBrightness = PPU.Brightness; + } + if ((Memory.FillRAM[0x2100] & 0x80) != (Byte & 0x80)) + { + IPPU.ColorsChanged = TRUE; + PPU.ForcedBlanking = (Byte >> 7) & 1; + } + } + break; + + case 0x2101: + // Sprite (OBJ) tile address + if (Byte != Memory.FillRAM [0x2101]) + { + FLUSH_REDRAW(); + PPU.OBJNameBase = (Byte & 3) << 14; + PPU.OBJNameSelect = ((Byte >> 3) & 3) << 13; + PPU.OBJSizeSelect = (Byte >> 5) & 7; + IPPU.OBJChanged = TRUE; + } + break; + + case 0x2102: + // Sprite write address (low) + PPU.OAMAddr = ((Memory.FillRAM[0x2103] & 1) << 8) | Byte; + PPU.OAMFlip = 2; + PPU.OAMReadFlip = 0; + PPU.SavedOAMAddr = PPU.OAMAddr; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xFE) >> 1; + IPPU.OBJChanged = TRUE; + } + break; + + 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; + if (PPU.OAMPriorityRotation) + { + if (PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xFE) >> 1; + IPPU.OBJChanged = TRUE; + } + } + else + { + if (PPU.FirstSprite != 0) + { + PPU.FirstSprite = 0; + IPPU.OBJChanged = TRUE; + } + } + PPU.OAMFlip = 0; + PPU.OAMReadFlip = 0; + PPU.SavedOAMAddr = PPU.OAMAddr; + break; + + case 0x2104: + // Sprite register write + REGISTER_2104(Byte); + break; + + case 0x2105: + // Screen mode (0 - 7), background tile sizes and background 3 + // priority + if (Byte != Memory.FillRAM [0x2105]) + { + FLUSH_REDRAW(); + PPU.BG[0].BGSize = (Byte >> 4) & 1; + PPU.BG[1].BGSize = (Byte >> 5) & 1; + PPU.BG[2].BGSize = (Byte >> 6) & 1; + PPU.BG[3].BGSize = (Byte >> 7) & 1; + PPU.BGMode = Byte & 7; + // BJ: BG3Priority only takes effect if BGMode==1 and the bit is set + PPU.BG3Priority = ((Byte & 0x0f) == 0x09); + if (PPU.BGMode == 5 || PPU.BGMode == 6) + IPPU.Interlace = Memory.FillRAM[0x2133] & 1; + } + break; + + case 0x2106: + // Mosaic pixel size and enable + if (Byte != Memory.FillRAM [0x2106]) + { + FLUSH_REDRAW(); + PPU.Mosaic = (Byte >> 4) + 1; + PPU.BGMosaic [0] = (Byte & 1) && PPU.Mosaic > 1; + PPU.BGMosaic [1] = (Byte & 2) && PPU.Mosaic > 1; + PPU.BGMosaic [2] = (Byte & 4) && PPU.Mosaic > 1; + PPU.BGMosaic [3] = (Byte & 8) && PPU.Mosaic > 1; + } + break; + case 0x2107: // [BG0SC] + case 0x2108: // [BG1SC] + case 0x2109: // [BG2SC] + case 0x210A: // [BG3SC] + if (Byte != Memory.FillRAM [Address]) + { + FLUSH_REDRAW(); + PPU.BG[Address - 0x2107].SCSize = Byte & 3; + PPU.BG[Address - 0x2107].SCBase = (Byte & 0x7c) << 8; + } + break; + + case 0x210B: // [BG01NBA] + if (Byte != Memory.FillRAM [0x210b]) + { + FLUSH_REDRAW(); + PPU.BG[0].NameBase = (Byte & 7) << 12; + PPU.BG[1].NameBase = ((Byte >> 4) & 7) << 12; + } + break; + + case 0x210C: // [BG23NBA] + if (Byte != Memory.FillRAM [0x210c]) + { + FLUSH_REDRAW(); + PPU.BG[2].NameBase = (Byte & 7) << 12; + PPU.BG[3].NameBase = ((Byte >> 4) & 7) << 12; + } + break; + + + //This is the Theme Park fix - it appears all these registers + //share a previous byte value for setting them. + + case 0x210D: + //TEST9 if(last_written != 0x210d) PPU.BGnxOFSbyte = 0; + PPU.BG[0].HOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[0].HOffset = %04x %d)\n", Byte, Address, PPU.BG[0].HOffset, CPU.V_Counter); + break; + + case 0x210E: + PPU.BG[0].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[0].VOffset = %04x %d)\n", Byte, Address, PPU.BG[0].VOffset, CPU.V_Counter); + break; + + case 0x210F: + PPU.BG[1].HOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[1].HOffset = %04x %d)\n", Byte, Address, PPU.BG[1].HOffset, CPU.V_Counter); + break; + + case 0x2110: + PPU.BG[1].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[1].VOffset = %04x %d)\n", Byte, Address, PPU.BG[1].VOffset, CPU.V_Counter); + break; + + case 0x2111: + PPU.BG[2].HOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[2].HOffset = %04x %d)\n", Byte, Address, PPU.BG[2].HOffset, CPU.V_Counter); + break; + + case 0x2112: + PPU.BG[2].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[2].VOffset = %04x %d)\n", Byte, Address, PPU.BG[2].VOffset, CPU.V_Counter); + break; + + case 0x2113: + PPU.BG[3].HOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[3].HOffset = %04x %d)\n", Byte, Address, PPU.BG[3].HOffset, CPU.V_Counter); + break; + + case 0x2114: + PPU.BG[3].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + // fprintf(stderr, "%02x to %04x (PPU.BG[3].VOffset = %04x %d)\n", Byte, Address, PPU.BG[3].VOffset, CPU.V_Counter); + break; + + //end Theme Park + + case 0x2115: + // VRAM byte/word access flag and increment + PPU.VMA.High = (Byte & 0x80) == 0 ? FALSE : TRUE; + switch (Byte & 3) + { + case 0: + PPU.VMA.Increment = 1; + break; + case 1: + PPU.VMA.Increment = 32; + break; + case 2: + case 3: + PPU.VMA.Increment = 128; + break; + } + if (Byte & 0x0c) + { + static uint16 IncCount [4] = { 0, 32, 64, 128 }; + static uint16 Shift [4] = { 0, 5, 6, 7 }; + // PPU.VMA.Increment = 1; + uint8 i = (Byte & 0x0c) >> 2; + PPU.VMA.FullGraphicCount = IncCount [i]; + PPU.VMA.Mask1 = IncCount [i] * 8 - 1; + PPU.VMA.Shift = Shift [i]; + } + else + PPU.VMA.FullGraphicCount = 0; + break; + + case 0x2116: + // VRAM read/write address (low) + PPU.VMA.Address &= 0xFF00; + PPU.VMA.Address |= Byte; #ifdef CORRECT_VRAM_READS - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + - (rem >> PPU.VMA.Shift) + - ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((address << 1) & 0xFFFF)); - } else - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((PPU.VMA.Address << 1) & 0xffff)); + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xFFFF)); + } + else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & + 0xffff)); #else - IPPU.FirstVRAMRead = TRUE; + IPPU.FirstVRAMRead = TRUE; #endif - break; + break; - case 0x2117: - // VRAM read/write address (high) - PPU.VMA.Address &= 0x00FF; - PPU.VMA.Address |= Byte << 8; + case 0x2117: + // VRAM read/write address (high) + PPU.VMA.Address &= 0x00FF; + PPU.VMA.Address |= Byte << 8; #ifdef CORRECT_VRAM_READS - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + - (rem >> PPU.VMA.Shift) + - ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((address << 1) & 0xFFFF)); - } else - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((PPU.VMA.Address << 1) & 0xffff)); + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xFFFF)); + } + else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & + 0xffff)); #else - IPPU.FirstVRAMRead = TRUE; + IPPU.FirstVRAMRead = TRUE; #endif - break; + break; - case 0x2118: - // VRAM write data (low) + case 0x2118: + // VRAM write data (low) #ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; + IPPU.FirstVRAMRead = TRUE; #endif - REGISTER_2118(Byte); - break; + REGISTER_2118(Byte); + break; - case 0x2119: - // VRAM write data (high) + case 0x2119: + // VRAM write data (high) #ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; + IPPU.FirstVRAMRead = TRUE; #endif - REGISTER_2119(Byte); - break; - - case 0x211a: - // Mode 7 outside rotation area display mode and flipping - if (Byte != Memory.FillRAM [0x211a]) - { - FLUSH_REDRAW (); - PPU.Mode7Repeat = Byte >> 6; - if (PPU.Mode7Repeat == 1) - PPU.Mode7Repeat = 0; - PPU.Mode7VFlip = (Byte & 2) >> 1; - PPU.Mode7HFlip = Byte & 1; - } - break; - case 0x211b: - // Mode 7 matrix A (low & high) - PPU.MatrixA = ((PPU.MatrixA >> 8) & 0xff) | (Byte << 8); - PPU.Need16x8Mulitply = TRUE; - break; - case 0x211c: - // Mode 7 matrix B (low & high) - PPU.MatrixB = ((PPU.MatrixB >> 8) & 0xff) | (Byte << 8); - PPU.Need16x8Mulitply = TRUE; - break; - 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) - PPU.MatrixD = ((PPU.MatrixD >> 8) & 0xff) | (Byte << 8); - break; - 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) - PPU.CentreY = ((PPU.CentreY >> 8) & 0xff) | (Byte << 8); - break; - - case 0x2121: - // CG-RAM address - PPU.CGFLIP = 0; - PPU.CGFLIPRead = 0; - PPU.CGADD = Byte; - break; - - case 0x2122: - REGISTER_2122(Byte); - break; - - case 0x2123: - // Window 1 and 2 enable for backgrounds 1 and 2 - if (Byte != Memory.FillRAM [0x2123]) - { - FLUSH_REDRAW (); - PPU.ClipWindow1Enable [0] = !!(Byte & 0x02); - PPU.ClipWindow1Enable [1] = !!(Byte & 0x20); - PPU.ClipWindow2Enable [0] = !!(Byte & 0x08); - PPU.ClipWindow2Enable [1] = !!(Byte & 0x80); - PPU.ClipWindow1Inside [0] = !(Byte & 0x01); - PPU.ClipWindow1Inside [1] = !(Byte & 0x10); - PPU.ClipWindow2Inside [0] = !(Byte & 0x04); - PPU.ClipWindow2Inside [1] = !(Byte & 0x40); - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x2124: - // Window 1 and 2 enable for backgrounds 3 and 4 - if (Byte != Memory.FillRAM [0x2124]) - { - FLUSH_REDRAW (); - PPU.ClipWindow1Enable [2] = !!(Byte & 0x02); - PPU.ClipWindow1Enable [3] = !!(Byte & 0x20); - PPU.ClipWindow2Enable [2] = !!(Byte & 0x08); - PPU.ClipWindow2Enable [3] = !!(Byte & 0x80); - PPU.ClipWindow1Inside [2] = !(Byte & 0x01); - PPU.ClipWindow1Inside [3] = !(Byte & 0x10); - PPU.ClipWindow2Inside [2] = !(Byte & 0x04); - PPU.ClipWindow2Inside [3] = !(Byte & 0x40); - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x2125: - // Window 1 and 2 enable for objects and colour window - if (Byte != Memory.FillRAM [0x2125]) - { - FLUSH_REDRAW (); - PPU.ClipWindow1Enable [4] = !!(Byte & 0x02); - PPU.ClipWindow1Enable [5] = !!(Byte & 0x20); - PPU.ClipWindow2Enable [4] = !!(Byte & 0x08); - PPU.ClipWindow2Enable [5] = !!(Byte & 0x80); - PPU.ClipWindow1Inside [4] = !(Byte & 0x01); - PPU.ClipWindow1Inside [5] = !(Byte & 0x10); - PPU.ClipWindow2Inside [4] = !(Byte & 0x04); - PPU.ClipWindow2Inside [5] = !(Byte & 0x40); - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x2126: - // Window 1 left position - if (Byte != Memory.FillRAM [0x2126]) - { - FLUSH_REDRAW (); - PPU.Window1Left = Byte; - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x2127: - // Window 1 right position - if (Byte != Memory.FillRAM [0x2127]) - { - FLUSH_REDRAW (); - PPU.Window1Right = Byte; - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x2128: - // Window 2 left position - if (Byte != Memory.FillRAM [0x2128]) - { - FLUSH_REDRAW (); - PPU.Window2Left = Byte; - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x2129: - // Window 2 right position - if (Byte != Memory.FillRAM [0x2129]) - { - FLUSH_REDRAW (); - PPU.Window2Right = Byte; - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x212a: - // Windows 1 & 2 overlap logic for backgrounds 1 - 4 - if (Byte != Memory.FillRAM [0x212a]) - { - FLUSH_REDRAW (); - PPU.ClipWindowOverlapLogic [0] = (Byte & 0x03); - PPU.ClipWindowOverlapLogic [1] = (Byte & 0x0c) >> 2; - PPU.ClipWindowOverlapLogic [2] = (Byte & 0x30) >> 4; - PPU.ClipWindowOverlapLogic [3] = (Byte & 0xc0) >> 6; - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x212b: - // Windows 1 & 2 overlap logic for objects and colour window - if (Byte != Memory.FillRAM [0x212b]) - { - FLUSH_REDRAW (); - PPU.ClipWindowOverlapLogic [4] = Byte & 0x03; - PPU.ClipWindowOverlapLogic [5] = (Byte & 0x0c) >> 2; - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x212c: - // Main screen designation (backgrounds 1 - 4 and objects) - if (Byte != Memory.FillRAM [0x212c]) - { - FLUSH_REDRAW (); - PPU.RecomputeClipWindows = TRUE; - Memory.FillRAM [Address] = Byte; - return; - } - break; - case 0x212d: - // Sub-screen designation (backgrounds 1 - 4 and objects) - if (Byte != Memory.FillRAM [0x212d]) - { - FLUSH_REDRAW (); - PPU.RecomputeClipWindows = TRUE; - Memory.FillRAM [Address] = Byte; - return; - } - break; - case 0x212e: - // Window mask designation for main screen ? - case 0x212f: - // Window mask designation for sub-screen ? - if (Byte != Memory.FillRAM [Address]) - { - FLUSH_REDRAW (); - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x2130: - // Fixed colour addition or screen addition - if (Byte != Memory.FillRAM [0x2130]) - { - FLUSH_REDRAW (); - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x2131: - // Colour addition or subtraction select - if (Byte != Memory.FillRAM[0x2131]) - { - FLUSH_REDRAW (); - // Backgrounds 1 - 4, objects and backdrop colour add/sub enable - Memory.FillRAM[0x2131] = Byte; - } - break; - case 0x2132: - if (Byte != Memory.FillRAM [0x2132]) - { - FLUSH_REDRAW (); - // Colour data for fixed colour addition/subtraction - if (Byte & 0x80) - PPU.FixedColourBlue = Byte & 0x1f; - if (Byte & 0x40) - PPU.FixedColourGreen = Byte & 0x1f; - if (Byte & 0x20) - PPU.FixedColourRed = Byte & 0x1f; - } - break; - case 0x2133: - // Screen settings - if (Byte != Memory.FillRAM [0x2133]) - { - if (Byte & 0x04) - { - PPU.ScreenHeight = SNES_HEIGHT_EXTENDED; - if(IPPU.DoubleHeightPixels) - IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; - else - IPPU.RenderedScreenHeight = PPU.ScreenHeight; - } - else PPU.ScreenHeight = SNES_HEIGHT; - - //if((Byte & 1)&&(PPU.BGMode==5||PPU.BGMode==6)) - //IPPU.Interlace=1; - if((Memory.FillRAM [0x2133] ^ Byte)&3) - { - FLUSH_REDRAW (); - if((Memory.FillRAM [0x2133] ^ Byte)&2) - IPPU.OBJChanged = TRUE; - if(PPU.BGMode==5||PPU.BGMode==6) - IPPU.Interlace = Byte&1; - IPPU.InterlaceSprites=0; - // IPPU.InterlaceSprites = (Byte&2)>>1; - } - - } - 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 0x2139: - case 0x213a: - // VRAM read data (read-only) - /* fall through */ - case 0x213b: - // CG-RAM read data (read-only) - /* fall through */ - 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) - return; - case 0x2140: case 0x2141: case 0x2142: case 0x2143: - case 0x2144: case 0x2145: case 0x2146: case 0x2147: - case 0x2148: case 0x2149: case 0x214a: case 0x214b: - case 0x214c: case 0x214d: case 0x214e: case 0x214f: - case 0x2150: case 0x2151: case 0x2152: case 0x2153: - case 0x2154: case 0x2155: case 0x2156: case 0x2157: - case 0x2158: case 0x2159: case 0x215a: case 0x215b: - case 0x215c: case 0x215d: case 0x215e: case 0x215f: - case 0x2160: case 0x2161: case 0x2162: case 0x2163: - case 0x2164: case 0x2165: case 0x2166: case 0x2167: - case 0x2168: case 0x2169: case 0x216a: case 0x216b: - case 0x216c: case 0x216d: case 0x216e: case 0x216f: - case 0x2170: case 0x2171: case 0x2172: case 0x2173: - case 0x2174: case 0x2175: case 0x2176: case 0x2177: - case 0x2178: case 0x2179: case 0x217a: case 0x217b: - case 0x217c: case 0x217d: case 0x217e: case 0x217f: + REGISTER_2119(Byte); + break; + + case 0x211a: + // Mode 7 outside rotation area display mode and flipping + if (Byte != Memory.FillRAM [0x211a]) + { + FLUSH_REDRAW(); + PPU.Mode7Repeat = Byte >> 6; + if (PPU.Mode7Repeat == 1) + PPU.Mode7Repeat = 0; + PPU.Mode7VFlip = (Byte & 2) >> 1; + PPU.Mode7HFlip = Byte & 1; + } + break; + case 0x211b: + // Mode 7 matrix A (low & high) + PPU.MatrixA = ((PPU.MatrixA >> 8) & 0xff) | (Byte << 8); + PPU.Need16x8Mulitply = TRUE; + break; + case 0x211c: + // Mode 7 matrix B (low & high) + PPU.MatrixB = ((PPU.MatrixB >> 8) & 0xff) | (Byte << 8); + PPU.Need16x8Mulitply = TRUE; + break; + 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) + PPU.MatrixD = ((PPU.MatrixD >> 8) & 0xff) | (Byte << 8); + break; + 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) + PPU.CentreY = ((PPU.CentreY >> 8) & 0xff) | (Byte << 8); + break; + + case 0x2121: + // CG-RAM address + PPU.CGFLIP = 0; + PPU.CGFLIPRead = 0; + PPU.CGADD = Byte; + break; + + case 0x2122: + REGISTER_2122(Byte); + break; + + case 0x2123: + // Window 1 and 2 enable for backgrounds 1 and 2 + if (Byte != Memory.FillRAM [0x2123]) + { + FLUSH_REDRAW(); + PPU.ClipWindow1Enable [0] = !!(Byte & 0x02); + PPU.ClipWindow1Enable [1] = !!(Byte & 0x20); + PPU.ClipWindow2Enable [0] = !!(Byte & 0x08); + PPU.ClipWindow2Enable [1] = !!(Byte & 0x80); + PPU.ClipWindow1Inside [0] = !(Byte & 0x01); + PPU.ClipWindow1Inside [1] = !(Byte & 0x10); + PPU.ClipWindow2Inside [0] = !(Byte & 0x04); + PPU.ClipWindow2Inside [1] = !(Byte & 0x40); + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2124: + // Window 1 and 2 enable for backgrounds 3 and 4 + if (Byte != Memory.FillRAM [0x2124]) + { + FLUSH_REDRAW(); + PPU.ClipWindow1Enable [2] = !!(Byte & 0x02); + PPU.ClipWindow1Enable [3] = !!(Byte & 0x20); + PPU.ClipWindow2Enable [2] = !!(Byte & 0x08); + PPU.ClipWindow2Enable [3] = !!(Byte & 0x80); + PPU.ClipWindow1Inside [2] = !(Byte & 0x01); + PPU.ClipWindow1Inside [3] = !(Byte & 0x10); + PPU.ClipWindow2Inside [2] = !(Byte & 0x04); + PPU.ClipWindow2Inside [3] = !(Byte & 0x40); + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2125: + // Window 1 and 2 enable for objects and colour window + if (Byte != Memory.FillRAM [0x2125]) + { + FLUSH_REDRAW(); + PPU.ClipWindow1Enable [4] = !!(Byte & 0x02); + PPU.ClipWindow1Enable [5] = !!(Byte & 0x20); + PPU.ClipWindow2Enable [4] = !!(Byte & 0x08); + PPU.ClipWindow2Enable [5] = !!(Byte & 0x80); + PPU.ClipWindow1Inside [4] = !(Byte & 0x01); + PPU.ClipWindow1Inside [5] = !(Byte & 0x10); + PPU.ClipWindow2Inside [4] = !(Byte & 0x04); + PPU.ClipWindow2Inside [5] = !(Byte & 0x40); + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2126: + // Window 1 left position + if (Byte != Memory.FillRAM [0x2126]) + { + FLUSH_REDRAW(); + PPU.Window1Left = Byte; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2127: + // Window 1 right position + if (Byte != Memory.FillRAM [0x2127]) + { + FLUSH_REDRAW(); + PPU.Window1Right = Byte; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2128: + // Window 2 left position + if (Byte != Memory.FillRAM [0x2128]) + { + FLUSH_REDRAW(); + PPU.Window2Left = Byte; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2129: + // Window 2 right position + if (Byte != Memory.FillRAM [0x2129]) + { + FLUSH_REDRAW(); + PPU.Window2Right = Byte; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x212a: + // Windows 1 & 2 overlap logic for backgrounds 1 - 4 + if (Byte != Memory.FillRAM [0x212a]) + { + FLUSH_REDRAW(); + PPU.ClipWindowOverlapLogic [0] = (Byte & 0x03); + PPU.ClipWindowOverlapLogic [1] = (Byte & 0x0c) >> 2; + PPU.ClipWindowOverlapLogic [2] = (Byte & 0x30) >> 4; + PPU.ClipWindowOverlapLogic [3] = (Byte & 0xc0) >> 6; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x212b: + // Windows 1 & 2 overlap logic for objects and colour window + if (Byte != Memory.FillRAM [0x212b]) + { + FLUSH_REDRAW(); + PPU.ClipWindowOverlapLogic [4] = Byte & 0x03; + PPU.ClipWindowOverlapLogic [5] = (Byte & 0x0c) >> 2; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x212c: + // Main screen designation (backgrounds 1 - 4 and objects) + if (Byte != Memory.FillRAM [0x212c]) + { + FLUSH_REDRAW(); + PPU.RecomputeClipWindows = TRUE; + Memory.FillRAM [Address] = Byte; + return; + } + break; + case 0x212d: + // Sub-screen designation (backgrounds 1 - 4 and objects) + if (Byte != Memory.FillRAM [0x212d]) + { + FLUSH_REDRAW(); + PPU.RecomputeClipWindows = TRUE; + Memory.FillRAM [Address] = Byte; + return; + } + break; + case 0x212e: + // Window mask designation for main screen ? + case 0x212f: + // Window mask designation for sub-screen ? + if (Byte != Memory.FillRAM [Address]) + { + FLUSH_REDRAW(); + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2130: + // Fixed colour addition or screen addition + if (Byte != Memory.FillRAM [0x2130]) + { + FLUSH_REDRAW(); + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2131: + // Colour addition or subtraction select + if (Byte != Memory.FillRAM[0x2131]) + { + FLUSH_REDRAW(); + // Backgrounds 1 - 4, objects and backdrop colour add/sub enable + Memory.FillRAM[0x2131] = Byte; + } + break; + case 0x2132: + if (Byte != Memory.FillRAM [0x2132]) + { + FLUSH_REDRAW(); + // Colour data for fixed colour addition/subtraction + if (Byte & 0x80) + PPU.FixedColourBlue = Byte & 0x1f; + if (Byte & 0x40) + PPU.FixedColourGreen = Byte & 0x1f; + if (Byte & 0x20) + PPU.FixedColourRed = Byte & 0x1f; + } + break; + case 0x2133: + // Screen settings + if (Byte != Memory.FillRAM [0x2133]) + { + if (Byte & 0x04) + { + PPU.ScreenHeight = SNES_HEIGHT_EXTENDED; + if (IPPU.DoubleHeightPixels) + IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; + else + IPPU.RenderedScreenHeight = PPU.ScreenHeight; + } + else PPU.ScreenHeight = SNES_HEIGHT; + + //if((Byte & 1)&&(PPU.BGMode==5||PPU.BGMode==6)) + //IPPU.Interlace=1; + if ((Memory.FillRAM [0x2133] ^ Byte) & 3) + { + FLUSH_REDRAW(); + if ((Memory.FillRAM [0x2133] ^ Byte) & 2) + IPPU.OBJChanged = TRUE; + if (PPU.BGMode == 5 || PPU.BGMode == 6) + IPPU.Interlace = Byte & 1; + IPPU.InterlaceSprites = 0; + // IPPU.InterlaceSprites = (Byte&2)>>1; + } + + } + 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 0x2139: + case 0x213a: + // VRAM read data (read-only) + /* fall through */ + case 0x213b: + // CG-RAM read data (read-only) + /* fall through */ + 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) + return; + case 0x2140: + case 0x2141: + case 0x2142: + case 0x2143: + case 0x2144: + case 0x2145: + case 0x2146: + case 0x2147: + case 0x2148: + case 0x2149: + case 0x214a: + case 0x214b: + case 0x214c: + case 0x214d: + case 0x214e: + case 0x214f: + case 0x2150: + case 0x2151: + case 0x2152: + case 0x2153: + case 0x2154: + case 0x2155: + case 0x2156: + case 0x2157: + case 0x2158: + case 0x2159: + case 0x215a: + case 0x215b: + case 0x215c: + case 0x215d: + case 0x215e: + case 0x215f: + case 0x2160: + case 0x2161: + case 0x2162: + case 0x2163: + case 0x2164: + case 0x2165: + case 0x2166: + case 0x2167: + case 0x2168: + case 0x2169: + case 0x216a: + case 0x216b: + case 0x216c: + case 0x216d: + case 0x216e: + case 0x216f: + case 0x2170: + case 0x2171: + case 0x2172: + case 0x2173: + case 0x2174: + case 0x2175: + case 0x2176: + case 0x2177: + case 0x2178: + case 0x2179: + case 0x217a: + case 0x217b: + case 0x217c: + case 0x217d: + case 0x217e: + case 0x217f: #ifdef SPCTOOL - _SPCInPB (Address & 3, Byte); -#else - // CPU.Flags |= DEBUG_MODE_FLAG; - Memory.FillRAM [Address] = Byte; - IAPU.RAM [(Address & 3) + 0xf4] = Byte; + _SPCInPB(Address & 3, Byte); +#else + // CPU.Flags |= DEBUG_MODE_FLAG; + Memory.FillRAM [Address] = Byte; + IAPU.RAM [(Address & 3) + 0xf4] = Byte; #ifdef SPC700_SHUTDOWN - IAPU.APUExecuting = Settings.APUEnabled; - IAPU.WaitCounter++; + IAPU.APUExecuting = Settings.APUEnabled; + IAPU.WaitCounter++; #endif #endif // SPCTOOL - break; - case 0x2180: - REGISTER_2180(Byte); - break; - case 0x2181: - PPU.WRAM &= 0x1FF00; - PPU.WRAM |= Byte; - break; - case 0x2182: - PPU.WRAM &= 0x100FF; - PPU.WRAM |= Byte << 8; - break; - case 0x2183: - PPU.WRAM &= 0x0FFFF; - PPU.WRAM |= Byte << 16; - PPU.WRAM &= 0x1FFFF; - break; - } - } - else - { - if (Settings.SA1) - { - if (Address >= 0x2200 && Address <0x23ff) - S9xSetSA1 (Byte, Address); - else - Memory.FillRAM [Address] = Byte; - - return; - } - else - // Dai Kaijyu Monogatari II - if (Address == 0x2801 && Settings.SRTC) - S9xSetSRTC (Byte, Address); - else - if (Address >= 0x3000 && Address < 0x3300) - { - if (!Settings.SuperFX) - { - return; - } + break; + case 0x2180: + REGISTER_2180(Byte); + break; + case 0x2181: + PPU.WRAM &= 0x1FF00; + PPU.WRAM |= Byte; + break; + case 0x2182: + PPU.WRAM &= 0x100FF; + PPU.WRAM |= Byte << 8; + break; + case 0x2183: + PPU.WRAM &= 0x0FFFF; + PPU.WRAM |= Byte << 16; + PPU.WRAM &= 0x1FFFF; + break; + } + } + else + { + if (Settings.SA1) + { + if (Address >= 0x2200 && Address < 0x23ff) + S9xSetSA1(Byte, Address); + else + Memory.FillRAM [Address] = Byte; + + return; + } + else + // Dai Kaijyu Monogatari II + if (Address == 0x2801 && Settings.SRTC) + S9xSetSRTC(Byte, Address); + else if (Address >= 0x3000 && Address < 0x3300) + { + if (!Settings.SuperFX) + return; #ifdef ZSNES_FX - Memory.FillRAM [Address] = Byte; - if (Address < 0x3040) - S9xSuperFXWriteReg (Byte, Address); + Memory.FillRAM [Address] = Byte; + if (Address < 0x3040) + S9xSuperFXWriteReg(Byte, Address); #else - switch (Address) - { - case 0x3030: - if ((Memory.FillRAM [0x3030] ^ Byte) & FLG_G) - { - Memory.FillRAM [Address] = Byte; - // Go flag has been changed - if (Byte & FLG_G) - S9xSuperFXExec (); - else - FxFlushCache (); - } - else - Memory.FillRAM [Address] = Byte; - break; - - case 0x3031: - case 0x3033: - case 0x3037: - case 0x3039: - case 0x303a: - case 0x303f: - Memory.FillRAM [Address] = Byte; - break; - case 0x3034: - case 0x3036: - Memory.FillRAM [Address] = Byte & 0x7f; - break; - case 0x3038: - Memory.FillRAM [Address] = Byte; - fx_dirtySCBR(); - break; - case 0x303b: - break; - case 0x303c: - Memory.FillRAM [Address] = Byte; - fx_updateRamBank(Byte); - break; - case 0x301f: - Memory.FillRAM [Address] = Byte; - Memory.FillRAM [0x3000 + GSU_SFR] |= FLG_G; - S9xSuperFXExec (); - return; - - default: - Memory.FillRAM[Address] = Byte; - if (Address >= 0x3100) - { - FxCacheWriteAccess (Address); - } - break; - } + switch (Address) + { + case 0x3030: + if ((Memory.FillRAM [0x3030] ^ Byte) & FLG_G) + { + Memory.FillRAM [Address] = Byte; + // Go flag has been changed + if (Byte & FLG_G) + S9xSuperFXExec(); + else + FxFlushCache(); + } + else + Memory.FillRAM [Address] = Byte; + break; + + case 0x3031: + case 0x3033: + case 0x3037: + case 0x3039: + case 0x303a: + case 0x303f: + Memory.FillRAM [Address] = Byte; + break; + case 0x3034: + case 0x3036: + Memory.FillRAM [Address] = Byte & 0x7f; + break; + case 0x3038: + Memory.FillRAM [Address] = Byte; + fx_dirtySCBR(); + break; + case 0x303b: + break; + case 0x303c: + Memory.FillRAM [Address] = Byte; + fx_updateRamBank(Byte); + break; + case 0x301f: + Memory.FillRAM [Address] = Byte; + Memory.FillRAM [0x3000 + GSU_SFR] |= FLG_G; + S9xSuperFXExec(); + return; + + default: + Memory.FillRAM[Address] = Byte; + if (Address >= 0x3100) + FxCacheWriteAccess(Address); + break; + } #endif - return; - } - } - Memory.FillRAM[Address] = Byte; + return; + } + } + Memory.FillRAM[Address] = Byte; } @@ -906,1972 +954,2021 @@ void S9xSetPPU (uint8 Byte, uint16 Address) /* S9xGetPPU() */ /* This function retrieves a PPU Register */ /******************************************************************************/ -uint8 S9xGetPPU (uint16 Address) +uint8 S9xGetPPU(uint16 Address) { - uint8 byte = OpenBus; - if(Address<0x2100)//not a real PPU reg - return OpenBus; //treat as unmapped memory returning last byte on the bus - if (Address <= 0x2190) - { - switch (Address) - { - case 0x2100: - case 0x2101: - case 0x2102: - case 0x2103: - return OpenBus; - - case 0x2104: - case 0x2105: - case 0x2106: - case 0x2108: - case 0x2109: - case 0x210a: - case 0x2115: - case 0x2116: - case 0x2118: - case 0x2119: - case 0x211a: - case 0x2124: - case 0x2125: - case 0x2126: - case 0x2128: - case 0x2129: - case 0x212a: - return PPU.OpenBus1; - - case 0x2107: - case 0x2117: - case 0x2121: - case 0x2122: - case 0x2123: - case 0x2127: - case 0x212b: - case 0x212c: - case 0x212d: - case 0x212e: - case 0x212f: - case 0x2130: - case 0x2131: - case 0x2132: - case 0x2133: - return OpenBus; - - case 0x210b: - case 0x210c: - case 0x210d: - case 0x210e: - case 0x210f: - case 0x2110: - case 0x2111: - case 0x2112: - case 0x2113: - return OpenBus; - - case 0x2114: - case 0x211b: - case 0x211c: - case 0x211d: - case 0x211e: - case 0x211f: - case 0x2120: - return OpenBus; - - - case 0x2134: - case 0x2135: - case 0x2136: - // 16bit x 8bit multiply read result. - if (PPU.Need16x8Mulitply) - { - int32 r = (int32) PPU.MatrixA * (int32) (PPU.MatrixB >> 8); - - Memory.FillRAM[0x2134] = (uint8) r; - Memory.FillRAM[0x2135] = (uint8)(r >> 8); - Memory.FillRAM[0x2136] = (uint8)(r >> 16); - PPU.Need16x8Mulitply = FALSE; - } - return (PPU.OpenBus1 = Memory.FillRAM[Address]); - case 0x2137: - S9xLatchCounters(0); - return OpenBus; - - case 0x2138: - // Read OAM (sprite) control data - if(PPU.OAMAddr&0x100){ - if (!(PPU.OAMFlip&1)) - { - byte = PPU.OAMData [(PPU.OAMAddr&0x10f) << 1]; - } - else - { - byte = PPU.OAMData [((PPU.OAMAddr&0x10f) << 1) + 1]; - PPU.OAMAddr=(PPU.OAMAddr+1)&0x1ff; - if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) - { - PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; - IPPU.OBJChanged = TRUE; - } - } - } else { - if (!(PPU.OAMFlip&1)) - { - byte = PPU.OAMData [PPU.OAMAddr << 1]; - } - else - { - byte = PPU.OAMData [(PPU.OAMAddr << 1) + 1]; - ++PPU.OAMAddr; - if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) - { - PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; - IPPU.OBJChanged = TRUE; - } - } - } - PPU.OAMFlip ^= 1; - return (PPU.OpenBus1 = byte); - - case 0x2139: - // Read vram low byte + uint8 byte = OpenBus; + if (Address < 0x2100) //not a real PPU reg + return OpenBus; //treat as unmapped memory returning last byte on the bus + if (Address <= 0x2190) + { + switch (Address) + { + case 0x2100: + case 0x2101: + case 0x2102: + case 0x2103: + return OpenBus; + + case 0x2104: + case 0x2105: + case 0x2106: + case 0x2108: + case 0x2109: + case 0x210a: + case 0x2115: + case 0x2116: + case 0x2118: + case 0x2119: + case 0x211a: + case 0x2124: + case 0x2125: + case 0x2126: + case 0x2128: + case 0x2129: + case 0x212a: + return PPU.OpenBus1; + + case 0x2107: + case 0x2117: + case 0x2121: + case 0x2122: + case 0x2123: + case 0x2127: + case 0x212b: + case 0x212c: + case 0x212d: + case 0x212e: + case 0x212f: + case 0x2130: + case 0x2131: + case 0x2132: + case 0x2133: + return OpenBus; + + case 0x210b: + case 0x210c: + case 0x210d: + case 0x210e: + case 0x210f: + case 0x2110: + case 0x2111: + case 0x2112: + case 0x2113: + return OpenBus; + + case 0x2114: + case 0x211b: + case 0x211c: + case 0x211d: + case 0x211e: + case 0x211f: + case 0x2120: + return OpenBus; + + + case 0x2134: + case 0x2135: + case 0x2136: + // 16bit x 8bit multiply read result. + if (PPU.Need16x8Mulitply) + { + int32 r = (int32) PPU.MatrixA * (int32)(PPU.MatrixB >> 8); + + Memory.FillRAM[0x2134] = (uint8) r; + Memory.FillRAM[0x2135] = (uint8)(r >> 8); + Memory.FillRAM[0x2136] = (uint8)(r >> 16); + PPU.Need16x8Mulitply = FALSE; + } + return (PPU.OpenBus1 = Memory.FillRAM[Address]); + case 0x2137: + S9xLatchCounters(0); + return OpenBus; + + case 0x2138: + // Read OAM (sprite) control data + if (PPU.OAMAddr & 0x100) + { + if (!(PPU.OAMFlip & 1)) + byte = PPU.OAMData [(PPU.OAMAddr & 0x10f) << 1]; + else + { + byte = PPU.OAMData [((PPU.OAMAddr & 0x10f) << 1) + 1]; + PPU.OAMAddr = (PPU.OAMAddr + 1) & 0x1ff; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xFE) >> 1; + IPPU.OBJChanged = TRUE; + } + } + } + else + { + if (!(PPU.OAMFlip & 1)) + byte = PPU.OAMData [PPU.OAMAddr << 1]; + else + { + byte = PPU.OAMData [(PPU.OAMAddr << 1) + 1]; + ++PPU.OAMAddr; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xFE) >> 1; + IPPU.OBJChanged = TRUE; + } + } + } + PPU.OAMFlip ^= 1; + return (PPU.OpenBus1 = byte); + + case 0x2139: + // Read vram low byte #ifdef CORRECT_VRAM_READS - byte = IPPU.VRAMReadBuffer & 0xff; - if (!PPU.VMA.High) - { - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + - (rem >> PPU.VMA.Shift) + - ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((address << 1) & 0xFFFF)); - } else - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((PPU.VMA.Address << 1) & 0xffff)); - PPU.VMA.Address += PPU.VMA.Increment; - } + byte = IPPU.VRAMReadBuffer & 0xff; + if (!PPU.VMA.High) + { + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xFFFF)); + } + else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & + 0xffff)); + PPU.VMA.Address += PPU.VMA.Increment; + } #else - if (IPPU.FirstVRAMRead) - byte = Memory.VRAM[(PPU.VMA.Address << 1)&0xFFFF]; - else - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address - 1; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + - (rem >> PPU.VMA.Shift) + - ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - byte = Memory.VRAM [((address << 1) - 2) & 0xFFFF]; - } - else - byte = Memory.VRAM[((PPU.VMA.Address << 1) - 2) & 0xffff]; - - if (!PPU.VMA.High) - { - PPU.VMA.Address += PPU.VMA.Increment; - IPPU.FirstVRAMRead = FALSE; - } + if (IPPU.FirstVRAMRead) + byte = Memory.VRAM[(PPU.VMA.Address << 1) & 0xFFFF]; + else if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address - 1; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + byte = Memory.VRAM [((address << 1) - 2) & 0xFFFF]; + } + else + byte = Memory.VRAM[((PPU.VMA.Address << 1) - 2) & 0xffff]; + + if (!PPU.VMA.High) + { + PPU.VMA.Address += PPU.VMA.Increment; + IPPU.FirstVRAMRead = FALSE; + } #endif - PPU.OpenBus1 = byte; - break; - case 0x213A: - // Read vram high byte + PPU.OpenBus1 = byte; + break; + case 0x213A: + // Read vram high byte #ifdef CORRECT_VRAM_READS - byte = (IPPU.VRAMReadBuffer>>8) & 0xff; - if (PPU.VMA.High) - { - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + - (rem >> PPU.VMA.Shift) + - ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((address << 1) & 0xFFFF)); - } else - IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM+((PPU.VMA.Address << 1) & 0xffff)); - PPU.VMA.Address += PPU.VMA.Increment; - } + byte = (IPPU.VRAMReadBuffer >> 8) & 0xff; + if (PPU.VMA.High) + { + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xFFFF)); + } + else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & + 0xffff)); + PPU.VMA.Address += PPU.VMA.Increment; + } #else - if (IPPU.FirstVRAMRead) - byte = Memory.VRAM[((PPU.VMA.Address << 1) + 1) & 0xffff]; - else - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address - 1; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + - (rem >> PPU.VMA.Shift) + - ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - byte = Memory.VRAM [((address << 1) - 1) & 0xFFFF]; - } - else - byte = Memory.VRAM[((PPU.VMA.Address << 1) - 1) & 0xFFFF]; - if (PPU.VMA.High) - { - PPU.VMA.Address += PPU.VMA.Increment; - IPPU.FirstVRAMRead = FALSE; - } + if (IPPU.FirstVRAMRead) + byte = Memory.VRAM[((PPU.VMA.Address << 1) + 1) & 0xffff]; + else if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address - 1; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + byte = Memory.VRAM [((address << 1) - 1) & 0xFFFF]; + } + else + byte = Memory.VRAM[((PPU.VMA.Address << 1) - 1) & 0xFFFF]; + if (PPU.VMA.High) + { + PPU.VMA.Address += PPU.VMA.Increment; + IPPU.FirstVRAMRead = FALSE; + } #endif - PPU.OpenBus1 = byte; - break; - - case 0x213B: - // Read palette data - if (PPU.CGFLIPRead) - byte = PPU.CGDATA [PPU.CGADD++] >> 8; - else - byte = PPU.CGDATA [PPU.CGADD] & 0xff; - - PPU.CGFLIPRead ^= 1; - return (PPU.OpenBus2 = byte); - - case 0x213C: - // Horizontal counter value 0-339 - if (PPU.HBeamFlip) - byte = (PPU.OpenBus2 & 0xfe) - | ((PPU.HBeamPosLatched >> 8) & 0x01); - - else - byte = (uint8)PPU.HBeamPosLatched; - PPU.OpenBus2 = byte; - PPU.HBeamFlip ^= 1; - break; - - case 0x213D: - // Vertical counter value 0-262 - if (PPU.VBeamFlip) - byte = (PPU.OpenBus2 & 0xfe) - | ((PPU.VBeamPosLatched >> 8) & 0x01); - else - byte = (uint8)PPU.VBeamPosLatched; - PPU.OpenBus2 = byte; - PPU.VBeamFlip ^= 1; - break; - - case 0x213E: - // PPU time and range over flags - FLUSH_REDRAW (); - - //so far, 5c77 version is always 1. - return (PPU.OpenBus1 = (Model->_5C77 | PPU.RangeTimeOver)); - - case 0x213F: - // NTSC/PAL and which field flags - PPU.VBeamFlip = PPU.HBeamFlip = 0; - //neviksti found a 2 and a 3 here. SNEeSe uses a 3. - //XXX: field flags not emulated - return ((Settings.PAL ? 0x10 : 0) | (Memory.FillRAM[0x213f] & 0xc0)| Model->_5C78) | (~PPU.OpenBus2 & 0x20); - - case 0x2140: case 0x2141: case 0x2142: case 0x2143: - case 0x2144: case 0x2145: case 0x2146: case 0x2147: - case 0x2148: case 0x2149: case 0x214a: case 0x214b: - case 0x214c: case 0x214d: case 0x214e: case 0x214f: - case 0x2150: case 0x2151: case 0x2152: case 0x2153: - case 0x2154: case 0x2155: case 0x2156: case 0x2157: - case 0x2158: case 0x2159: case 0x215a: case 0x215b: - case 0x215c: case 0x215d: case 0x215e: case 0x215f: - case 0x2160: case 0x2161: case 0x2162: case 0x2163: - case 0x2164: case 0x2165: case 0x2166: case 0x2167: - case 0x2168: case 0x2169: case 0x216a: case 0x216b: - case 0x216c: case 0x216d: case 0x216e: case 0x216f: - case 0x2170: case 0x2171: case 0x2172: case 0x2173: - case 0x2174: case 0x2175: case 0x2176: case 0x2177: - case 0x2178: case 0x2179: case 0x217a: case 0x217b: - case 0x217c: case 0x217d: case 0x217e: case 0x217f: + PPU.OpenBus1 = byte; + break; + + case 0x213B: + // Read palette data + if (PPU.CGFLIPRead) + byte = PPU.CGDATA [PPU.CGADD++] >> 8; + else + byte = PPU.CGDATA [PPU.CGADD] & 0xff; + + PPU.CGFLIPRead ^= 1; + return (PPU.OpenBus2 = byte); + + case 0x213C: + // Horizontal counter value 0-339 + if (PPU.HBeamFlip) + byte = (PPU.OpenBus2 & 0xfe) + | ((PPU.HBeamPosLatched >> 8) & 0x01); + + else + byte = (uint8)PPU.HBeamPosLatched; + PPU.OpenBus2 = byte; + PPU.HBeamFlip ^= 1; + break; + + case 0x213D: + // Vertical counter value 0-262 + if (PPU.VBeamFlip) + byte = (PPU.OpenBus2 & 0xfe) + | ((PPU.VBeamPosLatched >> 8) & 0x01); + else + byte = (uint8)PPU.VBeamPosLatched; + PPU.OpenBus2 = byte; + PPU.VBeamFlip ^= 1; + break; + + case 0x213E: + // PPU time and range over flags + FLUSH_REDRAW(); + + //so far, 5c77 version is always 1. + return (PPU.OpenBus1 = (Model->_5C77 | PPU.RangeTimeOver)); + + case 0x213F: + // NTSC/PAL and which field flags + PPU.VBeamFlip = PPU.HBeamFlip = 0; + //neviksti found a 2 and a 3 here. SNEeSe uses a 3. + //XXX: field flags not emulated + return ((Settings.PAL ? 0x10 : 0) | (Memory.FillRAM[0x213f] & 0xc0) | + Model->_5C78) | (~PPU.OpenBus2 & 0x20); + + case 0x2140: + case 0x2141: + case 0x2142: + case 0x2143: + case 0x2144: + case 0x2145: + case 0x2146: + case 0x2147: + case 0x2148: + case 0x2149: + case 0x214a: + case 0x214b: + case 0x214c: + case 0x214d: + case 0x214e: + case 0x214f: + case 0x2150: + case 0x2151: + case 0x2152: + case 0x2153: + case 0x2154: + case 0x2155: + case 0x2156: + case 0x2157: + case 0x2158: + case 0x2159: + case 0x215a: + case 0x215b: + case 0x215c: + case 0x215d: + case 0x215e: + case 0x215f: + case 0x2160: + case 0x2161: + case 0x2162: + case 0x2163: + case 0x2164: + case 0x2165: + case 0x2166: + case 0x2167: + case 0x2168: + case 0x2169: + case 0x216a: + case 0x216b: + case 0x216c: + case 0x216d: + case 0x216e: + case 0x216f: + case 0x2170: + case 0x2171: + case 0x2172: + case 0x2173: + case 0x2174: + case 0x2175: + case 0x2176: + case 0x2177: + case 0x2178: + case 0x2179: + case 0x217a: + case 0x217b: + case 0x217c: + case 0x217d: + case 0x217e: + case 0x217f: #ifdef SPCTOOL - return ((uint8) _SPCOutP [Address & 3]); + return ((uint8) _SPCOutP [Address & 3]); #else - // CPU.Flags |= DEBUG_MODE_FLAG; -#ifdef SPC700_SHUTDOWN - IAPU.APUExecuting = Settings.APUEnabled; - IAPU.WaitCounter++; + // CPU.Flags |= DEBUG_MODE_FLAG; +#ifdef SPC700_SHUTDOWN + IAPU.APUExecuting = Settings.APUEnabled; + IAPU.WaitCounter++; #endif - if (Settings.APUEnabled) - { + if (Settings.APUEnabled) + { #ifdef CPU_SHUTDOWN -// CPU.WaitAddress = CPU.PCAtOpcodeStart; + // CPU.WaitAddress = CPU.PCAtOpcodeStart; #endif - if (SNESGameFixes.APU_OutPorts_ReturnValueFix && - Address >= 0x2140 && Address <= 0x2143 && !CPU.V_Counter) - { - return (uint8)((Address & 1) ? ((rand() & 0xff00) >> 8) : - (rand() & 0xff)); - } - - return (APU.OutPorts [Address & 3]); - } - - switch (Settings.SoundSkipMethod) - { - case 0: - case 1: - case 3: - CPU.BranchSkip = TRUE; - break; - case 2: - break; - } - if ((Address & 3) < 2) - { - int r = rand (); - if (r & 2) - { - if (r & 4) - return ((Address & 3) == 1 ? 0xaa : 0xbb); - else - return ((r >> 3) & 0xff); - } - } - else - { - int r = rand (); - if (r & 2) - return ((r >> 3) & 0xff); - } - return (Memory.FillRAM[Address]); + if (SNESGameFixes.APU_OutPorts_ReturnValueFix && + Address >= 0x2140 && Address <= 0x2143 && !CPU.V_Counter) + { + return (uint8)((Address & 1) ? ((rand() & 0xff00) >> 8) : + (rand() & 0xff)); + } + + return (APU.OutPorts [Address & 3]); + } + + switch (Settings.SoundSkipMethod) + { + case 0: + case 1: + case 3: + CPU.BranchSkip = TRUE; + break; + case 2: + break; + } + if ((Address & 3) < 2) + { + int r = rand(); + if (r & 2) + { + if (r & 4) + return ((Address & 3) == 1 ? 0xaa : 0xbb); + else + return ((r >> 3) & 0xff); + } + } + else + { + int r = rand(); + if (r & 2) + return ((r >> 3) & 0xff); + } + return (Memory.FillRAM[Address]); #endif // SPCTOOL - case 0x2180: - // Read WRAM - byte = Memory.RAM [PPU.WRAM++]; - PPU.WRAM &= 0x1FFFF; - break; - case 0x2181: - case 0x2182: - case 0x2183: - default: - return OpenBus; - } - } - else - { - if (Settings.SA1) - return (S9xGetSA1 (Address)); - - if (Address <= 0x2fff || Address >= 0x3300) - { - switch (Address) - { - case 0x21c2: - if(Model->_5C77 ==2) - return (0x20); - - // fprintf(stderr, "Read from $21c2!\n"); - return OpenBus; - case 0x21c3: - if(Model->_5C77 ==2) - return (0); - // fprintf(stderr, "Read from $21c3!\n"); - return OpenBus; - case 0x2800: - // For Dai Kaijyu Monogatari II - if (Settings.SRTC) - return (S9xGetSRTC (Address)); - /*FALL*/ - - default: - return OpenBus; - } - } - - if (!Settings.SuperFX) - return OpenBus; + case 0x2180: + // Read WRAM + byte = Memory.RAM [PPU.WRAM++]; + PPU.WRAM &= 0x1FFFF; + break; + case 0x2181: + case 0x2182: + case 0x2183: + default: + return OpenBus; + } + } + else + { + if (Settings.SA1) + return (S9xGetSA1(Address)); + + if (Address <= 0x2fff || Address >= 0x3300) + { + switch (Address) + { + case 0x21c2: + if (Model->_5C77 == 2) + return (0x20); + + // fprintf(stderr, "Read from $21c2!\n"); + return OpenBus; + case 0x21c3: + if (Model->_5C77 == 2) + return (0); + // fprintf(stderr, "Read from $21c3!\n"); + return OpenBus; + case 0x2800: + // For Dai Kaijyu Monogatari II + if (Settings.SRTC) + return (S9xGetSRTC(Address)); + /*FALL*/ + + default: + return OpenBus; + } + } + + if (!Settings.SuperFX) + return OpenBus; #ifdef ZSNES_FX - if (Address < 0x3040) - byte = S9xSuperFXReadReg (Address); - else - byte = Memory.FillRAM [Address]; + if (Address < 0x3040) + byte = S9xSuperFXReadReg(Address); + else + byte = Memory.FillRAM [Address]; #ifdef CPU_SHUTDOWN - if (Address == 0x3030) - CPU.WaitAddress = CPU.PCAtOpcodeStart; -#endif - if (Address == 0x3031) - CLEAR_IRQ_SOURCE (GSU_IRQ_SOURCE); + if (Address == 0x3030) + CPU.WaitAddress = CPU.PCAtOpcodeStart; +#endif + if (Address == 0x3031) + CLEAR_IRQ_SOURCE(GSU_IRQ_SOURCE); #else - byte = Memory.FillRAM [Address]; + byte = Memory.FillRAM [Address]; -//if (Address != 0x3030 && Address != 0x3031) -//printf ("%04x\n", Address); + //if (Address != 0x3030 && Address != 0x3031) + //printf ("%04x\n", Address); #ifdef CPU_SHUTDOWN - if (Address == 0x3030) - { - CPU.WaitAddress = CPU.PCAtOpcodeStart; - } - else + if (Address == 0x3030) + CPU.WaitAddress = CPU.PCAtOpcodeStart; + else #endif - if (Address == 0x3031) - { - CLEAR_IRQ_SOURCE (GSU_IRQ_SOURCE); - Memory.FillRAM [0x3031] = byte & 0x7f; - } - return (byte); + if (Address == 0x3031) + { + CLEAR_IRQ_SOURCE(GSU_IRQ_SOURCE); + Memory.FillRAM [0x3031] = byte & 0x7f; + } + return (byte); #endif - } -// fprintf(stderr, "%03d: %02x from %04x\n", CPU.V_Counter, byte, Address); - return (byte); + } + // fprintf(stderr, "%03d: %02x from %04x\n", CPU.V_Counter, byte, Address); + return (byte); } /******************************************************************************/ /* S9xSetCPU() */ /* This function sets a CPU/DMA Register to a specific byte */ /******************************************************************************/ -void S9xSetCPU (uint8 byte, uint16 Address) +void S9xSetCPU(uint8 byte, uint16 Address) { - int d; -// fprintf(stderr, "%03d: %02x to %04x\n", CPU.V_Counter, byte, Address); - - if (Address < 0x4200) - { - CPU.Cycles += ONE_CYCLE; - switch (Address) - { - case 0x4016: - // S9xReset reading of old-style joypads - if ((byte & 1) && !(Memory.FillRAM [Address] & 1)) - { - PPU.Joypad1ButtonReadPos = 0; - PPU.Joypad2ButtonReadPos = 0; - PPU.Joypad3ButtonReadPos = 0; - } - break; - case 0x4017: - break; - default: - break; - } - } - else - switch (Address) - { - case 0x4200: - // NMI, V & H IRQ and joypad reading enable flags - if (byte & 0x20) - { - //if(!SNESGameFixes.umiharakawaseFix && PPU.IRQVBeamPos==262) fprintf(stderr, "PPU.IRQVBeamPos = %d, CPU.V_Counter = %d\n", PPU.IRQVBeamPos, CPU.V_Counter); - if (!PPU.VTimerEnabled) - { - PPU.VTimerEnabled = TRUE; - if (PPU.HTimerEnabled) - S9xUpdateHTimer (); - else - if (PPU.IRQVBeamPos == CPU.V_Counter) - S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); - } - } - else - { - PPU.VTimerEnabled = FALSE; -// if (SNESGameFixes.umiharakawaseFix) -// byte &= ~0x20; - } - - if (byte & 0x10) - { - if (!PPU.HTimerEnabled) - { - PPU.HTimerEnabled = TRUE; - S9xUpdateHTimer (); - } - } - else - { - // No need to check for HTimer being disabled as the scanline - // event trigger code won't trigger an H-IRQ unless its enabled. - PPU.HTimerEnabled = FALSE; - PPU.HTimerPosition = Settings.H_Max + 1; - } - if (!Settings.DaffyDuck) - CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); - - if ((byte & 0x80) && - !(Memory.FillRAM [0x4200] & 0x80) && - CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && - CPU.V_Counter <= PPU.ScreenHeight + - (SNESGameFixes.alienVSpredetorFix ? 25 : 15) && //jyam 15->25 alien vs predetor -// Panic Bomberman clears the NMI pending flag @ scanline 230 before enabling -// NMIs again. The NMI routine crashes the CPU if it is called without the NMI -// pending flag being set... - (Memory.FillRAM [0x4210] & 0x80) && - !CPU.NMIActive) - { - CPU.Flags |= NMI_FLAG; - CPU.NMIActive = TRUE; - CPU.NMICycleCount = CPU.NMITriggerPoint; - } - break; - case 0x4201: - if((byte&0x80)==0 && (Memory.FillRAM[0x4213]&0x80)==0x80) - S9xLatchCounters(1); - Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = byte; - break; - case 0x4202: - // Multiplier (for multply) - break; - case 0x4203: - { - // Multiplicand - uint32 res = Memory.FillRAM[0x4202] * byte; + int d; + // fprintf(stderr, "%03d: %02x to %04x\n", CPU.V_Counter, byte, Address); + + if (Address < 0x4200) + { + CPU.Cycles += ONE_CYCLE; + switch (Address) + { + case 0x4016: + // S9xReset reading of old-style joypads + if ((byte & 1) && !(Memory.FillRAM [Address] & 1)) + { + PPU.Joypad1ButtonReadPos = 0; + PPU.Joypad2ButtonReadPos = 0; + PPU.Joypad3ButtonReadPos = 0; + } + break; + case 0x4017: + break; + default: + break; + } + } + else + switch (Address) + { + case 0x4200: + // NMI, V & H IRQ and joypad reading enable flags + if (byte & 0x20) + { + //if(!SNESGameFixes.umiharakawaseFix && PPU.IRQVBeamPos==262) fprintf(stderr, "PPU.IRQVBeamPos = %d, CPU.V_Counter = %d\n", PPU.IRQVBeamPos, CPU.V_Counter); + if (!PPU.VTimerEnabled) + { + PPU.VTimerEnabled = TRUE; + if (PPU.HTimerEnabled) + S9xUpdateHTimer(); + else if (PPU.IRQVBeamPos == CPU.V_Counter) + S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); + } + } + else + { + PPU.VTimerEnabled = FALSE; + // if (SNESGameFixes.umiharakawaseFix) + // byte &= ~0x20; + } + + if (byte & 0x10) + { + if (!PPU.HTimerEnabled) + { + PPU.HTimerEnabled = TRUE; + S9xUpdateHTimer(); + } + } + else + { + // No need to check for HTimer being disabled as the scanline + // event trigger code won't trigger an H-IRQ unless its enabled. + PPU.HTimerEnabled = FALSE; + PPU.HTimerPosition = Settings.H_Max + 1; + } + if (!Settings.DaffyDuck) + CLEAR_IRQ_SOURCE(PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + + if ((byte & 0x80) && + !(Memory.FillRAM [0x4200] & 0x80) && + CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && + CPU.V_Counter <= PPU.ScreenHeight + + (SNESGameFixes.alienVSpredetorFix ? 25 : 15) + && //jyam 15->25 alien vs predetor + // Panic Bomberman clears the NMI pending flag @ scanline 230 before enabling + // NMIs again. The NMI routine crashes the CPU if it is called without the NMI + // pending flag being set... + (Memory.FillRAM [0x4210] & 0x80) && + !CPU.NMIActive) + { + CPU.Flags |= NMI_FLAG; + CPU.NMIActive = TRUE; + CPU.NMICycleCount = CPU.NMITriggerPoint; + } + break; + case 0x4201: + if ((byte & 0x80) == 0 && (Memory.FillRAM[0x4213] & 0x80) == 0x80) + S9xLatchCounters(1); + Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = byte; + break; + case 0x4202: + // Multiplier (for multply) + break; + case 0x4203: + { + // Multiplicand + uint32 res = Memory.FillRAM[0x4202] * byte; #if defined FAST_LSB_WORD_ACCESS || defined FAST_ALIGNED_LSB_WORD_ACCESS - // assume malloc'd memory is 2-byte aligned - * ((uint16 *) &Memory.FillRAM[0x4216]) = res; + // assume malloc'd memory is 2-byte aligned + * ((uint16*) &Memory.FillRAM[0x4216]) = res; #else - Memory.FillRAM[0x4216] = (uint8) res; - Memory.FillRAM[0x4217] = (uint8) (res >> 8); + Memory.FillRAM[0x4216] = (uint8) res; + Memory.FillRAM[0x4217] = (uint8)(res >> 8); #endif - break; - } - case 0x4204: - case 0x4205: - // Low and high muliplier (for divide) - break; - case 0x4206: - { + break; + } + case 0x4204: + case 0x4205: + // Low and high muliplier (for divide) + break; + case 0x4206: + { #if defined FAST_LSB_WORD_ACCESS || defined FAST_ALIGNED_LSB_WORD_ACCESS - // assume malloc'd memory is 2-byte aligned - uint16 a = *((uint16 *) &Memory.FillRAM[0x4204]); + // assume malloc'd memory is 2-byte aligned + uint16 a = *((uint16*) &Memory.FillRAM[0x4204]); #else - uint16 a = Memory.FillRAM[0x4204] + (Memory.FillRAM[0x4205] << 8); + uint16 a = Memory.FillRAM[0x4204] + (Memory.FillRAM[0x4205] << 8); #endif - uint16 div = byte ? a / byte : 0xffff; - uint16 rem = byte ? a % byte : a; + uint16 div = byte ? a / byte : 0xffff; + uint16 rem = byte ? a % byte : a; #if defined FAST_LSB_WORD_ACCESS || defined FAST_ALIGNED_LSB_WORD_ACCESS - // assume malloc'd memory is 2-byte aligned - * ((uint16 *) &Memory.FillRAM[0x4214]) = div; - * ((uint16 *) &Memory.FillRAM[0x4216]) = rem; + // assume malloc'd memory is 2-byte aligned + * ((uint16*) &Memory.FillRAM[0x4214]) = div; + * ((uint16*) &Memory.FillRAM[0x4216]) = rem; #else - Memory.FillRAM[0x4214] = (uint8)div; - Memory.FillRAM[0x4215] = div >> 8; - Memory.FillRAM[0x4216] = (uint8)rem; - Memory.FillRAM[0x4217] = rem >> 8; + Memory.FillRAM[0x4214] = (uint8)div; + Memory.FillRAM[0x4215] = div >> 8; + Memory.FillRAM[0x4216] = (uint8)rem; + Memory.FillRAM[0x4217] = rem >> 8; #endif - break; - } - case 0x4207: - d = PPU.IRQHBeamPos; - PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF00) | byte; - - if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) - S9xUpdateHTimer (); - break; - - case 0x4208: - d = PPU.IRQHBeamPos; - PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF) | ((byte & 1) << 8); - - if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) - S9xUpdateHTimer (); - - break; - - case 0x4209: - d = PPU.IRQVBeamPos; - PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF00) | byte; - if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) - { - if (PPU.HTimerEnabled) - S9xUpdateHTimer (); - else - { - if (PPU.IRQVBeamPos == CPU.V_Counter) - S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); - } - } - break; - - case 0x420A: - d = PPU.IRQVBeamPos; - PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF) | ((byte & 1) << 8); - if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) - { - if (PPU.HTimerEnabled) - S9xUpdateHTimer (); - else - { - if (PPU.IRQVBeamPos == CPU.V_Counter) - S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); - } - } - break; - - case 0x420B: - if ((byte & 0x01) != 0) - S9xDoDMA (0); - if ((byte & 0x02) != 0) - S9xDoDMA (1); - if ((byte & 0x04) != 0) - S9xDoDMA (2); - if ((byte & 0x08) != 0) - S9xDoDMA (3); - if ((byte & 0x10) != 0) - S9xDoDMA (4); - if ((byte & 0x20) != 0) - S9xDoDMA (5); - if ((byte & 0x40) != 0) - S9xDoDMA (6); - if ((byte & 0x80) != 0) - 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 +) - if ((byte & 1) != (Memory.FillRAM [0x420d] & 1)) - { - if (byte & 1) - { - CPU.FastROMSpeed = ONE_CYCLE; - } - else CPU.FastROMSpeed = SLOW_ONE_CYCLE; - - FixROMSpeed (); - } - break; - - case 0x420e: - case 0x420f: - // --->>> Unknown - break; - 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) - 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) - /* fall through */ - case 0x4213: - // I/O Port (read-only) - /* fall through */ - case 0x4214: - case 0x4215: - // Quotent of divide (read-only) - /* fall through */ - case 0x4216: - case 0x4217: - // Multiply product (read-only) - /* fall through */ - case 0x4218: - case 0x4219: - case 0x421a: - case 0x421b: - case 0x421c: - case 0x421d: - case 0x421e: - case 0x421f: - // Joypad values (read-only) - return; - - case 0x4300: - case 0x4310: - case 0x4320: - case 0x4330: - case 0x4340: - case 0x4350: - case 0x4360: - case 0x4370: - d = (Address >> 4) & 0x7; - DMA[d].TransferDirection = (byte & 128) != 0 ? 1 : 0; - DMA[d].HDMAIndirectAddressing = (byte & 64) != 0 ? 1 : 0; - DMA[d].AAddressDecrement = (byte & 16) != 0 ? 1 : 0; - DMA[d].AAddressFixed = (byte & 8) != 0 ? 1 : 0; - DMA[d].TransferMode = (byte & 7); - break; - - case 0x4301: - case 0x4311: - case 0x4321: - case 0x4331: - case 0x4341: - case 0x4351: - case 0x4361: - case 0x4371: - DMA[((Address >> 4) & 0x7)].BAddress = byte; - break; - - case 0x4302: - case 0x4312: - case 0x4322: - case 0x4332: - case 0x4342: - case 0x4352: - case 0x4362: - case 0x4372: - d = (Address >> 4) & 0x7; - DMA[d].AAddress &= 0xFF00; - DMA[d].AAddress |= byte; - break; - - case 0x4303: - case 0x4313: - case 0x4323: - case 0x4333: - case 0x4343: - case 0x4353: - case 0x4363: - case 0x4373: - d = (Address >> 4) & 0x7; - DMA[d].AAddress &= 0xFF; - DMA[d].AAddress |= byte << 8; - break; - - case 0x4304: - case 0x4314: - case 0x4324: - case 0x4334: - case 0x4344: - case 0x4354: - case 0x4364: - case 0x4374: - DMA[((Address >> 4) & 0x7)].ABank = byte; - HDMAMemPointers[((Address >> 4) & 0x7)]=NULL; - - break; - - case 0x4305: - case 0x4315: - case 0x4325: - case 0x4335: - case 0x4345: - case 0x4355: - case 0x4365: - case 0x4375: - d = (Address >> 4) & 0x7; - DMA[d].TransferBytes &= 0xFF00; - DMA[d].TransferBytes |= byte; - DMA[d].IndirectAddress &= 0xff00; - DMA[d].IndirectAddress |= byte; - HDMAMemPointers[d]=NULL; - break; - - case 0x4306: - case 0x4316: - case 0x4326: - case 0x4336: - case 0x4346: - case 0x4356: - case 0x4366: - case 0x4376: - d = (Address >> 4) & 0x7; - DMA[d].TransferBytes &= 0xFF; - DMA[d].TransferBytes |= byte << 8; - DMA[d].IndirectAddress &= 0xff; - DMA[d].IndirectAddress |= byte << 8; - HDMAMemPointers[d]=NULL; - break; - - case 0x4307: - case 0x4317: - case 0x4327: - case 0x4337: - case 0x4347: - case 0x4357: - case 0x4367: - case 0x4377: - DMA[d = ((Address >> 4) & 0x7)].IndirectBank = byte; - HDMAMemPointers[d]=NULL; - break; - - case 0x4308: - case 0x4318: - case 0x4328: - case 0x4338: - case 0x4348: - case 0x4358: - case 0x4368: - case 0x4378: - d = (Address >> 4) & 7; - DMA[d].Address &= 0xff00; - DMA[d].Address |= byte; - HDMAMemPointers[d] = NULL; - break; - - case 0x4309: - case 0x4319: - case 0x4329: - case 0x4339: - case 0x4349: - case 0x4359: - case 0x4369: - case 0x4379: - d = (Address >> 4) & 0x7; - DMA[d].Address &= 0xff; - DMA[d].Address |= byte << 8; - HDMAMemPointers[d] = NULL; - break; - - case 0x430A: - case 0x431A: - case 0x432A: - case 0x433A: - case 0x434A: - case 0x435A: - case 0x436A: - case 0x437A: - d = (Address >> 4) & 0x7; - DMA[d].LineCount = byte & 0x7f; - DMA[d].Repeat = !(byte & 0x80); - break; - - case 0x430F: - case 0x431F: - case 0x432F: - case 0x433F: - case 0x434F: - case 0x435F: - case 0x436F: - case 0x437F: - Address &= ~4; // Convert 43xF to 43xB - /* fall through */ - case 0x430B: - case 0x431B: - case 0x432B: - case 0x433B: - case 0x434B: - case 0x435B: - case 0x436B: - case 0x437B: - - // Unknown, but they seem to be RAM-ish + break; + } + case 0x4207: + d = PPU.IRQHBeamPos; + PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF00) | byte; + + if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) + S9xUpdateHTimer(); + break; + + case 0x4208: + d = PPU.IRQHBeamPos; + PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF) | ((byte & 1) << 8); + + if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) + S9xUpdateHTimer(); + + break; + + case 0x4209: + d = PPU.IRQVBeamPos; + PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF00) | byte; + if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) + { + if (PPU.HTimerEnabled) + S9xUpdateHTimer(); + else + { + if (PPU.IRQVBeamPos == CPU.V_Counter) + S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); + } + } + break; + + case 0x420A: + d = PPU.IRQVBeamPos; + PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF) | ((byte & 1) << 8); + if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) + { + if (PPU.HTimerEnabled) + S9xUpdateHTimer(); + else + { + if (PPU.IRQVBeamPos == CPU.V_Counter) + S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); + } + } + break; + + case 0x420B: + if ((byte & 0x01) != 0) + S9xDoDMA(0); + if ((byte & 0x02) != 0) + S9xDoDMA(1); + if ((byte & 0x04) != 0) + S9xDoDMA(2); + if ((byte & 0x08) != 0) + S9xDoDMA(3); + if ((byte & 0x10) != 0) + S9xDoDMA(4); + if ((byte & 0x20) != 0) + S9xDoDMA(5); + if ((byte & 0x40) != 0) + S9xDoDMA(6); + if ((byte & 0x80) != 0) + 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 +) + if ((byte & 1) != (Memory.FillRAM [0x420d] & 1)) + { + if (byte & 1) + CPU.FastROMSpeed = ONE_CYCLE; + else CPU.FastROMSpeed = SLOW_ONE_CYCLE; + + FixROMSpeed(); + } + break; + + case 0x420e: + case 0x420f: + // --->>> Unknown + break; + 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) + 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) + /* fall through */ + case 0x4213: + // I/O Port (read-only) + /* fall through */ + case 0x4214: + case 0x4215: + // Quotent of divide (read-only) + /* fall through */ + case 0x4216: + case 0x4217: + // Multiply product (read-only) + /* fall through */ + case 0x4218: + case 0x4219: + case 0x421a: + case 0x421b: + case 0x421c: + case 0x421d: + case 0x421e: + case 0x421f: + // Joypad values (read-only) + return; + + case 0x4300: + case 0x4310: + case 0x4320: + case 0x4330: + case 0x4340: + case 0x4350: + case 0x4360: + case 0x4370: + d = (Address >> 4) & 0x7; + DMA[d].TransferDirection = (byte & 128) != 0 ? 1 : 0; + DMA[d].HDMAIndirectAddressing = (byte & 64) != 0 ? 1 : 0; + DMA[d].AAddressDecrement = (byte & 16) != 0 ? 1 : 0; + DMA[d].AAddressFixed = (byte & 8) != 0 ? 1 : 0; + DMA[d].TransferMode = (byte & 7); + break; + + case 0x4301: + case 0x4311: + case 0x4321: + case 0x4331: + case 0x4341: + case 0x4351: + case 0x4361: + case 0x4371: + DMA[((Address >> 4) & 0x7)].BAddress = byte; + break; + + case 0x4302: + case 0x4312: + case 0x4322: + case 0x4332: + case 0x4342: + case 0x4352: + case 0x4362: + case 0x4372: + d = (Address >> 4) & 0x7; + DMA[d].AAddress &= 0xFF00; + DMA[d].AAddress |= byte; + break; + + case 0x4303: + case 0x4313: + case 0x4323: + case 0x4333: + case 0x4343: + case 0x4353: + case 0x4363: + case 0x4373: + d = (Address >> 4) & 0x7; + DMA[d].AAddress &= 0xFF; + DMA[d].AAddress |= byte << 8; + break; + + case 0x4304: + case 0x4314: + case 0x4324: + case 0x4334: + case 0x4344: + case 0x4354: + case 0x4364: + case 0x4374: + DMA[((Address >> 4) & 0x7)].ABank = byte; + HDMAMemPointers[((Address >> 4) & 0x7)] = NULL; + + break; + + case 0x4305: + case 0x4315: + case 0x4325: + case 0x4335: + case 0x4345: + case 0x4355: + case 0x4365: + case 0x4375: + d = (Address >> 4) & 0x7; + DMA[d].TransferBytes &= 0xFF00; + DMA[d].TransferBytes |= byte; + DMA[d].IndirectAddress &= 0xff00; + DMA[d].IndirectAddress |= byte; + HDMAMemPointers[d] = NULL; + break; + + case 0x4306: + case 0x4316: + case 0x4326: + case 0x4336: + case 0x4346: + case 0x4356: + case 0x4366: + case 0x4376: + d = (Address >> 4) & 0x7; + DMA[d].TransferBytes &= 0xFF; + DMA[d].TransferBytes |= byte << 8; + DMA[d].IndirectAddress &= 0xff; + DMA[d].IndirectAddress |= byte << 8; + HDMAMemPointers[d] = NULL; + break; + + case 0x4307: + case 0x4317: + case 0x4327: + case 0x4337: + case 0x4347: + case 0x4357: + case 0x4367: + case 0x4377: + DMA[d = ((Address >> 4) & 0x7)].IndirectBank = byte; + HDMAMemPointers[d] = NULL; + break; + + case 0x4308: + case 0x4318: + case 0x4328: + case 0x4338: + case 0x4348: + case 0x4358: + case 0x4368: + case 0x4378: + d = (Address >> 4) & 7; + DMA[d].Address &= 0xff00; + DMA[d].Address |= byte; + HDMAMemPointers[d] = NULL; + break; + + case 0x4309: + case 0x4319: + case 0x4329: + case 0x4339: + case 0x4349: + case 0x4359: + case 0x4369: + case 0x4379: + d = (Address >> 4) & 0x7; + DMA[d].Address &= 0xff; + DMA[d].Address |= byte << 8; + HDMAMemPointers[d] = NULL; + break; + + case 0x430A: + case 0x431A: + case 0x432A: + case 0x433A: + case 0x434A: + case 0x435A: + case 0x436A: + case 0x437A: + d = (Address >> 4) & 0x7; + DMA[d].LineCount = byte & 0x7f; + DMA[d].Repeat = !(byte & 0x80); + break; + + case 0x430F: + case 0x431F: + case 0x432F: + case 0x433F: + case 0x434F: + case 0x435F: + case 0x436F: + case 0x437F: + Address &= ~4; // Convert 43xF to 43xB + /* fall through */ + case 0x430B: + case 0x431B: + case 0x432B: + case 0x433B: + case 0x434B: + case 0x435B: + case 0x436B: + case 0x437B: + + // Unknown, but they seem to be RAM-ish #if 0 - fprintf(stderr, "Write %02x to %04x!\n", byte, Address); + fprintf(stderr, "Write %02x to %04x!\n", byte, Address); #endif - break; - - //These registers are used by both the S-DD1 and the SPC7110 - case 0x4800: - case 0x4801: - case 0x4802: - case 0x4803: - if(Settings.SPC7110) - S9xSetSPC7110(byte, Address); - //printf ("%02x->%04x\n", byte, Address); - break; - - case 0x4804: - case 0x4805: - case 0x4806: - case 0x4807: - //printf ("%02x->%04x\n", byte, Address); - 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: - case 0x480B: - case 0x480C: - case 0x4810: - case 0x4811: - case 0x4812: - case 0x4813: - case 0x4814: - case 0x4815: - case 0x4816: - case 0x4817: - case 0x4818: - case 0x481A: - case 0x4820: - case 0x4821: - case 0x4822: - case 0x4823: - case 0x4824: - case 0x4825: - case 0x4826: - case 0x4827: - case 0x4828: - case 0x4829: - case 0x482A: - case 0x482B: - case 0x482C: - case 0x482D: - case 0x482E: - case 0x482F: - case 0x4830: - case 0x4831: - case 0x4832: - case 0x4833: - case 0x4834: - case 0x4840: - case 0x4841: - case 0x4842: - if(Settings.SPC7110) - { - S9xSetSPC7110(byte, Address); - break; - } - - default: - break; - } - Memory.FillRAM [Address] = byte; + break; + + //These registers are used by both the S-DD1 and the SPC7110 + case 0x4800: + case 0x4801: + case 0x4802: + case 0x4803: + if (Settings.SPC7110) + S9xSetSPC7110(byte, Address); + //printf ("%02x->%04x\n", byte, Address); + break; + + case 0x4804: + case 0x4805: + case 0x4806: + case 0x4807: + //printf ("%02x->%04x\n", byte, Address); + 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: + case 0x480B: + case 0x480C: + case 0x4810: + case 0x4811: + case 0x4812: + case 0x4813: + case 0x4814: + case 0x4815: + case 0x4816: + case 0x4817: + case 0x4818: + case 0x481A: + case 0x4820: + case 0x4821: + case 0x4822: + case 0x4823: + case 0x4824: + case 0x4825: + case 0x4826: + case 0x4827: + case 0x4828: + case 0x4829: + case 0x482A: + case 0x482B: + case 0x482C: + case 0x482D: + case 0x482E: + case 0x482F: + case 0x4830: + case 0x4831: + case 0x4832: + case 0x4833: + case 0x4834: + case 0x4840: + case 0x4841: + case 0x4842: + if (Settings.SPC7110) + { + S9xSetSPC7110(byte, Address); + break; + } + + default: + break; + } + Memory.FillRAM [Address] = byte; } /******************************************************************************/ /* S9xGetCPU() */ /* This function retrieves a CPU/DMA Register */ /******************************************************************************/ -uint8 S9xGetCPU (uint16 Address) +uint8 S9xGetCPU(uint16 Address) { - uint8 byte; -// fprintf(stderr, "read from %04x\n", Address); - - if (Address < 0x4200) - { - CPU.Cycles += ONE_CYCLE; - switch (Address) - { - case 0x4016: - { - if (Memory.FillRAM [0x4016] & 1) - { - if ((!Settings.SwapJoypads && - IPPU.Controller == SNES_MOUSE_SWAPPED) || - (Settings.SwapJoypads && - IPPU.Controller == SNES_MOUSE)) - { - if (++PPU.MouseSpeed [0] > 2) - PPU.MouseSpeed [0] = 0; - } - return (0); - } - - int ind = Settings.SwapJoypads ? 1 : 0; - byte = IPPU.Joypads[ind] >> (PPU.Joypad1ButtonReadPos ^ 15); - PPU.Joypad1ButtonReadPos++; - return (byte & 1); - } - case 0x4017: - { - if (Memory.FillRAM [0x4016] & 1) - { - // MultiPlayer5 adaptor is only allowed to be plugged into port 2 - switch (IPPU.Controller) - { - case SNES_MULTIPLAYER5: - return (2); - case SNES_MOUSE_SWAPPED: - if (Settings.SwapJoypads && ++PPU.MouseSpeed [0] > 2) - PPU.MouseSpeed [0] = 0; - break; - - case SNES_MOUSE: - if (!Settings.SwapJoypads && ++PPU.MouseSpeed [0] > 2) - PPU.MouseSpeed [0] = 0; - break; - } - return (0x00); - } - - int ind = Settings.SwapJoypads ? 0 : 1; - - if (IPPU.Controller == SNES_MULTIPLAYER5) - { - if (Memory.FillRAM [0x4201] & 0x80) - { - byte = ((IPPU.Joypads[ind] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) | - (((IPPU.Joypads[2] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) << 1); - PPU.Joypad2ButtonReadPos++; - return (byte); - } - else - { - byte = ((IPPU.Joypads[3] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) | - (((IPPU.Joypads[4] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) << 1); - PPU.Joypad3ButtonReadPos++; - return (byte); - } - } - else if(IPPU.Controller ==SNES_JUSTIFIER || IPPU.Controller ==SNES_JUSTIFIER_2) - { - uint8 rv; - rv=(1&(justifiers>>in_bit)); - in_bit++; - in_bit%=32; - return rv; - } - return ((IPPU.Joypads[ind] >> (PPU.Joypad2ButtonReadPos++ ^ 15)) & 1); - } - default: - return OpenBus; - } -// return (Memory.FillRAM [Address]); - } - else - switch (Address) - { - case 0x4200: - case 0x4201: - case 0x4202: - case 0x4203: - case 0x4204: - case 0x4205: - case 0x4206: - case 0x4207: - case 0x4208: - case 0x4209: - case 0x420a: - case 0x420b: - case 0x420c: - case 0x420d: - case 0x420e: - case 0x420f: - return OpenBus; - - case 0x4210: + uint8 byte; + // fprintf(stderr, "read from %04x\n", Address); + + if (Address < 0x4200) + { + CPU.Cycles += ONE_CYCLE; + switch (Address) + { + case 0x4016: + { + if (Memory.FillRAM [0x4016] & 1) + { + if ((!Settings.SwapJoypads && + IPPU.Controller == SNES_MOUSE_SWAPPED) || + (Settings.SwapJoypads && + IPPU.Controller == SNES_MOUSE)) + { + if (++PPU.MouseSpeed [0] > 2) + PPU.MouseSpeed [0] = 0; + } + return (0); + } + + int ind = Settings.SwapJoypads ? 1 : 0; + byte = IPPU.Joypads[ind] >> (PPU.Joypad1ButtonReadPos ^ 15); + PPU.Joypad1ButtonReadPos++; + return (byte & 1); + } + case 0x4017: + { + if (Memory.FillRAM [0x4016] & 1) + { + // MultiPlayer5 adaptor is only allowed to be plugged into port 2 + switch (IPPU.Controller) + { + case SNES_MULTIPLAYER5: + return (2); + case SNES_MOUSE_SWAPPED: + if (Settings.SwapJoypads && ++PPU.MouseSpeed [0] > 2) + PPU.MouseSpeed [0] = 0; + break; + + case SNES_MOUSE: + if (!Settings.SwapJoypads && ++PPU.MouseSpeed [0] > 2) + PPU.MouseSpeed [0] = 0; + break; + } + return (0x00); + } + + int ind = Settings.SwapJoypads ? 0 : 1; + + if (IPPU.Controller == SNES_MULTIPLAYER5) + { + if (Memory.FillRAM [0x4201] & 0x80) + { + byte = ((IPPU.Joypads[ind] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) | + (((IPPU.Joypads[2] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) << 1); + PPU.Joypad2ButtonReadPos++; + return (byte); + } + else + { + byte = ((IPPU.Joypads[3] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) | + (((IPPU.Joypads[4] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) << 1); + PPU.Joypad3ButtonReadPos++; + return (byte); + } + } + else if (IPPU.Controller == SNES_JUSTIFIER + || IPPU.Controller == SNES_JUSTIFIER_2) + { + uint8 rv; + rv = (1 & (justifiers >> in_bit)); + in_bit++; + in_bit %= 32; + return rv; + } + return ((IPPU.Joypads[ind] >> (PPU.Joypad2ButtonReadPos++ ^ 15)) & 1); + } + default: + return OpenBus; + } + // return (Memory.FillRAM [Address]); + } + else + switch (Address) + { + case 0x4200: + case 0x4201: + case 0x4202: + case 0x4203: + case 0x4204: + case 0x4205: + case 0x4206: + case 0x4207: + case 0x4208: + case 0x4209: + case 0x420a: + case 0x420b: + case 0x420c: + case 0x420d: + case 0x420e: + case 0x420f: + return OpenBus; + + case 0x4210: #ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PCAtOpcodeStart; -#endif - byte = Memory.FillRAM[0x4210]; - Memory.FillRAM[0x4210] = Model->_5A22; - //SNEeSe returns 2 for 5A22 version. - return ((byte&0x80) - |(OpenBus&0x70) - |Model->_5A22); - - case 0x4211: - byte = (CPU.IRQActive & (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE)) ? 0x80 : 0; - // Super Robot Wars Ex ROM bug requires this. - byte |= CPU.Cycles >= Settings.HBlankStart ? 0x40 : 0; - CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); - - // Maybe? Register Scan indicated open bus... - byte |= OpenBus&0x3f; - - return (byte); - - case 0x4212: - // V-blank, h-blank and joypads being read flags (read-only) + CPU.WaitAddress = CPU.PCAtOpcodeStart; +#endif + byte = Memory.FillRAM[0x4210]; + Memory.FillRAM[0x4210] = Model->_5A22; + //SNEeSe returns 2 for 5A22 version. + return ((byte & 0x80) + | (OpenBus & 0x70) + | Model->_5A22); + + case 0x4211: + byte = (CPU.IRQActive & (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE)) ? + 0x80 : 0; + // Super Robot Wars Ex ROM bug requires this. + byte |= CPU.Cycles >= Settings.HBlankStart ? 0x40 : 0; + CLEAR_IRQ_SOURCE(PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + + // Maybe? Register Scan indicated open bus... + byte |= OpenBus & 0x3f; + + return (byte); + + case 0x4212: + // V-blank, h-blank and joypads being read flags (read-only) #ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PCAtOpcodeStart; + CPU.WaitAddress = CPU.PCAtOpcodeStart; #endif - 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 */ - case 0x4214: - case 0x4215: - // Quotient of divide result - case 0x4216: - case 0x4217: - // Multiplcation result (for multiply) or remainder of - // divison. - /* fall through */ - case 0x4218: - case 0x4219: - case 0x421a: - case 0x421b: - case 0x421c: - case 0x421d: - case 0x421e: - case 0x421f: - // Joypads 1-4 button and direction state. - /* fall through */ - case 0x4300: - case 0x4310: - case 0x4320: - case 0x4330: - case 0x4340: - case 0x4350: - case 0x4360: - case 0x4370: - // DMA direction, address type, fixed flag, - /* fall through */ - case 0x4301: - case 0x4311: - case 0x4321: - case 0x4331: - case 0x4341: - case 0x4351: - case 0x4361: - case 0x4371: - /* fall through */ - case 0x4302: - case 0x4312: - case 0x4322: - case 0x4332: - case 0x4342: - case 0x4352: - case 0x4362: - case 0x4372: - /* fall through */ - case 0x4303: - case 0x4313: - case 0x4323: - case 0x4333: - case 0x4343: - case 0x4353: - case 0x4363: - case 0x4373: - /* fall through */ - case 0x4304: - case 0x4314: - case 0x4324: - case 0x4334: - case 0x4344: - case 0x4354: - case 0x4364: - case 0x4374: - /* fall through */ - case 0x4305: - case 0x4315: - case 0x4325: - case 0x4335: - case 0x4345: - case 0x4355: - case 0x4365: - case 0x4375: - /* fall through */ - case 0x4306: - case 0x4316: - case 0x4326: - case 0x4336: - case 0x4346: - case 0x4356: - case 0x4366: - case 0x4376: - /* fall through */ - case 0x4308: - case 0x4318: - case 0x4328: - case 0x4338: - case 0x4348: - case 0x4358: - case 0x4368: - case 0x4378: - /* fall through */ - case 0x4309: - case 0x4319: - case 0x4329: - case 0x4339: - case 0x4349: - case 0x4359: - case 0x4369: - case 0x4379: - return (Memory.FillRAM[Address]); - - case 0x4307: - case 0x4317: - case 0x4327: - case 0x4337: - case 0x4347: - case 0x4357: - case 0x4367: - case 0x4377: - return (DMA[(Address >> 4) & 7].IndirectBank); - - case 0x430A: - case 0x431A: - case 0x432A: - case 0x433A: - case 0x434A: - case 0x435A: - case 0x436A: - case 0x437A: - { - int d = (Address & 0x70) >> 4; - if (IPPU.HDMA & (1 << d)) - { - return (DMA[d].LineCount); - } - return (Memory.FillRAM[Address]); - } - - case 0x430F: - case 0x431F: - case 0x432F: - case 0x433F: - case 0x434F: - case 0x435F: - case 0x436F: - case 0x437F: - Address &= ~4; // Convert 43xF to 43xB - /* fall through */ - case 0x430B: - case 0x431B: - case 0x432B: - case 0x433B: - case 0x434B: - case 0x435B: - case 0x436B: - case 0x437B: - - // Unknown, but they seem to be RAM-ish - return (Memory.FillRAM[Address]); - - default: - if(Address>= 0x4800&&Settings.SPC7110) - return S9xGetSPC7110(Address); - - if(Address>=0x4800&&Address<=0x4807&&Settings.SDD1) - { - return Memory.FillRAM[Address]; - } - - return OpenBus; - } -// return (Memory.FillRAM[Address]); + 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 */ + case 0x4214: + case 0x4215: + // Quotient of divide result + case 0x4216: + case 0x4217: + // Multiplcation result (for multiply) or remainder of + // divison. + /* fall through */ + case 0x4218: + case 0x4219: + case 0x421a: + case 0x421b: + case 0x421c: + case 0x421d: + case 0x421e: + case 0x421f: + // Joypads 1-4 button and direction state. + /* fall through */ + case 0x4300: + case 0x4310: + case 0x4320: + case 0x4330: + case 0x4340: + case 0x4350: + case 0x4360: + case 0x4370: + // DMA direction, address type, fixed flag, + /* fall through */ + case 0x4301: + case 0x4311: + case 0x4321: + case 0x4331: + case 0x4341: + case 0x4351: + case 0x4361: + case 0x4371: + /* fall through */ + case 0x4302: + case 0x4312: + case 0x4322: + case 0x4332: + case 0x4342: + case 0x4352: + case 0x4362: + case 0x4372: + /* fall through */ + case 0x4303: + case 0x4313: + case 0x4323: + case 0x4333: + case 0x4343: + case 0x4353: + case 0x4363: + case 0x4373: + /* fall through */ + case 0x4304: + case 0x4314: + case 0x4324: + case 0x4334: + case 0x4344: + case 0x4354: + case 0x4364: + case 0x4374: + /* fall through */ + case 0x4305: + case 0x4315: + case 0x4325: + case 0x4335: + case 0x4345: + case 0x4355: + case 0x4365: + case 0x4375: + /* fall through */ + case 0x4306: + case 0x4316: + case 0x4326: + case 0x4336: + case 0x4346: + case 0x4356: + case 0x4366: + case 0x4376: + /* fall through */ + case 0x4308: + case 0x4318: + case 0x4328: + case 0x4338: + case 0x4348: + case 0x4358: + case 0x4368: + case 0x4378: + /* fall through */ + case 0x4309: + case 0x4319: + case 0x4329: + case 0x4339: + case 0x4349: + case 0x4359: + case 0x4369: + case 0x4379: + return (Memory.FillRAM[Address]); + + case 0x4307: + case 0x4317: + case 0x4327: + case 0x4337: + case 0x4347: + case 0x4357: + case 0x4367: + case 0x4377: + return (DMA[(Address >> 4) & 7].IndirectBank); + + case 0x430A: + case 0x431A: + case 0x432A: + case 0x433A: + case 0x434A: + case 0x435A: + case 0x436A: + case 0x437A: + { + int d = (Address & 0x70) >> 4; + if (IPPU.HDMA & (1 << d)) + return (DMA[d].LineCount); + return (Memory.FillRAM[Address]); + } + + case 0x430F: + case 0x431F: + case 0x432F: + case 0x433F: + case 0x434F: + case 0x435F: + case 0x436F: + case 0x437F: + Address &= ~4; // Convert 43xF to 43xB + /* fall through */ + case 0x430B: + case 0x431B: + case 0x432B: + case 0x433B: + case 0x434B: + case 0x435B: + case 0x436B: + case 0x437B: + + // Unknown, but they seem to be RAM-ish + return (Memory.FillRAM[Address]); + + default: + if (Address >= 0x4800 && Settings.SPC7110) + return S9xGetSPC7110(Address); + + if (Address >= 0x4800 && Address <= 0x4807 && Settings.SDD1) + return Memory.FillRAM[Address]; + + return OpenBus; + } + // return (Memory.FillRAM[Address]); } -static void CommonPPUReset () +static void CommonPPUReset() { - PPU.BGMode = 0; - PPU.BG3Priority = 0; - PPU.Brightness = 0; - PPU.VMA.High = 0; - PPU.VMA.Increment = 1; - PPU.VMA.Address = 0; - PPU.VMA.FullGraphicCount = 0; - PPU.VMA.Shift = 0; + PPU.BGMode = 0; + PPU.BG3Priority = 0; + PPU.Brightness = 0; + PPU.VMA.High = 0; + PPU.VMA.Increment = 1; + PPU.VMA.Address = 0; + PPU.VMA.FullGraphicCount = 0; + PPU.VMA.Shift = 0; uint8 B; for (B = 0; B != 4; B++) - { - PPU.BG[B].SCBase = 0; - PPU.BG[B].VOffset = 0; - PPU.BG[B].HOffset = 0; - PPU.BG[B].BGSize = 0; - PPU.BG[B].NameBase = 0; - PPU.BG[B].SCSize = 0; - - PPU.ClipCounts[B] = 0; - PPU.ClipWindowOverlapLogic [B] = CLIP_OR; - PPU.ClipWindow1Enable[B] = FALSE; - PPU.ClipWindow2Enable[B] = FALSE; - PPU.ClipWindow1Inside[B] = TRUE; - PPU.ClipWindow2Inside[B] = TRUE; - } - - PPU.ClipCounts[4] = 0; - PPU.ClipCounts[5] = 0; - PPU.ClipWindowOverlapLogic[4] = PPU.ClipWindowOverlapLogic[5] = CLIP_OR; - PPU.ClipWindow1Enable[4] = PPU.ClipWindow1Enable[5] = FALSE; - PPU.ClipWindow2Enable[4] = PPU.ClipWindow2Enable[5] = FALSE; - PPU.ClipWindow1Inside[4] = PPU.ClipWindow1Inside[5] = TRUE; - PPU.ClipWindow2Inside[4] = PPU.ClipWindow2Inside[5] = TRUE; - - PPU.CGFLIP = 0; - int c; - for (c = 0; c < 256; c++) - { - IPPU.Red [c] = (c & 7) << 2; - IPPU.Green [c] = ((c >> 3) & 7) << 2; - IPPU.Blue [c] = ((c >> 6) & 2) << 3; - PPU.CGDATA [c] = IPPU.Red [c] | (IPPU.Green [c] << 5) | - (IPPU.Blue [c] << 10); - } - - PPU.FirstSprite = 0; - PPU.LastSprite = 127; + { + PPU.BG[B].SCBase = 0; + PPU.BG[B].VOffset = 0; + PPU.BG[B].HOffset = 0; + PPU.BG[B].BGSize = 0; + PPU.BG[B].NameBase = 0; + PPU.BG[B].SCSize = 0; + + PPU.ClipCounts[B] = 0; + PPU.ClipWindowOverlapLogic [B] = CLIP_OR; + PPU.ClipWindow1Enable[B] = FALSE; + PPU.ClipWindow2Enable[B] = FALSE; + PPU.ClipWindow1Inside[B] = TRUE; + PPU.ClipWindow2Inside[B] = TRUE; + } + + PPU.ClipCounts[4] = 0; + PPU.ClipCounts[5] = 0; + PPU.ClipWindowOverlapLogic[4] = PPU.ClipWindowOverlapLogic[5] = CLIP_OR; + PPU.ClipWindow1Enable[4] = PPU.ClipWindow1Enable[5] = FALSE; + PPU.ClipWindow2Enable[4] = PPU.ClipWindow2Enable[5] = FALSE; + PPU.ClipWindow1Inside[4] = PPU.ClipWindow1Inside[5] = TRUE; + PPU.ClipWindow2Inside[4] = PPU.ClipWindow2Inside[5] = TRUE; + + PPU.CGFLIP = 0; + int c; + for (c = 0; c < 256; c++) + { + IPPU.Red [c] = (c & 7) << 2; + IPPU.Green [c] = ((c >> 3) & 7) << 2; + IPPU.Blue [c] = ((c >> 6) & 2) << 3; + PPU.CGDATA [c] = IPPU.Red [c] | (IPPU.Green [c] << 5) | + (IPPU.Blue [c] << 10); + } + + PPU.FirstSprite = 0; + PPU.LastSprite = 127; int Sprite; for (Sprite = 0; Sprite < 128; Sprite++) - { - PPU.OBJ[Sprite].HPos = 0; - PPU.OBJ[Sprite].VPos = 0; - PPU.OBJ[Sprite].VFlip = 0; - PPU.OBJ[Sprite].HFlip = 0; - PPU.OBJ[Sprite].Priority = 0; - PPU.OBJ[Sprite].Palette = 0; - PPU.OBJ[Sprite].Name = 0; - PPU.OBJ[Sprite].Size = 0; - } - PPU.OAMPriorityRotation = 0; - PPU.OAMWriteRegister = 0; - PPU.RangeTimeOver = 0; - PPU.OpenBus1 = 0; - PPU.OpenBus2 = 0; - - PPU.OAMFlip = 0; - PPU.OAMTileAddress = 0; - PPU.OAMAddr = 0; - PPU.IRQVBeamPos = 0; - PPU.IRQHBeamPos = 0; - PPU.VBeamPosLatched = 0; - PPU.HBeamPosLatched = 0; - - PPU.HBeamFlip = 0; - PPU.VBeamFlip = 0; - PPU.HVBeamCounterLatched = 0; - - PPU.MatrixA = PPU.MatrixB = PPU.MatrixC = PPU.MatrixD = 0; - PPU.CentreX = PPU.CentreY = 0; - PPU.CGADD = 0; - PPU.FixedColourRed = PPU.FixedColourGreen = PPU.FixedColourBlue = 0; - PPU.SavedOAMAddr = 0; - PPU.ScreenHeight = SNES_HEIGHT; - PPU.WRAM = 0; - PPU.BG_Forced = 0; - PPU.ForcedBlanking = TRUE; - PPU.OBJThroughMain = FALSE; - PPU.OBJThroughSub = FALSE; - PPU.OBJSizeSelect = 0; - PPU.OBJNameSelect = 0; - PPU.OBJNameBase = 0; - PPU.OBJAddition = FALSE; - PPU.OAMReadFlip = 0; - PPU.BGnxOFSbyte = 0; - ZeroMemory (PPU.OAMData, 512 + 32); - - PPU.VTimerEnabled = FALSE; - PPU.HTimerEnabled = FALSE; - PPU.HTimerPosition = Settings.H_Max + 1; - PPU.Mosaic = 0; - PPU.BGMosaic [0] = PPU.BGMosaic [1] = FALSE; - PPU.BGMosaic [2] = PPU.BGMosaic [3] = FALSE; - PPU.Mode7HFlip = FALSE; - PPU.Mode7VFlip = FALSE; - PPU.Mode7Repeat = 0; - PPU.Window1Left = 1; - PPU.Window1Right = 0; - PPU.Window2Left = 1; - PPU.Window2Right = 0; - PPU.RecomputeClipWindows = TRUE; - PPU.CGFLIPRead = 0; - PPU.Need16x8Mulitply = FALSE; - PPU.MouseSpeed[0] = PPU.MouseSpeed[1] = 0; - - IPPU.ColorsChanged = TRUE; - IPPU.HDMA = 0; - IPPU.HDMAStarted = FALSE; - IPPU.MaxBrightness = 0; - IPPU.LatchedBlanking = 0; - IPPU.OBJChanged = TRUE; - IPPU.RenderThisFrame = TRUE; - IPPU.DirectColourMapsNeedRebuild = TRUE; - IPPU.FrameCount = 0; - IPPU.RenderedFramesCount = 0; - IPPU.DisplayedRenderedFrameCount = 0; - IPPU.SkippedFrames = 0; - IPPU.FrameSkip = 0; - ZeroMemory (IPPU.TileCached [TILE_2BIT], MAX_2BIT_TILES); - ZeroMemory (IPPU.TileCached [TILE_4BIT], MAX_4BIT_TILES); - ZeroMemory (IPPU.TileCached [TILE_8BIT], MAX_8BIT_TILES); + { + PPU.OBJ[Sprite].HPos = 0; + PPU.OBJ[Sprite].VPos = 0; + PPU.OBJ[Sprite].VFlip = 0; + PPU.OBJ[Sprite].HFlip = 0; + PPU.OBJ[Sprite].Priority = 0; + PPU.OBJ[Sprite].Palette = 0; + PPU.OBJ[Sprite].Name = 0; + PPU.OBJ[Sprite].Size = 0; + } + PPU.OAMPriorityRotation = 0; + PPU.OAMWriteRegister = 0; + PPU.RangeTimeOver = 0; + PPU.OpenBus1 = 0; + PPU.OpenBus2 = 0; + + PPU.OAMFlip = 0; + PPU.OAMTileAddress = 0; + PPU.OAMAddr = 0; + PPU.IRQVBeamPos = 0; + PPU.IRQHBeamPos = 0; + PPU.VBeamPosLatched = 0; + PPU.HBeamPosLatched = 0; + + PPU.HBeamFlip = 0; + PPU.VBeamFlip = 0; + PPU.HVBeamCounterLatched = 0; + + PPU.MatrixA = PPU.MatrixB = PPU.MatrixC = PPU.MatrixD = 0; + PPU.CentreX = PPU.CentreY = 0; + PPU.CGADD = 0; + PPU.FixedColourRed = PPU.FixedColourGreen = PPU.FixedColourBlue = 0; + PPU.SavedOAMAddr = 0; + PPU.ScreenHeight = SNES_HEIGHT; + PPU.WRAM = 0; + PPU.BG_Forced = 0; + PPU.ForcedBlanking = TRUE; + PPU.OBJThroughMain = FALSE; + PPU.OBJThroughSub = FALSE; + PPU.OBJSizeSelect = 0; + PPU.OBJNameSelect = 0; + PPU.OBJNameBase = 0; + PPU.OBJAddition = FALSE; + PPU.OAMReadFlip = 0; + PPU.BGnxOFSbyte = 0; + ZeroMemory(PPU.OAMData, 512 + 32); + + PPU.VTimerEnabled = FALSE; + PPU.HTimerEnabled = FALSE; + PPU.HTimerPosition = Settings.H_Max + 1; + PPU.Mosaic = 0; + PPU.BGMosaic [0] = PPU.BGMosaic [1] = FALSE; + PPU.BGMosaic [2] = PPU.BGMosaic [3] = FALSE; + PPU.Mode7HFlip = FALSE; + PPU.Mode7VFlip = FALSE; + PPU.Mode7Repeat = 0; + PPU.Window1Left = 1; + PPU.Window1Right = 0; + PPU.Window2Left = 1; + PPU.Window2Right = 0; + PPU.RecomputeClipWindows = TRUE; + PPU.CGFLIPRead = 0; + PPU.Need16x8Mulitply = FALSE; + PPU.MouseSpeed[0] = PPU.MouseSpeed[1] = 0; + + IPPU.ColorsChanged = TRUE; + IPPU.HDMA = 0; + IPPU.HDMAStarted = FALSE; + IPPU.MaxBrightness = 0; + IPPU.LatchedBlanking = 0; + IPPU.OBJChanged = TRUE; + IPPU.RenderThisFrame = TRUE; + IPPU.DirectColourMapsNeedRebuild = TRUE; + IPPU.FrameCount = 0; + IPPU.RenderedFramesCount = 0; + IPPU.DisplayedRenderedFrameCount = 0; + IPPU.SkippedFrames = 0; + IPPU.FrameSkip = 0; + ZeroMemory(IPPU.TileCached [TILE_2BIT], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached [TILE_4BIT], MAX_4BIT_TILES); + ZeroMemory(IPPU.TileCached [TILE_8BIT], MAX_8BIT_TILES); #ifdef CORRECT_VRAM_READS - IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better? + IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better? #else - IPPU.FirstVRAMRead = FALSE; + IPPU.FirstVRAMRead = FALSE; #endif - IPPU.Interlace = FALSE; - IPPU.InterlaceSprites = FALSE; - IPPU.DoubleWidthPixels = FALSE; - IPPU.HalfWidthPixels = FALSE; - IPPU.DoubleHeightPixels = FALSE; - IPPU.RenderedScreenWidth = SNES_WIDTH; - IPPU.RenderedScreenHeight = SNES_HEIGHT; - IPPU.XB = NULL; - for (c = 0; c < 256; c++) - IPPU.ScreenColors [c] = c; - S9xFixColourBrightness (); - IPPU.PreviousLine = IPPU.CurrentLine = 0; - - if (Settings.ControllerOption == 0) - IPPU.Controller = SNES_MAX_CONTROLLER_OPTIONS - 1; - else - IPPU.Controller = Settings.ControllerOption - 1; - S9xNextController (); - - for (c = 0; c < 2; c++) - memset (&IPPU.Clip [c], 0, sizeof (struct ClipData)); - - if (Settings.MouseMaster) - { - S9xProcessMouse (0); - S9xProcessMouse (1); - } + IPPU.Interlace = FALSE; + IPPU.InterlaceSprites = FALSE; + IPPU.DoubleWidthPixels = FALSE; + IPPU.HalfWidthPixels = FALSE; + IPPU.DoubleHeightPixels = FALSE; + IPPU.RenderedScreenWidth = SNES_WIDTH; + IPPU.RenderedScreenHeight = SNES_HEIGHT; + IPPU.XB = NULL; + for (c = 0; c < 256; c++) + IPPU.ScreenColors [c] = c; + S9xFixColourBrightness(); + IPPU.PreviousLine = IPPU.CurrentLine = 0; + + if (Settings.ControllerOption == 0) + IPPU.Controller = SNES_MAX_CONTROLLER_OPTIONS - 1; + else + IPPU.Controller = Settings.ControllerOption - 1; + S9xNextController(); + + for (c = 0; c < 2; c++) + memset(&IPPU.Clip [c], 0, sizeof(struct ClipData)); + + if (Settings.MouseMaster) + { + S9xProcessMouse(0); + S9xProcessMouse(1); + } } -void S9xResetPPU () +void S9xResetPPU() { - CommonPPUReset (); - PPU.Joypad1ButtonReadPos = 0; - PPU.Joypad2ButtonReadPos = 0; - PPU.Joypad3ButtonReadPos = 0; - - IPPU.Joypads[0] = IPPU.Joypads[1] = IPPU.Joypads[2] = 0; - IPPU.Joypads[3] = IPPU.Joypads[4] = 0; - IPPU.SuperScope = 0; - IPPU.Mouse[0] = IPPU.Mouse[1] = 0; - IPPU.PrevMouseX[0] = IPPU.PrevMouseX[1] = 256 / 2; - IPPU.PrevMouseY[0] = IPPU.PrevMouseY[1] = 224 / 2; + CommonPPUReset(); + PPU.Joypad1ButtonReadPos = 0; + PPU.Joypad2ButtonReadPos = 0; + PPU.Joypad3ButtonReadPos = 0; + + IPPU.Joypads[0] = IPPU.Joypads[1] = IPPU.Joypads[2] = 0; + IPPU.Joypads[3] = IPPU.Joypads[4] = 0; + IPPU.SuperScope = 0; + IPPU.Mouse[0] = IPPU.Mouse[1] = 0; + IPPU.PrevMouseX[0] = IPPU.PrevMouseX[1] = 256 / 2; + IPPU.PrevMouseY[0] = IPPU.PrevMouseY[1] = 224 / 2; int c; for (c = 0; c < 0x8000; c += 0x100) - { - if ( !Settings.SuperFX ) - { - memset (&Memory.FillRAM [c], c >> 8, 0x100); - } - else if ( (unsigned)c < 0x3000 || (unsigned)c >= 0x3300 ) - { - /* Don't overwrite SFX pvRegisters at 0x3000-0x32FF, - * they were set in FxReset. - */ - memset (&Memory.FillRAM [c], c >> 8, 0x100); - } - } - - ZeroMemory (&Memory.FillRAM [0x2100], 0x100); - ZeroMemory (&Memory.FillRAM [0x4200], 0x100); - ZeroMemory (&Memory.FillRAM [0x4000], 0x100); - // For BS Suttehakkun 2... - ZeroMemory (&Memory.FillRAM [0x1000], 0x1000); - - Memory.FillRAM[0x4201]=Memory.FillRAM[0x4213]=0xFF; + { + if (!Settings.SuperFX) + memset(&Memory.FillRAM [c], c >> 8, 0x100); + else if ((unsigned)c < 0x3000 || (unsigned)c >= 0x3300) + { + /* Don't overwrite SFX pvRegisters at 0x3000-0x32FF, + * they were set in FxReset. + */ + memset(&Memory.FillRAM [c], c >> 8, 0x100); + } + } + + ZeroMemory(&Memory.FillRAM [0x2100], 0x100); + ZeroMemory(&Memory.FillRAM [0x4200], 0x100); + ZeroMemory(&Memory.FillRAM [0x4000], 0x100); + // For BS Suttehakkun 2... + ZeroMemory(&Memory.FillRAM [0x1000], 0x1000); + + Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = 0xFF; } -void S9xSoftResetPPU () +void S9xSoftResetPPU() { - CommonPPUReset (); -// PPU.Joypad1ButtonReadPos = 0; -// PPU.Joypad2ButtonReadPos = 0; -// PPU.Joypad3ButtonReadPos = 0; - -// IPPU.Joypads[0] = IPPU.Joypads[1] = IPPU.Joypads[2] = 0; -// IPPU.Joypads[3] = IPPU.Joypads[4] = 0; -// IPPU.SuperScope = 0; -// IPPU.Mouse[0] = IPPU.Mouse[1] = 0; -// IPPU.PrevMouseX[0] = IPPU.PrevMouseX[1] = 256 / 2; -// IPPU.PrevMouseY[0] = IPPU.PrevMouseY[1] = 224 / 2; + CommonPPUReset(); + // PPU.Joypad1ButtonReadPos = 0; + // PPU.Joypad2ButtonReadPos = 0; + // PPU.Joypad3ButtonReadPos = 0; + + // IPPU.Joypads[0] = IPPU.Joypads[1] = IPPU.Joypads[2] = 0; + // IPPU.Joypads[3] = IPPU.Joypads[4] = 0; + // IPPU.SuperScope = 0; + // IPPU.Mouse[0] = IPPU.Mouse[1] = 0; + // IPPU.PrevMouseX[0] = IPPU.PrevMouseX[1] = 256 / 2; + // IPPU.PrevMouseY[0] = IPPU.PrevMouseY[1] = 224 / 2; int c; for (c = 0; c < 0x8000; c += 0x100) - memset (&Memory.FillRAM [c], c >> 8, 0x100); + memset(&Memory.FillRAM [c], c >> 8, 0x100); - ZeroMemory (&Memory.FillRAM [0x2100], 0x100); - ZeroMemory (&Memory.FillRAM [0x4200], 0x100); - ZeroMemory (&Memory.FillRAM [0x4000], 0x100); - // For BS Suttehakkun 2... - ZeroMemory (&Memory.FillRAM [0x1000], 0x1000); + ZeroMemory(&Memory.FillRAM [0x2100], 0x100); + ZeroMemory(&Memory.FillRAM [0x4200], 0x100); + ZeroMemory(&Memory.FillRAM [0x4000], 0x100); + // For BS Suttehakkun 2... + ZeroMemory(&Memory.FillRAM [0x1000], 0x1000); - Memory.FillRAM[0x4201]=Memory.FillRAM[0x4213]=0xFF; + Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = 0xFF; } -void S9xProcessMouse (int which1) +void S9xProcessMouse(int which1) { - int x, y; - uint32 buttons; - - if ((IPPU.Controller == SNES_MOUSE || IPPU.Controller == SNES_MOUSE_SWAPPED) && S9xReadMousePosition (which1, &x, &y, &buttons)) - { - int delta_x, delta_y; + int x, y; + uint32 buttons; + + if ((IPPU.Controller == SNES_MOUSE || IPPU.Controller == SNES_MOUSE_SWAPPED) + && S9xReadMousePosition(which1, &x, &y, &buttons)) + { + int delta_x, delta_y; #define MOUSE_SIGNATURE 0x1 - IPPU.Mouse [which1] = MOUSE_SIGNATURE | - (PPU.MouseSpeed [which1] << 4) | - ((buttons & 1) << 6) | ((buttons & 2) << 6); - - delta_x = x - IPPU.PrevMouseX[which1]; - delta_y = y - IPPU.PrevMouseY[which1]; - - if (delta_x > 63) - { - delta_x = 63; - IPPU.PrevMouseX[which1] += 63; - } - else - if (delta_x < -63) - { - delta_x = -63; - IPPU.PrevMouseX[which1] -= 63; - } - else - IPPU.PrevMouseX[which1] = x; - - if (delta_y > 63) - { - delta_y = 63; - IPPU.PrevMouseY[which1] += 63; - } - else - if (delta_y < -63) - { - delta_y = -63; - IPPU.PrevMouseY[which1] -= 63; - } - else - IPPU.PrevMouseY[which1] = y; - - if (delta_x < 0) - { - delta_x = -delta_x; - IPPU.Mouse [which1] |= (delta_x | 0x80) << 16; - } - else - IPPU.Mouse [which1] |= delta_x << 16; - - if (delta_y < 0) - { - delta_y = -delta_y; - IPPU.Mouse [which1] |= (delta_y | 0x80) << 24; - } - else - IPPU.Mouse [which1] |= delta_y << 24; - - if (IPPU.Controller == SNES_MOUSE_SWAPPED) - IPPU.Joypads [0] = IPPU.Mouse [which1]; - else - IPPU.Joypads [1] = IPPU.Mouse [which1]; - } + IPPU.Mouse [which1] = MOUSE_SIGNATURE | + (PPU.MouseSpeed [which1] << 4) | + ((buttons & 1) << 6) | ((buttons & 2) << 6); + + delta_x = x - IPPU.PrevMouseX[which1]; + delta_y = y - IPPU.PrevMouseY[which1]; + + if (delta_x > 63) + { + delta_x = 63; + IPPU.PrevMouseX[which1] += 63; + } + else if (delta_x < -63) + { + delta_x = -63; + IPPU.PrevMouseX[which1] -= 63; + } + else + IPPU.PrevMouseX[which1] = x; + + if (delta_y > 63) + { + delta_y = 63; + IPPU.PrevMouseY[which1] += 63; + } + else if (delta_y < -63) + { + delta_y = -63; + IPPU.PrevMouseY[which1] -= 63; + } + else + IPPU.PrevMouseY[which1] = y; + + if (delta_x < 0) + { + delta_x = -delta_x; + IPPU.Mouse [which1] |= (delta_x | 0x80) << 16; + } + else + IPPU.Mouse [which1] |= delta_x << 16; + + if (delta_y < 0) + { + delta_y = -delta_y; + IPPU.Mouse [which1] |= (delta_y | 0x80) << 24; + } + else + IPPU.Mouse [which1] |= delta_y << 24; + + if (IPPU.Controller == SNES_MOUSE_SWAPPED) + IPPU.Joypads [0] = IPPU.Mouse [which1]; + else + IPPU.Joypads [1] = IPPU.Mouse [which1]; + } } -void ProcessSuperScope () +void ProcessSuperScope() { - int x, y; - uint32 buttons; + int x, y; + uint32 buttons; - if (IPPU.Controller == SNES_SUPERSCOPE && - S9xReadSuperScopePosition (&x, &y, &buttons)) - { + if (IPPU.Controller == SNES_SUPERSCOPE && + S9xReadSuperScopePosition(&x, &y, &buttons)) + { #define SUPERSCOPE_SIGNATURE 0x00ff - uint32 scope; - - 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; - if (x > 295) - x = 295; - if (x < 40) - x = 40; - if (y > PPU.ScreenHeight - 1) - y = PPU.ScreenHeight - 1; - if (y < 0) - y = 0; - - PPU.VBeamPosLatched = (uint16) (y + 1); - PPU.HBeamPosLatched = (uint16) x; - PPU.HVBeamCounterLatched = TRUE; - Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; - } - IPPU.Joypads [1] = scope; - } + uint32 scope; + + 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; + if (x > 295) + x = 295; + if (x < 40) + x = 40; + if (y > PPU.ScreenHeight - 1) + y = PPU.ScreenHeight - 1; + if (y < 0) + y = 0; + + PPU.VBeamPosLatched = (uint16)(y + 1); + PPU.HBeamPosLatched = (uint16) x; + PPU.HVBeamCounterLatched = TRUE; + Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; + } + IPPU.Joypads [1] = scope; + } } -void S9xNextController () +void S9xNextController() { - switch (IPPU.Controller) - { - case SNES_MULTIPLAYER5: - IPPU.Controller = SNES_JOYPAD; - break; - case SNES_JOYPAD: - if (Settings.MouseMaster) - { - IPPU.Controller = SNES_MOUSE_SWAPPED; - break; - } - case SNES_MOUSE_SWAPPED: - if (Settings.MouseMaster) - { - IPPU.Controller = SNES_MOUSE; - break; - } - case SNES_MOUSE: - if (Settings.SuperScopeMaster) - { - IPPU.Controller = SNES_SUPERSCOPE; - break; - } - case SNES_SUPERSCOPE: - if (Settings.JustifierMaster) - { - IPPU.Controller = SNES_JUSTIFIER; - break; - } - case SNES_JUSTIFIER: - if(Settings.JustifierMaster) - { - IPPU.Controller=SNES_JUSTIFIER_2; - break; - } - case SNES_JUSTIFIER_2: - if(Settings.MultiPlayer5Master) - { - IPPU.Controller=SNES_MULTIPLAYER5; - break; - } - default: - IPPU.Controller = SNES_JOYPAD; - break; - } + switch (IPPU.Controller) + { + case SNES_MULTIPLAYER5: + IPPU.Controller = SNES_JOYPAD; + break; + case SNES_JOYPAD: + if (Settings.MouseMaster) + { + IPPU.Controller = SNES_MOUSE_SWAPPED; + break; + } + case SNES_MOUSE_SWAPPED: + if (Settings.MouseMaster) + { + IPPU.Controller = SNES_MOUSE; + break; + } + case SNES_MOUSE: + if (Settings.SuperScopeMaster) + { + IPPU.Controller = SNES_SUPERSCOPE; + break; + } + case SNES_SUPERSCOPE: + if (Settings.JustifierMaster) + { + IPPU.Controller = SNES_JUSTIFIER; + break; + } + case SNES_JUSTIFIER: + if (Settings.JustifierMaster) + { + IPPU.Controller = SNES_JUSTIFIER_2; + break; + } + case SNES_JUSTIFIER_2: + if (Settings.MultiPlayer5Master) + { + IPPU.Controller = SNES_MULTIPLAYER5; + break; + } + default: + IPPU.Controller = SNES_JOYPAD; + break; + } } void S9xUpdateJustifiers() { - static bool last_p1; - in_bit=0; -// static int p1count; - justifiers=0xFFFF00AA; + static bool last_p1; + in_bit = 0; + // static int p1count; + justifiers = 0xFFFF00AA; - bool offscreen=JustifierOffscreen(); + bool offscreen = JustifierOffscreen(); JustifierButtons(&justifiers); -// if(p1count==32) -// { - last_p1=!last_p1; -// p1count=0; -// } -// p1count++; - - if(!last_p1) - justifiers|=0x1000; - - int x,y; - uint32 buttons; - - if(Memory.FillRAM[0x4201]&0x80) - { - - S9xReadSuperScopePosition(&x,&y,&buttons); - - x+=40; - if (x > 295) - x = 295; - if (x < 40) - x = 40; - if (y > PPU.ScreenHeight - 1) - y = PPU.ScreenHeight - 1; - if (y < 0) - y = 0; - - if(last_p1) - { - - PPU.HVBeamCounterLatched = FALSE; - Memory.FillRAM [0x213F] = Model->_5C78; - - //process latch as Justifier 2 - if(Settings.SecondJustifier) - { - if(IPPU.Controller==SNES_JUSTIFIER_2) - { - if(!offscreen) - { - - PPU.VBeamPosLatched = (uint16) (y + 1); - PPU.HBeamPosLatched = (uint16) x; - PPU.HVBeamCounterLatched = TRUE; - Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; - } - } - } - } - else - { - - PPU.HVBeamCounterLatched = FALSE; - Memory.FillRAM [0x213F] = Model->_5C78; - - //emulate player 1. - if(IPPU.Controller==SNES_JUSTIFIER) - { - if(!offscreen) - { - PPU.VBeamPosLatched = (uint16) (y + 1); - PPU.HBeamPosLatched = (uint16) x; - PPU.HVBeamCounterLatched = TRUE; - Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; - } - } - } - - //needs restructure - if(!offscreen) - { - - if((!last_p1&&IPPU.Controller==SNES_JUSTIFIER)||(last_p1&&IPPU.Controller==SNES_JUSTIFIER_2)) - { - PPU.VBeamPosLatched = (uint16) (y + 1); - PPU.HBeamPosLatched = (uint16) x; - PPU.HVBeamCounterLatched = TRUE; - Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; - } - else - { - PPU.HVBeamCounterLatched = FALSE; - Memory.FillRAM [0x213F] = Model->_5C78; - - } - } - else - { - PPU.HVBeamCounterLatched = FALSE; - Memory.FillRAM [0x213F] = Model->_5C78; - } - } + // if(p1count==32) + // { + last_p1 = !last_p1; + // p1count=0; + // } + // p1count++; + + if (!last_p1) + justifiers |= 0x1000; + + int x, y; + uint32 buttons; + + if (Memory.FillRAM[0x4201] & 0x80) + { + + S9xReadSuperScopePosition(&x, &y, &buttons); + + x += 40; + if (x > 295) + x = 295; + if (x < 40) + x = 40; + if (y > PPU.ScreenHeight - 1) + y = PPU.ScreenHeight - 1; + if (y < 0) + y = 0; + + if (last_p1) + { + + PPU.HVBeamCounterLatched = FALSE; + Memory.FillRAM [0x213F] = Model->_5C78; + + //process latch as Justifier 2 + if (Settings.SecondJustifier) + { + if (IPPU.Controller == SNES_JUSTIFIER_2) + { + if (!offscreen) + { + + PPU.VBeamPosLatched = (uint16)(y + 1); + PPU.HBeamPosLatched = (uint16) x; + PPU.HVBeamCounterLatched = TRUE; + Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; + } + } + } + } + else + { + + PPU.HVBeamCounterLatched = FALSE; + Memory.FillRAM [0x213F] = Model->_5C78; + + //emulate player 1. + if (IPPU.Controller == SNES_JUSTIFIER) + { + if (!offscreen) + { + PPU.VBeamPosLatched = (uint16)(y + 1); + PPU.HBeamPosLatched = (uint16) x; + PPU.HVBeamCounterLatched = TRUE; + Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; + } + } + } + + //needs restructure + if (!offscreen) + { + + if ((!last_p1 && IPPU.Controller == SNES_JUSTIFIER) || (last_p1 + && IPPU.Controller == SNES_JUSTIFIER_2)) + { + PPU.VBeamPosLatched = (uint16)(y + 1); + PPU.HBeamPosLatched = (uint16) x; + PPU.HVBeamCounterLatched = TRUE; + Memory.FillRAM [0x213F] |= 0x40 | Model->_5C78; + } + else + { + PPU.HVBeamCounterLatched = FALSE; + Memory.FillRAM [0x213F] = Model->_5C78; + + } + } + else + { + PPU.HVBeamCounterLatched = FALSE; + Memory.FillRAM [0x213F] = Model->_5C78; + } + } } -void S9xUpdateJoypads () +void S9xUpdateJoypads() { - uint32 i; - - for (i = 0; i < 5; i++) - { - IPPU.Joypads [i] = S9xReadJoypad (i); - } - -// S9xMovieUpdate(); - - for (i = 0; i < 5; i++) - { - if ((IPPU.Joypads [i] & (SNES_LEFT_MASK | SNES_RIGHT_MASK)) == (SNES_LEFT_MASK | SNES_RIGHT_MASK)) - IPPU.Joypads [i] &= ~SNES_RIGHT_MASK; - if ((IPPU.Joypads [i] & (SNES_UP_MASK | SNES_DOWN_MASK)) == (SNES_UP_MASK | SNES_DOWN_MASK)) - 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) - { - for (i = 0; i < 2; i++) - S9xProcessMouse (i); - } - - // Read SuperScope if enabled - if (Settings.SuperScopeMaster) - ProcessSuperScope (); - - if (Memory.FillRAM [0x4200] & 1) - { - PPU.Joypad1ButtonReadPos = 16; - if (Memory.FillRAM [0x4201] & 0x80) - { - PPU.Joypad2ButtonReadPos = 16; - PPU.Joypad3ButtonReadPos = 0; - } - else - { - PPU.Joypad2ButtonReadPos = 0; - PPU.Joypad3ButtonReadPos = 16; - } - int ind = Settings.SwapJoypads ? 1 : 0; - - Memory.FillRAM [0x4218] = (uint8) IPPU.Joypads [ind]; - Memory.FillRAM [0x4219] = (uint8) (IPPU.Joypads [ind] >> 8); - Memory.FillRAM [0x421a] = (uint8) IPPU.Joypads [ind ^ 1]; - Memory.FillRAM [0x421b] = (uint8) (IPPU.Joypads [ind ^ 1] >> 8); - if (Memory.FillRAM [0x4201] & 0x80) - { - Memory.FillRAM [0x421c] = (uint8) IPPU.Joypads [ind]; - Memory.FillRAM [0x421d] = (uint8) (IPPU.Joypads [ind] >> 8); - Memory.FillRAM [0x421e] = (uint8) IPPU.Joypads [2]; - Memory.FillRAM [0x421f] = (uint8) (IPPU.Joypads [2] >> 8); - } - else - { - Memory.FillRAM [0x421c] = (uint8) IPPU.Joypads [3]; - Memory.FillRAM [0x421d] = (uint8) (IPPU.Joypads [3] >> 8); - Memory.FillRAM [0x421e] = (uint8) IPPU.Joypads [4]; - Memory.FillRAM [0x421f] = (uint8) (IPPU.Joypads [4] >> 8); - } - } - if(Settings.Justifier||Settings.SecondJustifier) - { - Memory.FillRAM [0x421a] = 0x0E; - Memory.FillRAM [0x421b] = 0; - S9xUpdateJustifiers(); - } - + uint32 i; + + for (i = 0; i < 5; i++) + IPPU.Joypads [i] = S9xReadJoypad(i); + + // S9xMovieUpdate(); + + for (i = 0; i < 5; i++) + { + if ((IPPU.Joypads [i] & (SNES_LEFT_MASK | SNES_RIGHT_MASK)) == + (SNES_LEFT_MASK | SNES_RIGHT_MASK)) + IPPU.Joypads [i] &= ~SNES_RIGHT_MASK; + if ((IPPU.Joypads [i] & (SNES_UP_MASK | SNES_DOWN_MASK)) == + (SNES_UP_MASK | SNES_DOWN_MASK)) + 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) + { + for (i = 0; i < 2; i++) + S9xProcessMouse(i); + } + + // Read SuperScope if enabled + if (Settings.SuperScopeMaster) + ProcessSuperScope(); + + if (Memory.FillRAM [0x4200] & 1) + { + PPU.Joypad1ButtonReadPos = 16; + if (Memory.FillRAM [0x4201] & 0x80) + { + PPU.Joypad2ButtonReadPos = 16; + PPU.Joypad3ButtonReadPos = 0; + } + else + { + PPU.Joypad2ButtonReadPos = 0; + PPU.Joypad3ButtonReadPos = 16; + } + int ind = Settings.SwapJoypads ? 1 : 0; + + Memory.FillRAM [0x4218] = (uint8) IPPU.Joypads [ind]; + Memory.FillRAM [0x4219] = (uint8)(IPPU.Joypads [ind] >> 8); + Memory.FillRAM [0x421a] = (uint8) IPPU.Joypads [ind ^ 1]; + Memory.FillRAM [0x421b] = (uint8)(IPPU.Joypads [ind ^ 1] >> 8); + if (Memory.FillRAM [0x4201] & 0x80) + { + Memory.FillRAM [0x421c] = (uint8) IPPU.Joypads [ind]; + Memory.FillRAM [0x421d] = (uint8)(IPPU.Joypads [ind] >> 8); + Memory.FillRAM [0x421e] = (uint8) IPPU.Joypads [2]; + Memory.FillRAM [0x421f] = (uint8)(IPPU.Joypads [2] >> 8); + } + else + { + Memory.FillRAM [0x421c] = (uint8) IPPU.Joypads [3]; + Memory.FillRAM [0x421d] = (uint8)(IPPU.Joypads [3] >> 8); + Memory.FillRAM [0x421e] = (uint8) IPPU.Joypads [4]; + Memory.FillRAM [0x421f] = (uint8)(IPPU.Joypads [4] >> 8); + } + } + if (Settings.Justifier || Settings.SecondJustifier) + { + Memory.FillRAM [0x421a] = 0x0E; + Memory.FillRAM [0x421b] = 0; + S9xUpdateJustifiers(); + } + } #ifndef ZSNES_FX -void S9xSuperFXExec () +void S9xSuperFXExec() { #if 1 - if (Settings.SuperFX) - { - if ((Memory.FillRAM [0x3000 + GSU_SFR] & FLG_G) && - (Memory.FillRAM [0x3000 + GSU_SCMR] & 0x18) == 0x18) - { - if (!Settings.WinterGold||Settings.StarfoxHack) - FxEmulate (~0); - else - FxEmulate ((Memory.FillRAM [0x3000 + GSU_CLSR] & 1) ? 700 : 350); - int GSUStatus = Memory.FillRAM [0x3000 + GSU_SFR] | - (Memory.FillRAM [0x3000 + GSU_SFR + 1] << 8); - if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ) - { - // Trigger a GSU IRQ. - S9xSetIRQ (GSU_IRQ_SOURCE); - } - } - } + if (Settings.SuperFX) + { + if ((Memory.FillRAM [0x3000 + GSU_SFR] & FLG_G) && + (Memory.FillRAM [0x3000 + GSU_SCMR] & 0x18) == 0x18) + { + if (!Settings.WinterGold || Settings.StarfoxHack) + FxEmulate(~0); + else + FxEmulate((Memory.FillRAM [0x3000 + GSU_CLSR] & 1) ? 700 : 350); + int GSUStatus = Memory.FillRAM [0x3000 + GSU_SFR] | + (Memory.FillRAM [0x3000 + GSU_SFR + 1] << 8); + if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ) + { + // Trigger a GSU IRQ. + S9xSetIRQ(GSU_IRQ_SOURCE); + } + } + } #else - uint32 tmp = (Memory.FillRAM[0x3034] << 16) + *(uint16 *) &Memory.FillRAM [0x301e]; + uint32 tmp = (Memory.FillRAM[0x3034] << 16) + *(uint16*) + &Memory.FillRAM [0x301e]; #if 0 - if (tmp == 0x018428) - { - *(uint16 *) &SRAM [0x0064] = 0xbc00; - *(uint16 *) &SRAM [0x002c] = 0x8000; - } + if (tmp == 0x018428) + { + *(uint16*) &SRAM [0x0064] = 0xbc00; + *(uint16*) &SRAM [0x002c] = 0x8000; + } #endif - if (tmp == -1)//0x018428) //0x01bfc3) //0x09edaf) //-1) //0x57edaf) - { - while (Memory.FillRAM [0x3030] & 0x20) - { - int i; - int32 vError; - uint8 avReg[0x40]; - char tmp[128]; - uint8 vPipe; - uint8 vColr; - uint8 vPor; - - FxPipeString (tmp); - /* Make the string 32 chars long */ - if(strlen(tmp) < 32) { memset(&tmp[strlen(tmp)],' ',32-strlen(tmp)); tmp[32] = 0; } - - /* Copy registers (so we can see if any changed) */ - vColr = FxGetColorRegister(); - vPor = FxGetPlotOptionRegister(); - memcpy(avReg,SuperFX.pvRegisters,0x40); - - /* Print the pipe string */ - printf(tmp); - - /* Execute the instruction in the pipe */ - vPipe = FxPipe(); - vError = FxEmulate(1); - - /* Check if any registers changed (and print them if they did) */ - for(i=0; i<16; i++) - { - uint32 a = 0; - uint32 r1 = ((uint32)avReg[i*2]) | (((uint32)avReg[(i*2)+1])<<8); - uint32 r2 = (uint32)(SuperFX.pvRegisters[i*2]) | (((uint32)SuperFX.pvRegisters[(i*2)+1])<<8); - if(i==15) - a = OPCODE_BYTES(vPipe); - if(((r1+a)&0xffff) != r2) - printf(" r%d=$%04x",i,r2); - } - { - /* Check SFR */ - uint32 r1 = ((uint32)avReg[0x30]) | (((uint32)avReg[0x31])<<8); - uint32 r2 = (uint32)(SuperFX.pvRegisters[0x30]) | (((uint32)SuperFX.pvRegisters[0x31])<<8); - if((r1&(1<<1)) != (r2&(1<<1))) - printf(" Z=%d",(uint32)(!!(r2&(1<<1)))); - if((r1&(1<<2)) != (r2&(1<<2))) - printf(" CY=%d",(uint32)(!!(r2&(1<<2)))); - if((r1&(1<<3)) != (r2&(1<<3))) - printf(" S=%d",(uint32)(!!(r2&(1<<3)))); - if((r1&(1<<4)) != (r2&(1<<4))) - printf(" OV=%d",(uint32)(!!(r2&(1<<4)))); - if((r1&(1<<5)) != (r2&(1<<5))) - printf(" G=%d",(uint32)(!!(r2&(1<<5)))); - if((r1&(1<<6)) != (r2&(1<<6))) - printf(" R=%d",(uint32)(!!(r2&(1<<6)))); - if((r1&(1<<8)) != (r2&(1<<8))) - printf(" ALT1=%d",(uint32)(!!(r2&(1<<8)))); - if((r1&(1<<9)) != (r2&(1<<9))) - printf(" ALT2=%d",(uint32)(!!(r2&(1<<9)))); - if((r1&(1<<10)) != (r2&(1<<10))) - printf(" IL=%d",(uint32)(!!(r2&(1<<10)))); - if((r1&(1<<11)) != (r2&(1<<11))) - printf(" IH=%d",(uint32)(!!(r2&(1<<11)))); - if((r1&(1<<12)) != (r2&(1<<12))) - printf(" B=%d",(uint32)(!!(r2&(1<<12)))); - if((r1&(1<<15)) != (r2&(1<<15))) - printf(" IRQ=%d",(uint32)(!!(r2&(1<<15)))); - } - { - /* Check PBR */ - uint32 r1 = ((uint32)avReg[0x34]); - uint32 r2 = (uint32)(SuperFX.pvRegisters[0x34]); - if(r1 != r2) - printf(" PBR=$%02x",r2); - } - { - /* Check ROMBR */ - uint32 r1 = ((uint32)avReg[0x36]); - uint32 r2 = (uint32)(SuperFX.pvRegisters[0x36]); - if(r1 != r2) - printf(" ROMBR=$%02x",r2); - } - { - /* Check RAMBR */ - uint32 r1 = ((uint32)avReg[0x3c]); - uint32 r2 = (uint32)(SuperFX.pvRegisters[0x3c]); - if(r1 != r2) - printf(" RAMBR=$%02x",r2); - } - { - /* Check CBR */ - uint32 r1 = ((uint32)avReg[0x3e]) | (((uint32)avReg[0x3f])<<8); - uint32 r2 = (uint32)(SuperFX.pvRegisters[0x3e]) | (((uint32)SuperFX.pvRegisters[0x3f])<<8); - if(r1 != r2) - printf(" CBR=$%04x",r2); - } - { - /* Check COLR */ - if(vColr != FxGetColorRegister()) - printf(" COLR=$%02x",FxGetColorRegister()); - } - { - /* Check POR */ - if(vPor != FxGetPlotOptionRegister()) - printf(" POR=$%02x",FxGetPlotOptionRegister()); - } - printf ("\n"); - } - S9xExit (); - } - else - { - uint32 t = (Memory.FillRAM [0x3034] << 16) + - (Memory.FillRAM [0x301f] << 8) + - (Memory.FillRAM [0x301e] << 0); - -printf ("%06x: %d\n", t, FxEmulate (2000000)); -// FxEmulate (2000000); - } + if (tmp == -1)//0x018428) //0x01bfc3) //0x09edaf) //-1) //0x57edaf) + { + while (Memory.FillRAM [0x3030] & 0x20) + { + int i; + int32 vError; + uint8 avReg[0x40]; + char tmp[128]; + uint8 vPipe; + uint8 vColr; + uint8 vPor; + + FxPipeString(tmp); + /* Make the string 32 chars long */ + if (strlen(tmp) < 32) + { + memset(&tmp[strlen(tmp)], ' ', 32 - strlen(tmp)); + tmp[32] = 0; + } + + /* Copy registers (so we can see if any changed) */ + vColr = FxGetColorRegister(); + vPor = FxGetPlotOptionRegister(); + memcpy(avReg, SuperFX.pvRegisters, 0x40); + + /* Print the pipe string */ + printf(tmp); + + /* Execute the instruction in the pipe */ + vPipe = FxPipe(); + vError = FxEmulate(1); + + /* Check if any registers changed (and print them if they did) */ + for (i = 0; i < 16; i++) + { + uint32 a = 0; + uint32 r1 = ((uint32)avReg[i * 2]) | (((uint32)avReg[(i * 2) + 1]) << 8); + uint32 r2 = (uint32)(SuperFX.pvRegisters[i * 2]) | (((uint32) + SuperFX.pvRegisters[(i * 2) + 1]) << 8); + if (i == 15) + a = OPCODE_BYTES(vPipe); + if (((r1 + a) & 0xffff) != r2) + printf(" r%d=$%04x", i, r2); + } + { + /* Check SFR */ + uint32 r1 = ((uint32)avReg[0x30]) | (((uint32)avReg[0x31]) << 8); + uint32 r2 = (uint32)(SuperFX.pvRegisters[0x30]) | (((uint32) + SuperFX.pvRegisters[0x31]) << 8); + if ((r1 & (1 << 1)) != (r2 & (1 << 1))) + printf(" Z=%d", (uint32)(!!(r2 & (1 << 1)))); + if ((r1 & (1 << 2)) != (r2 & (1 << 2))) + printf(" CY=%d", (uint32)(!!(r2 & (1 << 2)))); + if ((r1 & (1 << 3)) != (r2 & (1 << 3))) + printf(" S=%d", (uint32)(!!(r2 & (1 << 3)))); + if ((r1 & (1 << 4)) != (r2 & (1 << 4))) + printf(" OV=%d", (uint32)(!!(r2 & (1 << 4)))); + if ((r1 & (1 << 5)) != (r2 & (1 << 5))) + printf(" G=%d", (uint32)(!!(r2 & (1 << 5)))); + if ((r1 & (1 << 6)) != (r2 & (1 << 6))) + printf(" R=%d", (uint32)(!!(r2 & (1 << 6)))); + if ((r1 & (1 << 8)) != (r2 & (1 << 8))) + printf(" ALT1=%d", (uint32)(!!(r2 & (1 << 8)))); + if ((r1 & (1 << 9)) != (r2 & (1 << 9))) + printf(" ALT2=%d", (uint32)(!!(r2 & (1 << 9)))); + if ((r1 & (1 << 10)) != (r2 & (1 << 10))) + printf(" IL=%d", (uint32)(!!(r2 & (1 << 10)))); + if ((r1 & (1 << 11)) != (r2 & (1 << 11))) + printf(" IH=%d", (uint32)(!!(r2 & (1 << 11)))); + if ((r1 & (1 << 12)) != (r2 & (1 << 12))) + printf(" B=%d", (uint32)(!!(r2 & (1 << 12)))); + if ((r1 & (1 << 15)) != (r2 & (1 << 15))) + printf(" IRQ=%d", (uint32)(!!(r2 & (1 << 15)))); + } + { + /* Check PBR */ + uint32 r1 = ((uint32)avReg[0x34]); + uint32 r2 = (uint32)(SuperFX.pvRegisters[0x34]); + if (r1 != r2) + printf(" PBR=$%02x", r2); + } + { + /* Check ROMBR */ + uint32 r1 = ((uint32)avReg[0x36]); + uint32 r2 = (uint32)(SuperFX.pvRegisters[0x36]); + if (r1 != r2) + printf(" ROMBR=$%02x", r2); + } + { + /* Check RAMBR */ + uint32 r1 = ((uint32)avReg[0x3c]); + uint32 r2 = (uint32)(SuperFX.pvRegisters[0x3c]); + if (r1 != r2) + printf(" RAMBR=$%02x", r2); + } + { + /* Check CBR */ + uint32 r1 = ((uint32)avReg[0x3e]) | (((uint32)avReg[0x3f]) << 8); + uint32 r2 = (uint32)(SuperFX.pvRegisters[0x3e]) | (((uint32) + SuperFX.pvRegisters[0x3f]) << 8); + if (r1 != r2) + printf(" CBR=$%04x", r2); + } + { + /* Check COLR */ + if (vColr != FxGetColorRegister()) + printf(" COLR=$%02x", FxGetColorRegister()); + } + { + /* Check POR */ + if (vPor != FxGetPlotOptionRegister()) + printf(" POR=$%02x", FxGetPlotOptionRegister()); + } + printf("\n"); + } + S9xExit(); + } + else + { + uint32 t = (Memory.FillRAM [0x3034] << 16) + + (Memory.FillRAM [0x301f] << 8) + + (Memory.FillRAM [0x301e] << 0); + + printf("%06x: %d\n", t, FxEmulate(2000000)); + // FxEmulate (2000000); + } #if 0 - if (!(CPU.Flags & TRACE_FLAG)) - { - static int z = 1; - if (z == 0) - { - extern FILE *trace; - CPU.Flags |= TRACE_FLAG; - trace = fopen ("trace.log", "wb"); - } - else - z--; - } + if (!(CPU.Flags & TRACE_FLAG)) + { + static int z = 1; + if (z == 0) + { + extern FILE* trace; + CPU.Flags |= TRACE_FLAG; + trace = fopen("trace.log", "wb"); + } + else + z--; + } #endif - Memory.FillRAM [0x3030] &= ~0x20; - if (Memory.FillRAM [0x3031] & 0x80) - { - S9xSetIRQ (GSU_IRQ_SOURCE); - } + Memory.FillRAM [0x3030] &= ~0x20; + if (Memory.FillRAM [0x3031] & 0x80) + S9xSetIRQ(GSU_IRQ_SOURCE); #endif } #endif @@ -2880,258 +2977,258 @@ printf ("%06x: %d\n", t, FxEmulate (2000000)); uint8 REGISTER_4212() { - uint8 GetBank = 0; - if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && - CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE + 3) - GetBank = 1; + uint8 GetBank = 0; + 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; - if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) - GetBank |= 0x80; /* XXX: 0x80 or 0xc0 ? */ + GetBank |= CPU.Cycles >= Settings.HBlankStart ? 0x40 : 0; + if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) + GetBank |= 0x80; /* XXX: 0x80 or 0xc0 ? */ - return (GetBank); + return (GetBank); } -void FLUSH_REDRAW () +void FLUSH_REDRAW() { - if (IPPU.PreviousLine != IPPU.CurrentLine) - S9xUpdateScreen (); + if (IPPU.PreviousLine != IPPU.CurrentLine) + S9xUpdateScreen(); } -void REGISTER_2104 (uint8 byte) +void REGISTER_2104(uint8 byte) { - if (PPU.OAMAddr & 0x100) - { - int addr = ((PPU.OAMAddr & 0x10f) << 1) + (PPU.OAMFlip & 1); - if (byte != PPU.OAMData [addr]){ - FLUSH_REDRAW (); - PPU.OAMData [addr] = byte; - IPPU.OBJChanged = TRUE; - - // X position high bit, and sprite size (x4) - struct SOBJ *pObj = &PPU.OBJ [(addr & 0x1f) * 4]; - - pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 0) & 1]; - pObj++->Size = byte & 2; - pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 2) & 1]; - pObj++->Size = byte & 8; - pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 4) & 1]; - pObj++->Size = byte & 32; - pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 6) & 1]; - pObj->Size = byte & 128; - } - PPU.OAMFlip ^= 1; - if(!(PPU.OAMFlip & 1)){ - ++PPU.OAMAddr; - PPU.OAMAddr &= 0x1ff; - if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) - { - PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; - IPPU.OBJChanged = TRUE; - } - } else { - if (PPU.OAMPriorityRotation && (PPU.OAMAddr&1)) IPPU.OBJChanged = TRUE; - } - } else if(!(PPU.OAMFlip & 1)){ - PPU.OAMWriteRegister &= 0xff00; - PPU.OAMWriteRegister |= byte; - PPU.OAMFlip |= 1; - if (PPU.OAMPriorityRotation && (PPU.OAMAddr&1)) IPPU.OBJChanged = TRUE; - } else { - PPU.OAMWriteRegister &= 0x00ff; - uint8 lowbyte = (uint8)(PPU.OAMWriteRegister); - uint8 highbyte = byte; - PPU.OAMWriteRegister |= byte << 8; - - int addr = (PPU.OAMAddr << 1); - - if (lowbyte != PPU.OAMData [addr] || - highbyte != PPU.OAMData [addr+1]) - { - FLUSH_REDRAW (); - PPU.OAMData [addr] = lowbyte; - PPU.OAMData [addr+1] = highbyte; - IPPU.OBJChanged = TRUE; - if (addr & 2) - { - // Tile - PPU.OBJ[addr = PPU.OAMAddr >> 1].Name = PPU.OAMWriteRegister & 0x1ff; - - // priority, h and v flip. - PPU.OBJ[addr].Palette = (highbyte >> 1) & 7; - PPU.OBJ[addr].Priority = (highbyte >> 4) & 3; - PPU.OBJ[addr].HFlip = (highbyte >> 6) & 1; - PPU.OBJ[addr].VFlip = (highbyte >> 7) & 1; - } - else - { - // X position (low) - PPU.OBJ[addr = PPU.OAMAddr >> 1].HPos &= 0xFF00; - PPU.OBJ[addr].HPos |= lowbyte; - - // Sprite Y position - PPU.OBJ[addr].VPos = highbyte; - } - } - PPU.OAMFlip &= ~1; - ++PPU.OAMAddr; - if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) - { - PPU.FirstSprite = (PPU.OAMAddr&0xFE) >> 1; + if (PPU.OAMAddr & 0x100) + { + int addr = ((PPU.OAMAddr & 0x10f) << 1) + (PPU.OAMFlip & 1); + if (byte != PPU.OAMData [addr]) + { + FLUSH_REDRAW(); + PPU.OAMData [addr] = byte; + IPPU.OBJChanged = TRUE; + + // X position high bit, and sprite size (x4) + struct SOBJ* pObj = &PPU.OBJ [(addr & 0x1f) * 4]; + + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 0) & 1]; + pObj++->Size = byte & 2; + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 2) & 1]; + pObj++->Size = byte & 8; + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 4) & 1]; + pObj++->Size = byte & 32; + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 6) & 1]; + pObj->Size = byte & 128; + } + PPU.OAMFlip ^= 1; + if (!(PPU.OAMFlip & 1)) + { + ++PPU.OAMAddr; + PPU.OAMAddr &= 0x1ff; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xFE) >> 1; IPPU.OBJChanged = TRUE; - } - } + } + } + else + { + if (PPU.OAMPriorityRotation && (PPU.OAMAddr & 1)) IPPU.OBJChanged = TRUE; + } + } + else if (!(PPU.OAMFlip & 1)) + { + PPU.OAMWriteRegister &= 0xff00; + PPU.OAMWriteRegister |= byte; + PPU.OAMFlip |= 1; + if (PPU.OAMPriorityRotation && (PPU.OAMAddr & 1)) IPPU.OBJChanged = TRUE; + } + else + { + PPU.OAMWriteRegister &= 0x00ff; + uint8 lowbyte = (uint8)(PPU.OAMWriteRegister); + uint8 highbyte = byte; + PPU.OAMWriteRegister |= byte << 8; + + int addr = (PPU.OAMAddr << 1); + + if (lowbyte != PPU.OAMData [addr] || + highbyte != PPU.OAMData [addr + 1]) + { + FLUSH_REDRAW(); + PPU.OAMData [addr] = lowbyte; + PPU.OAMData [addr + 1] = highbyte; + IPPU.OBJChanged = TRUE; + if (addr & 2) + { + // Tile + PPU.OBJ[addr = PPU.OAMAddr >> 1].Name = PPU.OAMWriteRegister & 0x1ff; + + // priority, h and v flip. + PPU.OBJ[addr].Palette = (highbyte >> 1) & 7; + PPU.OBJ[addr].Priority = (highbyte >> 4) & 3; + PPU.OBJ[addr].HFlip = (highbyte >> 6) & 1; + PPU.OBJ[addr].VFlip = (highbyte >> 7) & 1; + } + else + { + // X position (low) + PPU.OBJ[addr = PPU.OAMAddr >> 1].HPos &= 0xFF00; + PPU.OBJ[addr].HPos |= lowbyte; + + // Sprite Y position + PPU.OBJ[addr].VPos = highbyte; + } + } + PPU.OAMFlip &= ~1; + ++PPU.OAMAddr; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xFE) >> 1; + IPPU.OBJChanged = TRUE; + } + } - Memory.FillRAM [0x2104] = byte; + Memory.FillRAM [0x2104] = byte; } -void REGISTER_2118 (uint8 Byte) +void REGISTER_2118(uint8 Byte) { - uint32 address; - if (PPU.VMA.FullGraphicCount) - { - uint32 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; - Memory.VRAM [address] = Byte; - } - else - { - Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xFFFF] = Byte; - } - IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; - IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE; - IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; - if (!PPU.VMA.High) - { - PPU.VMA.Address += PPU.VMA.Increment; - } -// Memory.FillRAM [0x2118] = Byte; + uint32 address; + if (PPU.VMA.FullGraphicCount) + { + uint32 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; + Memory.VRAM [address] = Byte; + } + else + Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xFFFF] = Byte; + IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; + if (!PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; + // Memory.FillRAM [0x2118] = Byte; } -void REGISTER_2118_tile (uint8 Byte) +void REGISTER_2118_tile(uint8 Byte) { - uint32 address; - uint32 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; - 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; - if (!PPU.VMA.High) - PPU.VMA.Address += PPU.VMA.Increment; -// Memory.FillRAM [0x2118] = Byte; + uint32 address; + uint32 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; + 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; + if (!PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; + // Memory.FillRAM [0x2118] = Byte; } -void REGISTER_2118_linear (uint8 Byte) +void REGISTER_2118_linear(uint8 Byte) { - uint32 address; - Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xFFFF] = Byte; - IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; - IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE; - IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; - if (!PPU.VMA.High) - PPU.VMA.Address += PPU.VMA.Increment; -// Memory.FillRAM [0x2118] = Byte; + uint32 address; + Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xFFFF] = Byte; + IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; + if (!PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; + // Memory.FillRAM [0x2118] = Byte; } -void REGISTER_2119 (uint8 Byte) +void REGISTER_2119(uint8 Byte) { - uint32 address; - if (PPU.VMA.FullGraphicCount) - { - uint32 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; - Memory.VRAM [address] = Byte; - } - else - { - Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xFFFF] = Byte; - } - IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; - IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE; - IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; - if (PPU.VMA.High) - { - PPU.VMA.Address += PPU.VMA.Increment; - } -// Memory.FillRAM [0x2119] = Byte; + uint32 address; + if (PPU.VMA.FullGraphicCount) + { + uint32 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; + Memory.VRAM [address] = Byte; + } + else + Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xFFFF] = Byte; + IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; + if (PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; + // Memory.FillRAM [0x2119] = Byte; } -void REGISTER_2119_tile (uint8 Byte) +void REGISTER_2119_tile(uint8 Byte) { - uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; - uint32 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; - IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; - if (PPU.VMA.High) - PPU.VMA.Address += PPU.VMA.Increment; -// Memory.FillRAM [0x2119] = Byte; + uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; + uint32 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; + IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; + if (PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; + // Memory.FillRAM [0x2119] = Byte; } -void REGISTER_2119_linear (uint8 Byte) +void REGISTER_2119_linear(uint8 Byte) { - uint32 address; - Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xFFFF] = Byte; - IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; - IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE; - IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; - if (PPU.VMA.High) - PPU.VMA.Address += PPU.VMA.Increment; -// Memory.FillRAM [0x2119] = Byte; + uint32 address; + Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xFFFF] = Byte; + IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached [TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached [TILE_8BIT][address >> 6] = FALSE; + if (PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; + // Memory.FillRAM [0x2119] = Byte; } void REGISTER_2122(uint8 Byte) { - // CG-RAM (palette) write - - if (PPU.CGFLIP) - { - if ((Byte & 0x7f) != (PPU.CGDATA[PPU.CGADD] >> 8)) - { - FLUSH_REDRAW (); - PPU.CGDATA[PPU.CGADD] &= 0x00FF; - PPU.CGDATA[PPU.CGADD] |= (Byte & 0x7f) << 8; - 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) BUILD_PIXEL (IPPU.Red [PPU.CGADD], - IPPU.Green [PPU.CGADD], - IPPU.Blue [PPU.CGADD]); - } - PPU.CGADD++; - } - else - { - if (Byte != (uint8) (PPU.CGDATA[PPU.CGADD] & 0xff)) - { - FLUSH_REDRAW (); - PPU.CGDATA[PPU.CGADD] &= 0x7F00; - PPU.CGDATA[PPU.CGADD] |= Byte; - IPPU.ColorsChanged = TRUE; - IPPU.Red [PPU.CGADD] = IPPU.XB [Byte & 0x1f]; - IPPU.Green [PPU.CGADD] = IPPU.XB [(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f]; - IPPU.ScreenColors [PPU.CGADD] = (uint16) BUILD_PIXEL (IPPU.Red [PPU.CGADD], - IPPU.Green [PPU.CGADD], - IPPU.Blue [PPU.CGADD]); - } - } - PPU.CGFLIP ^= 1; -// Memory.FillRAM [0x2122] = Byte; + // CG-RAM (palette) write + + if (PPU.CGFLIP) + { + if ((Byte & 0x7f) != (PPU.CGDATA[PPU.CGADD] >> 8)) + { + FLUSH_REDRAW(); + PPU.CGDATA[PPU.CGADD] &= 0x00FF; + PPU.CGDATA[PPU.CGADD] |= (Byte & 0x7f) << 8; + 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) BUILD_PIXEL(IPPU.Red [PPU.CGADD], + IPPU.Green [PPU.CGADD], + IPPU.Blue [PPU.CGADD]); + } + PPU.CGADD++; + } + else + { + if (Byte != (uint8)(PPU.CGDATA[PPU.CGADD] & 0xff)) + { + FLUSH_REDRAW(); + PPU.CGDATA[PPU.CGADD] &= 0x7F00; + PPU.CGDATA[PPU.CGADD] |= Byte; + IPPU.ColorsChanged = TRUE; + IPPU.Red [PPU.CGADD] = IPPU.XB [Byte & 0x1f]; + IPPU.Green [PPU.CGADD] = IPPU.XB [(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f]; + IPPU.ScreenColors [PPU.CGADD] = (uint16) BUILD_PIXEL(IPPU.Red [PPU.CGADD], + IPPU.Green [PPU.CGADD], + IPPU.Blue [PPU.CGADD]); + } + } + PPU.CGFLIP ^= 1; + // Memory.FillRAM [0x2122] = Byte; } void REGISTER_2180(uint8 Byte) { - Memory.RAM[PPU.WRAM++] = Byte; - PPU.WRAM &= 0x1FFFF; - Memory.FillRAM [0x2180] = Byte; + Memory.RAM[PPU.WRAM++] = Byte; + PPU.WRAM &= 0x1FFFF; + Memory.FillRAM [0x2180] = Byte; } -- cgit v1.2.3