// license:BSD-3-Clause
// copyright-holders:Miodrag Milanovic
/***************************************************************************
Specialist machine driver by Miodrag Milanovic
20/03/2008 Cassette support
15/03/2008 Preliminary driver.
****************************************************************************/
#include "emu.h"
#include "includes/special.h"
/* Driver initialization */
void special_state::init_special()
{
/* set initialy ROM to be visible on first bank */
uint8_t *RAM = m_region_maincpu->base();
memset(RAM,0x0000,0x3000); // make first page empty by default
m_bank1->configure_entries(1, 2, RAM, 0x0000);
m_bank1->configure_entries(0, 2, RAM, 0xc000);
}
READ8_MEMBER( special_state::specialist_8255_porta_r )
{
for (int i = 0; i < 8; i++)
if (m_io_line[i]->read() != 0xff)
return (1 << i) ^ 0xff;
return 0xff;
}
READ8_MEMBER( special_state::specialist_8255_portb_r )
{
uint8_t dat = 0xff;
for (int i = 0; i < 8; i++)
if (!BIT(m_specialist_8255_porta, i))
dat &= m_io_line[i]->read();
for (int i = 0; i < 4; i++)
if (!BIT(m_specialist_8255_portc, i))
dat &= m_io_line[8 + i]->read();
// shift key
if (BIT(~m_io_line[12]->read(), 0))
dat &= 0xfd;
// cassette
if (m_cassette->input() > 0.01)
dat &= 0xfe;
// strobe if a key is pressed
if (dat < 0xfc) dat &= 0x7f;
return dat;
}
READ8_MEMBER( special_state::specimx_8255_portb_r )
{
uint8_t dat = 0xff;
for (int i = 0; i < 8; i++)
if (!BIT(m_specialist_8255_porta, i))
dat &= m_io_line[i]->read();
for (int i = 0; i < 4; i++)
if (!BIT(m_specialist_8255_portc, i))
dat &= m_io_line[8 + i]->read();
// shift key
if (BIT(~m_io_line[12]->read(), 0))
dat &= 0xfd;
// cassette
if (m_cassette->input() > 0.01)
dat &= 0xfe;
return dat;
}
READ8_MEMBER( special_state::specialist_8255_portc_r )
{
for (int i = 0; i < 4; i++)
if (m_io_line[8 + i]->read() != 0xff)
return (1 << i) ^ 0x0f;
return 0x0f;
}
WRITE8_MEMBER( special_state::specialist_8255_porta_w )
{
m_specialist_8255_porta = data;
}
WRITE8_MEMBER( special_state::specialist_8255_portb_w )
{
m_specialist_8255_portb = data;
}
WRITE8_MEMBER( special_state::specialist_8255_portc_w )
{
m_specialist_8255_portc = data;
m_cassette->output(BIT(data, 7) ? 1 : -1);
m_dac->write(BIT(data, 5)); //beeper
}
void special_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
switch (id)
{
case TIMER_RESET:
m_bank1->set_entry(0);
break;
case TIMER_PIT8253_GATES:
{
m_pit->write_gate0(0);
m_pit->write_gate1(0);
m_pit->write_gate2(0);
break;
}
default:
assert_always(false, "Unknown id in special_state::device_timer");
}
}
MACHINE_RESET_MEMBER(special_state,special)
{
timer_set(attotime::from_usec(10), TIMER_RESET);
m_bank1->set_entry(1);
}
/*
Specialist MX
*/
WRITE8_MEMBER( special_state::video_memory_w )
{
m_ram->pointer()[0x9000 + offset] = data;
m_specimx_colorram[offset] = m_specimx_color;
}
WRITE8_MEMBER( special_state::specimx_video_color_w )
{
m_specimx_color = data;
}
READ8_MEMBER( special_state::specimx_video_color_r )
{
return m_specimx_color;
}
void special_state::specimx_set_bank(offs_t i, uint8_t data)
{
address_space &space = m_maincpu->space(AS_PROGRAM);
uint8_t *ram = m_ram->pointer();
space.install_write_bank(0xc000, 0xffbf, "bank3");
space.install_write_bank(0xffc0, 0xffdf, "bank4");
m_bank4->set_base(ram + 0xffc0);
switch(i)
{
case 0 :
space.install_write_bank(0x0000, 0x8fff, "bank1");
space.install_write_handler(0x9000, 0xbfff, write8_delegate(FUNC(special_state::video_memory_w), this));
m_bank1->set_base(ram);
m_bank2->set_base(ram + 0x9000);
m_bank3->set_base(ram + 0xc000);
break;
case 1 :
space.install_write_bank(0x0000, 0x8fff, "bank1");
space.install_write_bank(0x9000, 0xbfff, "bank2");
m_bank1->set_base(ram + 0x10000);
m_bank2->set_base(ram + 0x19000);
m_bank3->set_base(ram + 0x1c000);
break;
case 2 :
space.unmap_write(0x0000, 0x8fff);
space.unmap_write(0x9000, 0xbfff);
m_bank1->set_base(m_region_maincpu->base() + 0x10000);
m_bank2->set_base(m_region_maincpu->base() + 0x19000);
if (data & 0x80)
m_bank3->set_base(ram + 0x1c000);
else
m_bank3->set_base(ram + 0xc000);
break;
}
}
WRITE8_MEMBER( special_state::specimx_select_bank )
{
specimx_set_bank(offset, data);
}
MACHINE_START_MEMBER(special_state,specimx)
{
m_drive = 0;
}
MACHINE_RESET_MEMBER(special_state,specimx)
{
specimx_set_bank(2, 0); // Initiali load ROM disk
timer_set(attotime::zero, TIMER_PIT8253_GATES);
}
READ8_MEMBER( special_state::specimx_disk_ctrl_r )
{
return 0xff;
}
WRITE_LINE_MEMBER( special_state::fdc_drq )
{
/* Clears HALT state of CPU when data is ready to read */
if(state) {
m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
}
}
WRITE8_MEMBER( special_state::specimx_disk_ctrl_w )
{
floppy_image_device *floppy = nullptr;
floppy_connector *con = m_fdd[m_drive & 1].target();
if(con)
floppy = con->get_device();
m_fdc->set_floppy(floppy);
floppy->mon_w(0);
switch(offset)
{
case 0 :
m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
break;
case 2 :
floppy->ss_w(data & 1);
break;
case 3 :
m_drive = data & 1;
break;
}
}
/*
Erik
*/
void special_state::erik_set_bank()
{
uint8_t bank1 = m_RR_register & 3;
uint8_t bank2 = (m_RR_register >> 2) & 3;
uint8_t bank3 = (m_RR_register >> 4) & 3;
uint8_t bank4 = (m_RR_register >> 6) & 3;
uint8_t *mem = m_region_maincpu->base();
uint8_t *ram = m_ram->pointer();
address_space &space = m_maincpu->space(AS_PROGRAM);
space.install_write_bank(0x0000, 0x3fff, "bank1");
space.install_write_bank(0x4000, 0x8fff, "bank2");
space.install_write_bank(0x9000, 0xbfff, "bank3");
space.install_write_bank(0xc000, 0xefff, "bank4");
space.install_write_bank(0xf000, 0xf7ff, "bank5");
space.install_write_bank(0xf800, 0xffff, "bank6");
switch(bank1)
{
case 1:
case 2:
case 3:
m_bank1->set_base(ram + 0x10000*(bank1-1));
break;
case 0:
space.unmap_write(0x0000, 0x3fff);
m_bank1->set_base(mem + 0x10000);
break;
}
switch(bank2)
{
case 1:
case 2:
case 3:
m_bank2->set_base(ram + 0x10000*(bank2-1) + 0x4000);
break;
case 0:
space.unmap_write(0x4000, 0x8fff);
m_bank2->set_base(mem + 0x14000);
break;
}
switch(bank3)
{
case 1:
case 2:
case 3:
m_bank3->set_base(ram + 0x10000*(bank3-1) + 0x9000);
break;
case 0:
space.unmap_write(0x9000, 0xbfff);
m_bank3->set_base(mem + 0x19000);
break;
}
switch(bank4)
{
case 1:
case 2:
case 3:
m_bank4->set_base(ram + 0x10000*(bank4-1) + 0x0c000);
m_bank5->set_base(ram + 0x10000*(bank4-1) + 0x0f000);
m_bank6->set_base(ram + 0x10000*(bank4-1) + 0x0f800);
break;
case 0:
space.unmap_write(0xc000, 0xefff);
m_bank4->set_base(mem + 0x1c000);
space.unmap_write(0xf000, 0xf7ff);
space.nop_read(0xf000, 0xf7ff);
space.install_readwrite_handler(0xf800, 0xf803, 0, 0x7fc, 0, read8_delegate(FUNC(i8255_device::read), (i8255_device*)m_ppi), write8_delegate(FUNC(i8255_device::write), (i8255_device*)m_ppi));
break;
}
}
void special_state::init_erik()
{
m_erik_color_1 = 0;
m_erik_color_2 = 0;
m_erik_background = 0;
}
MACHINE_RESET_MEMBER(special_state,erik)
{
m_RR_register = 0x00;
m_RC_register = 0x00;
erik_set_bank();
}
READ8_MEMBER( special_state::erik_rr_reg_r )
{
return m_RR_register;
}
WRITE8_MEMBER( special_state::erik_rr_reg_w )
{
m_RR_register = data;
erik_set_bank();
}
READ8_MEMBER( special_state::erik_rc_reg_r )
{
return m_RC_register;
}
WRITE8_MEMBER( special_state::erik_rc_reg_w )
{
m_RC_register = data;
m_erik_color_1 = m_RC_register & 7;
m_erik_color_2 = (m_RC_register >> 3) & 7;
m_erik_background = BIT(m_RC_register, 6) + BIT(m_RC_register, 7) * 4;
}
READ8_MEMBER( special_state::erik_disk_reg_r )
{
return 0xff;
}
WRITE8_MEMBER( special_state::erik_disk_reg_w )
{
/*
wd17xx_set_side (m_fdc,data & 1);
wd17xx_set_drive(m_fdc,(data >> 1) & 1);
wd17xx_dden_w(m_fdc, BIT(data, 2));
floppy_mon_w(floppy_get_device(machine(), BIT(data, 1)), 0);
floppy_mon_w(floppy_get_device(machine(), BIT(data, 1) ^ 1), 1);
floppy_drive_set_ready_state(floppy_get_device(machine(), BIT(data, 1)), 1, 1);*/
}