diff options
Diffstat (limited to 'src/mame/drivers/pockstat.cpp')
-rw-r--r-- | src/mame/drivers/pockstat.cpp | 1023 |
1 files changed, 0 insertions, 1023 deletions
diff --git a/src/mame/drivers/pockstat.cpp b/src/mame/drivers/pockstat.cpp deleted file mode 100644 index c73721cd9fa..00000000000 --- a/src/mame/drivers/pockstat.cpp +++ /dev/null @@ -1,1023 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/*************************************************************************** - - Sony PocketStation - - PocketStation games were dowloaded from PS1 games into flash RAM after - the unit had been inserted in the memory card slot, and so this should - be emulated alongside the PS1. However, as many flash dumps exist, it - is possible to emulate the PocketStation in the meantime. - - CPU: ARM7T (32 bit RISC Processor) - Memory: 2Kbytes of SRAM, 128Kbytes of FlashROM - Graphics: 32x32 monochrome LCD - Sound: 1 12-bit PCM channel - Input: 5 input buttons, 1 reset button - Infrared communication: Bi-directional and uni-directional comms - Other: 1 LED indicator - - Currently, a handful of games run, but some die due to odd hardware - issues. - - To start a game: - - Wait for the set-date screen to appear - - Press Down - - Set date with directional controls (optional) - - Press Button 1, wait, press Button 1, press Right, game starts - - If you do nothing for about 20 secs, it turns itself off (screen goes white). - -****************************************************************************/ - -#include "emu.h" -#include "bus/generic/carts.h" -#include "bus/generic/slot.h" -#include "cpu/arm7/arm7.h" -#include "cpu/arm7/arm7core.h" -#include "sound/dac.h" -#include "sound/volt_reg.h" -#include "emupal.h" -#include "screen.h" -#include "speaker.h" - -#define LOG_UNKNOWN (1 << 0) -#define LOG_FTLB (1 << 1) -#define LOG_IRQS (1 << 2) -#define LOG_INTC (1 << 3) -#define LOG_TIMER (1 << 4) -#define LOG_CLOCK (1 << 5) -#define LOG_RTC (1 << 6) -#define LOG_LCD (1 << 7) -#define LOG_AUDIO (1 << 8) -#define LOG_ALL (LOG_UNKNOWN | LOG_FTLB | LOG_IRQS | LOG_INTC | LOG_TIMER | LOG_CLOCK | LOG_RTC | LOG_LCD | LOG_AUDIO) -#define LOG_DEFAULT LOG_ALL - -#define VERBOSE (0) -#include "logmacro.h" - -class pockstat_state : public driver_device -{ -public: - pockstat_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_lcd_buffer(*this, "lcd_buffer"), - m_maincpu(*this, "maincpu"), - m_cart(*this, "cartslot") - { } - - void pockstat(machine_config &config); - - DECLARE_INPUT_CHANGED_MEMBER(input_update); - -private: - virtual void machine_start() override; - virtual void machine_reset() override; - - void mem_map(address_map &map); - - uint32_t screen_update_pockstat(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - - void set_interrupt_line(uint32_t line, int state); - uint32_t get_interrupt_line(uint32_t line); - - void timer_start(int index); - - required_shared_ptr<uint32_t> m_lcd_buffer; - required_device<cpu_device> m_maincpu; - required_device<generic_slot_device> m_cart; - memory_region *m_cart_rom; - - static constexpr uint32_t TIMER_COUNT = 3; - - enum : uint32_t - { - CLOCK_STEADY = 0x10 - }; - - enum - { - INT_BTN_ACTION = 0x00000001, // "Action button" - INT_BTN_RIGHT = 0x00000002, // "Right button" - INT_BTN_LEFT = 0x00000004, // "Left button" - INT_BTN_DOWN = 0x00000008, // "Down button" - INT_BTN_UP = 0x00000010, // "Up button" - INT_UNKNOWN = 0x00000020, // "Unknown" - INT_COM = 0x00000040, // "COM" ??? - INT_TIMER0 = 0x00000080, // "Timer 0" - INT_TIMER1 = 0x00000100, // "Timer 1" - INT_RTC = 0x00000200, // "RTC" - INT_BATTERY = 0x00000400, // "Battery Monitor" - INT_IOP = 0x00000800, // "IOP" - INT_IRDA = 0x00001000, // "IrDA" - INT_TIMER2 = 0x00002000, // "Timer 2" - INT_IRQ_MASK = 0x00001fbf, - INT_FIQ_MASK = 0x00002040, - INT_STATUS_MASK = 0x0000021f - }; - - struct ftlb_regs_t - { - uint32_t control; - uint32_t stat; - uint32_t valid; - uint32_t wait1; - uint32_t wait2; - uint32_t entry[16]; - uint32_t serial; - } m_ftlb_regs; - - struct intc_regs_t - { - uint32_t hold; - uint32_t status; - uint32_t enable; - uint32_t mask; - } m_intc_regs; - - struct timer_t - { - uint32_t period; - uint32_t count; - uint32_t control; - emu_timer *timer; - } m_timers[TIMER_COUNT]; - - struct clock_regs_t - { - uint32_t mode; - uint32_t control; - } m_clock_regs; - - struct rtc_regs_t - { - uint32_t mode; - uint32_t control; - uint32_t time; - uint32_t date; - emu_timer *timer; - } m_rtc_regs; - - uint32_t m_lcd_control; - int32_t m_flash_write_enable_count; - int32_t m_flash_write_count; - - DECLARE_READ32_MEMBER(ftlb_r); - DECLARE_WRITE32_MEMBER(ftlb_w); - DECLARE_READ32_MEMBER(intc_r); - DECLARE_WRITE32_MEMBER(intc_w); - DECLARE_READ32_MEMBER(timer_r); - DECLARE_WRITE32_MEMBER(timer_w); - DECLARE_READ32_MEMBER(clock_r); - DECLARE_WRITE32_MEMBER(clock_w); - DECLARE_READ32_MEMBER(rtc_r); - DECLARE_WRITE32_MEMBER(rtc_w); - DECLARE_READ32_MEMBER(lcd_r); - DECLARE_WRITE32_MEMBER(lcd_w); - DECLARE_READ32_MEMBER(rombank_r); - DECLARE_READ32_MEMBER(flash_r); - DECLARE_WRITE32_MEMBER(flash_w); - DECLARE_READ32_MEMBER(audio_r); - DECLARE_WRITE32_MEMBER(audio_w); - TIMER_CALLBACK_MEMBER(timer_tick); - TIMER_CALLBACK_MEMBER(rtc_tick); - DECLARE_DEVICE_IMAGE_LOAD_MEMBER(flash_load); - - static const int CPU_FREQ[16]; -}; - -const int pockstat_state::CPU_FREQ[16] = -{ - 0x00f800, - 0x01f000, - 0x03e000, - 0x07c000, - 0x0f8000, - 0x1e8000, - 0x3d0000, - 0x7a0000, - 0x7a0000, - 0x7a0000, - 0x7a0000, - 0x7a0000, - 0x7a0000, - 0x7a0000, - 0x7a0000, - 0x7a0000 -}; - -READ32_MEMBER(pockstat_state::ftlb_r) -{ - switch(offset) - { - case 0x0000/4: - LOGMASKED(LOG_FTLB, "%s: FlashROM TLB Control = %08x & %08x\n", machine().describe_context(), m_ftlb_regs.control, mem_mask); - return m_ftlb_regs.control | 1; // ??? - case 0x0004/4: - LOGMASKED(LOG_FTLB, "%s: Unknown (F_STAT) = %08x & %08x\n", machine().describe_context(), m_ftlb_regs.stat, mem_mask); - return m_ftlb_regs.stat; - case 0x0008/4: - LOGMASKED(LOG_FTLB, "%s: FlashROM TLB Valid Tag = %08x & %08x\n", machine().describe_context(), m_ftlb_regs.valid, mem_mask); - return m_ftlb_regs.valid; - case 0x000c/4: - LOGMASKED(LOG_FTLB, "%s: Unknown (F_WAIT1) = %08x & %08x\n", machine().describe_context(), m_ftlb_regs.wait1, mem_mask); - return m_ftlb_regs.wait1; - case 0x0010/4: - LOGMASKED(LOG_FTLB, "%s: Unknown (F_WAIT2) = %08x & %08x\n", machine().describe_context(), m_ftlb_regs.wait2 | 0x04, mem_mask); - return m_ftlb_regs.wait2 | 0x04; - case 0x0100/4: - case 0x0104/4: - case 0x0108/4: - case 0x010c/4: - case 0x0110/4: - case 0x0114/4: - case 0x0118/4: - case 0x011c/4: - case 0x0120/4: - case 0x0124/4: - case 0x0128/4: - case 0x012c/4: - case 0x0130/4: - case 0x0134/4: - case 0x0138/4: - case 0x013c/4: - LOGMASKED(LOG_FTLB, "%s: FlashROM TLB Entry %d = %08x & %08x\n", machine().describe_context(), offset - 0x100/4, m_ftlb_regs.entry[offset - 0x100/4], - mem_mask); - return m_ftlb_regs.entry[offset - 0x100/4]; - case 0x0300/4: - LOGMASKED(LOG_FTLB, "%s: Unknown (F_SN) = %08x & %08x\n", machine().describe_context(), m_ftlb_regs.serial, mem_mask); - return m_ftlb_regs.serial; - default: - LOGMASKED(LOG_FTLB | LOG_UNKNOWN, "%s: Unknown Register %08x & %08x\n", machine().describe_context(), 0x06000000 + (offset << 2), mem_mask); - break; - } - return 0; -} - -WRITE32_MEMBER(pockstat_state::ftlb_w) -{ - switch(offset) - { - case 0x0000/4: - LOGMASKED(LOG_FTLB, "%s: FlashROM TLB Control = %08x & %08x\n", machine().describe_context(), data, mem_mask); - COMBINE_DATA(&m_ftlb_regs.control); - break; - case 0x0004/4: - LOGMASKED(LOG_FTLB, "%s: Unknown (F_STAT) = %08x & %08x\n", machine().describe_context(), data, mem_mask); - COMBINE_DATA(&m_ftlb_regs.stat); - break; - case 0x0008/4: - LOGMASKED(LOG_FTLB, "%s: FlashROM TLB Valid Tag = %08x & %08x\n", machine().describe_context(), data, mem_mask); - COMBINE_DATA(&m_ftlb_regs.valid); - break; - case 0x000c/4: - LOGMASKED(LOG_FTLB, "%s: Unknown (F_WAIT1) = %08x & %08x\n", machine().describe_context(), data, mem_mask); - COMBINE_DATA(&m_ftlb_regs.wait1); - break; - case 0x0010/4: - LOGMASKED(LOG_FTLB, "%s: Unknown (F_WAIT2) = %08x & %08x\n", machine().describe_context(), data, mem_mask); - COMBINE_DATA(&m_ftlb_regs.wait2); - break; - case 0x0100/4: - case 0x0104/4: - case 0x0108/4: - case 0x010c/4: - case 0x0110/4: - case 0x0114/4: - case 0x0118/4: - case 0x011c/4: - case 0x0120/4: - case 0x0124/4: - case 0x0128/4: - case 0x012c/4: - case 0x0130/4: - case 0x0134/4: - case 0x0138/4: - case 0x013c/4: - LOGMASKED(LOG_FTLB, "%s: FlashROM TLB Entry %d = %08x & %08x\n", machine().describe_context(), offset - 0x100/4, data, mem_mask); - COMBINE_DATA(&m_ftlb_regs.entry[offset - 0x100/4]); - break; - case 0x0300/4: - LOGMASKED(LOG_FTLB, "%s: Unknown (F_SN) = %08x & %08x\n", machine().describe_context(), data, mem_mask); - COMBINE_DATA(&m_ftlb_regs.serial); - break; - default: - LOGMASKED(LOG_FTLB | LOG_UNKNOWN, "%s: Unknown Register %08x = %08x & %08x\n", machine().describe_context(), 0x06000000 + (offset << 2), data, mem_mask); - break; - } -} - -uint32_t pockstat_state::get_interrupt_line(uint32_t line) -{ - return m_intc_regs.status & line; -} - -void pockstat_state::set_interrupt_line(uint32_t line, int state) -{ - if (line) - { - if (state) - { - m_intc_regs.status |= line & INT_STATUS_MASK; - m_intc_regs.hold |= line &~ INT_STATUS_MASK; - LOGMASKED(LOG_IRQS, "Setting IRQ line %08x, status = %08x, hold = %08x\n", line, m_intc_regs.status, m_intc_regs.hold); - } - else - { - m_intc_regs.status &= ~line; - m_intc_regs.hold &= ~line; - LOGMASKED(LOG_IRQS, "Clearing IRQ line %08x, status = %08x, hold = %08x\n", line, m_intc_regs.status, m_intc_regs.hold); - } - } - - const uint32_t new_irq = m_intc_regs.hold & m_intc_regs.enable & INT_IRQ_MASK; - if (new_irq) - { - m_maincpu->set_input_line(ARM7_IRQ_LINE, ASSERT_LINE); - } - else - { - m_maincpu->set_input_line(ARM7_IRQ_LINE, CLEAR_LINE); - } - - const uint32_t new_fiq = m_intc_regs.hold & m_intc_regs.enable & INT_FIQ_MASK; - if (new_fiq) - { - m_maincpu->set_input_line(ARM7_FIRQ_LINE, ASSERT_LINE); - } - else - { - m_maincpu->set_input_line(ARM7_FIRQ_LINE, CLEAR_LINE); - } -} - -READ32_MEMBER(pockstat_state::intc_r) -{ - switch(offset) - { - case 0x0000/4: - LOGMASKED(LOG_INTC, "%s: Held Interrupt Read: %08x & %08x\n", machine().describe_context(), m_intc_regs.hold, mem_mask); - return m_intc_regs.hold; - case 0x0004/4: - LOGMASKED(LOG_INTC, "%s: Interrupt Status Read: %08x & %08x\n", machine().describe_context(), m_intc_regs.status, mem_mask); - return m_intc_regs.status; - case 0x0008/4: - LOGMASKED(LOG_INTC, "%s: Interrupt Enable Read: %08x & %08x\n", machine().describe_context(), m_intc_regs.enable, mem_mask); - return m_intc_regs.enable; - case 0x000c/4: - LOGMASKED(LOG_INTC, "%s: Interrupt Mask Read (Invalid): %08x & %08x\n", machine().describe_context(), 0, mem_mask); - return 0; - case 0x0010/4: - LOGMASKED(LOG_INTC, "%s: Interrupt Acknowledge Read (Invalid): %08x & %08x\n", machine().describe_context(), 0, mem_mask); - return 0; - default: - LOGMASKED(LOG_INTC | LOG_UNKNOWN, "%s: Unknown Register Read: %08x & %08x\n", machine().describe_context(), 0x0a000000 + (offset << 2), mem_mask); - break; - } - return 0; -} - -WRITE32_MEMBER(pockstat_state::intc_w) -{ - switch(offset) - { - case 0x0000/4: - LOGMASKED(LOG_INTC, "%s: Held Interrupt (Invalid Write) = %08x & %08x\n", machine().describe_context(), data, mem_mask); - break; - case 0x0004/4: - LOGMASKED(LOG_INTC, "%s: Interrupt Status (Invalid Write) = %08x & %08x\n", machine().describe_context(), data, mem_mask); - break; - case 0x0008/4: - LOGMASKED(LOG_INTC, "%s: Interrupt Enable = %08x & %08x\n", machine().describe_context(), data, mem_mask); - m_intc_regs.enable |= data; - //COMBINE_DATA(&m_intc_regs.enable); - //m_intc_regs.status &= m_intc_regs.enable; - //m_intc_regs.hold &= m_intc_regs.enable; - set_interrupt_line(0, 0); - break; - case 0x000c/4: - LOGMASKED(LOG_INTC, "%s: Interrupt Mask = %08x & %08x\n", machine().describe_context(), data, mem_mask); - m_intc_regs.enable &= ~data; - COMBINE_DATA(&m_intc_regs.mask); - //m_intc_regs.status &= m_intc_regs.enable; - //m_intc_regs.hold &= m_intc_regs.enable; - set_interrupt_line(0, 0); - break; - case 0x0010/4: - LOGMASKED(LOG_INTC, "%s: Interrupt Acknowledge = %08x & %08x\n", machine().describe_context(), data, mem_mask); - m_intc_regs.hold &= ~data; - m_intc_regs.status &= ~data; - set_interrupt_line(0, 0); - //COMBINE_DATA(&m_intc_regs.acknowledge); - break; - default: - LOGMASKED(LOG_INTC | LOG_UNKNOWN, "%s: Unknown Register %08x = %08x & %08x\n", machine().describe_context(), 0x0a000000 + (offset << 2), data, mem_mask); - break; - } -} - -TIMER_CALLBACK_MEMBER(pockstat_state::timer_tick) -{ - set_interrupt_line(param == 2 ? INT_TIMER2 : (param == 1 ? INT_TIMER1 : INT_TIMER0), 1); - m_timers[param].count = m_timers[param].period; - timer_start(param); -} - -void pockstat_state::timer_start(int index) -{ - int divisor = 1; - attotime period; - switch (m_timers[index].control & 3) - { - case 0: - case 3: - divisor = 1; - break; - case 1: - divisor = 16; - break; - case 2: - divisor = 256; - break; - } - period = attotime::from_hz(CPU_FREQ[m_clock_regs.mode & 0x0f] / 2) * divisor * m_timers[index].count; - m_timers[index].timer->adjust(period, index); -} - -READ32_MEMBER(pockstat_state::timer_r) -{ - switch (offset) - { - case 0x0000/4: - case 0x0010/4: - case 0x0020/4: - { - const uint32_t index = offset / (0x10/4); - LOGMASKED(LOG_TIMER, "%s: Timer %d Period Read: %08x & %08x\n", machine().describe_context(), index, m_timers[index].period, mem_mask); - return m_timers[index].period; - } - case 0x0004/4: - case 0x0014/4: - case 0x0024/4: - { - const uint32_t index = offset / (0x10/4); - LOGMASKED(LOG_TIMER, "%s: Timer %d Count Read: %08x & %08x\n", machine().describe_context(), index, m_timers[index].count, mem_mask); - if(m_timers[index].control & 4) - { - m_timers[index].count--; - if (m_timers[index].count > m_timers[index].period) - { - m_timers[index].count = m_timers[index].period; - } - return --m_timers[index].count; - } - return m_timers[index].count; - } - case 0x0008/4: - case 0x0018/4: - case 0x0028/4: - { - const uint32_t index = offset / (0x10/4); - LOGMASKED(LOG_TIMER, "%s: Timer %d Control = %08x & %08x\n", machine().describe_context(), index, m_timers[index].control, mem_mask); - return m_timers[index].control; - } - default: - LOGMASKED(LOG_TIMER | LOG_UNKNOWN, "%s: Unknown Register %08x & %08x\n", machine().describe_context(), 0x0a800000 + (offset << 2), mem_mask); - break; - } - return 0; -} - -WRITE32_MEMBER(pockstat_state::timer_w) -{ - switch (offset) - { - case 0x0000/4: - case 0x0010/4: - case 0x0020/4: - { - const uint32_t index = offset / (0x10/4); - LOGMASKED(LOG_TIMER, "%s: Timer %d Period = %08x & %08x\n", machine().describe_context(), index, data, mem_mask); - COMBINE_DATA(&m_timers[index].period); - break; - } - case 0x0004/4: - case 0x0014/4: - case 0x0024/4: - { - const uint32_t index = offset / (0x10/4); - LOGMASKED(LOG_TIMER, "%s: Timer %d Count = %08x & %08x\n", machine().describe_context(), index, data, mem_mask); - COMBINE_DATA(&m_timers[index].count); - break; - } - case 0x0008/4: - case 0x0018/4: - case 0x0028/4: - { - const uint32_t index = offset / (0x10/4); - LOGMASKED(LOG_TIMER, "%s: Timer %d Control = %08x & %08x\n", machine().describe_context(), index, data, mem_mask); - COMBINE_DATA(&m_timers[index].control); - if(m_timers[index].control & 4) - { - timer_start(index); - } - else - { - m_timers[index].timer->adjust(attotime::never, index); - } - break; - } - default: - LOGMASKED(LOG_TIMER | LOG_UNKNOWN, "%s: Unknown Register %08x = %08x & %08x\n", machine().describe_context(), 0x0a800000 + (offset << 2), data, mem_mask); - break; - } -} - -READ32_MEMBER(pockstat_state::clock_r) -{ - switch(offset) - { - case 0x0000/4: - LOGMASKED(LOG_CLOCK, "%s: Clock Mode Read: %08x & %08x\n", machine().describe_context(), m_clock_regs.mode | 0x10, mem_mask); - return m_clock_regs.mode | CLOCK_STEADY; - case 0x0004/4: - LOGMASKED(LOG_CLOCK, "%s: Clock Control Read: %08x & %08x\n", machine().describe_context(), m_clock_regs.control, mem_mask); - return m_clock_regs.control; - default: - LOGMASKED(LOG_CLOCK | LOG_UNKNOWN, "%s: Unknown Register %08x & %08x\n", machine().describe_context(), 0x0b000000 + (offset << 2), mem_mask); - break; - } - return 0; -} - -WRITE32_MEMBER(pockstat_state::clock_w) -{ - switch(offset) - { - case 0x0000/4: - LOGMASKED(LOG_CLOCK, "%s: Clock Mode = %08x & %08x\n", machine().describe_context(), data, mem_mask); - COMBINE_DATA(&m_clock_regs.mode); - m_maincpu->set_unscaled_clock(CPU_FREQ[m_clock_regs.mode & 0x0f]); - break; - case 0x0004/4: - LOGMASKED(LOG_CLOCK, "%s: Clock Control = %08x & %08x\n", machine().describe_context(), data, mem_mask); - COMBINE_DATA(&m_clock_regs.control); - break; - default: - LOGMASKED(LOG_CLOCK | LOG_UNKNOWN, "%s: Unknown Register %08x = %08x & %08x\n", machine().describe_context(), 0x0b000000 + (offset << 2), data, mem_mask); - break; - } -} - -TIMER_CALLBACK_MEMBER(pockstat_state::rtc_tick) -{ - set_interrupt_line(INT_RTC, get_interrupt_line(INT_RTC) ? 0 : 1); - if (!(m_rtc_regs.mode & 1)) - { - m_rtc_regs.time++; - if ((m_rtc_regs.time & 0x0000000f) == 0x0000000a) - { - m_rtc_regs.time &= 0xfffffff0; - m_rtc_regs.time += 0x00000010; - if ((m_rtc_regs.time & 0x000000ff) == 0x00000060) - { - m_rtc_regs.time &= 0xffffff00; - m_rtc_regs.time += 0x00000100; - if ((m_rtc_regs.time & 0x00000f00) == 0x00000a00) - { - m_rtc_regs.time &= 0xfffff0ff; - m_rtc_regs.time += 0x00001000; - if ((m_rtc_regs.time & 0x0000ff00) == 0x00006000) - { - m_rtc_regs.time &= 0xffff00ff; - m_rtc_regs.time += 0x00010000; - if ((m_rtc_regs.time & 0x00ff0000) == 0x00240000) - { - m_rtc_regs.time &= 0xff00ffff; - m_rtc_regs.time += 0x01000000; - if ((m_rtc_regs.time & 0x0f000000) == 0x08000000) - { - m_rtc_regs.time &= 0xf0ffffff; - m_rtc_regs.time |= 0x01000000; - } - } - else if ((m_rtc_regs.time & 0x000f0000) == 0x000a0000) - { - m_rtc_regs.time &= 0xfff0ffff; - m_rtc_regs.time += 0x00100000; - } - } - } - } - } - } - m_rtc_regs.timer->adjust(attotime::from_hz(1)); -} - -READ32_MEMBER(pockstat_state::rtc_r) -{ - switch(offset) - { - case 0x0000/4: - LOGMASKED(LOG_RTC, "%s: RTC Mode Read: %08x & %08x\n", machine().describe_context(), m_rtc_regs.mode, mem_mask); - return m_rtc_regs.mode; - case 0x0004/4: - LOGMASKED(LOG_RTC, "%s: RTC Control Read: %08x & %08x\n", machine().describe_context(), m_rtc_regs.control, mem_mask); - return m_rtc_regs.control; - case 0x0008/4: - LOGMASKED(LOG_RTC, "%s: RTC Time Read: %08x & %08x\n", machine().describe_context(), m_rtc_regs.time, mem_mask); - return m_rtc_regs.time; - case 0x000c/4: - LOGMASKED(LOG_RTC, "%s: RTC Date Read: %08x & %08x\n", machine().describe_context(), m_rtc_regs.date, mem_mask); - return m_rtc_regs.date; - default: - LOGMASKED(LOG_RTC | LOG_UNKNOWN, "%s: Unknown Register %08x & %08x\n", machine().describe_context(), 0x0b800000 + (offset << 2), mem_mask); - break; - } - return 0; -} - -WRITE32_MEMBER(pockstat_state::rtc_w) -{ - switch (offset) - { - case 0x0000/4: - LOGMASKED(LOG_RTC, "%s: RTC Mode = %08x & %08x\n", machine().describe_context(), data, mem_mask); - COMBINE_DATA(&m_rtc_regs.mode); - break; - case 0x0004/4: - LOGMASKED(LOG_RTC, "%s: RTC Control = %08x & %08x\n", machine().describe_context(), data, mem_mask); - if (m_rtc_regs.control == 1 && data == 1) - { - switch (m_rtc_regs.mode >> 1) - { - case 0: // Seconds - m_rtc_regs.time += 0x00000001; - if ((m_rtc_regs.time & 0x0000000f) == 0x0000000a) - { - m_rtc_regs.time &= 0xfffffff0; - m_rtc_regs.time += 0x00000010; - if ((m_rtc_regs.time & 0x000000ff) == 0x00000060) - { - m_rtc_regs.time &= 0xffffff00; - } - } - break; - case 1: // Minutes - m_rtc_regs.time += 0x00000100; - if ((m_rtc_regs.time & 0x00000f00) == 0x00000a00) - { - m_rtc_regs.time &= 0xfffff0ff; - m_rtc_regs.time += 0x00001000; - if ((m_rtc_regs.time & 0x0000ff00) == 0x00006000) - { - m_rtc_regs.time &= 0xffff00ff; - } - } - break; - case 2: // Hours - m_rtc_regs.time += 0x00010000; - if ((m_rtc_regs.time & 0x00ff0000) == 0x00240000) - { - m_rtc_regs.time &= 0xff00ffff; - } - else if ((m_rtc_regs.time & 0x000f0000) == 0x000a0000) - { - m_rtc_regs.time &= 0xfff0ffff; - m_rtc_regs.time += 0x00100000; - } - break; - case 3: // Day of the week - m_rtc_regs.time += 0x01000000; - if ((m_rtc_regs.time & 0x0f000000) == 0x08000000) - { - m_rtc_regs.time &= 0xf0ffffff; - m_rtc_regs.time |= 0x01000000; - } - break; - case 4: // Day - m_rtc_regs.date += 0x00000001; - if ((m_rtc_regs.date & 0x000000ff) == 0x00000032) - { - m_rtc_regs.date &= 0xffffff00; - } - else if ((m_rtc_regs.date & 0x0000000f) == 0x0000000a) - { - m_rtc_regs.date &= 0xfffffff0; - m_rtc_regs.date += 0x00000010; - } - break; - case 5: // Month - m_rtc_regs.date += 0x00000100; - if ((m_rtc_regs.date & 0x0000ff00) == 0x00001300) - { - m_rtc_regs.date &= 0xffffff00; - m_rtc_regs.date |= 0x00000001; - } - else if ((m_rtc_regs.date & 0x00000f00) == 0x00000a00) - { - m_rtc_regs.date &= 0xfffff0ff; - m_rtc_regs.date += 0x00001000; - } - break; - case 6: // Year (LSB) - m_rtc_regs.date += 0x00010000; - if ((m_rtc_regs.date & 0x000f0000) == 0x000a0000) - { - m_rtc_regs.date &= 0xfff0ffff; - m_rtc_regs.date += 0x00100000; - if ((m_rtc_regs.date & 0x00f00000) == 0x00a00000) - { - m_rtc_regs.date &= 0xff00ffff; - } - } - break; - case 7: // Year (MSB) - break; - } - m_rtc_regs.control = 0; - } - else if(m_rtc_regs.control == 0) - { - COMBINE_DATA(&m_rtc_regs.control); - } - break; - default: - LOGMASKED(LOG_RTC | LOG_UNKNOWN, "%s: Unknown Register %08x = %08x & %08x\n", machine().describe_context(), 0x0b800000 + (offset << 2), data, mem_mask); - break; - } -} - - -READ32_MEMBER(pockstat_state::lcd_r) -{ - switch (offset) - { - case 0x0000/4: - LOGMASKED(LOG_LCD, "%s: LCD Control Read: %08x & %08x\n", machine().describe_context(), m_lcd_control | 0x100, mem_mask); - return m_lcd_control; - default: - LOGMASKED(LOG_LCD | LOG_UNKNOWN, "%s: Unknown Register %08x & %08x\n", machine().describe_context(), 0x0d000000 + (offset << 2), mem_mask); - break; - } - return 0; -} - -WRITE32_MEMBER(pockstat_state::lcd_w) -{ - switch (offset) - { - case 0x0000/4: - LOGMASKED(LOG_LCD, "%s: LCD Control = %08x & %08x\n", machine().describe_context(), data, mem_mask); - COMBINE_DATA(&m_lcd_control); - break; - default: - LOGMASKED(LOG_LCD | LOG_UNKNOWN, "%s: Unknown Register %08x = %08x & %08x\n", machine().describe_context(), 0x0d000000 + (offset << 2), data, mem_mask); - break; - } -} - -INPUT_CHANGED_MEMBER(pockstat_state::input_update) -{ - uint32_t buttons = ioport("BUTTONS")->read(); - - set_interrupt_line(INT_BTN_ACTION, (buttons & 1) ? 1 : 0); - set_interrupt_line(INT_BTN_RIGHT, (buttons & 2) ? 1 : 0); - set_interrupt_line(INT_BTN_LEFT, (buttons & 4) ? 1 : 0); - set_interrupt_line(INT_BTN_DOWN, (buttons & 8) ? 1 : 0); - set_interrupt_line(INT_BTN_UP, (buttons & 16) ? 1 : 0); -} - -READ32_MEMBER(pockstat_state::rombank_r) -{ - int32_t bank = (offset >> 11) & 0x0f; - for (int index = 0; index < 32; index++) - { - if (m_ftlb_regs.valid & (1 << index)) - { - if (m_ftlb_regs.entry[index] == bank) - { - return m_cart->read32_rom(index * (0x2000/4) + (offset & (0x1fff/4)), mem_mask); - } - } - } - return m_cart->read32_rom(offset & 0x7fff, mem_mask); -} - - -// Horrible hack, probably wrong -WRITE32_MEMBER(pockstat_state::flash_w) -{ - if (offset == (0x55a8/4)) - { - m_flash_write_enable_count++; - return; - } - if (offset == (0x2a54/4)) - { - m_flash_write_enable_count++; - return; - } - if (m_flash_write_enable_count == 3) - { - m_flash_write_enable_count = 0; - m_flash_write_count = 0x40; - return; - } - if (m_flash_write_count) - { - m_flash_write_count--; - COMBINE_DATA(&((uint32_t*)(m_cart_rom->base()))[offset]); - } -} - -READ32_MEMBER(pockstat_state::flash_r) -{ - return m_cart->read32_rom(offset, mem_mask); -} - -READ32_MEMBER(pockstat_state::audio_r) -{ - LOGMASKED(LOG_AUDIO | LOG_UNKNOWN, "%s: Unknown Audio Read: %08x = %08x & %08x\n", machine().describe_context(), 0xd800000 + (offset << 2), 0x10, mem_mask); - return 0; -} - -WRITE32_MEMBER(pockstat_state::audio_w) -{ - LOGMASKED(LOG_AUDIO | LOG_UNKNOWN, "%s: Unknown Audio Write: %08x = %08x & %08x\n", machine().describe_context(), 0xd800000 + (offset << 2), data, mem_mask); -} - -void pockstat_state::mem_map(address_map &map) -{ - map(0x00000000, 0x000007ff).ram(); - map(0x02000000, 0x02ffffff).r(FUNC(pockstat_state::rombank_r)); - map(0x04000000, 0x04003fff).rom().region("maincpu", 0); - map(0x06000000, 0x06000307).rw(FUNC(pockstat_state::ftlb_r), FUNC(pockstat_state::ftlb_w)); - map(0x08000000, 0x0801ffff).rw(FUNC(pockstat_state::flash_r), FUNC(pockstat_state::flash_w)); - map(0x0a000000, 0x0a000013).rw(FUNC(pockstat_state::intc_r), FUNC(pockstat_state::intc_w)); - map(0x0a800000, 0x0a80002b).rw(FUNC(pockstat_state::timer_r), FUNC(pockstat_state::timer_w)); - map(0x0b000000, 0x0b000007).rw(FUNC(pockstat_state::clock_r), FUNC(pockstat_state::clock_w)); - map(0x0b800000, 0x0b80000f).rw(FUNC(pockstat_state::rtc_r), FUNC(pockstat_state::rtc_w)); - map(0x0d000000, 0x0d000003).rw(FUNC(pockstat_state::lcd_r), FUNC(pockstat_state::lcd_w)); - map(0x0d000100, 0x0d00017f).ram().share("lcd_buffer"); - map(0x0d80000c, 0x0d80000f).rw(FUNC(pockstat_state::audio_r), FUNC(pockstat_state::audio_w)); - map(0x0d800014, 0x0d800015).w("dac", FUNC(dac_word_interface::data_w)); -} - -/* Input ports */ -static INPUT_PORTS_START( pockstat ) - PORT_START("BUTTONS") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Action Button") PORT_CHANGED_MEMBER(DEVICE_SELF, pockstat_state, input_update, 0) - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_NAME("Right") PORT_CHANGED_MEMBER(DEVICE_SELF, pockstat_state, input_update, 0) - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) PORT_NAME("Left") PORT_CHANGED_MEMBER(DEVICE_SELF, pockstat_state, input_update, 0) - PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) PORT_NAME("Down") PORT_CHANGED_MEMBER(DEVICE_SELF, pockstat_state, input_update, 0) - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) PORT_NAME("Up") PORT_CHANGED_MEMBER(DEVICE_SELF, pockstat_state, input_update, 0) - PORT_BIT( 0xe0, IP_ACTIVE_HIGH, IPT_UNUSED) -INPUT_PORTS_END - -void pockstat_state::machine_start() -{ - for (uint32_t index = 0; index < TIMER_COUNT; index++) - { - m_timers[index].timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pockstat_state::timer_tick), this)); - m_timers[index].timer->adjust(attotime::never, index); - } - - m_rtc_regs.time = 0x01000000; - m_rtc_regs.date = 0x19990101; - - m_rtc_regs.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pockstat_state::rtc_tick),this)); - m_rtc_regs.timer->adjust(attotime::from_hz(1), TIMER_COUNT); - - std::string region_tag; - m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str()); - - save_item(NAME(m_ftlb_regs.control)); - save_item(NAME(m_ftlb_regs.stat)); - save_item(NAME(m_ftlb_regs.valid)); - save_item(NAME(m_ftlb_regs.wait1)); - save_item(NAME(m_ftlb_regs.wait2)); - save_item(NAME(m_ftlb_regs.entry)); - - save_item(NAME(m_intc_regs.hold)); - save_item(NAME(m_intc_regs.status)); - save_item(NAME(m_intc_regs.enable)); - save_item(NAME(m_intc_regs.mask)); - - save_item(NAME(m_timers[0].period)); - save_item(NAME(m_timers[0].count)); - save_item(NAME(m_timers[0].control)); - save_item(NAME(m_timers[1].period)); - save_item(NAME(m_timers[1].count)); - save_item(NAME(m_timers[1].control)); - save_item(NAME(m_timers[2].period)); - save_item(NAME(m_timers[2].count)); - save_item(NAME(m_timers[2].control)); - - save_item(NAME(m_clock_regs.mode)); - save_item(NAME(m_clock_regs.control)); - - save_item(NAME(m_rtc_regs.mode)); - save_item(NAME(m_rtc_regs.control)); - save_item(NAME(m_rtc_regs.time)); - save_item(NAME(m_rtc_regs.date)); - - save_item(NAME(m_flash_write_enable_count)); - save_item(NAME(m_flash_write_count)); - - save_item(NAME(m_lcd_control)); -} - -void pockstat_state::machine_reset() -{ - m_maincpu->set_state_int(ARM7_R15, 0x4000000); - - m_flash_write_enable_count = 0; - m_flash_write_count = 0; -} - -uint32_t pockstat_state::screen_update_pockstat(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - for (int y = 0; y < 32; y++) - { - uint32_t *scanline = &bitmap.pix32(y); - for (int x = 0; x < 32; x++) - { - if (m_lcd_control != 0) // Hack - { - if (BIT(m_lcd_buffer[y], x)) - scanline[x] = 0x00000000; - else - scanline[x] = 0x00ffffff; - } - else - scanline[x] = 0x00ffffff; - } - } - return 0; -} - -DEVICE_IMAGE_LOAD_MEMBER(pockstat_state::flash_load) -{ - static const char *gme_id = "123-456-STD"; - char cart_id[0xf40]; - uint32_t size = image.length(); - - if (size != 0x20f40) - return image_init_result::FAIL; - - image.fread(cart_id, 0xf40); - - for (int i = 0; i < strlen(gme_id); i++) - { - if (cart_id[i] != gme_id[i]) - return image_init_result::FAIL; - } - - m_cart->rom_alloc(0x20000, GENERIC_ROM32_WIDTH, ENDIANNESS_LITTLE); - image.fread(m_cart->get_rom_base(), 0x20000); - - return image_init_result::PASS; -} - -void pockstat_state::pockstat(machine_config &config) -{ - static constexpr uint32_t DEFAULT_CLOCK = 2000000; - - /* basic machine hardware */ - ARM7(config, m_maincpu, DEFAULT_CLOCK); - m_maincpu->set_addrmap(AS_PROGRAM, &pockstat_state::mem_map); - - /* video hardware */ - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD)); - screen.set_refresh_hz(50); - screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */ - screen.set_size(32, 32); - screen.set_visarea(0, 32-1, 0, 32-1); - screen.set_screen_update(FUNC(pockstat_state::screen_update_pockstat)); - - PALETTE(config, "palette", palette_device::MONOCHROME); - - SPEAKER(config, "speaker").front_center(); - DAC_16BIT_R2R_TWOS_COMPLEMENT(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC - voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref")); - vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT); - vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT); - - /* cartridge */ - GENERIC_CARTSLOT(config, m_cart, generic_plain_slot, "pockstat_cart", "gme"); - m_cart->set_width(GENERIC_ROM32_WIDTH); - m_cart->set_endian(ENDIANNESS_LITTLE); - m_cart->set_device_load(FUNC(pockstat_state::flash_load)); -} - -/* ROM definition */ -ROM_START( pockstat ) - ROM_REGION( 0x4000, "maincpu", 0 ) - ROM_LOAD( "kernel.bin", 0x0000, 0x4000, CRC(5fb47dd8) SHA1(6ae880493ddde880827d1e9f08e9cb2c38f9f2ec) ) -ROM_END - -/* Driver */ - -// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -CONS( 1999, pockstat, 0, 0, pockstat, pockstat, pockstat_state, empty_init, "Sony Computer Entertainment Inc", "Sony PocketStation", MACHINE_SUPPORTS_SAVE ) |