diff options
Diffstat (limited to 'src/mess/machine/samcoupe.c')
-rw-r--r-- | src/mess/machine/samcoupe.c | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/src/mess/machine/samcoupe.c b/src/mess/machine/samcoupe.c new file mode 100644 index 00000000000..4e32e051f49 --- /dev/null +++ b/src/mess/machine/samcoupe.c @@ -0,0 +1,278 @@ +/*************************************************************************** + + SAM Coupe Driver - Written By Lee Hammerton, Dirk Best + +***************************************************************************/ + +#include "emu.h" +#include "includes/samcoupe.h" +#include "machine/msm6242.h" +#include "machine/ram.h" + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +#define LMPR_RAM0 0x20 /* If bit set ram is paged into bank 0, else its rom0 */ +#define LMPR_ROM1 0x40 /* If bit set rom1 is paged into bank 3, else its ram */ +#define HMPR_MCNTRL 0x80 /* If set external RAM is enabled */ + + +/*************************************************************************** + MEMORY BANKING +***************************************************************************/ + +static void samcoupe_update_bank(address_space *space, int bank_num, UINT8 *memory, int is_readonly) +{ + char bank[10]; + sprintf(bank,"bank%d",bank_num); + samcoupe_state *state = space->machine().driver_data<samcoupe_state>(); + if (memory) + { + state->membank(bank)->set_base(memory); + space->install_read_bank (((bank_num-1) * 0x4000), ((bank_num-1) * 0x4000) + 0x3FFF, bank); + if (is_readonly) { + space->unmap_write(((bank_num-1) * 0x4000), ((bank_num-1) * 0x4000) + 0x3FFF); + } else { + space->install_write_bank(((bank_num-1) * 0x4000), ((bank_num-1) * 0x4000) + 0x3FFF, bank); + } + } else { + space->nop_readwrite(((bank_num-1) * 0x4000), ((bank_num-1) * 0x4000) + 0x3FFF); + } +} + + +static void samcoupe_install_ext_mem(address_space *space) +{ + samcoupe_state *state = space->machine().driver_data<samcoupe_state>(); + UINT8 *mem; + + /* bank 3 */ + if (state->m_lext >> 6 < space->machine().device<ram_device>(RAM_TAG)->size() >> 20) + mem = &space->machine().device<ram_device>(RAM_TAG)->pointer()[(space->machine().device<ram_device>(RAM_TAG)->size() & 0xfffff) + (state->m_lext >> 6) * 0x100000 + (state->m_lext & 0x3f) * 0x4000]; + else + mem = NULL; + + samcoupe_update_bank(space, 3, mem, FALSE); + + /* bank 4 */ + if (state->m_hext >> 6 < space->machine().device<ram_device>(RAM_TAG)->size() >> 20) + mem = &space->machine().device<ram_device>(RAM_TAG)->pointer()[(space->machine().device<ram_device>(RAM_TAG)->size() & 0xfffff) + (state->m_hext >> 6) * 0x100000 + (state->m_hext & 0x3f) * 0x4000]; + else + mem = NULL; + + samcoupe_update_bank(space, 4, mem, FALSE); +} + + +void samcoupe_update_memory(address_space *space) +{ + samcoupe_state *state = space->machine().driver_data<samcoupe_state>(); + const int PAGE_MASK = ((space->machine().device<ram_device>(RAM_TAG)->size() & 0xfffff) / 0x4000) - 1; + UINT8 *rom = state->memregion("maincpu")->base(); + UINT8 *memory; + int is_readonly; + + /* BANK1 */ + if (state->m_lmpr & LMPR_RAM0) /* Is ram paged in at bank 1 */ + { + if ((state->m_lmpr & 0x1F) <= PAGE_MASK) + memory = &space->machine().device<ram_device>(RAM_TAG)->pointer()[(state->m_lmpr & PAGE_MASK) * 0x4000]; + else + memory = NULL; /* Attempt to page in non existant ram region */ + is_readonly = FALSE; + } + else + { + memory = rom; /* Rom0 paged in */ + is_readonly = TRUE; + } + samcoupe_update_bank(space, 1, memory, is_readonly); + + + /* BANK2 */ + if (((state->m_lmpr + 1) & 0x1f) <= PAGE_MASK) + memory = &space->machine().device<ram_device>(RAM_TAG)->pointer()[((state->m_lmpr + 1) & PAGE_MASK) * 0x4000]; + else + memory = NULL; /* Attempt to page in non existant ram region */ + samcoupe_update_bank(space, 2, memory, FALSE); + + /* only update bank 3 and 4 when external memory is not enabled */ + if (state->m_hmpr & HMPR_MCNTRL) + { + samcoupe_install_ext_mem(space); + } + else + { + /* BANK3 */ + if ((state->m_hmpr & 0x1F) <= PAGE_MASK ) + memory = &space->machine().device<ram_device>(RAM_TAG)->pointer()[(state->m_hmpr & PAGE_MASK)*0x4000]; + else + memory = NULL; /* Attempt to page in non existant ram region */ + samcoupe_update_bank(space, 3, memory, FALSE); + + + /* BANK4 */ + if (state->m_lmpr & LMPR_ROM1) /* Is Rom1 paged in at bank 4 */ + { + memory = rom + 0x4000; + is_readonly = TRUE; + } + else + { + if (((state->m_hmpr + 1) & 0x1f) <= PAGE_MASK) + memory = &space->machine().device<ram_device>(RAM_TAG)->pointer()[((state->m_hmpr + 1) & PAGE_MASK) * 0x4000]; + else + memory = NULL; /* Attempt to page in non existant ram region */ + is_readonly = FALSE; + } + samcoupe_update_bank(space, 4, memory, FALSE); + } + + /* video memory location */ + if (state->m_vmpr & 0x40) /* if bit set in 2 bank screen mode */ + state->m_videoram = &space->machine().device<ram_device>(RAM_TAG)->pointer()[((state->m_vmpr & 0x1e) & PAGE_MASK) * 0x4000]; + else + state->m_videoram = &space->machine().device<ram_device>(RAM_TAG)->pointer()[((state->m_vmpr & 0x1f) & PAGE_MASK) * 0x4000]; +} + + +WRITE8_MEMBER(samcoupe_state::samcoupe_ext_mem_w) +{ + address_space *space_program = machine().device("maincpu")->memory().space(AS_PROGRAM); + + if (offset & 1) + m_hext = data; + else + m_lext = data; + + /* external RAM enabled? */ + if (m_hmpr & HMPR_MCNTRL) + { + samcoupe_install_ext_mem(space_program); + } +} + + +/*************************************************************************** + REAL TIME CLOCK +***************************************************************************/ + +static READ8_DEVICE_HANDLER( samcoupe_rtc_r ) +{ + address_space *spaceio = device->machine().device("maincpu")->memory().space(AS_IO); + msm6242_device *rtc = dynamic_cast<msm6242_device*>(device); + return rtc->read(*spaceio,offset >> 12); +} + + +static WRITE8_DEVICE_HANDLER( samcoupe_rtc_w ) +{ + address_space *spaceio = device->machine().device("maincpu")->memory().space(AS_IO); + msm6242_device *rtc = dynamic_cast<msm6242_device*>(device); + rtc->write(*spaceio,offset >> 12, data); +} + + +/*************************************************************************** + MOUSE +***************************************************************************/ + +static TIMER_CALLBACK( samcoupe_mouse_reset ) +{ + samcoupe_state *state = machine.driver_data<samcoupe_state>(); + state->m_mouse_index = 0; +} + +UINT8 samcoupe_mouse_r(running_machine &machine) +{ + samcoupe_state *state = machine.driver_data<samcoupe_state>(); + UINT8 result; + + /* on a read, reset the timer */ + state->m_mouse_reset->adjust(attotime::from_usec(50)); + + /* update when we are about to read the first real values */ + if (state->m_mouse_index == 2) + { + /* update values */ + int mouse_x = machine.root_device().ioport("mouse_x")->read(); + int mouse_y = machine.root_device().ioport("mouse_y")->read(); + + int mouse_dx = state->m_mouse_x - mouse_x; + int mouse_dy = state->m_mouse_y - mouse_y; + + state->m_mouse_x = mouse_x; + state->m_mouse_y = mouse_y; + + /* button state */ + state->m_mouse_data[2] = machine.root_device().ioport("mouse_buttons")->read(); + + /* y-axis */ + state->m_mouse_data[3] = (mouse_dy & 0xf00) >> 8; + state->m_mouse_data[4] = (mouse_dy & 0x0f0) >> 4; + state->m_mouse_data[5] = (mouse_dy & 0x00f) >> 0; + + /* x-axis */ + state->m_mouse_data[6] = (mouse_dx & 0xf00) >> 8; + state->m_mouse_data[7] = (mouse_dx & 0x0f0) >> 4; + state->m_mouse_data[8] = (mouse_dx & 0x00f) >> 0; + } + + /* get current value */ + result = state->m_mouse_data[state->m_mouse_index++]; + + /* reset if we are at the end */ + if (state->m_mouse_index == sizeof(state->m_mouse_data)) + state->m_mouse_index = 1; + + return result; +} + +MACHINE_START( samcoupe ) +{ + samcoupe_state *state = machine.driver_data<samcoupe_state>(); + state->m_mouse_reset = machine.scheduler().timer_alloc(FUNC(samcoupe_mouse_reset)); + + /* schedule our video updates */ + state->m_video_update_timer = machine.scheduler().timer_alloc(FUNC(sam_video_update_callback)); + state->m_video_update_timer->adjust(machine.primary_screen->time_until_pos(0, 0)); +} + +/*************************************************************************** + RESET +***************************************************************************/ + +MACHINE_RESET( samcoupe ) +{ + address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM); + address_space *spaceio = machine.device("maincpu")->memory().space(AS_IO); + samcoupe_state *state = machine.driver_data<samcoupe_state>(); + + /* initialize state */ + state->m_lmpr = 0x0f; /* ROM0 paged in, ROM1 paged out RAM Banks */ + state->m_hmpr = 0x01; + state->m_vmpr = 0x81; + state->m_line_int = 0xff; /* line interrupts disabled */ + state->m_status = 0x1f; /* no interrupts active */ + + /* initialize mouse */ + state->m_mouse_index = 0; + state->m_mouse_data[0] = 0xff; + state->m_mouse_data[1] = 0xff; + + if (machine.root_device().ioport("config")->read() & 0x01) + { + /* install RTC */ + device_t *rtc = machine.device("sambus_clock"); + spaceio->install_legacy_readwrite_handler(*rtc, 0xef, 0xef, 0xffff, 0xff00, FUNC(samcoupe_rtc_r), FUNC(samcoupe_rtc_w)); + } + else + { + /* no RTC support */ + spaceio->unmap_readwrite(0xef, 0xef, 0xffff, 0xff00); + } + + /* initialize memory */ + samcoupe_update_memory(space); +} |