maikor_platform/
mem.rs

1pub mod sizes {
2    use crate::constants::{LAYER_COUNT, PALETTE_COUNT, SPRITE_COUNT};
3    use crate::input::controller_type;
4
5    pub const CODE_BANK: u16 = 4200;
6    pub const RAM_BANK: u16 = 4200;
7    pub const MAIN_CODE: u16 = 9000;
8    pub const MAIN_RAM: u16 = 9000;
9    pub const SOUND: u16 = 30;
10    pub const WAVE_TABLE: u16 = 16;
11    //Byte 0 is direction, byte 1 is action
12    pub const INPUT: u16 = 2;
13    pub const CODE_BANK_ID: u16 = 1;
14    pub const RAM_BANK_ID: u16 = 1;
15    pub const SAVE_BANK_ID: u16 = 1;
16    pub const SAVE_BANK: u16 = 4096;
17    pub const SAVE_CONTROL: u16 = 1;
18    pub const SPRITE: u16 = 5;
19    //255 sprites, each taking 5 bytes
20    //(8b X, 8b Y, 8b tile id, 1b flipV, 1b flipH, 2b palette, 1b src size, 2b order, 1b half alpha, 1b rotated, 1b enabled, 2b atlas, 3b ?)
21    pub const SPRITE_TABLE: u16 = SPRITE_COUNT as u16 * SPRITE;
22    //4 layers, each header is made of 3 bytes (8b X, 8b Y, 1b visible, 2b atlas)
23    pub const LAYERS_HEADER: u16 = 3 * LAYER_COUNT as u16;
24    //4 layers, each made of 1320 (44x30) tiles, each made of 2 bytes (8b tile id, 1b flipV, 1b flipH, 2b palette, 1b half alpha, 1b rotated, 2b ?)
25    pub const LAYERS_CONTENT: u16 = 1320 * 2 * LAYER_COUNT as u16;
26    //4 palettes, each made of 16 colors, each color is 3 bytes
27    pub const PALETTE: u16 = 16 * 3; //0,0,0 is transparent
28    pub const PALETTES_TOTAL: u16 = PALETTE * PALETTE_COUNT as u16;
29    //25x10 (tiles) 200x160 (pixels) 100x160 (bytes) atlas of palette index (two colour IDs per byte)
30    pub const ATLAS: u16 = 100 * 40;
31    pub const ATLAS_BANK_ID: u16 = 1;
32    pub const STACK: u16 = 1000;
33    pub const SP: u16 = 2;
34    pub const FP: u16 = 2;
35    pub const TIMER_CONTROL: u16 = 2;
36    pub const TIMER_VALUE: u16 = 1;
37    pub const TIMERS: u16 = TIMER_CONTROL + TIMER_VALUE * 4;
38    pub const VLINE: u16 = 1;
39    pub const IRQ_RET_ADDR: u16 = 2;
40    pub const IRQ_REG_DUMP: u16 = 8;
41    pub const IRQ_CONTROL: u16 = 1;
42    pub const IRQ_INTERNAL: u16 = IRQ_RET_ADDR + IRQ_REG_DUMP + IRQ_CONTROL;
43    //year (0=2000), month (1 = jan), day, hour (24), min, sec
44    pub const DATETIME: u16 = 6;
45    pub const RAND: u16 = 1;
46    //0,0,0 is transparent
47    pub const CONTROLLER_PALETTE: u16 = 3 * 8;
48    //8 sprites, each taking 3 bytes
49    //(bits) 8 x, 8 y, 1 enabled, 4 id, 3 ?
50    pub const CONTROLLER_TABLE: u16 = 3 * controller_type::COUNT as u16;
51    pub const CONTROLLER_TOTAL: u16 = CONTROLLER_PALETTE + CONTROLLER_TABLE;
52    pub const ATLAS_TOTAL: u16 = (ATLAS + ATLAS_BANK_ID) * 4;
53    pub const LAYER_TOTAL: u16 = LAYERS_CONTENT + LAYERS_HEADER;
54    pub const GRAPHICS_TOTAL: u16 =
55        LAYER_TOTAL + SPRITE_TABLE + PALETTES_TOTAL + ATLAS_TOTAL + CONTROLLER_TOTAL;
56    pub const SYSTEM_TOTAL: u16 = MAIN_CODE
57        + MAIN_RAM
58        + CODE_BANK
59        + CODE_BANK
60        + RAM_BANK
61        + RAM_BANK
62        + CODE_BANK_ID
63        + CODE_BANK_ID
64        + RAM_BANK_ID
65        + RAM_BANK_ID
66        + STACK
67        + SP
68        + FP
69        + TIMERS
70        + IRQ_INTERNAL
71        + VLINE;
72    pub const HARDWARE_TOTAL: u16 =
73        WAVE_TABLE + SOUND + INPUT + SAVE_BANK_ID + SAVE_BANK + SAVE_CONTROL + DATETIME + RAND;
74    pub const RESERVED: u16 = 106;
75    pub const TOTAL: usize =
76        (GRAPHICS_TOTAL + SYSTEM_TOTAL + HARDWARE_TOTAL) as usize + RESERVED as usize;
77}
78
79#[rustfmt::skip]
80pub mod address {
81    pub const CODE: u16 = 0x0; //0
82    pub const CODE_BANK_1: u16 = 0x2328; //9000
83    pub const CODE_BANK_2: u16 = 0x3390; //13200
84    pub const RAM: u16 = 0x43F8; //17400
85    pub const RAM_BANK_1: u16 = 0x6720; //26400
86    pub const RAM_BANK_2: u16 = 0x7788; //30600
87    pub const INPUT: u16 = 0x87F0; //34800
88    pub const SOUND: u16 = 0x87F2; //34802
89    pub const SAVE_BANK_ID: u16 = 0x8810; //34832
90    pub const SAVE_BANK: u16 = 0x8811; //34833
91    pub const ATLAS1: u16 = 0x9811; //38929
92    pub const ATLAS2: u16 = 0xA7B1; //42929
93    pub const ATLAS3: u16 = 0xB751; //46929
94    pub const ATLAS4: u16 = 0xC6F1; //50929
95    pub const PALETTES: u16 = 0xD691; //54929
96    pub const SPRITE_TABLE: u16 = 0xD751; //55121
97    pub const LAYER_HEADERS: u16 = 0xDC4C; //56396
98    pub const LAYERS: u16 = 0xDC55; //56405
99    pub const CODE_BANK_1_ID: u16 = 0xFB45; //64325
100    pub const RAM_BANK_1_ID: u16 = 0xFB46; //64326
101    pub const ATLAS1_BANK_ID: u16 = 0xFB47; //64327
102    pub const ATLAS2_BANK_ID: u16 = 0xFB48; //64328
103    pub const ATLAS3_BANK_ID: u16 = 0xFB49; //64329
104    pub const ATLAS4_BANK_ID: u16 = 0xFB4A; //64330
105    pub const SP: u16 = 0xFB4B; //64331
106    pub const FP: u16 = 0xFB4D; //64333
107    pub const TIMER_CONTROL: u16 = 0xFB4F; //64335
108    pub const TIMER_VALUE1: u16 = 0xFB51; //64337
109    pub const TIMER_VALUE2: u16 = 0xFB52; //64338
110    pub const TIMER_VALUE3: u16 = 0xFB53; //64339
111    pub const TIMER_VALUE4: u16 = 0xFB54; //64340
112    pub const IRQ_RET_ADDR: u16 = 0xFB55; //64341
113    pub const IRQ_REG_DUMP: u16 = 0xFB57; //64343
114    pub const CONTROLLER_PALETTE: u16 = 0xFB5F; //64351
115    pub const CONTROLLER_TABLE: u16 = 0xFB77; //64375
116    pub const IRQ_CONTROL: u16 = 0xFB92; //64402
117    pub const SAVE_CONTROL: u16 = 0xFB93; //64403
118    pub const DATETIME: u16 = 0xFB94; //64404
119    pub const RAND: u16 = 0xFB9A; //64410
120    pub const WAVE_TABLE: u16 = 0xFB9B; //64411
121    pub const CODE_BANK_2_ID: u16 = 0xFBAB; //64427
122    pub const RAM_BANK_2_ID: u16 = 0xFBAC; //64428
123    pub const VLINE: u16 = 0xFBAD; //64429
124    pub const RESERVED: u16 = 0xFBAE; //64430
125    pub const STACK: u16 = 0xFC18; //64536
126    pub const MAX: u16 = 0xFFFF; //65535
127
128    pub mod interrupt {
129        pub const IRQ_INPUT: u16 = 0x0200; //512
130        pub const IRQ_SCREEN_DRAW: u16 = 0x0220; //544
131        pub const IRQ_TIMER: u16 = 0x0240; //576
132        pub const IRQ_CONTROLLER: u16 = 0x0260; //608
133        pub const IRQ_DATETIME: u16 = 0x0280; //640
134        pub const IRQ_LINE_DRAW: u16 = 0x02A0; //672
135    }
136
137    /// Changing values at 'special' addresses can take many more cycles than normal
138    pub const fn is_special_memory(address: u16) -> bool {
139        matches!(
140            address,
141            CODE_BANK_1_ID
142                | RAM_BANK_1_ID
143            |CODE_BANK_2_ID
144                | RAM_BANK_2_ID
145                | ATLAS1_BANK_ID
146                | ATLAS2_BANK_ID
147                | ATLAS3_BANK_ID
148                | ATLAS4_BANK_ID
149                | TIMER_CONTROL
150                | SAVE_CONTROL
151                | SAVE_BANK_ID
152                | SOUND
153        )
154    }
155}
156
157pub mod save_flags {
158    pub const AUTO_SAVE: u8 = 4;
159    pub const WRITE: u8 = 0;
160}
161
162pub mod interrupt_flags {
163    pub const IRQ_SCREEN_DRAW: u8 = 1;
164    pub const IRQ_TIMER: u8 = 2;
165    pub const IRQ_DATETIME: u8 = 4;
166    pub const IRQ_CONTROLLER: u8 = 8;
167    pub const IRQ_INPUT: u8 = 16;
168    pub const IRQ_LINE_DRAW: u8 = 32;
169}
170
171#[cfg(test)]
172mod test {
173    use crate::mem::sizes::{RESERVED, TOTAL};
174    use crate::mem::{address, sizes};
175
176    #[test]
177    #[allow(clippy::assertions_on_constants)] //these are used as safe guards against changes
178    fn test_values() {
179        assert_eq!(TOTAL, 65536);
180        //the system needs at least 6 bytes available for internal use
181        //currently this is just VM::execute_op()
182        assert!(RESERVED > 6);
183    }
184
185    #[test]
186    fn test_sizes_address() {
187        assert_eq!(address::CODE, 0);
188        assert_eq!(address::CODE_BANK_1, address::CODE + sizes::MAIN_CODE);
189        assert_eq!(
190            address::CODE_BANK_2,
191            address::CODE_BANK_1 + sizes::CODE_BANK
192        );
193        assert_eq!(address::RAM, address::CODE_BANK_2 + sizes::CODE_BANK);
194        assert_eq!(address::RAM_BANK_1, address::RAM + sizes::MAIN_RAM);
195        assert_eq!(address::RAM_BANK_2, address::RAM_BANK_1 + sizes::RAM_BANK);
196        assert_eq!(address::INPUT, address::RAM_BANK_2 + sizes::RAM_BANK);
197        assert_eq!(address::SOUND, address::INPUT + sizes::INPUT);
198        assert_eq!(address::SAVE_BANK_ID, address::SOUND + sizes::SOUND);
199        assert_eq!(
200            address::SAVE_BANK,
201            address::SAVE_BANK_ID + sizes::SAVE_BANK_ID
202        );
203        assert_eq!(address::ATLAS1, address::SAVE_BANK + sizes::SAVE_BANK);
204        assert_eq!(address::ATLAS2, address::ATLAS1 + sizes::ATLAS);
205        assert_eq!(address::ATLAS3, address::ATLAS2 + sizes::ATLAS);
206        assert_eq!(address::ATLAS4, address::ATLAS3 + sizes::ATLAS);
207        assert_eq!(address::PALETTES, address::ATLAS4 + sizes::ATLAS);
208        assert_eq!(
209            address::SPRITE_TABLE,
210            address::PALETTES + sizes::PALETTES_TOTAL
211        );
212        assert_eq!(
213            address::LAYER_HEADERS,
214            address::SPRITE_TABLE + sizes::SPRITE_TABLE
215        );
216        assert_eq!(
217            address::LAYERS,
218            address::LAYER_HEADERS + sizes::LAYERS_HEADER
219        );
220        assert_eq!(
221            address::CODE_BANK_1_ID,
222            address::LAYERS + sizes::LAYERS_CONTENT
223        );
224        assert_eq!(
225            address::RAM_BANK_1_ID,
226            address::CODE_BANK_1_ID + sizes::CODE_BANK_ID
227        );
228        assert_eq!(
229            address::ATLAS1_BANK_ID,
230            address::RAM_BANK_1_ID + sizes::RAM_BANK_ID
231        );
232        assert_eq!(
233            address::ATLAS2_BANK_ID,
234            address::ATLAS1_BANK_ID + sizes::ATLAS_BANK_ID
235        );
236        assert_eq!(
237            address::ATLAS3_BANK_ID,
238            address::ATLAS2_BANK_ID + sizes::ATLAS_BANK_ID
239        );
240        assert_eq!(
241            address::ATLAS4_BANK_ID,
242            address::ATLAS3_BANK_ID + sizes::ATLAS_BANK_ID
243        );
244        assert_eq!(address::SP, address::ATLAS4_BANK_ID + sizes::ATLAS_BANK_ID);
245        assert_eq!(address::FP, address::SP + sizes::SP);
246        assert_eq!(address::TIMER_CONTROL, address::FP + sizes::FP);
247        assert_eq!(
248            address::TIMER_VALUE1,
249            address::TIMER_CONTROL + sizes::TIMER_CONTROL
250        );
251        assert_eq!(
252            address::TIMER_VALUE2,
253            address::TIMER_VALUE1 + sizes::TIMER_VALUE
254        );
255        assert_eq!(
256            address::TIMER_VALUE3,
257            address::TIMER_VALUE2 + sizes::TIMER_VALUE
258        );
259        assert_eq!(
260            address::TIMER_VALUE4,
261            address::TIMER_VALUE3 + sizes::TIMER_VALUE
262        );
263        assert_eq!(
264            address::IRQ_RET_ADDR,
265            address::TIMER_VALUE4 + sizes::TIMER_VALUE
266        );
267        assert_eq!(
268            address::IRQ_REG_DUMP,
269            address::IRQ_RET_ADDR + sizes::IRQ_RET_ADDR
270        );
271        assert_eq!(
272            address::CONTROLLER_PALETTE,
273            address::IRQ_REG_DUMP + sizes::IRQ_REG_DUMP
274        );
275        assert_eq!(
276            address::CONTROLLER_TABLE,
277            address::CONTROLLER_PALETTE + sizes::CONTROLLER_PALETTE
278        );
279        assert_eq!(
280            address::IRQ_CONTROL,
281            address::CONTROLLER_TABLE + sizes::CONTROLLER_TABLE
282        );
283        assert_eq!(
284            address::SAVE_CONTROL,
285            address::IRQ_CONTROL + sizes::IRQ_CONTROL
286        );
287        assert_eq!(
288            address::DATETIME,
289            address::SAVE_CONTROL + sizes::SAVE_CONTROL
290        );
291        assert_eq!(address::RAND, address::DATETIME + sizes::DATETIME);
292        assert_eq!(address::WAVE_TABLE, address::RAND + sizes::RAND);
293        assert_eq!(
294            address::CODE_BANK_2_ID,
295            address::WAVE_TABLE + sizes::WAVE_TABLE
296        );
297        assert_eq!(
298            address::RAM_BANK_2_ID,
299            address::CODE_BANK_2_ID + sizes::CODE_BANK_ID
300        );
301        assert_eq!(address::VLINE, address::RAM_BANK_2_ID + sizes::RAM_BANK_ID);
302        assert_eq!(address::RESERVED, address::VLINE + sizes::VLINE);
303        assert_eq!(address::STACK, address::RESERVED + RESERVED);
304        assert_eq!(65536, address::STACK as usize + sizes::STACK as usize);
305        assert_eq!(address::MAX, 0xFFFF);
306    }
307}