public override void AtVsyncNMI() { if (Patch_Vectors) { NES.cpu.NMI = true; } //strobe pad NES.WriteMemory(0x4016, 1); NES.WriteMemory(0x4016, 0); //read pad and create rising edge button signals so we dont trigger events as quickly as we hold the button down int currButtons = 0; for (int i = 0; i < 8; i++) { currButtons <<= 1; currButtons |= (NES.ReadMemory(0x4016) & 1); } int justDown = (~ButtonState) & currButtons; Bit a = (justDown >> 7) & 1; Bit b = (justDown >> 6) & 1; Bit sel = (justDown >> 5) & 1; Bit start = (justDown >> 4) & 1; Bit up = (justDown >> 3) & 1; Bit down = (justDown >> 2) & 1; Bit left = (justDown >> 1) & 1; Bit right = (justDown >> 0) & 1; ButtonState = currButtons; //RIGHT: next song //LEFT: prev song //A: restart song bool reset = false; if (right) { CurrentSong++; reset = true; } if (left) { CurrentSong--; reset = true; } if (a) { reset = true; } if (reset) { ReplayInit(); } }
public override byte ReadReg2xxx(int addr) { if (addr < 0x3800) { return(base.ReadReg2xxx(addr)); } else if (addr >= 0x3FF0) { switch (addr) { case 0x3FF0: { byte ret = 0; if (InitPending) { ret = 1; } InitPending = false; return(ret); } case 0x3FF1: { //kevtris's reset process seems not to work. dunno what all is going on in there //our own innovation, should work OK.. NES.apu.NESSoftReset(); //mostly fceux's guidance NES.WriteMemory(0x4015, 0); for (int i = 0; i < 14; i++) { NES.WriteMemory((ushort)(0x4000 + i), 0); } NES.WriteMemory(0x4015, 0x0F); //clearing APU misc stuff, maybe not needed with soft reset above //NES.WriteMemory(0x4017, 0xC0); //NES.WriteMemory(0x4017, 0xC0); //NES.WriteMemory(0x4017, 0x40); //important to NSF standard for ram to be cleared, otherwise replayers are confused on account of not initializing memory themselves var ram = NES.ram; var wram = this.WRAM; int wram_size = wram.Length; for (int i = 0; i < 0x800; i++) { ram[i] = 0; } for (int i = 0; i < wram_size; i++) { wram[i] = 0; } //store specified initial bank state if (BankSwitched) { for (int i = 0; i < 8; i++) { WriteEXP(0x5FF8 + i - 0x4000, InitBankSwitches[i]); } } return((byte)(CurrentSong - 1)); } case 0x3FF2: return(0); //always return NTSC for now case 0x3FF3: Patch_Vectors = false; return(0); case 0x3FF4: Patch_Vectors = true; return(0); default: return(base.ReadReg2xxx(addr)); } } else if (addr - 0x3800 < NSFROM.Length) { return(NSFROM[addr - 0x3800]); } else { return(base.ReadReg2xxx(addr)); } }
public override void AtVsyncNmi() { if (Patch_Vectors) { NES.cpu.NMI = true; } //strobe pad NES.WriteMemory(0x4016, 1); NES.WriteMemory(0x4016, 0); //read pad and create rising edge button signals so we don't trigger events as quickly as we hold the button down int currButtons = 0; for (int i = 0; i < 8; i++) { currButtons <<= 1; currButtons |= (NES.ReadMemory(0x4016) & 1); } int justDown = (~ButtonState) & currButtons; Bit a = (justDown >> 7) & 1; Bit b = (justDown >> 6) & 1; Bit sel = (justDown >> 5) & 1; Bit start = (justDown >> 4) & 1; Bit up = (justDown >> 3) & 1; Bit down = (justDown >> 2) & 1; Bit left = (justDown >> 1) & 1; Bit right = (justDown >> 0) & 1; ButtonState = currButtons; //RIGHT: next song //LEFT: prev song //A: restart song //RTC_Hijack :: control NSF from System Bus 0x00CE ushort songChangeAdress = 0x00CE; //RTC_Hijack byte songValue = NES.ReadMemory(songChangeAdress); //RTC_Hijack bool reset = false; if (right || (songValue == 0xFB)) //RTC_Hijack { NES.WriteMemory(songChangeAdress, 0xFF); //RTC_Hijack if (CurrentSong < nsf.TotalSongs - 1) { CurrentSong++; reset = true; } } if (left || (songValue == 0xFA)) //RTC_Hijack { NES.WriteMemory(songChangeAdress, 0xFF); //RTC_Hijack if (CurrentSong > 0) { CurrentSong--; reset = true; } } if (a) { reset = true; } if (reset) { ReplayInit(); } }
public void WriteMemory(ushort address, byte value) => _nes.WriteMemory(address, value);