@@ -12,18 +12,21 @@ use rand::rngs::ThreadRng;
12
12
/// specifies the ID of the VF register which is often used for flags
13
13
const FLAG_REG_ID : u8 = 0xF ;
14
14
15
- /// specifies the address where the font data is stored in memory
15
+ /// specifies the address where the fonts data is stored in memory
16
16
const FONT_START_ADDRESS : u16 = 0x050 ;
17
17
18
18
/// specifies the address where the program is stored in memory
19
19
pub const PROGRAM_START_ADDRESS : u16 = 0x200 ;
20
20
21
21
const INSTRUCTION_EXEC_DURATION : Duration = Duration :: from_nanos ( 1_428_571 ) ; // 1_428_571
22
22
23
+ const FONT_DATA_SIZE : usize = 80 ; // 5 rows per char * 16 chars
24
+
23
25
#[ derive( Debug ) ]
24
26
pub enum Chip8Error {
25
27
InstructionNotImplemented ( String ) ,
26
-
28
+ MemoryOverflow ( String ) ,
29
+ InvalidFontData ( String ) ,
27
30
}
28
31
29
32
pub struct Chip8 {
@@ -470,7 +473,7 @@ impl Chip8 {
470
473
self . exec_time += frame_duration;
471
474
472
475
// run instructions
473
- while self . exec_time >= INSTRUCTION_EXEC_DURATION {
476
+ while self . exec_time >= INSTRUCTION_EXEC_DURATION && ! self . reached_end_of_file {
474
477
self . exec_next_instruction ( ) ?;
475
478
self . exec_time -= INSTRUCTION_EXEC_DURATION ;
476
479
}
@@ -497,9 +500,9 @@ impl Chip8 {
497
500
}
498
501
}
499
502
500
- pub fn load_bytes_into_memory ( & mut self , bytes : & Vec < u8 > , address : u16 ) {
501
- for ( idx , byte) in bytes . iter ( ) . enumerate ( ) {
502
- self . memory [ ( address as usize ) + idx ] = * byte;
503
+ pub fn load_bytes_into_memory ( & mut self , data : & Vec < u8 > , address : u16 ) {
504
+ for ( offset , byte) in data . iter ( ) . enumerate ( ) {
505
+ self . memory [ ( address as usize ) + offset ] = * byte;
503
506
}
504
507
}
505
508
@@ -518,16 +521,24 @@ impl Chip8 {
518
521
}
519
522
}
520
523
521
- pub fn load_font_into_memory ( & mut self , font_data : [ [ u8 ; 5 ] ; 16 ] ) {
522
- let mut address: u16 = FONT_START_ADDRESS ;
523
- for character in font_data {
524
- for byte in character {
525
- self . memory [ address as usize ] = byte;
526
- address += 1 ;
527
- }
524
+ pub fn load_program ( & mut self , program_data : & Vec < u8 > ) -> Result < ( ) , Chip8Error > {
525
+ if program_data. len ( ) > ( self . memory . len ( ) - ( PROGRAM_START_ADDRESS as usize ) ) {
526
+ return Err ( Chip8Error :: MemoryOverflow ( String :: from ( "the program does not fit into its predefined memory space" ) ) ) ;
527
+ }
528
+
529
+ self . load_bytes_into_memory ( program_data, PROGRAM_START_ADDRESS ) ;
530
+
531
+ return Ok ( ( ) ) ;
532
+ }
533
+
534
+ pub fn load_font ( & mut self , font_data : & Vec < u8 > ) -> Result < ( ) , Chip8Error > {
535
+ if font_data. len ( ) != FONT_DATA_SIZE {
536
+ return Err ( Chip8Error :: InvalidFontData ( String :: from ( "the fonts data does not fit into its predefined memory space" ) ) ) ;
528
537
}
529
538
530
- assert_eq ! ( address, 0xA0 ) ;
539
+ self . load_bytes_into_memory ( font_data, FONT_START_ADDRESS ) ;
540
+
541
+ return Ok ( ( ) ) ;
531
542
}
532
543
533
544
pub fn load_register ( & mut self , reg_id : u8 , value : u8 ) {
@@ -1072,7 +1083,7 @@ mod tests {
1072
1083
run_emulator ( & mut chip8) ;
1073
1084
1074
1085
// verify result
1075
- assert_eq ! ( chip8. index_reg, FONT_START_ADDRESS + ( 15 * 5 ) , "failed to correctly set the index register to the font location; index_reg: 0x{:04x}; character: 0x{:02x}" , chip8. index_reg, val_1) ;
1086
+ assert_eq ! ( chip8. index_reg, FONT_START_ADDRESS + ( 15 * 5 ) , "failed to correctly set the index register to the fonts location; index_reg: 0x{:04x}; character: 0x{:02x}" , chip8. index_reg, val_1) ;
1076
1087
}
1077
1088
1078
1089
#[ test]
0 commit comments