📄 ppu.cpp
字号:
PPU.OAMAddr = 0; } PPU.OAMReadFlip ^= 1;#ifdef DEBUGGER missing.oam_read = 1;#endif return (byte); case 0x2139: // Read vram low byte#ifdef DEBUGGER missing.vram_read = 1;#endif if (IPPU.FirstVRAMRead) byte = Memory.VRAM[PPU.VMA.Address << 1]; 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; } break; case 0x213A: // Read vram high byte#ifdef DEBUGGER missing.vram_read = 1;#endif 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; } break; case 0x213B: // Read palette data#ifdef DEBUGGER missing.cgram_read = 1;#endif if (PPU.CGFLIPRead) byte = PPU.CGDATA [PPU.CGADD++] >> 8; else byte = PPU.CGDATA [PPU.CGADD] & 0xff; PPU.CGFLIPRead ^= 1; return (byte); case 0x213C: // Horizontal counter value 0-339#ifdef DEBUGGER missing.h_counter_read = 1;#endif if (PPU.HBeamFlip) byte = PPU.HBeamPosLatched >> 8; else byte = (uint8)PPU.HBeamPosLatched; PPU.HBeamFlip ^= 1; break; case 0x213D: // Vertical counter value 0-262#ifdef DEBUGGER missing.v_counter_read = 1;#endif if (PPU.VBeamFlip) byte = PPU.VBeamPosLatched >> 8; else byte = (uint8)PPU.VBeamPosLatched; PPU.VBeamFlip ^= 1; break; case 0x213E: // PPU time and range over flags return (0); case 0x213F: // NTSC/PAL and which field flags PPU.VBeamFlip = PPU.HBeamFlip = 0; return ((Settings.PAL ? 0x10 : 0) | (Memory.FillRAM[0x213f] & 0xc0)); 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]);#else // CPU.Flags |= DEBUG_MODE_FLAG;#ifdef SPC700_SHUTDOWN IAPU.APUExecuting = Settings.APUEnabled; IAPU.WaitCounter++;#endif if (Settings.APUEnabled) {#ifdef CPU_SHUTDOWN// CPU.WaitAddress = CPU.PCAtOpcodeStart;#endif return (APU.OutPorts [Address & 3]); } switch (Settings.SoundSkipMethod) { case 0: case 1: CPU.BranchSkip = TRUE; break; case 2: break; case 3: CPU.BranchSkip = TRUE; 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#ifdef DEBUGGER missing.wram_read = 1;#endif byte = Memory.RAM [PPU.WRAM++]; PPU.WRAM &= 0x1FFFF; break; case 0x2181: case 0x2182: case 0x2183: return (Memory.FillRAM [Address]); case 0x2190: return (1); } } else { if (Settings.SA1) return (S9xGetSA1 (Address)); if (Address <= 0x2fff || Address >= 0x3000 + 768) { switch (Address) { case 0x21c2: return (0x20); case 0x21c3: return (0); case 0x2800: // For Dai Kaijyu Monogatari II if (Settings.SRTC) return (S9xGetSRTC (Address)); /*FALL*/ default:#ifdef DEBUGGER missing.unknownppu_read = Address; if (Settings.TraceUnknownRegisters) { sprintf (String, "Unknown register read: $%04X\n", Address); S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); }#endif // XXX: return (0); //Memory.FillRAM[Address]); } } if (!Settings.SuperFX) return (0x30);#ifdef ZSNES_FX 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);#else byte = Memory.FillRAM [Address];//if (Address != 0x3030 && Address != 0x3031)//printf ("%04x\n", Address);#ifdef CPU_SHUTDOWN 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);#endif } return (byte);}/**********************************************************************************************//* S9xSetCPU() *//* This function sets a CPU/DMA Register to a specific byte *//**********************************************************************************************/void S9xSetCPU (uint8 byte, uint16 Address){ int d; if (Address < 0x4200) {#ifdef VAR_CYCLES CPU.Cycles += ONE_CYCLE;#endif 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:#ifdef DEBUGGER missing.unknowncpu_write = Address; if (Settings.TraceUnknownRegisters) { sprintf (String, "Unknown register register write: $%02X->$%04X\n", byte, Address); S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); }#endif break; } } else switch (Address) { case 0x4200: // NMI, V & H IRQ and joypad reading enable flags if (byte & 0x20) { if (!PPU.VTimerEnabled) {#ifdef DEBUGGER missing.virq = 1; missing.virq_pos = PPU.IRQVBeamPos;#endif 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 (byte & 0x10) { if (!PPU.HTimerEnabled) {#ifdef DEBUGGER missing.hirq = 1; missing.hirq_pos = PPU.IRQHBeamPos;#endif 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 (CPU.IRQCycleCount == 0) 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 + 15 && !CPU.NMIActive) { CPU.Flags |= NMI_FLAG; CPU.NMIActive = TRUE; CPU.NMICycleCount = CPU.NMITriggerPoint; } break; case 0x4201: // I/O port output case 0x4202: // Multiplier (for multply) break; case 0x4203: { // Multiplicand uint32 res = Memory.FillRAM[0x4202] * byte; Memory.FillRAM[0x4216] = (uint8) res; Memory.FillRAM[0x4217] = (uint8) (res >> 8); break; } case 0x4204: case 0x4205: // Low and high muliplier (for divide) break; case 0x4206: { // Divisor uint16 a = Memory.FillRAM[0x4204] + (Memory.FillRAM[0x4205] << 8); uint16 div = byte ? a / byte : 0xffff; uint16 rem = byte ? a % byte : a; Memory.FillRAM[0x4214] = (uint8)div; Memory.FillRAM[0x4215] = div >> 8; Memory.FillRAM[0x4216] = (uint8)rem; Memory.FillRAM[0x4217] = rem >> 8; 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;#ifdef DEBUGGER missing.virq_pos = PPU.IRQVBeamPos;#endif 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);#ifdef DEBUGGER missing.virq_pos = PPU.IRQVBeamPos;#endif 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:#ifdef DEBUGGER missing.dma_this_frame = byte; missing.dma_channels = byte;#endif 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:#ifdef DEBUGGER missing.hdma_this_frame |= byte; missing.hdma_channels |= byte; #endif 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 = 6;#ifdef DEBUGGER missing.fast_rom = 1;#endif } else CPU.FastROMSpeed = 8; Memory.FixROMSpeed (); } /* FALL */ case 0x420e: case 0x420f: // --->>> Unknown break; case 0x4210: // NMI ocurred flag (reset on read or write) Memory.FillRAM[0x4210] = 0; 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) case 0x4213: // I/O Port (read-only) case 0x4214: case 0x4215: // Quotent of divide (read-only) case 0x4216: case 0x4217: // Multiply product (read-only) return; case 0x4218: case 0x4219: case 0x421a: case 0x421b: case 0x421c: case 0x421d:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -