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

@ -1287,13 +1287,37 @@ impl Parser {
let span = self.current_span();
self.advance();
// Check for button.X
// Check for button.X (player 1 default)
if name == "button" && *self.peek() == TokenKind::Dot {
self.advance();
let (button, _) = self.expect_name()?;
return Ok(Expr::ButtonRead(None, button, span));
}
// Check for p1.button.X / p2.button.X
if (name == "p1" || name == "p2") && *self.peek() == TokenKind::Dot {
self.advance();
// Expect 'button'
if let TokenKind::Ident(kw) = self.peek().clone() {
if kw == "button" {
self.advance();
self.expect(&TokenKind::Dot)?;
let (button, _) = self.expect_name()?;
let player = if name == "p1" {
Some(Player::P1)
} else {
Some(Player::P2)
};
return Ok(Expr::ButtonRead(player, button, span));
}
}
return Err(Diagnostic::error(
ErrorCode::E0201,
"expected 'button' after 'p1.' or 'p2.'",
self.current_span(),
));
}
// Check for array index
if *self.peek() == TokenKind::LBracket {
self.advance();