📄 ppu.cpp
字号:
#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 (SNESGameFixes.umiharakawaseFix)// byte &= ~0x20; } 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 (!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; 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 = ONE_CYCLE;#ifdef DEBUGGER missing.fast_rom = 1;#endif } else CPU.FastROMSpeed = SLOW_ONE_CYCLE; Memory.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) 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: 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 fprintf(stderr, "Write %02x to %04x!\n", byte, Address); 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:#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;// 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -