@@ -367,21 +367,35 @@ impl Bus {
367367 }
368368
369369 pub fn step ( & mut self , cycles : u32 ) {
370- self . step_div ( cycles) ;
371- self . step_timer ( cycles) ;
372- let _ = self . apu . step ( cycles) ;
373- self . step_ppu ( cycles) ;
370+ // In double-speed mode, CPU cycles are twice as fast, but subsystems
371+ // (PPU, APU, timers) run at normal speed. Scale cycles accordingly.
372+ let subsystem_cycles = if self . double_speed {
373+ cycles / 2
374+ } else {
375+ cycles
376+ } ;
377+
378+ self . step_div ( subsystem_cycles) ;
379+ self . step_timer ( subsystem_cycles) ;
380+ let _ = self . apu . step ( subsystem_cycles) ;
381+ self . step_ppu ( subsystem_cycles) ;
374382 self . step_hdma ( ) ;
375- self . step_dma ( cycles ) ;
376- self . mbc . tick ( cycles ) ;
383+ self . step_dma ( subsystem_cycles ) ;
384+ self . mbc . tick ( subsystem_cycles ) ;
377385 }
378386
379387 pub fn set_rtc_mode ( & mut self , mode : RtcMode ) {
380388 self . mbc . set_rtc_mode ( mode) ;
381389 }
382390
383391 pub fn apu_step ( & mut self , cycles : u32 ) {
384- let _ = self . apu . step ( cycles) ;
392+ // In double-speed mode, scale APU cycles appropriately
393+ let subsystem_cycles = if self . double_speed {
394+ cycles / 2
395+ } else {
396+ cycles
397+ } ;
398+ let _ = self . apu . step ( subsystem_cycles) ;
385399 }
386400
387401 pub fn apu_sample_rate_hz ( & self ) -> f64 {
@@ -1508,6 +1522,119 @@ mod tests {
15081522 assert ! ( !bus. speed_switch_pending( ) ) ;
15091523 }
15101524
1525+ #[ test]
1526+ fn bus_double_speed_scales_timer_correctly ( ) {
1527+ let mut rom = vec ! [ 0 ; ROM_BANK_SIZE ] ;
1528+ rom[ 0x0147 ] = 0x00 ;
1529+ rom[ 0x0143 ] = 0x80 ; // CGB supported
1530+ let cartridge = Cartridge :: from_bytes ( rom) . expect ( "cartridge" ) ;
1531+ let mut bus = Bus :: new ( cartridge) . expect ( "bus" ) ;
1532+
1533+ // Enable timer with fastest rate (16 cycles per increment in normal speed)
1534+ bus. write8 ( REG_TAC , 0x05 ) ; // Enable, 16-cycle period
1535+ bus. write8 ( REG_TIMA , 0x00 ) ;
1536+
1537+ // In normal speed, 16 cycles should increment TIMA once
1538+ bus. step ( 16 ) ;
1539+ assert_eq ! (
1540+ bus. read8( REG_TIMA ) ,
1541+ 1 ,
1542+ "Normal speed: 16 cycles = 1 increment"
1543+ ) ;
1544+
1545+ // Switch to double speed
1546+ bus. write8 ( REG_KEY1 , 0x01 ) ;
1547+ bus. perform_speed_switch ( ) ;
1548+ assert ! ( bus. is_double_speed( ) ) ;
1549+
1550+ bus. write8 ( REG_TIMA , 0x00 ) ;
1551+
1552+ // In double speed, CPU cycles are twice as fast, so we need 32 CPU cycles
1553+ // for the timer to see 16 timer cycles
1554+ bus. step ( 32 ) ;
1555+ assert_eq ! (
1556+ bus. read8( REG_TIMA ) ,
1557+ 1 ,
1558+ "Double speed: 32 CPU cycles = 16 timer cycles = 1 increment"
1559+ ) ;
1560+ }
1561+
1562+ #[ test]
1563+ fn bus_double_speed_scales_div_correctly ( ) {
1564+ let mut rom = vec ! [ 0 ; ROM_BANK_SIZE ] ;
1565+ rom[ 0x0147 ] = 0x00 ;
1566+ rom[ 0x0143 ] = 0x80 ; // CGB supported
1567+ let cartridge = Cartridge :: from_bytes ( rom) . expect ( "cartridge" ) ;
1568+ let mut bus = Bus :: new ( cartridge) . expect ( "bus" ) ;
1569+
1570+ // DIV increments every 256 cycles
1571+ bus. write8 ( REG_DIV , 0x00 ) ;
1572+ let initial_div = bus. read8 ( REG_DIV ) ;
1573+
1574+ // In normal speed, 256 cycles should increment DIV once
1575+ bus. step ( 256 ) ;
1576+ let after_normal = bus. read8 ( REG_DIV ) ;
1577+ assert_eq ! (
1578+ after_normal,
1579+ initial_div. wrapping_add( 1 ) ,
1580+ "Normal speed: 256 cycles = 1 DIV increment"
1581+ ) ;
1582+
1583+ // Switch to double speed
1584+ bus. write8 ( REG_KEY1 , 0x01 ) ;
1585+ bus. perform_speed_switch ( ) ;
1586+ assert ! ( bus. is_double_speed( ) ) ;
1587+
1588+ bus. write8 ( REG_DIV , 0x00 ) ;
1589+ let initial_div_double = bus. read8 ( REG_DIV ) ;
1590+
1591+ // In double speed, need 512 CPU cycles for DIV to see 256 timer cycles
1592+ bus. step ( 512 ) ;
1593+ let after_double = bus. read8 ( REG_DIV ) ;
1594+ assert_eq ! (
1595+ after_double,
1596+ initial_div_double. wrapping_add( 1 ) ,
1597+ "Double speed: 512 CPU cycles = 256 timer cycles = 1 DIV increment"
1598+ ) ;
1599+ }
1600+
1601+ #[ test]
1602+ fn bus_double_speed_ppu_timing ( ) {
1603+ let mut rom = vec ! [ 0 ; ROM_BANK_SIZE ] ;
1604+ rom[ 0x0147 ] = 0x00 ;
1605+ rom[ 0x0143 ] = 0x80 ; // CGB supported
1606+ let cartridge = Cartridge :: from_bytes ( rom) . expect ( "cartridge" ) ;
1607+ let mut bus = Bus :: new ( cartridge) . expect ( "bus" ) ;
1608+
1609+ // PPU line takes 456 cycles in normal mode
1610+ bus. write8 ( REG_LY , 0x00 ) ;
1611+ let initial_ly = bus. read8 ( REG_LY ) ;
1612+
1613+ // Step one full line worth of cycles
1614+ bus. step ( 456 ) ;
1615+ let after_normal = bus. read8 ( REG_LY ) ;
1616+ assert ! (
1617+ after_normal > initial_ly || after_normal == 0 ,
1618+ "Normal speed: LY should advance or wrap"
1619+ ) ;
1620+
1621+ // Switch to double speed
1622+ bus. write8 ( REG_KEY1 , 0x01 ) ;
1623+ bus. perform_speed_switch ( ) ;
1624+ assert ! ( bus. is_double_speed( ) ) ;
1625+
1626+ bus. write8 ( REG_LY , 0x00 ) ;
1627+ let initial_ly_double = bus. read8 ( REG_LY ) ;
1628+
1629+ // In double speed, need 912 CPU cycles for PPU to see 456 PPU cycles
1630+ bus. step ( 912 ) ;
1631+ let after_double = bus. read8 ( REG_LY ) ;
1632+ assert ! (
1633+ after_double > initial_ly_double || after_double == 0 ,
1634+ "Double speed: LY should advance with scaled cycles"
1635+ ) ;
1636+ }
1637+
15111638 #[ test]
15121639 fn bus_hdma_gdma_minimal ( ) {
15131640 let mut rom = vec ! [ 0 ; ROM_BANK_SIZE ] ;
0 commit comments