diff options
Diffstat (limited to 'src/mame/drivers/pokemini.cpp')
-rw-r--r-- | src/mame/drivers/pokemini.cpp | 1804 |
1 files changed, 0 insertions, 1804 deletions
diff --git a/src/mame/drivers/pokemini.cpp b/src/mame/drivers/pokemini.cpp deleted file mode 100644 index 39ed4cf2eda..00000000000 --- a/src/mame/drivers/pokemini.cpp +++ /dev/null @@ -1,1804 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Wilbert Pol -/******************************************************************** - -Driver file to handle emulation of the Nintendo Pokemon Mini handheld -by Wilbert Pol. - -The LCD is likely to be a SSD1828 LCD. - -********************************************************************/ - -#include "emu.h" -#include "cpu/minx/minx.h" -#include "machine/i2cmem.h" -#include "sound/spkrdev.h" -#include "bus/generic/slot.h" -#include "bus/generic/carts.h" -#include "emupal.h" -#include "screen.h" -#include "softlist.h" -#include "speaker.h" - - -class pokemini_state : public driver_device -{ -public: - pokemini_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_maincpu(*this, "maincpu") - , m_screen(*this, "screen") - , m_p_ram(*this, "p_ram") - , m_speaker(*this, "speaker") - , m_i2cmem(*this, "i2cmem") - , m_cart(*this, "cartslot") - , m_inputs(*this, "INPUTS") - { } - - void pokemini(machine_config &config); - -protected: - enum - { - TIMER_SECONDS, - TIMER_256HZ, - TIMER_1, - TIMER_1_HI, - TIMER_2, - TIMER_2_HI, - TIMER_3, - TIMER_3_HI, - TIMER_PRC - }; - - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; - - virtual void video_start() override; - virtual void machine_start() override; - -private: - struct PRC - { - uint8_t colors_inverted; - uint8_t background_enabled; - uint8_t sprites_enabled; - uint8_t copy_enabled; - uint8_t map_size; - uint8_t map_size_x; - uint8_t frame_count; - uint8_t max_frame_count; - uint32_t bg_tiles; - uint32_t spr_tiles; - uint8_t count; - emu_timer *count_timer; - }; - - - struct TIMERS - { - emu_timer *seconds_timer; - emu_timer *hz256_timer; - emu_timer *timer1; // Timer 1 low or 16bit - emu_timer *timer1_hi; // Timer 1 hi - emu_timer *timer2; // Timer 2 low or 16bit - emu_timer *timer2_hi; // Timer 2 high - emu_timer *timer3; // Timer 3 low or 16bit - emu_timer *timer3_hi; // Timer 3 high - }; - - uint8_t m_pm_reg[0x100]; - PRC m_prc; - TIMERS m_timers; - bitmap_ind16 m_bitmap; - - required_device<cpu_device> m_maincpu; - required_device<screen_device> m_screen; - required_shared_ptr<uint8_t> m_p_ram; - required_device<speaker_sound_device> m_speaker; - required_device<i2cmem_device> m_i2cmem; - required_device<generic_slot_device> m_cart; - required_ioport m_inputs; - - uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - void pokemini_palette(palette_device &palette) const; - DECLARE_WRITE8_MEMBER(hwreg_w); - DECLARE_READ8_MEMBER(hwreg_r); - DECLARE_READ8_MEMBER(rom_r); - DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load); - - void pokemini_mem_map(address_map &map); - - void check_irqs(); - void update_sound(); - void seconds_timer_callback(); - void timer_256hz_callback(); - void timer1_callback(); - void timer1_hi_callback(); - void timer2_callback(); - void timer2_hi_callback(); - void timer3_callback(); - void timer3_hi_callback(); - void prc_counter_callback(); - -}; - - -READ8_MEMBER( pokemini_state::rom_r ) -{ - offset += 0x2100; - return m_cart->read_rom(offset & 0x1fffff); -} - -void pokemini_state::pokemini_mem_map(address_map &map) -{ - map(0x000000, 0x000fff).rom(); /* bios */ - map(0x001000, 0x001fff).ram().share("p_ram"); /* VRAM/RAM */ - map(0x002000, 0x0020ff).rw(FUNC(pokemini_state::hwreg_r), FUNC(pokemini_state::hwreg_w)); /* hardware registers */ - map(0x002100, 0x1fffff).r(FUNC(pokemini_state::rom_r)); /* cartridge area */ -} - - -static INPUT_PORTS_START( pokemini ) - PORT_START("INPUTS") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Button A") - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("Button B") - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_NAME("Button C") - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_NAME("Up") - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_NAME("Down") - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_NAME("Left") - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_NAME("Right") - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START1) PORT_NAME("Power") -INPUT_PORTS_END - - -void pokemini_state::pokemini_palette(palette_device &palette) const -{ - palette.set_pen_color(0, rgb_t(0xff, 0xfb, 0x87)); - palette.set_pen_color(1, rgb_t(0xb1, 0xae, 0x4e)); - palette.set_pen_color(2, rgb_t(0x84, 0x80, 0x4e)); - palette.set_pen_color(3, rgb_t(0x4e, 0x4e, 0x4e)); -} - - -void pokemini_state::check_irqs() -{ - int irq_set[4] = { 1, 0, 0, 0 }; - int prio, vector; - - /* Check IRQ $03-$04 */ - prio = ( m_pm_reg[0x20] >> 6 ) & 0x03; - if ( ! irq_set[prio] ) - { - if ( m_pm_reg[0x23] & m_pm_reg[0x27] & 0x40 ) - irq_set[prio] = 0x04; - - if ( m_pm_reg[0x23] & m_pm_reg[0x27] & 0x80 ) - irq_set[prio] = 0x03; - } - - /* Check IRQ $05-$06 */ - prio = ( m_pm_reg[0x20] >> 4 ) & 0x03; - if ( ! irq_set[prio] ) - { - if ( m_pm_reg[0x23] & m_pm_reg[0x27] & 0x10 ) - irq_set[prio] = 0x06; - - if ( m_pm_reg[0x23] & m_pm_reg[0x27] & 0x20 ) - irq_set[prio] = 0x05; - } - - /* Check IRQ $07-$08 */ - prio = ( m_pm_reg[0x20] >> 2 ) & 0x03; - if ( ! irq_set[prio] ) - { - if ( m_pm_reg[0x23] & m_pm_reg[0x27] & 0x04 ) - irq_set[prio] = 0x08; - - if ( m_pm_reg[0x23] & m_pm_reg[0x27] & 0x08 ) - irq_set[prio] = 0x07; - } - - /* Check IRQ $09-$0A */ - prio = ( m_pm_reg[0x20] >> 0 ) & 0x03; - if ( ! irq_set[prio] ) - { - if ( m_pm_reg[0x23] & m_pm_reg[0x27] & 0x01 ) - irq_set[prio] = 0x0A; - - if ( m_pm_reg[0x23] & m_pm_reg[0x27] & 0x02 ) - irq_set[prio] = 0x09; - } - - /* Check IRQ $0B-$0E */ - prio = ( m_pm_reg[0x21] >> 6 ) & 0x03; - if ( ! irq_set[prio] ) - { - if ( m_pm_reg[0x24] & m_pm_reg[0x28] & 0x04 ) - irq_set[prio] = 0x0E; - - if ( m_pm_reg[0x24] & m_pm_reg[0x28] & 0x08 ) - irq_set[prio] = 0x0D; - - if ( m_pm_reg[0x24] & m_pm_reg[0x28] & 0x10 ) - irq_set[prio] = 0x0C; - - if ( m_pm_reg[0x24] & m_pm_reg[0x28] & 0x20 ) - irq_set[prio] = 0x0B; - } - - /* Check IRQ $0F-$10 */ - prio = ( m_pm_reg[0x22] >> 0 ) & 0x03; - if ( ! irq_set[prio] ) - { - if ( m_pm_reg[0x26] & m_pm_reg[0x2A] & 0x40 ) - irq_set[prio] = 0x10; - - if ( m_pm_reg[0x26] & m_pm_reg[0x2A] & 0x80 ) - irq_set[prio] = 0x0F; - } - - /* Check IRQ $13-$14 */ - prio = ( m_pm_reg[0x21] >> 4 ) & 0x03; - if ( ! irq_set[prio] ) - { - if ( m_pm_reg[0x24] & m_pm_reg[0x28] & 0x01 ) - irq_set[prio] = 0x14; - - if ( m_pm_reg[0x24] & m_pm_reg[0x28] & 0x02 ) - irq_set[prio] = 0x13; - } - - /* Check IRQ $15-$1C */ - prio = ( m_pm_reg[0x21] >> 2 ) & 0x03; - if ( ! irq_set[prio] ) - { - if ( m_pm_reg[0x25] & m_pm_reg[0x29] & 0x01 ) - irq_set[prio] = 0x1C; - - if ( m_pm_reg[0x25] & m_pm_reg[0x29] & 0x02 ) - irq_set[prio] = 0x1B; - - if ( m_pm_reg[0x25] & m_pm_reg[0x29] & 0x04 ) - irq_set[prio] = 0x1A; - - if ( m_pm_reg[0x25] & m_pm_reg[0x29] & 0x08 ) - irq_set[prio] = 0x19; - - if ( m_pm_reg[0x25] & m_pm_reg[0x29] & 0x10 ) - irq_set[prio] = 0x18; - - if ( m_pm_reg[0x25] & m_pm_reg[0x29] & 0x20 ) - irq_set[prio] = 0x17; - - if ( m_pm_reg[0x25] & m_pm_reg[0x29] & 0x40 ) - irq_set[prio] = 0x16; - - if ( m_pm_reg[0x25] & m_pm_reg[0x29] & 0x80 ) - irq_set[prio] = 0x15; - } - - /* Check IRQ $1D-$1F */ - prio = ( m_pm_reg[0x21] >> 0 ) & 0x03; - if ( ! irq_set[prio] && ( m_pm_reg[0x26] & m_pm_reg[0x2A] & 0x07 ) ) - { - if ( m_pm_reg[0x26] & m_pm_reg[0x2A] & 0x01 ) - irq_set[prio] = 0x1F; - - if ( m_pm_reg[0x26] & m_pm_reg[0x2A] & 0x02 ) - irq_set[prio] = 0x1E; - - if ( m_pm_reg[0x26] & m_pm_reg[0x2A] & 0x04 ) - irq_set[prio] = 0x1D; - } - - /* Determine vector */ - vector = 0; - if ( irq_set[1] ) - vector = irq_set[1]; - if ( irq_set[2] ) - vector = irq_set[2]; - if ( irq_set[3] ) - vector = irq_set[3]; - - if ( vector ) - { - //logerror("Triggering IRQ with vector %02x\n", vector ); - /* Trigger interrupt and set vector */ - m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, vector ); // MINX - } - else - { - m_maincpu->set_input_line(0, CLEAR_LINE ); - } -} - - -void pokemini_state::update_sound() -{ - /* Check if sound should be muted */ - if ( m_pm_reg[0x70] & 0x03 ) - { - m_speaker->level_w(0); - } - else - { - ///static const int levels[4] = { 0, 1, 1, 2 }; - int level; /// silence clang warning/// = levels[ m_pm_reg[0x71] & 0x03 ]; - -// if ( ( ( m_pm_reg[0x48] & 0x80 ) && ( m_pm_reg[0x4E] | ( m_pm_reg[0x4F] << 8 ) ) > ( m_pm_reg[0x4C] | ( m_pm_reg[0x4D] << 8 ) ) ) -// || ( ( m_pm_reg[0x48] & 0x80 ) && m_pm_reg[0x4F] > m_pm_reg[0x4D] ) ) -// { - level = 0; -// } - - m_speaker->level_w(level); - } -} - - -void pokemini_state::seconds_timer_callback() -{ - if ( m_pm_reg[0x08] & 0x01 ) - { - m_pm_reg[0x09] += 1; - if ( ! m_pm_reg[0x09] ) - { - m_pm_reg[0x0A] += 1; - if ( ! m_pm_reg[0x0A] ) - { - m_pm_reg[0x0B] += 1; - } - } - } -} - - -void pokemini_state::timer_256hz_callback() -{ - if ( m_pm_reg[0x40] & 0x01 ) - { - m_pm_reg[0x41] += 1; - /* Check if the 32Hz IRQ should be triggered */ - if ( ! ( m_pm_reg[0x41] & 0x07 ) ) - { - m_pm_reg[0x28] |= 0x20; - - /* Check if the 8Hz IRQ should be triggered */ - if ( ! ( m_pm_reg[0x41] & 0x1F ) ) - { - m_pm_reg[0x28] |= 0x10; - - /* Check if the 2Hz IRQ should be triggered */ - if ( ! ( m_pm_reg[0x41] & 0x7F ) ) - { - m_pm_reg[0x28] |= 0x08; - - /* Check if the 1Hz IRQ should be triggered */ - if ( ! m_pm_reg[0x41] ) - { - m_pm_reg[0x28] |= 0x04; - } - } - } - - check_irqs(); - } - } -} - - -void pokemini_state::timer1_callback() -{ - m_pm_reg[0x36] -= 1; - /* Check for underflow of timer */ - if ( m_pm_reg[0x36] == 0xFF ) - { - /* Check if timer1 is running in 16bit mode */ - if ( m_pm_reg[0x30] & 0x80 ) - { - m_pm_reg[0x37] -= 1; - if ( m_pm_reg[0x37] == 0xFF ) - { - m_pm_reg[0x27] |= 0x08; - check_irqs(); - m_pm_reg[0x36] = m_pm_reg[0x32]; - m_pm_reg[0x37] = m_pm_reg[0x33]; - } - } - else - { - m_pm_reg[0x27] |= 0x04; - check_irqs(); - m_pm_reg[0x36] = m_pm_reg[0x32]; - } - } -} - - -void pokemini_state::timer1_hi_callback() -{ - m_pm_reg[0x37] -= 1; - /* Check for underflow of timer */ - if ( m_pm_reg[0x37] == 0xFF ) - { - m_pm_reg[0x27] |= 0x08; - check_irqs(); - m_pm_reg[0x37] = m_pm_reg[0x33]; - } -} - - -void pokemini_state::timer2_callback() -{ - m_pm_reg[0x3E] -= 1; - /* Check for underflow of timer */ - if ( m_pm_reg[0x3E] == 0xFF ) - { - /* Check if timer2 is running in 16bit mode */ - if ( m_pm_reg[0x38] & 0x80 ) - { - m_pm_reg[0x3F] -= 1; - if ( m_pm_reg[0x3F] == 0xFF ) - { - m_pm_reg[0x27] |= 0x20; - check_irqs(); - m_pm_reg[0x3E] = m_pm_reg[0x3A]; - m_pm_reg[0x3F] = m_pm_reg[0x3B]; - } - } - else - { - m_pm_reg[0x27] |= 0x10; - check_irqs(); - m_pm_reg[0x3E] = m_pm_reg[0x3A]; - } - } -} - - -void pokemini_state::timer2_hi_callback() -{ - m_pm_reg[0x3F] -= 1; - /* Check for underfow of timer */ - if ( m_pm_reg[0x3F] == 0xFF ) - { - m_pm_reg[0x27] |= 0x20; - check_irqs(); - m_pm_reg[0x3F] = m_pm_reg[0x3B]; - } -} - - -void pokemini_state::timer3_callback() -{ - m_pm_reg[0x4E] -= 1; - /* Check for underflow of timer */ - if ( m_pm_reg[0x4E] == 0xFF ) - { - /* Check if timer3 is running in 16bit mode */ - if ( m_pm_reg[0x48] & 0x80 ) - { - m_pm_reg[0x4F] -= 1; - if ( m_pm_reg[0x4F] == 0xFF ) - { - m_pm_reg[0x27] |= 0x02; - check_irqs(); - m_pm_reg[0x4E] = m_pm_reg[0x4A]; - m_pm_reg[0x4F] = m_pm_reg[0x4B]; - } - } - else - { - m_pm_reg[0x4E] = m_pm_reg[0x4A]; - } - } - - if ( m_pm_reg[0x48] & 0x80 ) - { - if ( ( m_pm_reg[0x4E] == m_pm_reg[0x4C] ) && ( m_pm_reg[0x4F] == m_pm_reg[0x4D] ) ) - { - m_pm_reg[0x27] |= 0x01; - check_irqs(); - } - update_sound(); - } -} - - -void pokemini_state::timer3_hi_callback() -{ - m_pm_reg[0x4F] -= 1; - /* Check for underflow of timer */ - if ( m_pm_reg[0x4F] == 0xFF ) - { - m_pm_reg[0x27] |= 0x02; - check_irqs(); - m_pm_reg[0x4F] = m_pm_reg[0x4B]; - } - - if ( ! ( m_pm_reg[0x48] & 0x80 ) ) - { - if( m_pm_reg[0x4F] == m_pm_reg[0x4D] ) - { - m_pm_reg[0x27] |= 0x01; - check_irqs(); - } - update_sound(); - } -} - - -WRITE8_MEMBER(pokemini_state::hwreg_w) -{ - static const int timer_to_cycles_fast[8] = { 2, 8, 32, 64, 128, 256, 1024, 4096 }; - static const int timer_to_cycles_slow[8] = { 128, 256, 512, 1024, 2048, 4096, 8192, 16384 }; - - //logerror( "%0X: Write to hardware address: %02X, %02X\n", m_maincpu->pc(), offset, data ); - - switch( offset ) - { - case 0x00: /* start-up contrast - Bit 0-1 R/W Must be 1(?) - Bit 2-7 R/W Start up contrast (doesn't affect contrast until after reboot) - */ - case 0x01: /* CPU related? - Bit 0-7 R/W Unknown - */ - case 0x02: /* CPU related? - Bit 0-7 R/W Unknown - */ - logerror( "%0X: Write to unknown hardware address: %02X, %02X\n", m_maincpu->pc(), offset, data ); - break; - case 0x08: /* Seconds-timer control - Bit 0 R/W Timer enable - Bit 1 W Timer reset - Bit 2-7 Unused - */ - if ( data & 0x02 ) - { - m_pm_reg[0x09] = 0x00; - m_pm_reg[0x0A] = 0x00; - m_pm_reg[0x0B] = 0x00; - data &= ~0x02; - } - break; - case 0x09: /* Seconds-timer (low), read only - Bit 0-7 R Seconds timer bit 0-7 - */ - return; - case 0x0A: /* Seconds-timer (mid), read only - Bit 0-7 R Seconds timer bit 8-15 - */ - return; - case 0x0B: /* Seconds-timer (high), read only - Bit 0-7 R Seconds timer bit 16-23 - */ - return; - case 0x10: /* Low power detector - Bit 0-4 R/W Unknown - Bit 5 R Battery status: 0 - battery OK, 1 - battery low - Bit 6-7 Unused - */ - logerror( "%0X: Write to unknown hardware address: %02X, %02X\n", m_maincpu->pc(), offset, data ); - break; - case 0x18: /* Timer 1 pre-scale + enable - Bit 0-2 R/W low timer 1 prescaler select - 000 - 2 or 128 cycles - 001 - 8 or 256 cycles - 010 - 32 or 512 cycles - 011 - 64 or 1024 cycles - 100 - 128 or 2048 cycles - 101 - 256 or 4096 cycles - 110 - 1024 or 8192 cycles - 111 - 4096 or 16384 cycles - Bit 3 R/W Enable low counting - Bit 4-6 R/W high timer 1 prescaler select - Bit 7 R/W Enable high counting - */ - /* Check for prescaler change for the low counter */ - if ( ( data & 0x07 ) != ( m_pm_reg[0x18] & 0x07 ) ) - { - int index = data & 0x07; - int cycles = ( m_pm_reg[0x19] & 0x01 ) ? timer_to_cycles_slow[index] : timer_to_cycles_fast[index]; - - m_timers.timer1->adjust(attotime::zero, 0, m_maincpu->cycles_to_attotime(cycles)); - } - - /* Check for prescaler change for the high counter */ - if ( ( data & 0x70 ) != ( m_pm_reg[0x18] & 0x70 ) ) - { - int index = ( data >> 4 ) & 0x07; - int cycles = ( m_pm_reg[0x19] & 0x02 ) ? timer_to_cycles_slow[index] : timer_to_cycles_fast[index]; - - m_timers.timer1_hi->adjust(attotime::zero, 0, m_maincpu->cycles_to_attotime(cycles)); - } - - /* Check if timer1 low should be enabled */ - if ( ( data & 0x08 ) && ( m_pm_reg[0x30] & 0x04 ) && - ( ( ( m_pm_reg[0x19] & 0x10 ) && ( m_pm_reg[0x19] & 0x01 ) ) || - ( ( m_pm_reg[0x19] & 0x20 ) && ! ( m_pm_reg[0x19] & 0x01 ) ) ) ) - { - m_timers.timer1->enable( 1 ); - } - else - { - m_timers.timer1->enable( 0 ); - } - - /* Check if timer1 high should be enabled */ - if ( ( data & 0x80 ) && ( m_pm_reg[0x31] & 0x04 ) && ! ( m_pm_reg[0x30] & 0x80 ) && - ( ( ( m_pm_reg[0x19] & 0x10 ) && ( m_pm_reg[0x19] & 0x02 ) ) || - ( ( m_pm_reg[0x19] & 0x20 ) && ! ( m_pm_reg[0x19] & 0x02 ) ) ) ) - { - m_timers.timer1_hi->enable( 1 ); - } - else - { - m_timers.timer1_hi->enable( 0 ); - } - break; - case 0x19: /* Timers 1 speed - Bit 0 R/W Select slow timer for timer 1 lo - Bit 1 R/W Select slow timer for timer 1 hi - Bit 2-3 Unused - Bit 4 R/W Enable slow timers - Bit 5 R/W Enable fast timers - Bit 6-7 Unused - */ - /* Check for prescaler change for the high counter */ - if ( ( data & 0x01 ) != ( m_pm_reg[0x19] & 0x01 ) ) - { - int index = m_pm_reg[0x18] & 0x07; - int cycles = ( data & 0x01 ) ? timer_to_cycles_slow[index] : timer_to_cycles_fast[index]; - - m_timers.timer1->adjust(attotime::zero, 0, m_maincpu->cycles_to_attotime(cycles)); - } - - /* Check for prescaler change for the low counter */ - if ( ( data & 0x02 ) != ( m_pm_reg[0x19] & 0x02 ) ) - { - int index = ( m_pm_reg[0x18] >> 4 ) & 0x07; - int cycles = ( data & 0x02 ) ? timer_to_cycles_slow[index] : timer_to_cycles_fast[index]; - - m_timers.timer1_hi->adjust(attotime::zero, 0, m_maincpu->cycles_to_attotime(cycles)); - } - - { - int timer1_enable = 0, timer1_hi_enable = 0; - int timer2_enable = 0, timer2_hi_enable = 0; - int timer3_enable = 0, timer3_hi_enable = 0; - - /* Check which fast timers should be enabled */ - if ( data & 0x20 ) - { - if ( ( m_pm_reg[0x18] & 0x08 ) && ( m_pm_reg[0x30] & 0x04 ) && ! ( data & 0x01 ) ) - timer1_enable = 1; - - if ( ( m_pm_reg[0x18] & 0x80 ) && ( m_pm_reg[0x31] & 0x04 ) && ! ( m_pm_reg[0x30] & 0x80 ) && ! ( data & 0x02 ) ) - timer1_hi_enable = 1; - - if ( ( m_pm_reg[0x1A] & 0x08 ) && ( m_pm_reg[0x38] & 0x04 ) && ! ( m_pm_reg[0x1B] & 0x01 ) ) - timer2_enable = 1; - - if ( ( m_pm_reg[0x1A] & 0x80 ) && ( m_pm_reg[0x39] & 0x04 ) && ! ( m_pm_reg[0x38] & 0x80 ) && ! ( m_pm_reg[0x1B] & 0x02 ) ) - timer2_hi_enable = 1; - - if ( ( m_pm_reg[0x1C] & 0x08 ) && ( m_pm_reg[0x48] & 0x04 ) && ! ( m_pm_reg[0x1D] & 0x01 ) ) - timer3_enable = 1; - - if ( ( m_pm_reg[0x1C] & 0x80 ) && ( m_pm_reg[0x49] & 0x04 ) && ! ( m_pm_reg[0x48] & 0x80 ) && ! ( m_pm_reg[0x1D] & 0x02 ) ) - timer3_hi_enable = 1; - } - - /* Check which slow timers should be enabled */ - if ( data & 0x10 ) - { - if ( ( m_pm_reg[0x18] & 0x08 ) && ( data & 0x01 ) ) - timer1_enable = 1; - - if ( ( m_pm_reg[0x1A] & 0x08 ) && ( m_pm_reg[0x1B] & 0x01 ) ) - timer2_enable = 1; - - if ( ( m_pm_reg[0x1C] & 0x08 ) && ( m_pm_reg[0x1D] & 0x01 ) ) - timer3_enable = 1; - } - m_timers.timer1->enable( timer1_enable ); - m_timers.timer1_hi->enable( timer1_hi_enable ); - m_timers.timer2->enable( timer2_enable ); - m_timers.timer2_hi->enable( timer2_hi_enable ); - m_timers.timer3->enable( timer3_enable ); - m_timers.timer3_hi->enable( timer3_hi_enable ); - } - break; - case 0x1A: /* Timer 2 pre-scale + enable - Bit 0-2 R/W low timer 2 prescaler select - 000 - 2 or 128 cycles - 001 - 8 or 256 cycles - 010 - 32 or 512 cycles - 011 - 64 or 1024 cycles - 100 - 128 or 2048 cycles - 101 - 256 or 4096 cycles - 110 - 1024 or 8192 cycles - 111 - 4096 or 16384 cycles - Bit 3 R/W Enable low counting - Bit 4-6 R/W high timer 2 prescaler select - Bit 7 R/W Enable high counting - */ - /* Check for prescaler change for the low counter */ - if ( ( data & 0x07 ) != ( m_pm_reg[0x1A] & 0x07 ) ) - { - int index = data & 0x07; - int cycles = ( m_pm_reg[0x1B] & 0x01 ) ? timer_to_cycles_slow[index] : timer_to_cycles_fast[index]; - - m_timers.timer2->adjust(attotime::zero, 0, m_maincpu->cycles_to_attotime(cycles)); - } - - /* Check for prescaler change for the high counter */ - if ( ( data & 0x70 ) != ( m_pm_reg[0x1A] & 0x70 ) ) - { - int index = ( data >> 4 ) & 0x07; - int cycles = ( m_pm_reg[0x1B] & 0x02 ) ? timer_to_cycles_slow[index] : timer_to_cycles_fast[index]; - - m_timers.timer2_hi->adjust(attotime::zero, 0, m_maincpu->cycles_to_attotime(cycles)); - } - - /* Check if timer2 low should be enabled */ - if ( ( data & 0x08 ) && ( m_pm_reg[0x38] & 0x04 ) && - ( ( ( m_pm_reg[0x19] & 0x10 ) && ( m_pm_reg[0x1B] & 0x01 ) ) || - ( ( m_pm_reg[0x19] & 0x20 ) && ! ( m_pm_reg[0x1B] & 0x01 ) ) ) ) - { - m_timers.timer2->enable( 1 ); - } - else - { - m_timers.timer2->enable( 0 ); - } - - /* Check if timer2 high should be enabled */ - if ( ( data & 0x80 ) && ( m_pm_reg[0x39] & 0x04 ) && ! ( m_pm_reg[0x38] & 0x80 ) && - ( ( ( m_pm_reg[0x19] & 0x10 ) && ( m_pm_reg[0x1B] & 0x02 ) ) || - ( ( m_pm_reg[0x19] & 0x20 ) && ! ( m_pm_reg[0x1B] & 0x02 ) ) ) ) - { - m_timers.timer2_hi->enable( 1 ); - } - else - { - m_timers.timer2_hi->enable( 0 ); - } - break; - case 0x1B: /* Timer 2 speeds - Bit 0 R/W Select slow timer for timer 2 lo - Bit 1 R/W Select slow timer for timer 2 hi - */ - /* Check for prescaler change for the high counter */ - if ( ( data & 0x01 ) != ( m_pm_reg[0x1B] & 0x01 ) ) - { - int index = m_pm_reg[0x1A] & 0x07; - int cycles = ( data & 0x01 ) ? timer_to_cycles_slow[index] : timer_to_cycles_fast[index]; - - m_timers.timer2->adjust(attotime::zero, 0, m_maincpu->cycles_to_attotime(cycles)); - - if ( ( m_pm_reg[0x1A] & 0x08 ) && ( m_pm_reg[0x38] & 0x04 ) && - ( ( ( m_pm_reg[0x19] & 0x10 ) && ( data & 0x01 ) ) || - ( ( m_pm_reg[0x19] & 0x20 ) && ! ( data & 0x01 ) ) ) ) - { - m_timers.timer2->enable( 1 ); - } - else - { - m_timers.timer2->enable( 0 ); - } - } - - /* Check for prescaler change for the low counter */ - if ( ( data & 0x02 ) != ( m_pm_reg[0x1B] & 0x02 ) ) - { - int index = ( m_pm_reg[0x1A] >> 4 ) & 0x07; - int cycles = ( data & 0x02 ) ? timer_to_cycles_slow[index] : timer_to_cycles_fast[index]; - - m_timers.timer2_hi->adjust(attotime::zero, 0, m_maincpu->cycles_to_attotime(cycles)); - - if ( ( m_pm_reg[0x1A] & 0x80 ) && ( m_pm_reg[0x39] & 0x04 ) && ! ( m_pm_reg[0x38] & 0x80 ) && - ( ( ( m_pm_reg[0x19] & 0x10 ) && ( data & 0x02 ) ) || - ( ( m_pm_reg[0x19] & 0x20 ) && ! ( data & 0x02 ) ) ) ) - { - m_timers.timer2_hi->enable( 1 ); - } - else - { - m_timers.timer2_hi->enable( 0 ); - } - } - break; - case 0x1C: /* Timer 3 pre-scale + enable - Bit 0-2 R/W low timer 3 prescaler select - 000 - 2 or 128 cycles - 001 - 8 or 256 cycles - 010 - 32 or 512 cycles - 011 - 64 or 1024 cycles - 100 - 128 or 2048 cycles - 101 - 256 or 4096 cycles - 110 - 1024 or 8192 cycles - 111 - 4096 or 16384 cycles - Bit 3 R/W Enable low counting - Bit 4-6 R/W high timer 3 prescaler select - Bit 7 R/W Enable high counting - */ - /* Check for prescaler change for the low counter */ - if ( ( data & 0x07 ) != ( m_pm_reg[0x1C] & 0x07 ) ) - { - int index = data & 0x07; - int cycles = ( m_pm_reg[0x1D] & 0x01 ) ? timer_to_cycles_slow[index] : timer_to_cycles_fast[index]; - - m_timers.timer3->adjust(attotime::zero, 0, m_maincpu->cycles_to_attotime(cycles)); - } - - /* Check for prescaler change for the high counter */ - if ( ( data & 0x70 ) != ( m_pm_reg[0x1C] & 0x70 ) ) - { - int index = ( data >> 4 ) & 0x07; - int cycles = ( m_pm_reg[0x1D] & 0x02 ) ? timer_to_cycles_slow[index] : timer_to_cycles_fast[index]; - - m_timers.timer3_hi->adjust(attotime::zero, 0, m_maincpu->cycles_to_attotime(cycles)); - } - - /* Check if timer2 low should be enabled */ - if ( ( data & 0x08 ) && ( m_pm_reg[0x48] & 0x04 ) && - ( ( ( m_pm_reg[0x19] & 0x10 ) && ( m_pm_reg[0x1D] & 0x01 ) ) || - ( ( m_pm_reg[0x19] & 0x20 ) && ! ( m_pm_reg[0x1D] & 0x01 ) ) ) ) - { - m_timers.timer3->enable( 1 ); - } - else - { - m_timers.timer3->enable( 0 ); - } - - /* Check if timer2 high should be enabled */ - if ( ( data & 0x80 ) && ( m_pm_reg[0x49] & 0x04 ) && ! ( m_pm_reg[0x48] & 0x80 ) && - ( ( ( m_pm_reg[0x19] & 0x10 ) && ( m_pm_reg[0x1D] & 0x02 ) ) || - ( ( m_pm_reg[0x19] & 0x20 ) && ! ( m_pm_reg[0x1D] & 0x02 ) ) ) ) - { - m_timers.timer3_hi->enable( 1 ); - } - else - { - m_timers.timer3_hi->enable( 0 ); - } - break; - case 0x1D: /* Timer 3 speeds - Bit 0 R/W Select slow timer for timer 3 lo - Bit 1 R/W Select slow timer for timer 3 hi - */ - /* Check for prescaler change for the high counter */ - if ( ( data & 0x01 ) != ( m_pm_reg[0x1D] & 0x01 ) ) - { - int index = m_pm_reg[0x1C] & 0x07; - int cycles = ( data & 0x01 ) ? timer_to_cycles_slow[index] : timer_to_cycles_fast[index]; - - m_timers.timer3->adjust(attotime::zero, 0, m_maincpu->cycles_to_attotime(cycles)); - - if ( ( m_pm_reg[0x1C] & 0x08 ) && ( m_pm_reg[0x48] & 0x04 ) && - ( ( ( m_pm_reg[0x19] & 0x10 ) && ( data & 0x01 ) ) || - ( ( m_pm_reg[0x19] & 0x20 ) && ! ( data & 0x01 ) ) ) ) - { - m_timers.timer3->enable( 1 ); - } - else - { - m_timers.timer3->enable( 0 ); - } - } - - /* Check for prescaler change for the low counter */ - if ( ( data & 0x02 ) != ( m_pm_reg[0x1D] & 0x02 ) ) - { - int index = ( m_pm_reg[0x1C] >> 4 ) & 0x07; - int cycles = ( data & 0x02 ) ? timer_to_cycles_slow[index] : timer_to_cycles_fast[index]; - - m_timers.timer3_hi->adjust(attotime::zero, 0, m_maincpu->cycles_to_attotime(cycles)); - - if ( ( m_pm_reg[0x1C] & 0x80 ) && ( m_pm_reg[0x49] & 0x04 ) && ! ( m_pm_reg[0x48] & 0x80 ) && - ( ( ( m_pm_reg[0x19] & 0x10 ) && ( data & 0x02 ) ) || - ( ( m_pm_reg[0x19] & 0x20 ) && ! ( data & 0x02 ) ) ) ) - { - m_timers.timer3_hi->enable( 1 ); - } - else - { - m_timers.timer3_hi->enable( 0 ); - } - } - break; - case 0x20: /* Event #1-#8 priority - Bit 0-1 R/W Timer 3 overflow Interrupt #7-#8 - Bit 2-3 R/W Timer 1 overflow Interrupt #5-#6 - Bit 4-5 R/W Timer 2 overflow Interrupt #3-#4 - Bit 6-7 R/W VDraw/VBlank trigger Interrupt #1-#2 - */ - m_pm_reg[0x20] = data; - check_irqs(); - break; - case 0x21: /* Event #15-#22 priority - Bit 0-1 R/W Unknown - Bit 2-3 R/W All keypad interrupts - Interrupt #15-#22 - Bit 4-7 R/W Unknown - */ - m_pm_reg[0x21] = data; - check_irqs(); - break; - case 0x22: /* Event #9-#14 priority - Bit 0-1 R/W All #9 - #14 events - Interrupt #9-#14 - Bit 2-7 Unused - */ - m_pm_reg[0x22] = data; - check_irqs(); - break; - case 0x23: /* Event #1-#8 enable - Bit 0 R/W Timer 3 overflow (mirror) - Enable Interrupt #8 - Bit 1 R/W Timer 3 overflow - Enable Interrupt #7 - Bit 2 R/W Not called... - Enable Interrupt #6 - Bit 3 R/W Timer 1 overflow - Enable Interrupt #5 - Bit 4 R/W Not called... - Enable Interrupt #4 - Bit 5 R/W Timer 2 overflow - Enable Interrupt #3 - Bit 6 R/W V-Draw trigger - Enable Interrupt #2 - Bit 7 R/W V-Blank trigger - Enable Interrupt #1 - */ - m_pm_reg[0x23] = data; - check_irqs(); - break; - case 0x24: /* Event #9-#12 enable - Bit 0-5 R/W Unknown - Bit 6-7 Unused - */ - m_pm_reg[0x24] = data; - check_irqs(); - break; - case 0x25: /* Event #15-#22 enable - Bit 0 R/W Press key "A" event - Enable interrupt #22 - Bit 1 R/W Press key "B" event - Enable interrupt #21 - Bit 2 R/W Press key "C" event - Enable interrupt #20 - Bit 3 R/W Press D-pad up key event - Enable interrupt #19 - Bit 4 R/W Press D-pad down key event - Enable interrupt #18 - Bit 5 R/W Press D-pad left key event - Enable interrupt #17 - Bit 6 R/W Press D-pad right key event - Enable interrupt #16 - Bit 7 R/W Press power button event - Enable interrupt #15 - */ - m_pm_reg[0x25] = data; - check_irqs(); - break; - case 0x26: /* Event #13-#14 enable - Bit 0-2 R/W Unknown - Bit 3 Unused - Bit 4-5 R/W Unknown - Bit 6 R/W Shock detector trigger - Enable interrupt #14 - Bit 7 R/W IR receiver - low to high trigger - Enable interrupt #13 - */ - m_pm_reg[0x26] = data; - check_irqs(); - break; - case 0x27: /* Interrupt active flag #1-#8 - Bit 0 Timer 3 overflow (mirror) / Clear interrupt #8 - Bit 1 Timer 3 overflow / Clear interrupt #7 - Bit 2 Not called ... / Clear interrupt #6 - Bit 3 Timer 1 overflow / Clear interrupt #5 - Bit 4 Not called ... / Clear interrupt #4 - Bit 5 Timer 2 overflow / Clear interrupt #3 - Bit 6 VDraw trigger / Clear interrupt #2 - Bit 7 VBlank trigger / Clear interrupt #1 - */ - m_pm_reg[0x27] &= ~data; - check_irqs(); - return; - case 0x28: /* Interrupt active flag #9-#12 - Bit 0-1 Unknown - Bit 2 Unknown / Clear interrupt #12 - Bit 3 Unknown / Clear interrupt #11 - Bit 4 Unknown / Clear interrupt #10 - Bit 5 Unknown / Clear interrupt #9 - Bit 6-7 Unknown - */ - m_pm_reg[0x28] &= ~data; - check_irqs(); - return; - case 0x29: /* Interrupt active flag #15-#22 - Bit 0 Press key "A" event / Clear interrupt #22 - Bit 1 Press key "B" event / Clear interrupt #21 - Bit 2 Press key "C" event / Clear interrupt #20 - Bit 3 Press D-pad up key event / Clear interrupt #19 - Bit 4 Press D-pad down key event / Clear interrupt #18 - Bit 5 Press D-pad left key event / Clear interrupt #17 - Bit 6 Press D-pad right key event / Clear interrupt #16 - Bit 7 Press power button event / Clear interrupt #15 - */ - m_pm_reg[0x29] &= ~data; - check_irqs(); - return; - case 0x2A: /* Interrupt active flag #13-#14 - Bit 0-5 Unknown - Bit 6 Shock detector trigger / Clear interrupt #14 - Bit 7 Unknown / Clear interrupt #13 - */ - m_pm_reg[0x2A] &= ~data; - check_irqs(); - return; - case 0x30: /* Timer 1 control 1 - Bit 0 R/W Unknown - Bit 1 W Reset low counter - Bit 2 R/W Enable high counter - Bit 3 R/W Unknown - Bit 4-6 Unused - Bit 7 R/W Enable 16bit mode - */ - if ( data & 0x02 ) - { - m_pm_reg[0x36] = m_pm_reg[0x32]; - data &= ~0x02; - } - - if ( ( data & 0x04 ) && ( m_pm_reg[0x18] & 0x08 ) && - ( ( ( m_pm_reg[0x19] & 0x20 ) && ! ( m_pm_reg[0x19] & 0x01 ) ) || - ( ( m_pm_reg[0x19] & 0x10 ) && ( m_pm_reg[0x19] & 0x01 ) ) ) ) - { - m_timers.timer1->enable( 1 ); - } - else - { - m_timers.timer1->enable( 0 ); - } - - if ( ( m_pm_reg[0x31] & 0x04 ) && ! ( data & 0x80 ) && ( m_pm_reg[0x18] & 0x80 ) && - ( ( ( m_pm_reg[0x19] & 0x20 ) && ! ( m_pm_reg[0x19] & 0x02 ) ) || - ( ( m_pm_reg[0x19] & 0x10 ) && ( m_pm_reg[0x19] & 0x02 ) ) ) ) - { - m_timers.timer1_hi->enable( 1 ); - } - else - { - m_timers.timer1_hi->enable( 0 ); - } - break; - case 0x31: /* Timer 1 control 2 - Bit 0 R/W Unknown - Bit 1 W Reset hi counter - Bit 2 R/W Enable high counter - Bit 3 R/W Unknown - Bit 4-7 Unused - */ - if ( data & 0x02 ) - { - m_pm_reg[0x37] = m_pm_reg[0x33]; - data &= ~0x02; - } - - if ( ( data & 0x04 ) && ! ( m_pm_reg[0x30] & 0x80 ) && ( m_pm_reg[0x18] & 0x80 ) && - ( ( ( m_pm_reg[0x19] & 0x20 ) && ! ( m_pm_reg[0x19] & 0x02 ) ) || - ( ( m_pm_reg[0x19] & 0x10 ) && ( m_pm_reg[0x19] & 0x02 ) ) ) ) - { - m_timers.timer1_hi->enable( 1 ); - } - else - { - m_timers.timer1_hi->enable( 0 ); - } - break; - case 0x32: /* Timer 1 preset value (low) - Bit 0-7 R/W Timer 1 preset value bit 0-7 - */ - break; - case 0x33: /* Timer 1 preset value (high) - Bit 0-7 R/W Timer 1 preset value bit 8-15 - */ - break; - case 0x34: /* Timer 1 sound-pivot (low, unused) - */ - case 0x35: /* Timer 1 sound-pivot (high, unused) - */ - logerror( "%0X: Write to unknown hardware address: %02X, %02X\n", m_maincpu->pc(), offset, data ); - break; - case 0x36: /* Timer 1 counter (low), read only - */ - return; - case 0x37: /* Timer 1 counter (high), read only - */ - return; - case 0x38: /* Timer 2 control 1 - Bit 0 R/W Unknown - Bit 1 W Reset low counter - Bit 2 R/W Enable high counter - Bit 3 R/W Unknown - Bit 4-6 Unused - Bit 7 R/W Enable 16bit mode - */ - if ( data & 0x02 ) - { - m_pm_reg[0x3E] = m_pm_reg[0x3A]; - data &= ~0x02; - } - - if ( ( data & 0x04 ) && ( m_pm_reg[0x1A] & 0x08 ) && - ( ( ( m_pm_reg[0x19] & 0x20 ) && ! ( m_pm_reg[0x1A] & 0x01 ) ) || - ( ( m_pm_reg[0x19] & 0x10 ) && ( m_pm_reg[0x1A] & 0x01 ) ) ) ) - { - m_timers.timer2->enable( 1 ); - } - else - { - m_timers.timer2->enable( 0 ); - } - if ( ( m_pm_reg[0x39] & 0x04 ) && ! ( data & 0x80 ) && ( m_pm_reg[0x1A] & 0x80 ) && - ( ( ( m_pm_reg[0x19] & 0x20 ) && ! ( m_pm_reg[0x1B] & 0x02 ) ) || - ( ( m_pm_reg[0x19] & 0x10 ) && ( m_pm_reg[0x1B] & 0x02 ) ) ) ) - { - m_timers.timer2_hi->enable( 1 ); - } - else - { - m_timers.timer2_hi->enable( 0 ); - } - break; - case 0x39: /* Timer 2 control 2 - Bit 0 R/W Unknown - Bit 1 W Reset hi counter - Bit 2 R/W Enable high counter - Bit 3 R/W Unknown - Bit 4-7 Unused - */ - if ( data & 0x02 ) - { - m_pm_reg[0x3F] = m_pm_reg[0x3A]; - data &= ~0x02; - } - - if ( ( data & 0x04 ) && ! ( m_pm_reg[0x38] & 0x80 ) && ( m_pm_reg[0x1A] & 0x80 ) && - ( ( ( m_pm_reg[0x19] & 0x20 ) && ! ( m_pm_reg[0x1B] & 0x02 ) ) || - ( ( m_pm_reg[0x19] & 0x10 ) && ( m_pm_reg[0x1B] & 0x02 ) ) ) ) - { - m_timers.timer2_hi->enable( 1 ); - } - else - { - m_timers.timer2_hi->enable( 0 ); - } - break; - case 0x3A: /* Timer 2 preset value (low) - Bit 0-7 R/W Timer 2 preset value bit 0-7 - */ - break; - case 0x3B: /* Timer 2 preset value (high) - Bit 0-7 R/W Timer 2 preset value bit 8-15 - */ - break; - case 0x3C: /* Timer 2 sound-pivot (low, unused) - */ - case 0x3D: /* Timer 2 sound-pivot (high, unused) - */ - logerror( "%0X: Write to unknown hardware address: %02X, %02X\n", m_maincpu->pc(), offset, data ); - break; - case 0x3E: /* Timer 2 counter (low), read only - Bit 0-7 R/W Timer 2 counter value bit 0-7 - */ - return; - case 0x3F: /* Timer 2 counter (high), read only - Bit 0-7 R/W Timer 2 counter value bit 8-15 - */ - return; - case 0x40: /* 256Hz timer control - Bit 0 R/W Enable Timer - Bit 1 W Reset Timer - Bit 2-7 Unused - */ - if ( data & 0x02 ) - { - m_pm_reg[0x41] = 0; - data &= ~0x02; - } - break; - case 0x41: /* 256Hz timer counter - Bit 0-7 R 256Hz timer counter - */ - return; - case 0x48: /* Timer 3 control 1 - Bit 0 R/W Unknown - Bit 1 W Reset low counter - Bit 2 R/W Enable high counter - Bit 3 R/W Unknown - Bit 4-6 Unused - Bit 7 R/W Enable 16bit mode - */ - if ( data & 0x02 ) - { - m_pm_reg[0x4E] = m_pm_reg[0x4A]; - data &= ~0x02; - } - - if ( ( data & 0x04 ) && ( m_pm_reg[0x1C] & 0x08 ) && - ( ( ( m_pm_reg[0x19] & 0x20 ) && ! ( m_pm_reg[0x1D] & 0x01 ) ) || - ( ( m_pm_reg[0x19] & 0x10 ) && ( m_pm_reg[0x1D] & 0x01 ) ) ) ) - { - m_timers.timer3->enable( 1 ); - } - else - { - m_timers.timer3->enable( 0 ); - } - if ( ( m_pm_reg[0x49] & 0x04 ) && ! ( data & 0x80 ) && ( m_pm_reg[0x1C] & 0x80 ) && - ( ( ( m_pm_reg[0x19] & 0x20 ) && ! ( m_pm_reg[0x1D] & 0x02 ) ) || - ( ( m_pm_reg[0x19] & 0x10 ) && ( m_pm_reg[0x1D] & 0x02 ) ) ) ) - { - m_timers.timer3_hi->enable( 1 ); - } - else - { - m_timers.timer3_hi->enable( 0 ); - } - m_pm_reg[0x48] = data; - update_sound(); - break; - case 0x49: /* Timer 3 control 2 - Bit 0 R/W Unknown - Bit 1 W Reset hi counter - Bit 2 R/W Enable high counter - Bit 3 R/W Unknown - Bit 4-7 Unused - */ - if ( data & 0x02 ) - { - m_pm_reg[0x4F] = m_pm_reg[0x4B]; - data &= ~0x02; - } - - if ( ( data & 0x04 ) && ! ( m_pm_reg[0x48] & 0x80 ) && ( m_pm_reg[0x1C] & 0x80 ) && - ( ( ( m_pm_reg[0x19] & 0x20 ) && ! ( m_pm_reg[0x1D] & 0x02 ) ) || - ( ( m_pm_reg[0x19] & 0x10 ) && ( m_pm_reg[0x1D] & 0x02 ) ) ) ) - { - m_timers.timer3_hi->enable( 1 ); - } - else - { - m_timers.timer3_hi->enable( 0 ); - } - m_pm_reg[0x49] = data; - update_sound(); - break; - case 0x4A: /* Timer 3 preset value (low) - Bit 0-7 R/W Timer 3 preset value bit 0-7 - */ - m_pm_reg[0x4A] = data; - update_sound(); - break; - case 0x4B: /* Timer 3 preset value (high) - Bit 0-7 R/W Timer 3 preset value bit 8-15 - */ - m_pm_reg[0x4B] = data; - update_sound(); - break; - case 0x4C: /* Timer 3 sound-pivot (low) - Bit 0-7 R/W Timer 3 sound-pivot value bit 0-7 - */ - m_pm_reg[0x4C] = data; - update_sound(); - break; - case 0x4D: /* Timer 3 sound-pivot (high) - Bit 0-7 R/W Timer 3 sound-pivot value bit 8-15 - - Sound-pivot location: - Pulse-Width of 0% = 0x0000 - Pulse-Width of 50% = Half of preset-value - Pulse-Width of 100% = Same as preset-value - */ - m_pm_reg[0x4D] = data; - update_sound(); - break; - case 0x4E: /* Timer 3 counter (low), read only - Bit 0-7 R/W Timer 3 counter value bit 0-7 - */ - return; - case 0x4F: /* Timer 3 counter (high), read only - Bit 0-7 R/W Timer 3 counter value bit 8-15 - */ - return; - case 0x52: /* Keypad status - Bit 0 R Key "A" - Bit 1 R Key "B" - Bit 2 R Key "C" - Bit 3 R D-pad up - Bit 4 R D-pad down - Bit 5 R D-pad left - Bit 6 R D-pad right - Bit 7 R Power button - */ - return; - case 0x60: /* I/O peripheral circuit select - Bit 0 R/W Unknown - bit 1 R/W IR receive / transmit - Bit 2 R/W EEPROM / RTC data - Bit 3 R/W EEPROM / RTC clock - Bit 4 R/W Rumble controller - Bit 5 R/W IR enable/disable - Bit 6 R/W Unknown - Bit 7 R/W Unknown - */ - break; - case 0x61: /* I/O peripheral status control - Bit 0 R/W IR received bit (if device not selected: 0) - Bit 1 R/W IR transmit (if device not selected: 0) - Bit 2 R/W EEPROM / RTC data (if device not selected: 1) - Bit 3 R/W EEPROM / RTC clock (if device not selected: 0) - Bit 4 R/W Rumble on/off (if device not selected: 0) - Bit 5 R/W IR disable (receive & transmit) (if device not selected: 1) - Bit 6 Always 1 - Bit 7 R/W IR received bit (mirror, if device not selected: 0) - */ - if ( m_pm_reg[0x60] & 0x04 ) - m_i2cmem->write_sda( ( data & 0x04 ) ? 1 : 0 ); - - if ( m_pm_reg[0x60] & 0x08 ) - m_i2cmem->write_scl( ( data & 0x08 ) ? 1 : 0 ); - break; - case 0x70: /* Sound related */ - m_pm_reg[0x70] = data; - update_sound(); - break; - case 0x71: /* Sound volume - Bit 0-1 R/W Sound volume - 00 - 0% - 01 - 50% - 10 - 50% - 11 - 100% - Bit 2 R/W Always set to 0 - Bit 3-7 Unused - */ - m_pm_reg[0x71] = data; - update_sound(); - break; - case 0x80: /* LCD control - Bit 0 R/W Invert colors; 0 - normal, 1 - inverted - Bit 1 R/W Enable rendering of background - Bit 2 R/W Enable rendering of sprites - Bit 3 R/W Enable copy to LCD ram - Bit 4-5 R/W Map size - 00 - 12x16 - 01 - 16x12 - 10 - 24x8 - 11 - 24x8 (prohibited code) - Bit 6-7 Unused - */ - m_prc.colors_inverted = ( data & 0x01 ) ? 1 : 0; - m_prc.background_enabled = ( data & 0x02 ) ? 1 : 0; - m_prc.sprites_enabled = ( data & 0x04 ) ? 1 : 0; - m_prc.copy_enabled = ( data & 0x08 ) ? 1 : 0; - m_prc.map_size = ( data >> 4 ) & 0x03; - switch( m_prc.map_size ) - { - case 0: - m_prc.map_size_x = 12; break; - case 1: - m_prc.map_size_x = 16; break; - case 2: - case 3: - m_prc.map_size_x = 24; break; - } - break; - case 0x81: /* LCD render refresh rate - Bit 0 R/W Unknown - Bit 1-3 R/W LCD refresh rate divider - 000 - 60Hz / 3 = 20Hz (0 - 2) - 001 - 60Hz / 6 = 10Hz (0 - 5) - 010 - 60Hz / 9 = 6,6Hz (0 - 8) - 011 - 60Hz / 12 = 5Hz (0 - B) - 100 - 60Hz / 2 = 30Hz (0 - 1) - 101 - 60Hz / 4 = 15Hz (0 - 3) - 110 - 60Hz / 6 = 10Hz (0 - 5) - 111 - 60Hz / 8 = 7,5Hz (0 - 7) - Bit 4-7 R Divider position, when overflow the LCD is updated - */ - switch ( data & 0x0E ) - { - case 0x00: m_prc.max_frame_count = 3; break; - case 0x02: m_prc.max_frame_count = 6; break; - case 0x04: m_prc.max_frame_count = 9; break; - case 0x06: m_prc.max_frame_count = 12; break; - case 0x08: m_prc.max_frame_count = 2; break; - case 0x0A: m_prc.max_frame_count = 4; break; - case 0x0C: m_prc.max_frame_count = 6; break; - case 0x0E: m_prc.max_frame_count = 8; break; - } - break; - case 0x82: /* BG tile data memory offset (low) - Bit 0-2 Always "0" - Bit 3-7 R/W BG tile data memory offset bit 3-7 - */ - data &= 0xF8; - m_prc.bg_tiles = ( m_prc.bg_tiles & 0xFFFF00 ) | data; - break; - case 0x83: /* BG tile data memory offset (mid) - Bit 0-7 R/W BG tile data memory offset bit 8-15 - */ - m_prc.bg_tiles = ( m_prc.bg_tiles & 0xFF00FF ) | ( data << 8 ); - break; - case 0x84: /* BG tile data memory offset (high) - Bit 0-4 R/W BG tile data memory offset bit 16-20 - Bit 5-7 Unused - */ - data &= 0x1F; - m_prc.bg_tiles = ( m_prc.bg_tiles & 0x00FFFF ) | ( data << 16 ); - break; - case 0x85: /* BG vertical move - Bit 0-6 R/W Move the background up, move range: - Map size 0: 0x00 to 0x40 - Map size 1: 0x00 to 0x20 - Map size 2: move ignored - Bit 7 Unused - */ - case 0x86: /* BG horizontal move - Bit 0-6 R/W Move the background left, move range: - Map size 0: move ignored - Map size 1: 0x00 to 0x20 - Map size 2: 0x00 to 0x60 - Bit 7 Unused - */ - logerror( "%0X: Write to unknown hardware address: %02X, %02X\n", m_maincpu->pc(), offset, data ); - break; - case 0x87: /* Sprite tile data memory offset (low) - Bit 0-5 Always "0" - Bit 6-7 R/W Sprite tile data memory offset bit 6-7 - */ - data &= 0xC0; - m_prc.spr_tiles = ( m_prc.spr_tiles & 0xFFFF00 ) | data; - break; - case 0x88: /* Sprite tile data memory offset (med) - Bit 0-7 R/W Sprite tile data memory offset bit 8-15 - */ - m_prc.spr_tiles = ( m_prc.spr_tiles & 0xFF00FF ) | ( data << 8 ); - break; - case 0x89: /* Sprite tile data memory offset (high) - Bit 0-4 R/W Sprite tile data memory offset bit 16-20 - Bit 5-7 Unused - */ - data &= 0x1F; - m_prc.spr_tiles = ( m_prc.spr_tiles & 0x00FFFF ) | ( data << 16 ); - break; - case 0x8A: /* LCD status - Bit 0 R Unknown - Bit 1 R Unknown - Bit 2 R Unknown - Bit 3 R Unknown - Bit 4 R LCD during V-Sync / Rendering circuitry active or not ( 1 = not active) - Bit 5 R Unknown - Bit 6-7 Unused - */ - case 0xFE: /* Direct LCD control / data - Bit 0-7 R/W Direct LCD command or data - */ -// lcd_command_w( data ); - break; - case 0xFF: /* Direct LCD data - Bit 0-7 R/W Direct LCD data - */ -// lcd_data_w( data ); - break; - default: - logerror( "%0X: Write to unknown hardware address: %02X, %02X\n", m_maincpu->pc(), offset, data ); - break; - } - m_pm_reg[offset] = data; -} - -READ8_MEMBER(pokemini_state::hwreg_r) -{ - uint8_t data = m_pm_reg[offset]; - - switch( offset ) - { - case 0x52: return m_inputs->read(); - case 0x61: - if ( ! ( m_pm_reg[0x60] & 0x04 ) ) - { - data = ( data & ~ 0x04 ) | ( m_i2cmem->read_sda() ? 0x04 : 0x00 ); - } - - if ( ! ( m_pm_reg[0x60] & 0x08 ) ) - { - data &= ~0x08; - } - break; - case 0x81: return ( m_pm_reg[offset] & 0x0F ) | ( m_prc.frame_count << 4 ); - case 0x8A: return m_prc.count; - } - return data; -} - -DEVICE_IMAGE_LOAD_MEMBER( pokemini_state::cart_load ) -{ - uint32_t size = m_cart->common_get_size("rom"); - - /* Verify that the image is big enough */ - if (size <= 0x2100) - { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid ROM image: ROM image is too small"); - return image_init_result::FAIL; - } - - /* Verify that the image is not too big */ - if (size > 0x1fffff) - { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid ROM image: ROM image is too big"); - return image_init_result::FAIL; - } - - m_cart->rom_alloc(size, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE); - m_cart->common_load_rom(m_cart->get_rom_base(), size, "rom"); - - return image_init_result::PASS; -} - - -void pokemini_state::prc_counter_callback() -{ - address_space &space = m_maincpu->space( AS_PROGRAM ); - m_prc.count++; - - /* Check for overflow */ - if ( m_prc.count >= 0x42 ) - { - m_prc.count = 0; - m_prc.frame_count++; - } - else - { - if ( m_prc.count == 0x18 && m_prc.frame_count >= m_prc.max_frame_count ) - { - m_prc.frame_count = 0; - - /* Check if the background should be drawn */ - if ( m_prc.background_enabled ) - { - int x, y; - for ( y = 0; y < 8; y++ ) { - for ( x = 0; x < 12; x++ ) { - uint8_t tile = m_p_ram[ 0x360 + ( y * m_prc.map_size_x ) + x ]; - int i; - for( i = 0; i < 8; i++ ) { - m_p_ram[ ( y * 96 ) + ( x * 8 ) + i ] = space.read_byte( m_prc.bg_tiles + ( tile * 8 ) + i ); - } - } - } - } - - /* Check if the sprites should be drawn */ - if ( m_prc.sprites_enabled ) - { - uint16_t spr; - - for ( spr = 0x35C; spr >= 0x300; spr -= 4 ) - { - int spr_x = ( m_p_ram[ spr + 0 ] & 0x7F ) - 16; - int spr_y = ( m_p_ram[ spr + 1 ] & 0x7F ) - 16; - uint8_t spr_tile = m_p_ram[ spr + 2 ]; - uint8_t spr_flag = m_p_ram[ spr + 3 ]; - - if ( spr_flag & 0x08 ) - { - uint16_t gfx, mask; - uint32_t spr_base = m_prc.spr_tiles + spr_tile * 64; - int i, j; - - for ( i = 0; i < 16; i++ ) - { - if ( spr_x + i >= 0 && spr_x + i < 96 ) - { - int rel_x = ( spr_flag & 0x01 ) ? 15 - i : i; - uint32_t s = spr_base + ( ( rel_x & 0x08 ) << 2 ) + ( rel_x & 0x07 ); - - mask = ~ ( space.read_byte( s ) | ( space.read_byte( s + 8 ) << 8 ) ); - gfx = space.read_byte( s + 16 ) | ( space.read_byte( s + 24 ) << 8 ); - - /* Are the colors inverted? */ - if ( spr_flag & 0x04 ) - { - gfx = ~gfx; - } - - for ( j = 0; j < 16; j++ ) - { - if ( spr_y + j >= 0 && spr_y + j < 64 ) - { - uint16_t ram_addr = ( ( ( spr_y + j ) >> 3 ) * 96 ) + spr_x + i; - - if ( spr_flag & 0x02 ) - { - if ( mask & 0x8000 ) - { - m_p_ram[ ram_addr ] &= ~ ( 1 << ( ( spr_y + j ) & 0x07 ) ); - if ( gfx & 0x8000 ) - { - m_p_ram[ ram_addr ] |= ( 1 << ( ( spr_y + j ) & 0x07 ) ); - } - } - mask <<= 1; - gfx <<= 1; - } - else - { - if ( mask & 0x0001 ) - { - m_p_ram[ ram_addr ] &= ~ ( 1 << ( ( spr_y + j ) & 0x07 ) ); - if ( gfx & 0x0001 ) - { - m_p_ram[ ram_addr ] |= ( 1 << ( ( spr_y + j ) & 0x07 ) ); - } - } - mask >>= 1; - gfx >>= 1; - } - } - } - } - } - } - } - } - - /* Set PRC Render interrupt */ - m_pm_reg[0x27] |= 0x40; - check_irqs(); - - /* Check if the rendered data should be copied to the LCD */ - if ( m_prc.copy_enabled ) - { - int x, y; - - for( y = 0; y < 64; y += 8 ) { - for( x = 0; x < 96; x++ ) { - uint8_t data = m_p_ram[ ( y * 12 ) + x ]; - - m_bitmap.pix16(y + 0, x) = ( data & 0x01 ) ? 3 : 0; - m_bitmap.pix16(y + 1, x) = ( data & 0x02 ) ? 3 : 0; - m_bitmap.pix16(y + 2, x) = ( data & 0x04 ) ? 3 : 0; - m_bitmap.pix16(y + 3, x) = ( data & 0x08 ) ? 3 : 0; - m_bitmap.pix16(y + 4, x) = ( data & 0x10 ) ? 3 : 0; - m_bitmap.pix16(y + 5, x) = ( data & 0x20 ) ? 3 : 0; - m_bitmap.pix16(y + 6, x) = ( data & 0x40 ) ? 3 : 0; - m_bitmap.pix16(y + 7, x) = ( data & 0x80 ) ? 3 : 0; - } - } - - /* Set PRC Copy interrupt */ - m_pm_reg[0x27] |= 0x80; - check_irqs(); - } - } - - /* Set possible input irqs */ - m_pm_reg[0x29] |= ~ m_inputs->read(); - } -} - - -void pokemini_state::machine_start() -{ - /* Clear internal structures */ - memset( &m_prc, 0, sizeof(m_prc) ); - memset( &m_timers, 0, sizeof(m_timers) ); - memset( m_pm_reg, 0, sizeof(m_pm_reg) ); - - /* Set up timers */ - m_timers.seconds_timer = timer_alloc(TIMER_SECONDS); - m_timers.seconds_timer->adjust(attotime::zero, 0, attotime::from_seconds(1)); - - m_timers.hz256_timer = timer_alloc(TIMER_256HZ); - m_timers.hz256_timer->adjust(attotime::zero, 0, attotime::from_hz(256)); - - m_timers.timer1 = timer_alloc(TIMER_1); - m_timers.timer1_hi = timer_alloc(TIMER_1_HI); - m_timers.timer2 = timer_alloc(TIMER_2); - m_timers.timer2_hi = timer_alloc(TIMER_2_HI); - m_timers.timer3 = timer_alloc(TIMER_3); - m_timers.timer3_hi = timer_alloc(TIMER_3_HI); - - /* Set up the PRC */ - m_prc.max_frame_count = 2; - m_prc.count_timer = timer_alloc(TIMER_PRC); - m_prc.count_timer->adjust( attotime::zero, 0, m_maincpu->cycles_to_attotime(55640 / 65) ); -} - - -void pokemini_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - switch (id) - { - case TIMER_SECONDS: - seconds_timer_callback(); - break; - - case TIMER_256HZ: - timer_256hz_callback(); - break; - - case TIMER_1: - timer1_callback(); - break; - - case TIMER_1_HI: - timer1_hi_callback(); - break; - - case TIMER_2: - timer2_callback(); - break; - - case TIMER_2_HI: - timer2_hi_callback(); - break; - - case TIMER_3: - timer3_callback(); - break; - - case TIMER_3_HI: - timer3_hi_callback(); - break; - - case TIMER_PRC: - prc_counter_callback(); - break; - } -} - - -static const int16_t speaker_levels[] = {-32768, 0, 32767}; - -void pokemini_state::video_start() -{ - m_screen->register_screen_bitmap(m_bitmap); -} - - -uint32_t pokemini_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect); - return 0; -} - - -void pokemini_state::pokemini(machine_config &config) -{ - /* basic machine hardware */ - MINX(config, m_maincpu, 4000000); - m_maincpu->set_addrmap(AS_PROGRAM, &pokemini_state::pokemini_mem_map); - - config.set_maximum_quantum(attotime::from_hz(60)); - - I2CMEM(config, m_i2cmem, 0).set_data_size(0x2000); - - /* This still needs to be improved to actually match the hardware */ - SCREEN(config, m_screen, SCREEN_TYPE_LCD); - m_screen->set_screen_update(FUNC(pokemini_state::screen_update)); - m_screen->set_size(96, 64); - m_screen->set_visarea(0, 95, 0, 63); - m_screen->set_refresh_hz(72); - m_screen->set_palette("palette"); - - PALETTE(config, "palette", FUNC(pokemini_state::pokemini_palette), 4); - - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - SPEAKER_SOUND(config, m_speaker); - m_speaker->set_levels(3, speaker_levels); - m_speaker->add_route(ALL_OUTPUTS, "mono", 0.50); - - /* cartridge */ - GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "pokemini_cart", "bin,min").set_device_load(FUNC(pokemini_state::cart_load)); - - /* Software lists */ - SOFTWARE_LIST(config, "cart_list").set_original("pokemini"); -} - -ROM_START( pokemini ) - ROM_REGION( 0x200000, "maincpu", 0 ) - ROM_LOAD( "bios.min", 0x0000, 0x1000, CRC(aed3c14d) SHA1(daad4113713ed776fbd47727762bca81ba74915f) ) -ROM_END - - -CONS( 2001, pokemini, 0, 0, pokemini, pokemini, pokemini_state, empty_init, "Nintendo", "Pokemon Mini", MACHINE_NO_SOUND ) |