trunk/src/emu/cpu/lr35902/lr35902.h
| r30997 | r30998 | |
| 6 | 6 | |
| 7 | 7 | #define MCFG_LR35902_TIMER_CB(_devcb) \ |
| 8 | 8 | lr35902_cpu_device::set_timer_cb(*device, DEVCB_##_devcb); |
| 9 | |
| 10 | // The first release of this CPU has a bug where the programcounter |
| 11 | // is not incremented properly after an interrupt after the halt opcode. |
| 12 | // This was fixed in a newer revision. |
| 9 | 13 | #define MCFG_LR35902_HALT_BUG \ |
| 10 | 14 | lr35902_cpu_device::set_halt_bug(*device); |
| 11 | 15 | |
| r30997 | r30998 | |
| 28 | 32 | |
| 29 | 33 | // static configuration helpers |
| 30 | 34 | template<class _Object> static devcb_base &set_timer_cb(device_t &device, _Object object) { return downcast<lr35902_cpu_device &>(device).m_timer_func.set_callback(object); } |
| 31 | | static void set_halt_bug(device_t &device) { downcast<lr35902_cpu_device &>(device).m_features |= LR35902_FEATURE_HALT_BUG; } |
| 35 | static void set_halt_bug(device_t &device) { downcast<lr35902_cpu_device &>(device).m_has_halt_bug = true; } |
| 32 | 36 | |
| 33 | 37 | UINT8 get_speed(); |
| 34 | 38 | void set_speed( UINT8 speed_request ); |
| r30997 | r30998 | |
| 40 | 44 | void set_if( UINT8 data ) { m_IF = data; } |
| 41 | 45 | |
| 42 | 46 | protected: |
| 43 | | static const UINT8 LR35902_FEATURE_HALT_BUG = 0x01; |
| 44 | 47 | |
| 45 | 48 | // device-level overrides |
| 46 | 49 | virtual void device_start(); |
| r30997 | r30998 | |
| 71 | 74 | inline void mem_write_word(UINT16 addr, UINT16 data); |
| 72 | 75 | inline void check_interrupts(); |
| 73 | 76 | |
| 74 | | protected: |
| 75 | 77 | address_space_config m_program_config; |
| 76 | 78 | |
| 77 | 79 | UINT8 m_A; |
| r30997 | r30998 | |
| 86 | 88 | UINT16 m_SP; |
| 87 | 89 | UINT16 m_PC; |
| 88 | 90 | /* Interrupt related */ |
| 89 | | UINT8 m_IE; |
| 90 | | UINT8 m_IF; |
| 91 | UINT8 m_IE; |
| 92 | UINT8 m_IF; |
| 91 | 93 | int m_irq_state; |
| 92 | | int m_ei_delay; |
| 94 | bool m_handle_ei_delay; |
| 93 | 95 | lr35902_cpu_device *m_device; |
| 94 | 96 | address_space *m_program; |
| 95 | 97 | int m_icount; |
| 96 | 98 | /* Timer callback */ |
| 97 | 99 | devcb_write8 m_timer_func; |
| 98 | 100 | /* Fetch & execute related */ |
| 99 | | int m_execution_state; |
| 101 | int m_execution_state; |
| 100 | 102 | UINT8 m_op; |
| 101 | 103 | /* Others */ |
| 102 | 104 | int m_gb_speed; |
| 103 | 105 | int m_gb_speed_change_pending; |
| 104 | 106 | int m_enable; |
| 105 | | int m_doHALTbug; |
| 106 | | UINT8 m_features; |
| 107 | bool m_handle_halt_bug; |
| 108 | bool m_has_halt_bug; |
| 107 | 109 | }; |
| 108 | 110 | |
| 109 | 111 | extern const device_type LR35902; |
trunk/src/emu/cpu/lr35902/lr35902.c
| r30997 | r30998 | |
| 78 | 78 | , m_IF(0) |
| 79 | 79 | , m_timer_func(*this) |
| 80 | 80 | , m_enable(0) |
| 81 | | , m_features(0) |
| 81 | , m_has_halt_bug(false) |
| 82 | 82 | { |
| 83 | 83 | } |
| 84 | 84 | |
| r30997 | r30998 | |
| 144 | 144 | save_item(NAME(m_IE)); |
| 145 | 145 | save_item(NAME(m_IF)); |
| 146 | 146 | save_item(NAME(m_irq_state)); |
| 147 | | save_item(NAME(m_ei_delay)); |
| 147 | save_item(NAME(m_handle_ei_delay)); |
| 148 | 148 | save_item(NAME(m_execution_state)); |
| 149 | 149 | save_item(NAME(m_op)); |
| 150 | 150 | save_item(NAME(m_gb_speed)); |
| 151 | 151 | save_item(NAME(m_gb_speed_change_pending)); |
| 152 | 152 | save_item(NAME(m_enable)); |
| 153 | | save_item(NAME(m_doHALTbug)); |
| 153 | save_item(NAME(m_handle_halt_bug)); |
| 154 | 154 | |
| 155 | 155 | // Register state for debugger |
| 156 | 156 | state_add( LR35902_PC, "PC", m_PC ).callimport().callexport().formatstr("%04X"); |
| r30997 | r30998 | |
| 211 | 211 | m_IF = 0; |
| 212 | 212 | |
| 213 | 213 | m_execution_state = 0; |
| 214 | | m_doHALTbug = 0; |
| 215 | | m_ei_delay = 0; |
| 214 | m_handle_halt_bug = false; |
| 215 | m_handle_ei_delay = false; |
| 216 | 216 | m_gb_speed_change_pending = 0; |
| 217 | 217 | m_gb_speed = 1; |
| 218 | 218 | } |
| r30997 | r30998 | |
| 230 | 230 | UINT8 irq = m_IE & m_IF; |
| 231 | 231 | |
| 232 | 232 | /* Interrupts should be taken after the first instruction after an EI instruction */ |
| 233 | | if (m_ei_delay) { |
| 234 | | m_ei_delay = 0; |
| 233 | if (m_handle_ei_delay) { |
| 234 | m_handle_ei_delay = false; |
| 235 | 235 | return; |
| 236 | 236 | } |
| 237 | 237 | |
| r30997 | r30998 | |
| 255 | 255 | { |
| 256 | 256 | m_enable &= ~HALTED; |
| 257 | 257 | m_PC++; |
| 258 | | if ( m_features & LR35902_FEATURE_HALT_BUG ) { |
| 258 | if ( m_has_halt_bug ) { |
| 259 | 259 | if ( ! ( m_enable & IME ) ) { |
| 260 | 260 | /* Old cpu core (dmg/mgb/sgb) */ |
| 261 | | m_doHALTbug = 1; |
| 261 | m_handle_halt_bug = true; |
| 262 | 262 | } |
| 263 | 263 | } else { |
| 264 | 264 | /* New cpu core (cgb/agb/ags) */ |
| r30997 | r30998 | |
| 311 | 311 | m_execution_state = 1; |
| 312 | 312 | } else { |
| 313 | 313 | m_op = mem_read_byte( m_PC++ ); |
| 314 | | if ( m_doHALTbug ) { |
| 314 | if ( m_handle_halt_bug ) { |
| 315 | 315 | m_PC--; |
| 316 | | m_doHALTbug = 0; |
| 316 | m_handle_halt_bug = false; |
| 317 | 317 | } |
| 318 | 318 | } |
| 319 | 319 | } |
trunk/src/mess/drivers/gb.c
| r30997 | r30998 | |
| 12 | 12 | TODO list: |
| 13 | 13 | - Do correct lcd stat timing |
| 14 | 14 | - Add Game Boy Light (Japan, 1997) - does it differ from gbpocket? |
| 15 | - SGB should be moved to SNES driver |
| 15 | 16 | |
| 16 | 17 | |
| 17 | 18 | Timers |
| r30997 | r30998 | |
| 753 | 754 | static MACHINE_CONFIG_DERIVED( supergb, gameboy ) |
| 754 | 755 | |
| 755 | 756 | /* basic machine hardware */ |
| 756 | | MCFG_CPU_REPLACE("maincpu", LR35902, 4295454) /* 4.295454 MHz */ |
| 757 | MCFG_CPU_REPLACE("maincpu", LR35902, 4295454) /* 4.295454 MHz, derived from SNES xtal */ |
| 757 | 758 | MCFG_CPU_PROGRAM_MAP(sgb_map) |
| 758 | 759 | |
| 759 | 760 | MCFG_CPU_MODIFY("maincpu") |
| 760 | | MCFG_LR35902_TIMER_CB( WRITE8( gb_state, gb_timer_callback ) ) |
| 761 | MCFG_LR35902_TIMER_CB( WRITE8(gb_state, gb_timer_callback ) ) |
| 761 | 762 | MCFG_LR35902_HALT_BUG |
| 762 | 763 | |
| 763 | 764 | MCFG_MACHINE_START_OVERRIDE(gb_state, sgb) |
| r30997 | r30998 | |
| 792 | 793 | |
| 793 | 794 | /* basic machine hardware */ |
| 794 | 795 | MCFG_CPU_MODIFY("maincpu") // todo XTAL_8_388MHz |
| 795 | | MCFG_CPU_PROGRAM_MAP( gbc_map) |
| 796 | | MCFG_LR35902_TIMER_CB( WRITE8( gb_state, gb_timer_callback ) ) |
| 796 | MCFG_CPU_PROGRAM_MAP(gbc_map) |
| 797 | MCFG_LR35902_TIMER_CB( WRITE8(gb_state, gb_timer_callback ) ) |
| 797 | 798 | |
| 798 | 799 | MCFG_MACHINE_START_OVERRIDE(gb_state,gbc) |
| 799 | 800 | MCFG_MACHINE_RESET_OVERRIDE(gb_state,gbc) |
| r30997 | r30998 | |
| 820 | 821 | |
| 821 | 822 | /* basic machine hardware */ |
| 822 | 823 | MCFG_CPU_ADD("maincpu", LR35902, 4194304) /* 4.194304 MHz */ |
| 823 | | MCFG_CPU_PROGRAM_MAP( megaduck_map) |
| 824 | | MCFG_LR35902_TIMER_CB( WRITE8( gb_state, gb_timer_callback ) ) |
| 824 | MCFG_CPU_PROGRAM_MAP(megaduck_map) |
| 825 | MCFG_LR35902_TIMER_CB( WRITE8(gb_state, gb_timer_callback ) ) |
| 825 | 826 | MCFG_LR35902_HALT_BUG |
| 826 | 827 | |
| 827 | 828 | /* video hardware */ |