public void WriteMemory(ushort addr, byte value, bool poke) { var maskedAddr = (ushort)(addr & 0x3f); if (!poke) { BusState = value; } if (maskedAddr == 0x00) // VSYNC { if ((value & 0x02) != 0) { // Frame is complete, output to buffer _vsyncEnabled = true; } else if (_vsyncEnabled) { // When VSYNC is disabled, this will be the first line of the new frame // write to frame buffer OutputFrame(_currentScanLine); New_Frame = true; // Clear all from last frame _currentScanLine = 0; // Frame is done _vsyncEnabled = false; // Do not reset hsync, since we're on the first line of the new frame // hsyncCnt = 0; } } else if (maskedAddr == 0x01) // VBLANK { _vblankDelay = 1; _vblankValue = value; _capCharging = (value & 0x80) == 0; if ((value & 0x80) == 0) { _capChargeStart = _core.Cpu.TotalExecutedCycles; } } else if (maskedAddr == 0x02) // WSYNC { // Halt the CPU until we reach hblank _core.Cpu.RDY = false; } else if (maskedAddr == 0x04) // NUSIZ0 { _nusiz0Delay = 1; _nusiz0Val = value; } else if (maskedAddr == 0x05) // NUSIZ1 { _nusiz1Delay = 1; _nusiz1Val = value; } else if (maskedAddr == 0x06) // COLUP0 { _player0.Color = (byte)(value & 0xFE); } else if (maskedAddr == 0x07) // COLUP1 { _player1.Color = (byte)(value & 0xFE); } else if (maskedAddr == 0x08) // COLUPF { _playField.PfColor = (byte)(value & 0xFE); } else if (maskedAddr == 0x09) // COLUBK { _playField.BkColor = (byte)(value & 0xFE); } else if (maskedAddr == 0x0A) // CTRLPF { _playField.Reflect = (value & 0x01) != 0; _playField.Score = (value & 0x02) != 0; _playField.Priority = (value & 0x04) != 0; _ball.Size = (byte)((value & 0x30) >> 4); } else if (maskedAddr == 0x0B) // REFP0 { _player0.Reflect = (value & 0x08) != 0; } else if (maskedAddr == 0x0C) // REFP1 { _player1.Reflect = (value & 0x08) != 0; } else if (maskedAddr == 0x0D) // PF0 { _pf0Update = value; _pf0Updater = true; _pf0DelayClock = 0; if (((_hsyncCnt / 3) & 3) == 0) { _pf0MaxDelay = 4; } if (((_hsyncCnt / 3) & 3) == 1) { _pf0MaxDelay = 5; } if (((_hsyncCnt / 3) & 3) == 2) { _pf0MaxDelay = 2; } if (((_hsyncCnt / 3) & 3) == 3) { _pf0MaxDelay = 3; } } else if (maskedAddr == 0x0E) // PF1 { _pf1Update = value; _pf1Updater = true; _pf1DelayClock = 0; if (((_hsyncCnt / 3) & 3) == 0) { _pf1MaxDelay = 4; } if (((_hsyncCnt / 3) & 3) == 1) { _pf1MaxDelay = 5; } if (((_hsyncCnt / 3) & 3) == 2) { _pf1MaxDelay = 2; } if (((_hsyncCnt / 3) & 3) == 3) { _pf1MaxDelay = 3; } } else if (maskedAddr == 0x0F) // PF2 { _pf2Update = value; _pf2Updater = true; _pf2DelayClock = 0; if (((_hsyncCnt / 3) & 3) == 0) { _pf2MaxDelay = 4; } if (((_hsyncCnt / 3) & 3) == 1) { _pf2MaxDelay = 5; } if (((_hsyncCnt / 3) & 3) == 2) { _pf2MaxDelay = 2; } if (((_hsyncCnt / 3) & 3) == 3) { _pf2MaxDelay = 3; } } else if (maskedAddr == 0x10) // RESP0 { // RESP delays draw signal clocking _player0.Resp_check(); // Resp depends on HMOVE if (!_hmove.LateHBlankReset) { _player0.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4); if (_hsyncCnt == 67) { _player0.HPosCnt = 160 - 3; } } else { _player0.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 2 : 160 - 4); if (_hsyncCnt == 75) { _player0.HPosCnt = 160 - 3; } } } else if (maskedAddr == 0x11) // RESP1 { // RESP delays draw signal clocking _player1.Resp_check(); // RESP depends on HMOVE if (!_hmove.LateHBlankReset) { _player1.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4); if (_hsyncCnt == 67) { _player1.HPosCnt = 160 - 3; } } else { _player1.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 2 : 160 - 4); if (_hsyncCnt == 75) { _player1.HPosCnt = 160 - 3; } } } else if (maskedAddr == 0x12) // RESM0 { // RESP delays draw signal clocking _player0.Missile.Resp_check(); if (!_hmove.LateHBlankReset) { _player0.Missile.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4); if (_hsyncCnt == 67) { _player0.Missile.HPosCnt = 160 - 3; } } else { _player0.Missile.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 2 : 160 - 4); if (_hsyncCnt == 75) { _player0.Missile.HPosCnt = 160 - 3; } } } else if (maskedAddr == 0x13) // RESM1 { // RESP delays draw signal clocking _player1.Missile.Resp_check(); if (!_hmove.LateHBlankReset) { _player1.Missile.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4); if (_hsyncCnt == 67) { _player1.Missile.HPosCnt = 160 - 3; } } else { _player1.Missile.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 2 : 160 - 4); if (_hsyncCnt == 75) { _player1.Missile.HPosCnt = 160 - 3; } } } else if (maskedAddr == 0x14) // RESBL { _ball.Resp_check(); if (!_hmove.LateHBlankReset) { _ball.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4); if (_hsyncCnt == 67) { _ball.HPosCnt = 160 - 3; } } else { _ball.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 2 : 160 - 4); if (_hsyncCnt == 75) { _ball.HPosCnt = 160 - 3; } } } else if (maskedAddr == 0x15) // AUDC0 { AUD.AUDC_L = (byte)(value & 15); } else if (maskedAddr == 0x16) // AUDC1 { AUD.AUDC_R = (byte)(value & 15); } else if (maskedAddr == 0x17) // AUDF0 { AUD.AUDF_L = (byte)((value & 31) + 1); } else if (maskedAddr == 0x18) // AUDF1 { AUD.AUDF_R = (byte)((value & 31) + 1); } else if (maskedAddr == 0x19) // AUDV0 { AUD.AUDV_L = (byte)(value & 15); } else if (maskedAddr == 0x1A) // AUDV1 { AUD.AUDV_R = (byte)(value & 15); } else if (maskedAddr == 0x1B) // GRP0 { _prg0Val = value; _prg0Delay = 1; } else if (maskedAddr == 0x1C) // GRP1 { _prg1Val = value; _prg1Delay = 1; } else if (maskedAddr == 0x1D) // ENAM0 { _enam0Val = (value & 0x02) != 0; _enam0Delay = 1; } else if (maskedAddr == 0x1E) // ENAM1 { _enam1Val = (value & 0x02) != 0; _enam1Delay = 1; } else if (maskedAddr == 0x1F) // ENABL { _enambVal = (value & 0x02) != 0; _enambDelay = 1; } else if (maskedAddr == 0x20) // HMP0 { _hmp0Val = (byte)((value & 0xF0) >> 4); _hmp0Delay = 1; } else if (maskedAddr == 0x21) // HMP1 { _hmp1Val = (byte)((value & 0xF0) >> 4); _hmp1Delay = 1; } else if (maskedAddr == 0x22) // HMM0 { _hmm0Val = (byte)((value & 0xF0) >> 4); _hmm0Delay = 1; } else if (maskedAddr == 0x23) // HMM1 { _hmm1Val = (byte)((value & 0xF0) >> 4); _hmm1Delay = 1; } else if (maskedAddr == 0x24) // HMBL { _hmbVal = (byte)((value & 0xF0) >> 4); _hmbDelay = 1; } else if (maskedAddr == 0x25) // VDELP0 { _player0.Delay = (value & 0x01) != 0; } else if (maskedAddr == 0x26) // VDELP1 { _player1.Delay = (value & 0x01) != 0; } else if (maskedAddr == 0x27) // VDELBL { _ball.Delay = (value & 0x01) != 0; } else if (maskedAddr == 0x28) // RESMP0 { _player0.Missile.ResetToPlayer = (value & 0x02) != 0; } else if (maskedAddr == 0x29) // RESMP1 { _player1.Missile.ResetToPlayer = (value & 0x02) != 0; } else if (maskedAddr == 0x2A) // HMOVE { _hmove.HMoveEnabled = true; hmove_cnt_up = true; _hmove.HMoveDelayCnt = 0; } else if (maskedAddr == 0x2B) // HMCLR { _hmClrDelay = 1; } else if (maskedAddr == 0x2C) // CXCLR { _player0.Collisions = 0; _player0.Missile.Collisions = 0; _player1.Collisions = 0; _player1.Missile.Collisions = 0; _ball.Collisions = 0; } }