📄 ppu.cpp
字号:
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; 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; 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; break; case 0x4307: case 0x4317: case 0x4327: case 0x4337: case 0x4347: case 0x4357: case 0x4367: case 0x4377: DMA[d = ((Address >> 4) & 0x7)].IndirectBank = byte; 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; 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; 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 0x4800: case 0x4801: case 0x4802: case 0x4803: break; case 0x4804: case 0x4805: case 0x4806: case 0x4807: S9xSetSDD1MemoryMap (Address - 0x4804, byte & 7); break; default:#ifdef DEBUGGER missing.unknowncpu_write = Address; if (Settings.TraceUnknownRegisters) { sprintf (String, "Unknown register write: $%02X->$%04X\n", byte, Address); S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); }#endif break; } Memory.FillRAM [Address] = byte;}/**********************************************************************************************//* S9xGetCPU() *//* This function retrieves a CPU/DMA Register *//**********************************************************************************************/uint8 S9xGetCPU (uint16 Address){ uint8 byte; if (Address < 0x4200) {#ifdef VAR_CYCLES CPU.Cycles += ONE_CYCLE;#endif switch (Address) { // Secret of the Evermore case 0x4000: case 0x4001: return (0x40); 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); } } return ((IPPU.Joypads[ind] >> (PPU.Joypad2ButtonReadPos++ ^ 15)) & 1); } default:#ifdef DEBUGGER missing.unknowncpu_read = Address; if (Settings.TraceUnknownRegisters) { sprintf (String, "Unknown register read: $%04X\n", Address); S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); }#endif break; } return (Memory.FillRAM [Address]); } else switch (Address) { // BS Dynami Tracer! needs to be able to check if NMIs are enabled // already, otherwise the game locks up. case 0x4200: // NMI, h & v timers and joypad reading enable case 0x4201: // I/O port (output - write only?) case 0x4202: case 0x4203: // Multiplier and multiplicand (write) case 0x4204: case 0x4205: case 0x4206: // Divisor and dividend (write) return (Memory.FillRAM[Address]); case 0x4207: return (uint8)(PPU.IRQHBeamPos); case 0x4208: return (PPU.IRQHBeamPos >> 8); case 0x4209: return (uint8)(PPU.IRQVBeamPos); case 0x420a: return (PPU.IRQVBeamPos >> 8); case 0x420b: // General purpose DMA enable // Super Formation Soccer 95 della Serie A UCC Xaqua requires this // register should not always return zero. // .. But Aero 2 waits until this register goes zero.. // Just keep toggling the value for now in the hope that it breaks // the game out of its wait loop... Memory.FillRAM [0x420b] = !Memory.FillRAM [0x420b]; return (Memory.FillRAM [0x420b]); case 0x420c: // H-DMA enable return (IPPU.HDMA); case 0x420d: // Cycle speed 0 - 2.68Mhz, 1 - 3.58Mhz (banks 0x80 +) return (Memory.FillRAM[Address]); case 0x420e: case 0x420f: // --->>> Unknown return (Memory.FillRAM[Address]); case 0x4210:#ifdef CPU_SHUTDOWN CPU.WaitAddress = CPU.PCAtOpcodeStart;#endif byte = Memory.FillRAM[0x4210]; Memory.FillRAM[0x4210] = 0; return (byte); 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); return (byte);// case 0x4200: case 0x4212: // V-blank, h-blank and joypads being read flags (read-only)#ifdef CPU_SHUTDOWN CPU.WaitAddress = CPU.PCAtOpcodeStart;#endif return (REGISTER_4212()); case 0x4213: // I/O port input case 0x4214: case 0x4215: // Quotient of divide result case 0x4216: case 0x4217: // Multiplcation result (for multiply) or remainder of // divison. return (Memory.FillRAM[Address]); case 0x4218: case 0x4219: case 0x421a: case 0x421b: case 0x421c: case 0x421d: case 0x421e: case 0x421f: // Joypads 1-4 button and direction state. return (Memory.FillRAM [Address]); case 0x4300: case 0x4310: case 0x4320: case 0x4330: case 0x4340: case 0x4350: case 0x4360: case 0x4370: // DMA direction, address type, fixed flag, return (Memory.FillRAM[Address]); case 0x4301: case 0x4311: case 0x4321: case 0x4331: case 0x4341: case 0x4351: case 0x4361: case 0x4371: return (Memory.FillRAM[Address]); case 0x4302: case 0x4312: case 0x4322: case 0x4332: case 0x4342: case 0x4352: case 0x4362: case 0x4372: return (Memory.FillRAM[Address]); case 0x4303: case 0x4313: case 0x4323: case 0x4333: case 0x4343: case 0x4353: case 0x4363: case 0x4373: return (Memory.FillRAM[Address]); case 0x4304: case 0x4314: case 0x4324: case 0x4334: case 0x4344: case 0x4354: case 0x4364: case 0x4374: return (Memory.FillRAM[Address]); case 0x4305: case 0x4315: case 0x4325: case 0x4335: case 0x4345: case 0x4355: case 0x4365: case 0x4375: return (Memory.FillRAM[Address]); case 0x4306: case 0x4316: case 0x4326: case 0x4336: case 0x4346: case 0x4356: case 0x4366: case 0x4376: 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 0x4308: case 0x4318: case 0x4328: case 0x4338: case 0x4348: case 0x4358: case 0x4368: case 0x4378: return (Memory.FillRAM[Address]); case 0x4309: case 0x4319: case 0x4329: case 0x4339: case 0x4349: case 0x4359: case 0x4369: case 0x4379: return (Memory.FillRAM[Address]); 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]); } default:#ifdef DEBUGGER missing.unknowncpu_read = Address; if (Settings.TraceUnknownRegisters) { sprintf (String, "Unknown register read: $%04X\n", Address); S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); } #endif break; } return (Memory.FillRAM[Address]);}void S9xResetPPU (){ 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; for (uint8 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -