1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-08 17:06:04 +00:00

Add Player 2 controller support

Parser:
- p1.button.X and p2.button.X syntax
- Emits Expr::ButtonRead with Some(Player::P1) or Some(Player::P2)
- Plain button.X still works (defaults to P1)
- Removed #[allow(dead_code)] from Player::P1 and Player::P2

Runtime:
- NMI handler now reads both $4016 (JOY1) and $4017 (JOY2) in
  the same loop, shifting 8 bits into ZP_INPUT_P1 ($01) and
  ZP_INPUT_P2 ($08) simultaneously
- JOY2 register constant added

Codegen:
- Button reads select correct ZP address based on Player variant
- gen_condition and gen_expr both handle P1/P2 dispatching

Tests: 245 (3 new parser tests: p1/p2 button read + shift-assign)

https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
This commit is contained in:
Claude 2026-04-12 10:05:12 +00:00
parent 6430c3a935
commit 18e9bed258
No known key found for this signature in database
5 changed files with 100 additions and 8 deletions

View file

@ -16,6 +16,7 @@ const APU_FRAME: u16 = 0x4017;
/// Zero-page locations used by the runtime.
pub const ZP_FRAME_FLAG: u8 = 0x00;
pub const ZP_INPUT_P1: u8 = 0x01;
pub const ZP_INPUT_P2: u8 = 0x08;
/// Generate the NES hardware initialization sequence.
/// This runs at RESET and sets up the hardware before user code.
@ -110,12 +111,17 @@ pub fn gen_nmi() -> Vec<Instruction> {
out.push(Instruction::new(LDA, AM::Immediate(0x00)));
out.push(Instruction::new(STA, AM::Absolute(JOY1)));
// Read 8 button bits into ZP_INPUT_P1
// Read 8 button bits from controller 1 ($4016) into ZP_INPUT_P1
// and 8 button bits from controller 2 ($4017) into ZP_INPUT_P2
// simultaneously — shift each port's carry into its ZP byte.
out.push(Instruction::new(LDX, AM::Immediate(0x08)));
out.push(Instruction::new(NOP, AM::Label("__read_input".into())));
out.push(Instruction::new(LDA, AM::Absolute(JOY1)));
out.push(Instruction::new(LSR, AM::Accumulator));
out.push(Instruction::new(ROL, AM::ZeroPage(ZP_INPUT_P1)));
out.push(Instruction::new(LDA, AM::Absolute(0x4017))); // JOY2
out.push(Instruction::new(LSR, AM::Accumulator));
out.push(Instruction::new(ROL, AM::ZeroPage(ZP_INPUT_P2)));
out.push(Instruction::implied(DEX));
out.push(Instruction::new(
BNE,