Skip to main content

amx_sys/
utils.rs

1//! Utility functions for AMX operations
2
3use crate::registers::AmxState;
4
5/// Convert a u64 offset to X/Y register and element offset
6pub fn offset_to_register_and_position(offset: u64, register_size: usize) -> (usize, usize) {
7    let reg = (offset / (register_size as u64)) as usize;
8    let pos = (offset % (register_size as u64)) as usize;
9    (reg, pos)
10}
11
12/// Get a slice from X circular buffer at given offset
13pub fn get_x_slice(state: &AmxState, offset: usize, size: usize) -> Vec<u8> {
14    let mut result = Vec::new();
15    let total_size = 512;  // 8 registers * 64 bytes
16    
17    for i in 0..size {
18        let pos = (offset + i) % total_size;
19        let reg_idx = pos / 64;
20        let byte_idx = pos % 64;
21        
22        if reg_idx < 8 {
23            result.push(unsafe { state.x[reg_idx].u8[byte_idx] });
24        }
25    }
26    
27    result
28}
29
30/// Get a slice from Y circular buffer at given offset
31pub fn get_y_slice(state: &AmxState, offset: usize, size: usize) -> Vec<u8> {
32    let mut result = Vec::new();
33    let total_size = 512;  // 8 registers * 64 bytes
34    
35    for i in 0..size {
36        let pos = (offset + i) % total_size;
37        let reg_idx = pos / 64;
38        let byte_idx = pos % 64;
39        
40        if reg_idx < 8 {
41            result.push(unsafe { state.y[reg_idx].u8[byte_idx] });
42        }
43    }
44    
45    result
46}
47
48/// Set a slice in X circular buffer at given offset
49pub fn set_x_slice(state: &mut AmxState, offset: usize, data: &[u8]) {
50    let total_size = 512;
51    
52    for (i, &byte) in data.iter().enumerate() {
53        let pos = (offset + i) % total_size;
54        let reg_idx = pos / 64;
55        let byte_idx = pos % 64;
56        
57        if reg_idx < 8 {
58            unsafe {
59                state.x[reg_idx].u8[byte_idx] = byte;
60            }
61        }
62    }
63}
64
65/// Set a slice in Y circular buffer at given offset
66pub fn set_y_slice(state: &mut AmxState, offset: usize, data: &[u8]) {
67    let total_size = 512;
68    
69    for (i, &byte) in data.iter().enumerate() {
70        let pos = (offset + i) % total_size;
71        let reg_idx = pos / 64;
72        let byte_idx = pos % 64;
73        
74        if reg_idx < 8 {
75            unsafe {
76                state.y[reg_idx].u8[byte_idx] = byte;
77            }
78        }
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn test_offset_calculation() {
88        assert_eq!(offset_to_register_and_position(0, 64), (0, 0));
89        assert_eq!(offset_to_register_and_position(64, 64), (1, 0));
90        assert_eq!(offset_to_register_and_position(100, 64), (1, 36));
91    }
92
93    #[test]
94    fn test_x_slice_circular() {
95        let mut state = AmxState::new();
96        
97        let mut data = [0u8; 64];
98        for i in 0..64 {
99            data[i] = (i % 256) as u8;
100        }
101        crate::instructions::ldx(&mut state, 0, &data);
102        
103        let slice = get_x_slice(&state, 0, 64);
104        assert_eq!(slice.len(), 64);
105        for i in 0..64 {
106            assert_eq!(slice[i], (i % 256) as u8);
107        }
108    }
109
110    #[test]
111    fn test_y_slice_circular() {
112        let mut state = AmxState::new();
113        
114        let mut data = [0u8; 64];
115        for i in 0..64 {
116            data[i] = ((i * 2) % 256) as u8;
117        }
118        crate::instructions::ldy(&mut state, 0, &data);
119        
120        let slice = get_y_slice(&state, 0, 64);
121        assert_eq!(slice.len(), 64);
122        for i in 0..64 {
123            assert_eq!(slice[i], ((i * 2) % 256) as u8);
124        }
125    }
126}