public byte ReadMemory(ushort addr, bool peek) { var maskedAddr = (ushort)(addr & 0x000F); byte coll = 0; int mask = 0; if (maskedAddr == 0x00) // CXM0P { coll = (byte)((((_player0.Missile.Collisions & CXP1) != 0) ? 0x80 : 0x00) | (((_player0.Missile.Collisions & CXP0) != 0) ? 0x40 : 0x00)); mask = 0x3f; } if (maskedAddr == 0x01) // CXM1P { coll = (byte)((((_player1.Missile.Collisions & CXP0) != 0) ? 0x80 : 0x00) | (((_player1.Missile.Collisions & CXP1) != 0) ? 0x40 : 0x00)); mask = 0x3f; } if (maskedAddr == 0x02) // CXP0FB { coll = (byte)((((_player0.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player0.Collisions & CXBL) != 0) ? 0x40 : 0x00)); mask = 0x3f; } if (maskedAddr == 0x03) // CXP1FB { coll = (byte)((((_player1.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player1.Collisions & CXBL) != 0) ? 0x40 : 0x00)); mask = 0x3f; } if (maskedAddr == 0x04) // CXM0FB { coll = (byte)((((_player0.Missile.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player0.Missile.Collisions & CXBL) != 0) ? 0x40 : 0x00)); mask = 0x3f; } if (maskedAddr == 0x05) // CXM1FB { coll = (byte)((((_player1.Missile.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player1.Missile.Collisions & CXBL) != 0) ? 0x40 : 0x00)); mask = 0x3f; } if (maskedAddr == 0x06) // CXBLPF { coll = (byte)(((_ball.Collisions & CXPF) != 0) ? 0x80 : 0x00); mask = 0x7f; } if (maskedAddr == 0x07) // CXPPMM { coll = (byte)((((_player0.Collisions & CXP1) != 0) ? 0x80 : 0x00) | (((_player0.Missile.Collisions & CXM1) != 0) ? 0x40 : 0x00)); mask = 0x3f; } // inputs 0-3 are measured by a charging capacitor, these inputs are used with the paddles and the keyboard // Changing the hard coded value will change the paddle position. The range seems to be roughly 0-56000 according to values from stella // 6105 roughly centers the paddle in Breakout if (maskedAddr == 0x08) // INPT0 { if (_core.ReadPot1(0) > 0 && _capCharging && _core.Cpu.TotalExecutedCycles - _capChargeStart >= _core.ReadPot1(0)) { coll = 0x80; } else { coll = 0x00; } mask = 0x7f; } if (maskedAddr == 0x09) // INPT1 { if (_core.ReadPot1(1) > 0 && _capCharging && _core.Cpu.TotalExecutedCycles - _capChargeStart >= _core.ReadPot1(1)) { coll = 0x80; } else { coll = 0x00; } mask = 0x7f; } if (maskedAddr == 0x0A) // INPT2 { if (_core.ReadPot2(0) > 0 && _capCharging && _core.Cpu.TotalExecutedCycles - _capChargeStart >= _core.ReadPot2(0)) { coll = 0x80; } else { coll = 0x00; } mask = 0x7f; } if (maskedAddr == 0x0B) // INPT3 { if (_core.ReadPot2(1) > 0 && _capCharging && _core.Cpu.TotalExecutedCycles - _capChargeStart >= _core.ReadPot2(1)) { coll = 0x80; } else { coll = 0x00; } mask = 0x7f; } if (maskedAddr == 0x0C) // INPT4 { coll = (byte)((_core.ReadControls1(peek) & 0x08) != 0 ? 0x80 : 0x00); mask = 0x7f; } if (maskedAddr == 0x0D) // INPT5 { coll = (byte)((_core.ReadControls2(peek) & 0x08) != 0 ? 0x80 : 0x00); mask = 0x7f; } // some bits of the databus will be undriven when a read call is made. Our goal here is to sort out what // happens to the undriven pins. Most of the time, they will be in whatever state they were when previously // assigned in some other bus access, so let's go with that. coll += (byte)(mask & BusState); if (!peek) { BusState = coll; } return(coll); }
public byte ReadMemory(ushort addr, bool peek) { var maskedAddr = (ushort)(addr & 0x000F); if (maskedAddr == 0x00) // CXM0P { return((byte)((((_player0.Missile.Collisions & CXP1) != 0) ? 0x80 : 0x00) | (((_player0.Missile.Collisions & CXP0) != 0) ? 0x40 : 0x00))); } if (maskedAddr == 0x01) // CXM1P { return((byte)((((_player1.Missile.Collisions & CXP0) != 0) ? 0x80 : 0x00) | (((_player1.Missile.Collisions & CXP1) != 0) ? 0x40 : 0x00))); } if (maskedAddr == 0x02) // CXP0FB { return((byte)((((_player0.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player0.Collisions & CXBL) != 0) ? 0x40 : 0x00))); } if (maskedAddr == 0x03) // CXP1FB { return((byte)((((_player1.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player1.Collisions & CXBL) != 0) ? 0x40 : 0x00))); } if (maskedAddr == 0x04) // CXM0FB { return((byte)((((_player0.Missile.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player0.Missile.Collisions & CXBL) != 0) ? 0x40 : 0x00))); } if (maskedAddr == 0x05) // CXM1FB { return((byte)((((_player1.Missile.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player1.Missile.Collisions & CXBL) != 0) ? 0x40 : 0x00))); } if (maskedAddr == 0x06) // CXBLPF { return((byte)(((_ball.Collisions & CXPF) != 0) ? 0x80 : 0x00)); } if (maskedAddr == 0x07) // CXPPMM { return((byte)((((_player0.Collisions & CXP1) != 0) ? 0x80 : 0x00) | (((_player0.Missile.Collisions & CXM1) != 0) ? 0x40 : 0x00))); } if (maskedAddr == 0x08) // INPT0 { // Changing the hard coded value will change the paddle position. The range seems to be roughly 0-56000 according to values from stella // 6105 roughly centers the paddle in Breakout if (_capCharging && _core.Cpu.TotalExecutedCycles - _capChargeStart >= 6105) { return(0x80); } return(0x00); } if (maskedAddr == 0x0C) // INPT4 { return((byte)((_core.ReadControls1(peek) & 0x08) != 0 ? 0x80 : 0x00)); } if (maskedAddr == 0x0D) // INPT5 { return((byte)((_core.ReadControls2(peek) & 0x08) != 0 ? 0x80 : 0x00)); } return(0x00); }