@@ -36,14 +36,14 @@ impl fmt::Display for Registers {
3636 f,
3737 "PC:{:04X} A:{:02X} X:{:02X} Y:{:02X} P:{:02X} S:{:02X}\n N|V|-|B|D|I|Z|C\n {}|{}|{}|{}|{}|{}|{}|{}" ,
3838 self . pc, self . a, self . x, self . y, self . p, self . s,
39- if ( self . p & ( 1 << 7 ) ) != 0 { 1 } else { 0 } ,
40- if ( self . p & ( 1 << 6 ) ) != 0 { 1 } else { 0 } ,
41- if ( self . p & ( 1 << 5 ) ) != 0 { 1 } else { 0 } ,
42- if ( self . p & ( 1 << 4 ) ) != 0 { 1 } else { 0 } ,
43- if ( self . p & ( 1 << 3 ) ) != 0 { 1 } else { 0 } ,
44- if ( self . p & ( 1 << 2 ) ) != 0 { 1 } else { 0 } ,
45- if ( self . p & ( 1 << 1 ) ) != 0 { 1 } else { 0 } ,
46- if ( self . p & ( 1 << 0 ) ) != 0 { 1 } else { 0 } ,
39+ if ( self . p & ( 1 << 7 ) ) != 0 { 1 } else { 0 } ,
40+ if ( self . p & ( 1 << 6 ) ) != 0 { 1 } else { 0 } ,
41+ if ( self . p & ( 1 << 5 ) ) != 0 { 1 } else { 0 } ,
42+ if ( self . p & ( 1 << 4 ) ) != 0 { 1 } else { 0 } ,
43+ if ( self . p & ( 1 << 3 ) ) != 0 { 1 } else { 0 } ,
44+ if ( self . p & ( 1 << 2 ) ) != 0 { 1 } else { 0 } ,
45+ if ( self . p & ( 1 << 1 ) ) != 0 { 1 } else { 0 } ,
46+ if ( self . p & ( 1 << 0 ) ) != 0 { 1 } else { 0 } ,
4747 )
4848 }
4949}
@@ -137,7 +137,24 @@ enum Access {
137137 ReadModify ,
138138}
139139
140+ const NES_CPU_OPTIONS : CpuOptions = CpuOptions {
141+ ignore_decimal_bit : true ,
142+ } ;
143+
144+ pub struct CpuOptions {
145+ ignore_decimal_bit : bool ,
146+ }
147+
148+ impl Default for CpuOptions {
149+ fn default ( ) -> Self {
150+ Self {
151+ ignore_decimal_bit : false ,
152+ }
153+ }
154+ }
155+
140156pub struct Cpu {
157+ options : CpuOptions ,
141158 registers : Registers ,
142159 memory : MemoryMap ,
143160 clock_speed : u32 ,
@@ -341,9 +358,26 @@ impl Cpu {
341358
342359 let v = ( !( a ^ m) & ( a ^ result) & 0x80 ) != 0 ;
343360
344- self . registers . update_carry_bit ( sum > 0xFF ) ;
345- self . registers . update_overflow_bit ( v) ;
346- self . registers . update_a ( result) ;
361+ if !self . options . ignore_decimal_bit && self . registers . get_decimal_bit ( ) {
362+ let mut adj = 0u16 ;
363+ if ( ( a & 0x0F ) as u16 + ( m & 0x0F ) as u16 + c) > 9 {
364+ adj += 0x06 ;
365+ }
366+ if sum > 0x99 {
367+ adj += 0x60 ;
368+ }
369+ let bcd = result. wrapping_add ( adj as u8 ) ;
370+
371+ let carry = sum > 0x99 ;
372+
373+ self . registers . update_carry_bit ( carry) ;
374+ self . registers . update_overflow_bit ( v) ;
375+ self . registers . update_a ( bcd) ;
376+ } else {
377+ self . registers . update_carry_bit ( sum > 0xFF ) ;
378+ self . registers . update_overflow_bit ( v) ;
379+ self . registers . update_a ( result) ;
380+ }
347381 }
348382
349383 fn sbc ( & mut self , m : u8 ) {
@@ -1257,8 +1291,18 @@ impl Cpu {
12571291}
12581292
12591293impl Cpu {
1260- pub fn new ( memory : MemoryMap , clock_speed : u32 ) -> Self {
1294+ pub fn new ( options : CpuOptions , memory : MemoryMap , clock_speed : u32 ) -> Self {
1295+ Self {
1296+ options,
1297+ registers : Registers :: new ( memory. reset_vector ( ) ) ,
1298+ memory,
1299+ clock_speed,
1300+ }
1301+ }
1302+
1303+ pub fn with_nes_options ( memory : MemoryMap , clock_speed : u32 ) -> Self {
12611304 Self {
1305+ options : NES_CPU_OPTIONS ,
12621306 registers : Registers :: new ( memory. reset_vector ( ) ) ,
12631307 memory,
12641308 clock_speed,
@@ -1468,7 +1512,7 @@ impl Cpu {
14681512
14691513#[ cfg( test) ]
14701514mod test {
1471- use crate :: cpu:: Cpu ;
1515+ use crate :: cpu:: { Cpu , CpuOptions } ;
14721516 use crate :: memory_map:: MemoryMap ;
14731517 use crate :: nes_rom:: NesRom ;
14741518 use std:: fs:: File ;
@@ -1478,14 +1522,18 @@ mod test {
14781522 fn nestest ( ) {
14791523 let rom = NesRom :: read_from_file ( "./vendor/nestest/nestest.nes" ) . unwrap ( ) ;
14801524 let memory_map = MemoryMap :: new ( rom) ;
1481- let mut cpu = Cpu :: new ( memory_map, 1 << 16 ) ;
1525+ let mut cpu = Cpu :: with_nes_options ( memory_map, 1 << 16 ) ;
14821526 cpu. registers . pc = 0xC000 ;
14831527 cpu. registers . p = 0x24 ;
14841528 cpu. registers . s = 0xFD ;
14851529
14861530 let reference_log = File :: open ( "./vendor/nestest/nestest.log" ) . unwrap ( ) ;
14871531 let mut idx = 1 ;
14881532 for line in BufReader :: new ( reference_log) . lines ( ) . map ( |l| l. unwrap ( ) ) {
1533+ if idx == 5004 {
1534+ // first inofficial opcode (not currently supported)
1535+ break ;
1536+ }
14891537 let state = format ! (
14901538 "{:04X} A:{:02X} X:{:02X} Y:{:02X} P:{:02X} SP:{:02X}" ,
14911539 cpu. registers. pc,
0 commit comments