aboutsummaryrefslogtreecommitdiff
path: root/lib/xixanta
diff options
context:
space:
mode:
authorMiquel Sabaté Solà <mikisabate@gmail.com>2024-10-21 11:59:47 +0200
committerMiquel Sabaté Solà <mikisabate@gmail.com>2024-12-12 07:48:30 +0100
commitef22c6f29db80fd6daf3f14e516ddf190b0a1783 (patch)
treebf71a604dcde2b06bcfdf36f83db3a5b00534efc /lib/xixanta
parent4e3bb4f9065f7ab7a407946b8fb85f31bdffc3d9 (diff)
downloadtools.nes-ef22c6f29db80fd6daf3f14e516ddf190b0a1783.tar.gz
tools.nes-ef22c6f29db80fd6daf3f14e516ddf190b0a1783.zip
Implement the hibyte/lobyte functions
Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
Diffstat (limited to 'lib/xixanta')
-rw-r--r--lib/xixanta/src/assembler.rs62
1 files changed, 60 insertions, 2 deletions
diff --git a/lib/xixanta/src/assembler.rs b/lib/xixanta/src/assembler.rs
index 46d3d94..aa0db19 100644
--- a/lib/xixanta/src/assembler.rs
+++ b/lib/xixanta/src/assembler.rs
@@ -584,8 +584,42 @@ impl Assembler {
}
fn evaluate_control(&mut self, node: &PNode) -> Result<Bundle, EvalError> {
- println!("NODE: {:#?}", node);
- Ok(Bundle::default())
+ let function = node.value.value.as_str();
+
+ match function {
+ ".hibyte" => self.evaluate_byte(node, true),
+ ".lobyte" => self.evaluate_byte(node, false),
+ _ => Err(EvalError {
+ line: node.value.line,
+ message: format!(
+ "cannot handle control statement '{}' in this context",
+ function
+ ),
+ }),
+ }
+ }
+
+ fn evaluate_byte(&mut self, node: &PNode, high: bool) -> Result<Bundle, EvalError> {
+ // The parser actually guarantees that the ".hibyte" and ".lobyte"
+ // functions have exactly one argument. Hence, if this is not the case,
+ // it's fine to let "unwrap" panic: it's a sign that's something is
+ // wrong elsewhere.
+ let arg = node.args.as_ref().unwrap().first().unwrap();
+
+ // Get the bundle from the argument
+ let mut bundle = self.evaluate_node(arg)?;
+
+ // The bundle we got is going to be shuffled if we wanted the high byte.
+ // After that, just zero out the rest (not mandatory but let's do it out
+ // of consistency) and set the size to just one byte.
+ if high {
+ bundle.bytes[0] = bundle.bytes[1];
+ }
+ bundle.bytes[1] = 0x00;
+ bundle.bytes[2] = 0x00;
+ bundle.size = 1;
+
+ Ok(bundle)
}
fn evaluate_variable(&mut self, id: &PString) -> Result<Bundle, EvalError> {
@@ -1290,6 +1324,30 @@ lda #Scope::Variable
// Control statements
// TODO: .byte, .word, variables in between (e.g. `.byte Variable::Value`, `lda #.hibyte(Variable)`)
+ #[test]
+ fn hi_lo_byte() {
+ let mut asm = Assembler::new(EMPTY.to_vec());
+ let res = asm
+ .assemble(
+ r#"
+Var = $2002
+lda #.lobyte(Var)
+lda #.hibyte(Var)
+"#
+ .as_bytes(),
+ )
+ .unwrap();
+
+ assert_eq!(res.len(), 2);
+ let instrs: Vec<[u8; 2]> = vec![[0xA9, 0x02], [0xA9, 0x20]];
+
+ for i in 0..2 {
+ assert_eq!(res[i].size, 2);
+ assert_eq!(res[i].bytes[0], instrs[i][0]);
+ assert_eq!(res[i].bytes[1], instrs[i][1]);
+ }
+ }
+
// Macros
#[test]