summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/thomson.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/thomson.cpp')
-rw-r--r--src/mame/machine/thomson.cpp4560
1 files changed, 0 insertions, 4560 deletions
diff --git a/src/mame/machine/thomson.cpp b/src/mame/machine/thomson.cpp
deleted file mode 100644
index f8201ded8da..00000000000
--- a/src/mame/machine/thomson.cpp
+++ /dev/null
@@ -1,4560 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Antoine Mine
-/**********************************************************************
-
- Copyright (C) Antoine Mine' 2006
-
- Thomson 8-bit computers
-
-**********************************************************************/
-
-#include "emu.h"
-#include "includes/thomson.h"
-#include "machine/6821pia.h"
-#include "machine/ram.h"
-
-#define VERBOSE 0
-#define VERBOSE_IRQ 0
-#define VERBOSE_KBD 0 /* TO8 / TO9 / TO9+ keyboard */
-#define VERBOSE_BANK 0
-#define VERBOSE_VIDEO 0 /* video & lightpen */
-#define VERBOSE_IO 0 /* serial & parallel I/O */
-#define VERBOSE_MIDI 0
-
-#define PRINT(x) osd_printf_info x
-
-#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
-#define VLOG(x) do { if (VERBOSE > 1) logerror x; } while (0)
-#define LOG_IRQ(x) do { if (VERBOSE_IRQ) logerror x; } while (0)
-#define LOG_KBD(x) do { if (VERBOSE_KBD) logerror x; } while (0)
-#define LOG_BANK(x) do { if (VERBOSE_BANK) logerror x; } while (0)
-#define LOG_VIDEO(x) do { if (VERBOSE_VIDEO) logerror x; } while (0)
-#define LOG_IO(x) do { if (VERBOSE_IO) logerror x; } while (0)
-#define LOG_MIDI(x) do { if (VERBOSE_MIDI) logerror x; } while (0)
-
-/* This set to 1 handle the .k7 files without passing through .wav */
-/* It must be set accordingly in formats/thom_cas.c */
-#define K7_SPEED_HACK 0
-
-
-/*-------------- TO7 ------------*/
-
-
-/* On the TO7 & compatible (TO7/70,TO8,TO9, but not MO5,MO6), bits are coded
- in FM format with a 1.1 ms period (900 bauds):
- - 0 is 5 periods at 4.5 kHz
- - 1 is 7 periods at 6.3 kHz
-
- Moreover, a byte is represented using 11 bits:
- - one 0 start bit
- - eight data bits (low bit first)
- - two 1 stop bits
-
- There are also long (1 s) sequences of 1 bits to re-synchronize the
- cassette at places the motor can be cut off and back on (e.g., between
- files).
-
- The computer outputs a modulated wave that is directly put on the cassette.
- However, the input is demodulated by the cassette-reader before being
- sent to the computer: we got 0 when the signal is around 4.5 kHz and
- 1 when the signal is around 6.3 kHz.
-*/
-
-#define TO7_BIT_LENGTH 0.001114
-
-/* 1-bit cassette input to the computer
- inside the controller, two frequency filters (adjusted to 6.3 and 4.5 kHz)
- and a comparator demodulate the raw signal into 0s and 1s.
-*/
-int thomson_state::to7_get_cassette()
-{
- if ( m_cassette->exists() )
- {
- cassette_image* cass = m_cassette->get_image();
- cassette_state state = m_cassette->get_state();
- double pos = m_cassette->get_position();
- int bitpos = pos / TO7_BIT_LENGTH;
-
- if ( (state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED )
- return 1;
-
- if ( K7_SPEED_HACK && m_to7_k7_bits )
- {
- /* hack, feed existing bits */
- if ( bitpos >= m_to7_k7_bitsize )
- bitpos = m_to7_k7_bitsize -1;
- VLOG (( "$%04x %f to7_get_cassette: state=$%X pos=%f samppos=%i bit=%i\n",
- m_maincpu->pc(), machine().time().as_double(), state, pos, bitpos,
- m_to7_k7_bits[ bitpos ] ));
- return m_to7_k7_bits[ bitpos ];
- }
- else
- {
- /* demodulate wave signal on-the-fly */
- /* we simply count sign changes... */
- int k, chg;
- int8_t data[40];
- cass->get_samples( 0, pos, TO7_BIT_LENGTH * 15. / 14., 40, 1, data, 0 );
-
- for ( k = 1, chg = 0; k < 40; k++ )
- {
- if ( data[ k - 1 ] >= 0 && data[ k ] < 0 )
- chg++;
- if ( data[ k - 1 ] <= 0 && data[ k ] > 0 )
- chg++;
- }
- k = ( chg >= 13 ) ? 1 : 0;
- VLOG (( "$%04x %f to7_get_cassette: state=$%X pos=%f samppos=%i bit=%i (%i)\n",
- m_maincpu->pc(), machine().time().as_double(), state, pos, bitpos,
- k, chg ));
- return k;
- }
-
- }
- else
- return 0;
-}
-
-
-
-/* 1-bit cassette output */
-WRITE_LINE_MEMBER(thomson_state::to7_set_cassette)
-{
- m_cassette->output(state ? 1. : -1. );
-}
-
-
-
-WRITE_LINE_MEMBER( thomson_state::to7_set_cassette_motor )
-{
- cassette_state cassstate = m_cassette->get_state();
- double pos = m_cassette->get_position();
-
- LOG (( "$%04x %f to7_set_cassette_motor: cassette motor %s bitpos=%i\n",
- m_maincpu->pc(), machine().time().as_double(), state ? "off" : "on",
- (int) (pos / TO7_BIT_LENGTH) ));
-
- if ( (cassstate & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED && !state && pos > 0.3 )
- {
- /* rewind a little before starting the motor */
- m_cassette->seek(-0.3, SEEK_CUR );
- }
-
- m_cassette->change_state(state ? CASSETTE_MOTOR_DISABLED : CASSETTE_MOTOR_ENABLED,CASSETTE_MASK_MOTOR );
-}
-
-
-
-/*-------------- MO5 ------------*/
-
-
-/* Each byte is represented as 8 bits without start or stop bit (unlike TO7).
- Bits are coded in MFM, and the MFM signal is directly fed to the
- computer which has to decode it in software (unlike TO7).
- A 1 bit is one period at 1200 Hz; a 0 bit is one half-period at 600 Hz.
- Bit-order is most significant bit first (unlike TO7).
-
- Double-density MO6 cassettes follow the exact same mechanism, but with
- at double frequency (periods at 2400 Hz, and half-periods at 1200 Hz).
-*/
-
-
-#define MO5_BIT_LENGTH 0.000833
-#define MO5_HBIT_LENGTH (MO5_BIT_LENGTH / 2.)
-
-
-int thomson_state::mo5_get_cassette()
-{
- if ( m_cassette->exists() )
- {
- cassette_image* cass = m_cassette->get_image();
- cassette_state state = m_cassette->get_state();
- double pos = m_cassette->get_position();
- int32_t hbit;
-
- if ( (state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED )
- return 1;
-
- cass->get_sample( 0, pos, 0, &hbit );
- hbit = hbit >= 0;
-
- VLOG (( "$%04x %f mo5_get_cassette: state=$%X pos=%f hbitpos=%i hbit=%i\n",
- m_maincpu->pc(), machine().time().as_double(), state, pos,
- (int) (pos / MO5_HBIT_LENGTH), hbit ));
- return hbit;
- }
- else
- return 0;
-}
-
-
-
-void thomson_state::mo5_set_cassette( int data )
-{
- m_cassette->output(data ? 1. : -1. );
-}
-
-
-
-WRITE_LINE_MEMBER( thomson_state::mo5_set_cassette_motor )
-{
- cassette_state cassstate = m_cassette->get_state();
- double pos = m_cassette->get_position();
-
- LOG (( "$%04x %f mo5_set_cassette_motor: cassette motor %s hbitpos=%i\n",
- m_maincpu->pc(), machine().time().as_double(), state ? "off" : "on",
- (int) (pos / MO5_HBIT_LENGTH) ));
-
- if ( (cassstate & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED && !state && pos > 0.3 )
- {
- /* rewind a little before starting the motor */
- m_cassette->seek(-0.3, SEEK_CUR );
- }
-
- m_cassette->change_state(state ? CASSETTE_MOTOR_DISABLED : CASSETTE_MOTOR_ENABLED,CASSETTE_MASK_MOTOR );
-}
-
-
-
-
-/*************************** utilities ********************************/
-
-
-
-/* ------------ IRQs ------------ */
-
-
-void thomson_state::thom_irq_reset()
-{
- m_mainfirq->in_w<2>(0);
-}
-
-
-
-/*
- current IRQ usage:
-
- line 0 => 6846 interrupt
- line 1 => 6821 interrupts (shared for all 6821)
- line 2 => TO8 lightpen interrupt (from gate-array)
- line 3 => TO9 keyboard interrupt (from 6850 ACIA)
- line 4 => MIDI interrupt (from 6850 ACIA)
-*/
-
-
-
-/* ------------ 6850 defines ------------ */
-
-#define ACIA_6850_RDRF 0x01 /* Receive data register full */
-#define ACIA_6850_TDRE 0x02 /* Transmit data register empty */
-#define ACIA_6850_dcd 0x04 /* Data carrier detect, active low */
-#define ACIA_6850_cts 0x08 /* Clear to send, active low */
-#define ACIA_6850_FE 0x10 /* Framing error */
-#define ACIA_6850_OVRN 0x20 /* Receiver overrun */
-#define ACIA_6850_PE 0x40 /* Parity error */
-#define ACIA_6850_irq 0x80 /* Interrupt request, active low */
-
-
-
-/***************************** TO7 / T9000 *************************/
-
-DEVICE_IMAGE_LOAD_MEMBER( thomson_state::to7_cartridge )
-{
- int i,j;
- uint8_t* pos = &m_cart_rom[0];
- offs_t size;
- char name[129];
-
- if (!image.loaded_through_softlist())
- size = image.length();
- else
- size = image.get_software_region_length("rom");
-
- /* get size & number of 16-KB banks */
- if ( size <= 0x04000 )
- m_thom_cart_nb_banks = 1;
- else if ( size == 0x08000 )
- m_thom_cart_nb_banks = 2;
- else if ( size == 0x0c000 )
- m_thom_cart_nb_banks = 3;
- else if ( size == 0x10000 )
- m_thom_cart_nb_banks = 4;
- else
- {
- image.seterror(image_error::INVALIDIMAGE, string_format("Invalid cartridge size %u", size).c_str());
- return image_init_result::FAIL;
- }
-
- if (!image.loaded_through_softlist())
- {
- if ( image.fread( pos, size ) != size )
- {
- image.seterror(image_error::INVALIDIMAGE, "Read error");
- return image_init_result::FAIL;
- }
- }
- else
- {
- memcpy(pos, image.get_software_region("rom"), size);
- }
-
- /* extract name */
- for ( i = 0; i < size && pos[i] != ' '; i++ );
- for ( i++, j = 0; i + j < size && j < 128 && pos[i+j] >= 0x20; j++)
- name[j] = pos[i+j];
- name[j] = 0;
-
- /* sanitize name */
- for ( i = 0; name[i]; i++)
- {
- if ( name[i] < ' ' || name[i] >= 127 )
- name[i] = '?';
- }
-
- PRINT (( "to7_cartridge_load: cartridge \"%s\" banks=%i, size=%i\n", name, m_thom_cart_nb_banks, size ));
-
- return image_init_result::PASS;
-}
-
-
-
-void thomson_state::to7_update_cart_bank()
-{
- address_space& space = m_maincpu->space(AS_PROGRAM);
- int bank = 0;
- if ( m_thom_cart_nb_banks )
- {
- bank = m_thom_cart_bank % m_thom_cart_nb_banks;
- if ( bank != m_old_cart_bank && m_old_cart_bank < 0 )
- {
- space.install_read_handler(0x0000, 0x0003, read8sm_delegate(*this, FUNC(thomson_state::to7_cartridge_r)) );
- }
- }
- if ( bank != m_old_cart_bank )
- {
- m_cartbank->set_entry( bank );
- m_old_cart_bank = bank;
- LOG_BANK(( "to7_update_cart_bank: CART is cartridge bank %i\n", bank ));
- }
-}
-
-
-
-void thomson_state::to7_update_cart_bank_postload()
-{
- to7_update_cart_bank();
-}
-
-
-
-/* write signal to 0000-1fff generates a bank switch */
-void thomson_state::to7_cartridge_w(offs_t offset, uint8_t data)
-{
- if ( offset >= 0x2000 )
- return;
-
- m_thom_cart_bank = offset & 3;
- to7_update_cart_bank();
-}
-
-
-
-/* read signal to 0000-0003 generates a bank switch */
-uint8_t thomson_state::to7_cartridge_r(offs_t offset)
-{
- uint8_t data = m_cart_rom[offset + (m_thom_cart_bank % m_thom_cart_nb_banks) * 0x4000];
- if ( !machine().side_effects_disabled() )
- {
- m_thom_cart_bank = offset & 3;
- to7_update_cart_bank();
- }
- return data;
-}
-
-
-
-/* ------------ 6846 (timer, I/O) ------------ */
-
-
-
-void thomson_state::to7_timer_port_out(uint8_t data)
-{
- thom_set_mode_point( data & 1 ); /* bit 0: video bank switch */
- m_caps_led = (data & 8) ? 1 : 0; /* bit 3: keyboard led */
- thom_set_border_color( ((data & 0x10) ? 1 : 0) | /* bits 4-6: border color */
- ((data & 0x20) ? 2 : 0) |
- ((data & 0x40) ? 4 : 0) );
-}
-
-
-
-uint8_t thomson_state::to7_timer_port_in()
-{
- int lightpen = (m_io_lightpen_button->read() & 1) ? 2 : 0;
- int cass = to7_get_cassette() ? 0x80 : 0;
- return lightpen | cass;
-}
-
-
-
-/* ------------ lightpen automaton ------------ */
-
-
-void thomson_state::to7_lightpen_cb( int step )
-{
- if ( ! m_to7_lightpen )
- return;
-
- LOG_VIDEO(( "%f to7_lightpen_cb: step=%i\n", machine().time().as_double(), step ));
- m_pia_sys->cb1_w( 1 );
- m_pia_sys->cb1_w( 0 );
- m_to7_lightpen_step = step;
-}
-
-
-
-/* ------------ video ------------ */
-
-
-
-void thomson_state::to7_set_init( int init )
-{
- /* INIT signal wired to system PIA 6821 */
-
- LOG_VIDEO(( "%f to7_set_init: init=%i\n", machine().time().as_double(), init ));
- m_pia_sys->ca1_w( init );
-}
-
-
-
-/* ------------ system PIA 6821 ------------ */
-
-
-
-WRITE_LINE_MEMBER( thomson_state::to7_sys_cb2_out )
-{
- m_to7_lightpen = !state;
-}
-
-
-
-void thomson_state::to7_sys_portb_out(uint8_t data)
-{
- /* value fetched in to7_sys_porta_in */
-}
-
-
-
-#define TO7_LIGHTPEN_DECAL 17 /* horizontal lightpen shift, stored in $60D2 */
-
-
-
-uint8_t thomson_state::to7_sys_porta_in()
-{
- if ( m_to7_lightpen )
- {
- /* lightpen hi */
- return to7_lightpen_gpl( TO7_LIGHTPEN_DECAL, m_to7_lightpen_step ) >> 8;
- }
- else
- {
- /* keyboard */
- int keyline = m_pia_sys->b_output();
- uint8_t val = 0xff;
- int i;
-
- for ( i = 0; i < 8; i++ )
- {
- if ( ! (keyline & (1 << i)) )
- val &= m_io_keyboard[i]->read();
- }
- return val;
- }
-}
-
-
-
-uint8_t thomson_state::to7_sys_portb_in()
-{
- /* lightpen low */
- return to7_lightpen_gpl( TO7_LIGHTPEN_DECAL, m_to7_lightpen_step ) & 0xff;
-}
-
-
-
-/* ------------ CC 90-232 I/O extension ------------ */
-
-/* Features:
- - 6821 PIA
- - serial RS232: bit-banging?
- - parallel CENTRONICS: a printer (-prin) is emulated
- - usable on TO7(/70), MO5(E) only; not on TO9 and higher
-
- Note: it seems impossible to connect both a serial & a parallel device
- because the Data Transmit Ready bit is shared in an incompatible way!
-*/
-
-DEFINE_DEVICE_TYPE(TO7_IO_LINE, to7_io_line_device, "to7_io_line", "TO7 Serial source")
-
-//-------------------------------------------------
-// to7_io_line_device - constructor
-//-------------------------------------------------
-
-to7_io_line_device::to7_io_line_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, TO7_IO_LINE, tag, owner, clock),
- m_pia_io(*this, THOM_PIA_IO),
- m_rs232(*this, "rs232"),
- m_last_low(0)
-{
-}
-
-void to7_io_line_device::device_add_mconfig(machine_config &config)
-{
- /// THIS PIO is part of CC 90-232 expansion
- PIA6821(config, m_pia_io, 0);
- m_pia_io->readpa_handler().set(FUNC(to7_io_line_device::porta_in));
- m_pia_io->writepa_handler().set(FUNC(to7_io_line_device::porta_out));
- m_pia_io->writepb_handler().set("cent_data_out", FUNC(output_latch_device::write));
- m_pia_io->cb2_handler().set("centronics", FUNC(centronics_device::write_strobe));
- m_pia_io->irqa_handler().set("^mainfirq", FUNC(input_merger_device::in_w<1>));
- m_pia_io->irqb_handler().set("^mainfirq", FUNC(input_merger_device::in_w<1>));
-
- RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
- m_rs232->rxd_handler().set(FUNC(to7_io_line_device::write_rxd));
- m_rs232->cts_handler().set(FUNC(to7_io_line_device::write_cts));
- m_rs232->dsr_handler().set(FUNC(to7_io_line_device::write_dsr));
-
- centronics_device &centronics(CENTRONICS(config, "centronics", centronics_devices, "printer"));
- centronics.ack_handler().set(m_pia_io, FUNC(pia6821_device::cb1_w));
- centronics.busy_handler().set(FUNC(to7_io_line_device::write_centronics_busy));
-
- output_latch_device &cent_data_out(OUTPUT_LATCH(config, "cent_data_out"));
- centronics.set_output_latch(cent_data_out);
-}
-
-
-void to7_io_line_device::device_start()
-{
- m_rs232->write_dtr(0);
-}
-
-void to7_io_line_device::porta_out(uint8_t data)
-{
- int txd = (data >> 0) & 1;
- int rts = (data >> 1) & 1;
-
- LOG_IO(( "%s %f to7_io_porta_out: txd=%i, rts=%i\n", machine().describe_context(), machine().time().as_double(), txd, rts ));
-
- m_rs232->write_txd(txd);
- m_rs232->write_rts(rts);
-}
-
-
-
-WRITE_LINE_MEMBER(to7_io_line_device::write_rxd )
-{
- m_rxd = state;
-}
-
-WRITE_LINE_MEMBER(to7_io_line_device::write_dsr )
-{
- if (!state) m_last_low = 0;
-
- m_dsr = state;
-}
-
-WRITE_LINE_MEMBER(to7_io_line_device::write_cts )
-{
- m_pia_io->ca1_w(state);
- m_cts = state;
-}
-
-WRITE_LINE_MEMBER(to7_io_line_device::write_centronics_busy )
-{
- if (!state) m_last_low = 1;
-
- m_centronics_busy = state;
-}
-
-
-uint8_t to7_io_line_device::porta_in()
-{
- LOG_IO(( "%s %f to7_io_porta_in: select=%i cts=%i, dsr=%i, rd=%i\n", machine().describe_context(), machine().time().as_double(), m_centronics_busy, m_cts, m_dsr, m_rxd ));
-
- /// HACK: without high impedance we can't tell whether a device is driving a line high or if it's being pulled up.
- /// so assume the last device to drive it low is active.
- int dsr;
- if (m_last_low == 0)
- dsr = m_dsr;
- else
- dsr = !m_centronics_busy;
-
- return (0x1f /* not required when converted to write_pa */) | (m_cts << 5) | (dsr << 6) | (m_rxd << 7);
-}
-
-
-
-/* ------------ RF 57-932 RS232 extension ------------ */
-
-/* Features:
- - SY 6551 ACIA.
- - higher transfer rates than the CC 90-232
- - usable on all computer, including TO9 and higher
- */
-
-
-
-/* ------------ MD 90-120 MODEM extension (not functional) ------------ */
-
-/* Features:
- - 6850 ACIA
- - 6821 PIA
- - asymetric 1200/ 75 bauds (reversable)
-
- TODO!
- */
-
-
-WRITE_LINE_MEMBER( thomson_state::to7_modem_cb )
-{
- LOG(( "to7_modem_cb: called %i\n", state ));
-}
-
-
-
-WRITE_LINE_MEMBER( thomson_state::to7_modem_tx_w )
-{
- m_to7_modem_tx = state;
-}
-
-
-WRITE_LINE_MEMBER( thomson_state::write_acia_clock )
-{
- m_acia->write_txc(state);
- m_acia->write_rxc(state);
-}
-
-void thomson_state::to7_modem_reset()
-{
- LOG (( "to7_modem_reset called\n" ));
- m_acia->write_rxd(0);
- m_to7_modem_tx = 0;
- /* pia_reset() is called in machine_reset */
- /* acia_6850 has no reset (?) */
-}
-
-
-
-void thomson_state::to7_modem_init()
-{
- LOG (( "to7_modem_init: MODEM not implemented!\n" ));
- save_item(NAME(m_to7_modem_tx));
-}
-
-
-
-/* ------------ dispatch MODEM / speech extension ------------ */
-
-uint8_t thomson_state::to7_modem_mea8000_r(offs_t offset)
-{
- if ( machine().side_effects_disabled() )
- {
- return 0;
- }
-
- if ( m_io_mconfig->read() & 1 )
- {
- return m_mea8000->read(offset);
- }
- else
- {
- switch (offset)
- {
- case 0:
- case 1:
- return m_acia->read(offset & 1);
-
- default:
- return 0;
- }
- }
-}
-
-
-
-void thomson_state::to7_modem_mea8000_w(offs_t offset, uint8_t data)
-{
- if ( m_io_mconfig->read() & 1 )
- {
- m_mea8000->write(offset, data);
- }
- else
- {
- switch (offset)
- {
- case 0:
- case 1:
- m_acia->write(offset & 1, data);
- break;
- }
- }
-}
-
-
-
-/* ------------ SX 90-018 (model 2) music & game extension ------------ */
-
-/* features:
- - 6821 PIA
- - two 8-position, 2-button game pads
- - 2-button mouse (exclusive with pads)
- do not confuse with the TO9-specific mouse
- - 6-bit DAC sound
-
- extends the CM 90-112 (model 1) with one extra button per pad and a mouse
-*/
-
-
-
-#define TO7_GAME_POLL_PERIOD attotime::from_usec( 500 )
-
-
-/* The mouse is a very simple phase quadrature one.
- Each axis provides two 1-bit signals, A and B, that are toggled by the
- axis rotation. The two signals are not in phase, so that whether A is
- toggled before B or B before A gives the direction of rotation.
- This is similar Atari & Amiga mouses.
- Returns: 0 0 0 0 0 0 YB XB YA XA
- */
-uint8_t thomson_state::to7_get_mouse_signal()
-{
- uint8_t xa, xb, ya, yb;
- uint16_t dx = m_io_mouse_x->read(); /* x axis */
- uint16_t dy = m_io_mouse_y->read(); /* y axis */
- xa = ((dx + 1) & 3) <= 1;
- xb = (dx & 3) <= 1;
- ya = ((dy + 1) & 3) <= 1;
- yb = (dy & 3) <= 1;
- return xa | (ya << 1) | (xb << 2) | (yb << 3);
-}
-
-
-
-void thomson_state::to7_game_sound_update()
-{
- m_dac->write(m_to7_game_mute ? 0 : m_to7_game_sound );
-}
-
-
-
-uint8_t thomson_state::to7_game_porta_in()
-{
- uint8_t data;
- if ( m_io_config->read() & 1 )
- {
- /* mouse */
- data = to7_get_mouse_signal() & 0x0c; /* XB, YB */
- data |= m_io_mouse_button->read() & 3; /* buttons */
- }
- else
- {
- /* joystick */
- data = m_io_game_port_directions->read();
- /* bit 0=0 => P1 up bit 4=0 => P2 up
- bit 1=0 => P1 down bit 5=0 => P2 down
- bit 2=0 => P1 left bit 6=0 => P2 left
- bit 3=0 => P1 right bit 7=0 => P2 right
- */
- /* remove impossible combinations: up+down, left+right */
- if ( ! ( data & 0x03 ) )
- data |= 0x03;
- if ( ! ( data & 0x0c ) )
- data |= 0x0c;
- if ( ! ( data & 0x30 ) )
- data |= 0x30;
- if ( ! ( data & 0xc0 ) )
- data |= 0xc0;
- if ( ! ( data & 0x03 ) )
- data |= 0x03;
- if ( ! ( data & 0x0c ) )
- data |= 0x0c;
- if ( ! ( data & 0x30 ) )
- data |= 0x30;
- if ( ! ( data & 0xc0 ) )
- data |= 0xc0;
- }
- return data;
-}
-
-
-
-uint8_t thomson_state::to7_game_portb_in()
-{
- uint8_t data;
- if ( m_io_config->read() & 1 )
- {
- /* mouse */
- uint8_t mouse = to7_get_mouse_signal();
- data = 0;
- if ( mouse & 1 )
- data |= 0x04; /* XA */
- if ( mouse & 2 )
- data |= 0x40; /* YA */
- }
- else
- {
- /* joystick */
- /* bits 6-7: action buttons A (0=pressed) */
- /* bits 2-3: action buttons B (0=pressed) */
- /* bits 4-5: unused (ouput) */
- /* bits 0-1: unknown! */
- data = m_io_game_port_buttons->read();
- }
- return data;
-}
-
-
-
-void thomson_state::to7_game_portb_out(uint8_t data)
-{
- /* 6-bit DAC sound */
- m_to7_game_sound = data & 0x3f;
- to7_game_sound_update();
-}
-
-
-
-WRITE_LINE_MEMBER( thomson_state::to7_game_cb2_out )
-{
- /* undocumented */
- /* some TO8 games (e.g.: F15) seem to write here a lot */
-}
-
-
-
-/* this should be called periodically */
-TIMER_CALLBACK_MEMBER(thomson_state::to7_game_update_cb)
-{
- if ( m_io_config->read() & 1 )
- {
- /* mouse */
- uint8_t mouse = to7_get_mouse_signal();
- m_pia_game->ca1_w( (mouse & 1) ? 1 : 0 ); /* XA */
- m_pia_game->ca2_w( (mouse & 2) ? 1 : 0 ); /* YA */
- }
- else
- {
- /* joystick */
- uint8_t in = m_io_game_port_buttons->read();
- m_pia_game->cb2_w( (in & 0x80) ? 1 : 0 ); /* P2 action A */
- m_pia_game->ca2_w( (in & 0x40) ? 1 : 0 ); /* P1 action A */
- m_pia_game->cb1_w( (in & 0x08) ? 1 : 0 ); /* P2 action B */
- m_pia_game->ca1_w( (in & 0x04) ? 1 : 0 ); /* P1 action B */
- /* TODO:
- it seems that CM 90-112 behaves differently
- - ca1 is P1 action A, i.e., in & 0x40
- - ca2 is P2 action A, i.e., in & 0x80
- - cb1, cb2 are not connected (should not be a problem)
- */
- /* Note: the MO6 & MO5NR have slightly different connections
- (see mo6_game_update_cb)
- */
- }
-}
-
-
-
-void thomson_state::to7_game_init()
-{
- LOG (( "to7_game_init called\n" ));
- m_to7_game_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(thomson_state::to7_game_update_cb),this));
- m_to7_game_timer->adjust(TO7_GAME_POLL_PERIOD, 0, TO7_GAME_POLL_PERIOD);
- save_item(NAME(m_to7_game_sound));
- save_item(NAME(m_to7_game_mute));
-}
-
-
-
-void thomson_state::to7_game_reset()
-{
- LOG (( "to7_game_reset called\n" ));
- m_pia_game->ca1_w( 0 );
- m_to7_game_sound = 0;
- m_to7_game_mute = 0;
- to7_game_sound_update();
-}
-
-
-
-/* ------------ MIDI extension ------------ */
-
-/* IMPORTANT NOTE:
- The following is experimental and not compiled in by default.
- It relies on the existence of an hypothetical "character device" API able
- to transmit bytes between the MESS driver and the outside world
- (using, e.g., character device special files on some UNIX).
-*/
-
-/* Features an EF 6850 ACIA
-
- MIDI protocol is a serial asynchronous protocol
- Each 8-bit byte is transmitted as:
- - 1 start bit
- - 8 data bits
- - 1 stop bits
- 320 us per transmitted byte => 31250 baud
-
- Emulation is based on the Motorola 6850 documentation, not EF 6850.
-
- We do not emulate the seral line but pass bytes directly between the
- 6850 registers and the MIDI device.
-*/
-
-
-uint8_t thomson_state::to7_midi_r()
-{
- if(!machine().side_effects_disabled())
- logerror( "to7_midi_r: not implemented\n" );
- return 0;
-}
-
-
-
-void thomson_state::to7_midi_w(uint8_t data)
-{
- logerror( "to7_midi_w: not implemented\n" );
-}
-
-
-
-void thomson_state::to7_midi_reset()
-{
- logerror( "to7_midi_reset: not implemented\n" );
-}
-
-
-
-void thomson_state::to7_midi_init()
-{
- logerror( "to7_midi_init: not implemented\n" );
-}
-
-
-
-/* ------------ init / reset ------------ */
-
-
-
-MACHINE_RESET_MEMBER( thomson_state, to7 )
-{
- LOG (( "to7: machine reset called\n" ));
-
- /* subsystems */
- thom_irq_reset();
- to7_game_reset();
- to7_modem_reset();
- to7_midi_reset();
-
- m_extension->rom_map(m_maincpu->space(AS_PROGRAM), 0xe000, 0xe7bf);
- m_extension->io_map (m_maincpu->space(AS_PROGRAM), 0xe7d0, 0xe7df);
-
- /* video */
- thom_set_video_mode( THOM_VMODE_TO770 );
- m_thom_init_cb = &thomson_state::to7_set_init;
- m_thom_lightpen_cb = std::bind(&thomson_state::to7_lightpen_cb, this, std::placeholders::_1);
- thom_set_lightpen_callback( 3 );
- thom_set_mode_point( 0 );
- thom_set_border_color( 0 );
- m_pia_sys->cb1_w( 0 );
-
- /* memory */
- m_old_cart_bank = -1;
- to7_update_cart_bank();
- /* thom_cart_bank not reset */
-
- /* lightpen */
- m_to7_lightpen = 0;
-}
-
-
-
-MACHINE_START_MEMBER( thomson_state, to7 )
-{
- uint8_t* cartmem = &m_cart_rom[0];
- uint8_t* ram = m_ram->pointer();
-
- LOG (( "to7: machine start called\n" ));
-
- /* subsystems */
- to7_game_init();
- to7_modem_init();
- to7_midi_init();
-
- m_extension->rom_map(m_maincpu->space(AS_PROGRAM), 0xe000, 0xe7bf);
- m_extension->io_map (m_maincpu->space(AS_PROGRAM), 0xe7d0, 0xe7df);
-
- /* memory */
- m_thom_cart_bank = 0;
- m_thom_vram = ram;
- m_basebank->configure_entry( 0, ram + 0x4000);
- m_vrambank->configure_entries( 0, 2, m_thom_vram, 0x2000 );
- m_cartbank->configure_entries( 0, 4, cartmem, 0x4000 );
- m_basebank->set_entry( 0 );
- m_vrambank->set_entry( 0 );
- m_cartbank->set_entry( 0 );
-
- address_space& space = m_maincpu->space(AS_PROGRAM);
- space.unmap_readwrite(0x8000, 0xdfff);
-
- if ( m_ram->size() > 24*1024 )
- {
- /* install 16 KB or 16 KB + 8 KB memory extensions */
- /* BASIC instruction to see free memory: ?FRE(0) */
- int extram = m_ram->size() - 24*1024;
- space.install_write_bank(0x8000, 0x8000 + extram - 1, m_rambank);
- space.install_read_bank(0x8000, 0x8000 + extram - 1, m_rambank);
- m_rambank->configure_entry( 0, ram + 0x6000);
- m_rambank->set_entry( 0 );
- }
-
- /* force 2 topmost color bits to 1 */
- memset( m_thom_vram + 0x2000, 0xc0, 0x2000 );
-
- /* save-state */
- save_item(NAME(m_thom_cart_nb_banks));
- save_item(NAME(m_thom_cart_bank));
- save_item(NAME(m_to7_lightpen));
- save_item(NAME(m_to7_lightpen_step));
- save_pointer(NAME(cartmem), 0x10000 );
- machine().save().register_postload(save_prepost_delegate(FUNC(thomson_state::to7_update_cart_bank_postload),this));
-}
-
-
-
-/***************************** TO7/70 *************************/
-
-
-
-/* ------------ system PIA 6821 ------------ */
-
-
-
-WRITE_LINE_MEMBER( thomson_state::to770_sys_cb2_out )
-{
- /* video overlay: black pixels are transparent and show TV image underneath */
- LOG(( "$%04x to770_sys_cb2_out: video overlay %i\n", m_maincpu->pc(), state ));
-}
-
-
-
-uint8_t thomson_state::to770_sys_porta_in()
-{
- /* keyboard */
- int keyline = m_pia_sys->b_output() & 7;
-
- return m_io_keyboard[7 - keyline]->read();
-}
-
-
-
-void thomson_state::to770_update_ram_bank()
-{
- address_space& space = m_maincpu->space(AS_PROGRAM);
- uint8_t portb = m_pia_sys->port_b_z_mask();
- int bank;
-
- switch (portb & 0xf8)
- {
- /* 2 * 16 KB internal RAM */
- case 0xf0: bank = 0; break;
- case 0xe8: bank = 1; break;
-
- /* 4 * 16 KB extended RAM */
- case 0x18: bank = 2; break;
- case 0x98: bank = 3; break;
- case 0x58: bank = 4; break;
- case 0xd8: bank = 5; break;
-
- /* none selected */
- case 0xf8: return;
-
- default:
- logerror( "to770_update_ram_bank unknown bank $%02X\n", portb & 0xf8 );
- return;
- }
-
- if ( bank != m_old_ram_bank )
- {
- if ( m_ram->size() == 128*1024 || bank < 2 )
- {
- m_rambank->set_entry( bank );
- }
- else
- {
- /* RAM size is 48 KB only and unavailable bank
- * requested */
- space.nop_readwrite(0xa000, 0xdfff);
- }
- m_old_ram_bank = bank;
- LOG_BANK(( "to770_update_ram_bank: RAM bank change %i\n", bank ));
- }
-}
-
-
-
-void thomson_state::to770_update_ram_bank_postload()
-{
- to770_update_ram_bank();
-}
-
-
-
-void thomson_state::to770_sys_portb_out(uint8_t data)
-{
- to770_update_ram_bank();
-}
-
-
-
-/* ------------ 6846 (timer, I/O) ------------ */
-
-
-
-void thomson_state::to770_timer_port_out(uint8_t data)
-{
- thom_set_mode_point( data & 1 ); /* bit 0: video bank switch */
- m_caps_led = (data & 8) ? 1 : 0; /* bit 3: keyboard led */
- thom_set_border_color( ((data & 0x10) ? 1 : 0) | /* 4-bit border color */
- ((data & 0x20) ? 2 : 0) |
- ((data & 0x40) ? 4 : 0) |
- ((data & 0x04) ? 0 : 8) );
-}
-
-
-/* ------------ gate-array ------------ */
-
-
-
-uint8_t thomson_state::to770_gatearray_r(offs_t offset)
-{
- struct thom_vsignal v = thom_get_vsignal();
- struct thom_vsignal l = thom_get_lightpen_vsignal( TO7_LIGHTPEN_DECAL, m_to7_lightpen_step - 1, 0 );
- int count, inil, init, lt3;
- count = m_to7_lightpen ? l.count : v.count;
- inil = m_to7_lightpen ? l.inil : v.inil;
- init = m_to7_lightpen ? l.init : v.init;
- lt3 = m_to7_lightpen ? l.lt3 : v.lt3;
-
- switch ( offset )
- {
- case 0: return (count >> 8) & 0xff;
- case 1: return count & 0xff;
- case 2: return (lt3 << 7) | (inil << 6);
- case 3: return (init << 7);
- default:
- logerror( "$%04x to770_gatearray_r: invalid offset %i\n", m_maincpu->pc(), offset );
- return 0;
- }
-}
-
-
-
-void thomson_state::to770_gatearray_w(offs_t offset, uint8_t data)
-{
- if ( ! offset )
- m_to7_lightpen = data & 1;
-}
-
-
-
-/* ------------ init / reset ------------ */
-
-
-
-MACHINE_RESET_MEMBER( thomson_state, to770 )
-{
- LOG (( "to770: machine reset called\n" ));
-
- /* subsystems */
- thom_irq_reset();
- to7_game_reset();
- to7_modem_reset();
- to7_midi_reset();
-
- m_extension->rom_map(m_maincpu->space(AS_PROGRAM), 0xe000, 0xe7bf);
- m_extension->io_map (m_maincpu->space(AS_PROGRAM), 0xe7d0, 0xe7df);
-
- /* video */
- thom_set_video_mode( THOM_VMODE_TO770 );
- m_thom_init_cb = &thomson_state::to7_set_init;
- m_thom_lightpen_cb = std::bind(&thomson_state::to7_lightpen_cb, this, std::placeholders::_1);
- thom_set_lightpen_callback( 3 );
- thom_set_mode_point( 0 );
- thom_set_border_color( 8 );
- m_pia_sys->cb1_w( 0 );
-
- /* memory */
- m_old_ram_bank = -1;
- m_old_cart_bank = -1;
- to7_update_cart_bank();
- to770_update_ram_bank();
- /* thom_cart_bank not reset */
-
- /* lightpen */
- m_to7_lightpen = 0;
-}
-
-
-
-MACHINE_START_MEMBER( thomson_state, to770 )
-{
- uint8_t* cartmem = &m_cart_rom[0];
- uint8_t* ram = m_ram->pointer();
-
- LOG (( "to770: machine start called\n" ));
-
- /* subsystems */
- to7_game_init();
- to7_modem_init();
- to7_midi_init();
-
- m_extension->rom_map(m_maincpu->space(AS_PROGRAM), 0xe000, 0xe7bf);
- m_extension->io_map (m_maincpu->space(AS_PROGRAM), 0xe7d0, 0xe7df);
-
- /* memory */
- m_thom_cart_bank = 0;
- m_thom_vram = ram;
- m_basebank->configure_entry( 0, ram + 0x4000);
- m_rambank->configure_entries( 0, 6, ram + 0x8000, 0x4000 );
- m_vrambank->configure_entries( 0, 2, m_thom_vram, 0x2000 );
- m_cartbank->configure_entries( 0, 4, cartmem, 0x4000 );
- m_basebank->set_entry( 0 );
- m_rambank->set_entry( 0 );
- m_vrambank->set_entry( 0 );
- m_cartbank->set_entry( 0 );
-
- /* save-state */
- save_item(NAME(m_thom_cart_nb_banks));
- save_item(NAME(m_thom_cart_bank));
- save_item(NAME(m_to7_lightpen));
- save_item(NAME(m_to7_lightpen_step));
- save_pointer(NAME(cartmem), 0x10000 );
- machine().save().register_postload(save_prepost_delegate(FUNC(thomson_state::to770_update_ram_bank_postload), this));
- machine().save().register_postload(save_prepost_delegate(FUNC(thomson_state::to7_update_cart_bank_postload), this));
-}
-
-
-
-/***************************** MO5 *************************/
-
-
-
-/* ------------ lightpen automaton ------------ */
-
-
-
-void mo5_state::mo5_lightpen_cb( int step )
-{
- /* MO5 signals ca1 (TO7 signals cb1) */
- if ( ! m_to7_lightpen )
- return;
-
- m_pia_sys->ca1_w( 1 );
- m_pia_sys->ca1_w( 0 );
- m_to7_lightpen_step = step;
-}
-
-
-/* ------------ periodic interrupt ------------ */
-
-/* the MO5 & MO6 do not have a MC 6846 timer,
- they have a fixed 50 Hz timer instead
-*/
-
-
-TIMER_CALLBACK_MEMBER(thomson_state::mo5_periodic_cb)
-{
- /* pulse */
- m_pia_sys->cb1_w( 1 );
- m_pia_sys->cb1_w( 0 );
-}
-
-
-
-void thomson_state::mo5_init_timer()
-{
- /* time is a little faster than 50 Hz to match video framerate */
- m_mo5_periodic_timer->adjust(attotime::zero, 0, attotime::from_usec( 19968 ));
-}
-
-
-
-/* ------------ system PIA 6821 ------------ */
-
-
-
-void mo5_state::mo5_sys_porta_out(uint8_t data)
-{
- thom_set_mode_point( data & 1 ); /* bit 0: video bank switch */
- thom_set_border_color( (data >> 1) & 15 ); /* bit 1-4: border color */
- mo5_set_cassette( (data & 0x40) ? 1 : 0 ); /* bit 6: cassette output */
-}
-
-
-
-uint8_t mo5_state::mo5_sys_porta_in()
-{
- return
- ((m_io_lightpen_button->read() & 1) ? 0x20 : 0) | /* bit 5: lightpen button */
- (mo5_get_cassette() ? 0x80 : 0) | /* bit 7: cassette input */
- 0x5f; /* other bits are unconnected and pulled hi internally */
-}
-
-
-
-uint8_t mo5_state::mo5_sys_portb_in()
-{
- uint8_t portb = m_pia_sys->b_output();
- int col = (portb >> 1) & 7; /* key column */
- int lin = 7 - ((portb >> 4) & 7); /* key line */
-
- return ( m_io_keyboard[lin]->read() & (1 << col) ) ? 0x80 : 0;
-}
-
-
-
-/* ------------ gate-array ------------ */
-
-
-
-#define MO5_LIGHTPEN_DECAL 12
-
-
-
-uint8_t mo5_state::mo5_gatearray_r(offs_t offset)
-{
- struct thom_vsignal v = thom_get_vsignal();
- struct thom_vsignal l = thom_get_lightpen_vsignal( MO5_LIGHTPEN_DECAL, m_to7_lightpen_step - 1, 0 );
- int count, inil, init, lt3;
- count = m_to7_lightpen ? l.count : v.count;
- inil = m_to7_lightpen ? l.inil : v.inil;
- init = m_to7_lightpen ? l.init : v.init;
- lt3 = m_to7_lightpen ? l.lt3 : v.lt3;
-
- switch ( offset ) {
- case 0: return (count >> 8) & 0xff;
- case 1: return count & 0xff;
- case 2: return (lt3 << 7) | (inil << 6);
- case 3: return (init << 7);
- default:
- logerror( "$%04x mo5_gatearray_r: invalid offset %i\n", m_maincpu->pc(), offset );
- return 0;
- }
-}
-
-
-
-void mo5_state::mo5_gatearray_w(offs_t offset, uint8_t data)
-{
- if ( ! offset )
- m_to7_lightpen = data & 1;
-}
-
-
-
-/* ------------ cartridge / extended RAM ------------ */
-
-
-
-DEVICE_IMAGE_LOAD_MEMBER( thomson_state::mo5_cartridge )
-{
- uint8_t* pos = &m_cart_rom[0];
- uint64_t size, i;
- int j;
- char name[129];
-
- if (!image.loaded_through_softlist())
- size = image.length();
- else
- size = image.get_software_region_length("rom");
-
- /* get size & number of 16-KB banks */
- if ( size > 32 && size <= 0x04000 )
- m_thom_cart_nb_banks = 1;
- else if ( size == 0x08000 )
- m_thom_cart_nb_banks = 2;
- else if ( size == 0x0c000 )
- m_thom_cart_nb_banks = 3;
- else if ( size == 0x10000 )
- m_thom_cart_nb_banks = 4;
- else
- {
- image.seterror(image_error::INVALIDIMAGE, string_format("Invalid cartridge size %d", size).c_str());
- return image_init_result::FAIL;
- }
-
- if (!image.loaded_through_softlist())
- {
- if ( image.fread(pos, size ) != size )
- {
- image.seterror(image_error::INVALIDIMAGE, "Read error");
- return image_init_result::FAIL;
- }
- }
- else
- {
- memcpy(pos, image.get_software_region("rom"), size);
- }
-
- /* extract name */
- i = size - 32;
- while ( i < size && !pos[i] ) i++;
- for ( j = 0; i < size && pos[i] >= 0x20; j++, i++)
- name[j] = pos[i];
- name[j] = 0;
-
- /* sanitize name */
- for ( j = 0; name[j]; j++)
- {
- if ( name[j] < ' ' || name[j] >= 127 ) name[j] = '?';
- }
-
- PRINT (( "mo5_cartridge_load: cartridge \"%s\" banks=%i, size=%u\n", name, m_thom_cart_nb_banks, (unsigned) size ));
-
- return image_init_result::PASS;
-}
-
-
-
-void mo5_state::mo5_update_cart_bank()
-{
- address_space& space = m_maincpu->space(AS_PROGRAM);
- int rom_is_ram = m_mo5_reg_cart & 4;
- int bank = 0;
- int bank_is_read_only = 0;
-
-
- if ( rom_is_ram && m_thom_cart_nb_banks == 4 )
- {
- /* 64 KB ROM from "JANE" cartridge */
- bank = m_mo5_reg_cart & 3;
- if ( bank != m_old_cart_bank )
- {
- if ( m_old_cart_bank < 0 || m_old_cart_bank > 3 )
- {
- space.install_read_bank( 0xb000, 0xefff, m_cartbank);
- space.nop_write( 0xb000, 0xefff);
- }
- LOG_BANK(( "mo5_update_cart_bank: CART is cartridge bank %i (A7CB style)\n", bank ));
- }
- }
- else if ( rom_is_ram )
- {
- /* 64 KB RAM from network extension */
- bank = 4 + ( m_mo5_reg_cart & 3 );
- bank_is_read_only = (( m_mo5_reg_cart & 8 ) == 0);
-
- if ( bank != m_old_cart_bank || bank_is_read_only != m_old_cart_bank_was_read_only)
- {
- if ( bank_is_read_only )
- {
- space.install_read_bank( 0xb000, 0xefff, m_cartbank);
- space.nop_write( 0xb000, 0xefff );
- }
- else
- {
- space.install_readwrite_bank( 0xb000, 0xefff, m_cartbank);
- }
- LOG_BANK(( "mo5_update_cart_bank: CART is nanonetwork RAM bank %i (%s)\n",
- m_mo5_reg_cart & 3,
- bank_is_read_only ? "read-only":"read-write"));
- m_old_cart_bank_was_read_only = bank_is_read_only;
- }
- }
- else
- {
- /* regular cartridge bank switch */
- if ( m_thom_cart_nb_banks )
- {
- bank = m_thom_cart_bank % m_thom_cart_nb_banks;
- if ( bank != m_old_cart_bank )
- {
- if ( m_old_cart_bank < 0 )
- {
- space.install_read_bank( 0xb000, 0xefff, m_cartbank);
- space.install_write_handler( 0xb000, 0xefff, write8sm_delegate(*this, FUNC(mo5_state::mo5_cartridge_w)) );
- space.install_read_handler( 0xbffc, 0xbfff, read8sm_delegate(*this, FUNC(mo5_state::mo5_cartridge_r)) );
- }
- LOG_BANK(( "mo5_update_cart_bank: CART is cartridge bank %i\n", bank ));
- }
- }
- else
- {
- /* internal ROM */
- if ( m_old_cart_bank != 0 )
- {
- space.install_read_bank( 0xb000, 0xefff, m_cartbank);
- space.install_write_handler( 0xb000, 0xefff, write8sm_delegate(*this, FUNC(mo5_state::mo5_cartridge_w)) );
- LOG_BANK(( "mo5_update_cart_bank: CART is internal\n"));
- }
- }
- }
- if ( bank != m_old_cart_bank )
- {
- m_cartbank->set_entry( bank );
- m_old_cart_bank = bank;
- }
-}
-
-
-
-void mo5_state::mo5_update_cart_bank_postload()
-{
- mo5_update_cart_bank();
-}
-
-
-
-/* write signal to b000-cfff generates a bank switch */
-void mo5_state::mo5_cartridge_w(offs_t offset, uint8_t data)
-{
- if ( offset >= 0x2000 )
- return;
-
- m_thom_cart_bank = offset & 3;
- mo5_update_cart_bank();
-}
-
-
-
-/* read signal to bffc-bfff generates a bank switch */
-uint8_t mo5_state::mo5_cartridge_r(offs_t offset)
-{
- uint8_t data = m_cart_rom[offset + 0x3ffc + (m_thom_cart_bank % m_thom_cart_nb_banks) * 0x4000];
- if ( !machine().side_effects_disabled() )
- {
- m_thom_cart_bank = offset & 3;
- mo5_update_cart_bank();
- }
- return data;
-}
-
-
-
-/* 0xa7cb bank-switch register */
-void mo5_state::mo5_ext_w(uint8_t data)
-{
- m_mo5_reg_cart = data;
- mo5_update_cart_bank();
-}
-
-
-
-/* ------------ init / reset ------------ */
-
-
-
-MACHINE_RESET_MEMBER( mo5_state, mo5 )
-{
- LOG (( "mo5: machine reset called\n" ));
-
- /* subsystems */
- thom_irq_reset();
- to7_game_reset();
- to7_modem_reset();
- to7_midi_reset();
- mo5_init_timer();
-
- /* video */
- thom_set_video_mode( THOM_VMODE_MO5 );
- m_thom_lightpen_cb = std::bind(&mo5_state::mo5_lightpen_cb, this, std::placeholders::_1);
- thom_set_lightpen_callback( 3 );
- thom_set_mode_point( 0 );
- thom_set_border_color( 0 );
- m_pia_sys->ca1_w( 0 );
-
- /* memory */
- m_old_cart_bank = -1;
- mo5_update_cart_bank();
- /* mo5_reg_cart not reset */
- /* thom_cart_bank not reset */
-
- /* lightpen */
- m_to7_lightpen = 0;
-}
-
-
-
-MACHINE_START_MEMBER( mo5_state, mo5 )
-{
- uint8_t* mem = memregion("maincpu")->base();
- uint8_t* cartmem = &m_cart_rom[0];
- uint8_t* ram = m_ram->pointer();
-
- LOG (( "mo5: machine start called\n" ));
-
- /* subsystems */
- to7_game_init();
- to7_modem_init();
- to7_midi_init();
- m_mo5_periodic_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mo5_state::mo5_periodic_cb),this));
-
- m_extension->rom_map(m_maincpu->space(AS_PROGRAM), 0xa000, 0xa7bf);
- m_extension->io_map (m_maincpu->space(AS_PROGRAM), 0xa7d0, 0xa7df);
-
- /* memory */
- m_thom_cart_bank = 0;
- m_mo5_reg_cart = 0;
- m_thom_vram = ram;
- m_basebank->configure_entry( 0, ram + 0x4000);
- m_cartbank->configure_entry( 0, mem + 0x10000);
- m_cartbank->configure_entries( 1, 3, cartmem + 0x4000, 0x4000 );
- m_cartbank->configure_entries( 4, 4, ram + 0xc000, 0x4000 );
- m_vrambank->configure_entries( 0, 2, m_thom_vram, 0x2000 );
- m_basebank->set_entry( 0 );
- m_cartbank->set_entry( 0 );
- m_vrambank->set_entry( 0 );
-
- /* save-state */
- save_item(NAME(m_thom_cart_nb_banks));
- save_item(NAME(m_thom_cart_bank));
- save_item(NAME(m_to7_lightpen));
- save_item(NAME(m_to7_lightpen_step));
- save_item(NAME(m_mo5_reg_cart));
- save_pointer(NAME(cartmem), 0x10000 );
- machine().save().register_postload(save_prepost_delegate(FUNC(mo5_state::mo5_update_cart_bank_postload), this));
-}
-
-
-
-/***************************** TO9 *************************/
-
-
-
-/* ------------ IEEE extension ------------ */
-
-
-
-/* TODO: figure out what this extension is... IEEE-488 ??? */
-
-
-
-void to9_state::to9_ieee_w(offs_t offset, uint8_t data)
-{
- logerror( "$%04x %f to9_ieee_w: unhandled write $%02X to register %i\n", m_maincpu->pc(), machine().time().as_double(), data, offset );
-}
-
-
-
-uint8_t to9_state::to9_ieee_r(offs_t offset)
-{
- logerror( "$%04x %f to9_ieee_r: unhandled read from register %i\n", m_maincpu->pc(), machine().time().as_double(), offset );
- return 0;
-}
-
-
-
-/* ------------ system gate-array ------------ */
-
-
-
-#define TO9_LIGHTPEN_DECAL 8
-
-
-
-uint8_t to9_state::to9_gatearray_r(offs_t offset)
-{
- struct thom_vsignal v = thom_get_vsignal();
- struct thom_vsignal l = thom_get_lightpen_vsignal( TO9_LIGHTPEN_DECAL, m_to7_lightpen_step - 1, 0 );
- int count, inil, init, lt3;
- count = m_to7_lightpen ? l.count : v.count;
- inil = m_to7_lightpen ? l.inil : v.inil;
- init = m_to7_lightpen ? l.init : v.init;
- lt3 = m_to7_lightpen ? l.lt3 : v.lt3;
-
- switch ( offset )
- {
- case 0: return (count >> 8) & 0xff;
- case 1: return count & 0xff;
- case 2: return (lt3 << 7) | (inil << 6);
- case 3: return (v.init << 7) | (init << 6); /* != TO7/70 */
- default:
- logerror( "$%04x to9_gatearray_r: invalid offset %i\n", m_maincpu->pc(), offset );
- return 0;
- }
-}
-
-
-
-void to9_state::to9_gatearray_w(offs_t offset, uint8_t data)
-{
- if ( ! offset )
- m_to7_lightpen = data & 1;
-}
-
-
-
-/* ------------ video gate-array ------------ */
-
-
-
-/* style: 0 => TO9, 1 => TO8/TO9, 2 => MO6 */
-void to9_state::to9_set_video_mode( uint8_t data, int style )
-{
- switch ( data & 0x7f )
- {
- case 0x00:
- if ( style == 2 )
- thom_set_video_mode( THOM_VMODE_MO5 );
- else if ( style == 1 )
- thom_set_video_mode( THOM_VMODE_TO770 );
- else
- thom_set_video_mode( THOM_VMODE_TO9 );
- break;
-
- // undocumented, but tested on a real TO8D
- case 0x20: thom_set_video_mode( THOM_VMODE_MO5_ALT ); break;
-
- case 0x21: thom_set_video_mode( THOM_VMODE_BITMAP4 ); break;
-
- case 0x41: thom_set_video_mode( THOM_VMODE_BITMAP4_ALT ); break;
-
- // also undocumented but tested
- case 0x59: thom_set_video_mode( THOM_VMODE_BITMAP4_ALT_HALF ); break;
-
- case 0x2a:
- if ( style==0 )
- thom_set_video_mode( THOM_VMODE_80_TO9 );
- else
- thom_set_video_mode( THOM_VMODE_80 );
- break;
-
- case 0x7b: thom_set_video_mode( THOM_VMODE_BITMAP16 ); break;
-
- case 0x24: thom_set_video_mode( THOM_VMODE_PAGE1 ); break;
-
- case 0x25: thom_set_video_mode( THOM_VMODE_PAGE2 ); break;
-
- case 0x26: thom_set_video_mode( THOM_VMODE_OVERLAY ); break;
-
- // undocumented 160x200 variant of overlay
- case 0x3e: thom_set_video_mode( THOM_VMODE_OVERLAY_HALF ); break;
-
- case 0x3f: thom_set_video_mode( THOM_VMODE_OVERLAY3 ); break;
-
- // undocumented variant enconding for bitmap16
- case 0x5b: thom_set_video_mode( THOM_VMODE_BITMAP16_ALT ); break;
-
- default:
- logerror( "to9_set_video_mode: unknown mode $%02X tr=%i phi=%i mod=%i\n", data, (data >> 5) & 3, (data >> 3) & 2, data & 7 );
- }
-}
-
-
-
-uint8_t to9_state::to9_vreg_r(offs_t offset)
-{
- switch ( offset )
- {
- case 0: /* palette data */
- {
- uint8_t c = m_to9_palette_data[ m_to9_palette_idx ];
- if ( !machine().side_effects_disabled() )
- {
- m_to9_palette_idx = ( m_to9_palette_idx + 1 ) & 31;
- }
- return c;
- }
-
- case 1: /* palette address */
- return m_to9_palette_idx;
-
- case 2:
- case 3:
- return 0;
-
- default:
- logerror( "to9_vreg_r: invalid read offset %i\n", offset );
- return 0;
- }
-}
-
-
-
-void to9_state::to9_vreg_w(offs_t offset, uint8_t data)
-{
- LOG_VIDEO(( "$%04x %f to9_vreg_w: off=%i ($%04X) data=$%02X\n", m_maincpu->pc(), machine().time().as_double(), offset, 0xe7da + offset, data ));
-
- switch ( offset )
- {
- case 0: /* palette data */
- {
- uint16_t color, idx;
- m_to9_palette_data[ m_to9_palette_idx ] = data;
- idx = m_to9_palette_idx / 2;
- color = m_to9_palette_data[ 2 * idx + 1 ];
- color = m_to9_palette_data[ 2 * idx ] | (color << 8);
- thom_set_palette( idx ^ 8, color & 0x1fff );
- m_to9_palette_idx = ( m_to9_palette_idx + 1 ) & 31;
- }
- break;
-
- case 1: /* palette address */
- m_to9_palette_idx = data & 31;
- break;
-
- case 2: /* video mode */
- to9_set_video_mode( data, 0 );
- break;
-
- case 3: /* border color */
- thom_set_border_color( data & 15 );
- break;
-
- default:
- logerror( "to9_vreg_w: invalid write offset %i data=$%02X\n", offset, data );
- }
-}
-
-
-
-void to9_state::to9_palette_init()
-{
- m_to9_palette_idx = 0;
- memset( m_to9_palette_data, 0, sizeof( m_to9_palette_data ) );
- save_item(NAME(m_to9_palette_idx));
- save_item(NAME(m_to9_palette_data));
-}
-
-
-
-/* ------------ RAM / ROM banking ------------ */
-
-
-void to9_state::to9_update_cart_bank()
-{
- address_space& space = m_maincpu->space(AS_PROGRAM);
- int bank = 0;
- int slot = ( m_mc6846->get_output_port() >> 4 ) & 3; /* bits 4-5: ROM bank */
-
- switch ( slot )
- {
- case 0:
- /* BASIC (64 KB) */
- bank = 4 + m_to9_soft_bank;
- if ( bank != m_old_cart_bank )
- {
- if ( m_old_cart_bank < 4)
- {
- space.install_read_bank( 0x0000, 0x3fff, m_cartbank );
- }
- LOG_BANK(( "to9_update_cart_bank: CART is BASIC bank %i\n", m_to9_soft_bank ));
- }
- break;
- case 1:
- /* software 1 (32 KB) */
- bank = 8 + (m_to9_soft_bank & 1);
- if ( bank != m_old_cart_bank )
- {
- if ( m_old_cart_bank < 4)
- {
- space.install_read_bank( 0x0000, 0x3fff, m_cartbank );
- }
- LOG_BANK(( "to9_update_cart_bank: CART is software 1 bank %i\n", m_to9_soft_bank ));
- }
- break;
- case 2:
- /* software 2 (32 KB) */
- bank = 10 + (m_to9_soft_bank & 1);
- if ( bank != m_old_cart_bank )
- {
- if ( m_old_cart_bank < 4)
- {
- space.install_read_bank( 0x0000, 0x3fff, m_cartbank );
- }
- LOG_BANK(( "to9_update_cart_bank: CART is software 2 bank %i\n", m_to9_soft_bank ));
- }
- break;
- case 3:
- /* external cartridge */
- if ( m_thom_cart_nb_banks )
- {
- bank = m_thom_cart_bank % m_thom_cart_nb_banks;
- if ( bank != m_old_cart_bank )
- {
- if ( m_old_cart_bank < 0 || m_old_cart_bank > 3 )
- {
- space.install_read_bank( 0x0000, 0x3fff, m_cartbank );
- space.install_write_handler( 0x0000, 0x3fff, write8sm_delegate(*this, FUNC(to9_state::to9_cartridge_w)) );
- space.install_read_handler( 0x0000, 0x0003, read8sm_delegate(*this, FUNC(to9_state::to9_cartridge_r)) );
- }
- LOG_BANK(( "to9_update_cart_bank: CART is cartridge bank %i\n", m_thom_cart_bank ));
- }
- }
- else
- {
- if ( m_old_cart_bank != 0 )
- {
- space.nop_read( 0x0000, 0x3fff);
- LOG_BANK(( "to9_update_cart_bank: CART is unmapped\n"));
- }
- }
- break;
- }
- if ( bank != m_old_cart_bank )
- {
- m_cartbank->set_entry( bank );
- m_old_cart_bank = bank;
- }
-}
-
-
-
-void to9_state::to9_update_cart_bank_postload()
-{
- to9_update_cart_bank();
-}
-
-
-
-/* write signal to 0000-1fff generates a bank switch */
-void to9_state::to9_cartridge_w(offs_t offset, uint8_t data)
-{
- int slot = ( m_mc6846->get_output_port() >> 4 ) & 3; /* bits 4-5: ROM bank */
-
- if ( offset >= 0x2000 )
- return;
-
- if ( slot == 3 )
- m_thom_cart_bank = offset & 3;
- else
- m_to9_soft_bank = offset & 3;
- to9_update_cart_bank();
-}
-
-
-
-/* read signal to 0000-0003 generates a bank switch */
-uint8_t to9_state::to9_cartridge_r(offs_t offset)
-{
- uint8_t data = m_cart_rom[offset + (m_thom_cart_bank % m_thom_cart_nb_banks) * 0x4000];
- if ( !machine().side_effects_disabled() )
- {
- m_thom_cart_bank = offset & 3;
- to9_update_cart_bank();
- }
- return data;
-}
-
-
-
-void to9_state::to9_update_ram_bank()
-{
- address_space& space = m_maincpu->space(AS_PROGRAM);
- uint8_t port = m_mc6846->get_output_port();
- uint8_t portb = m_pia_sys->port_b_z_mask();
- uint8_t disk = ((port >> 2) & 1) | ((port >> 5) & 2); /* bits 6,2: RAM bank */
- int bank;
-
- switch ( portb & 0xf8 )
- {
- /* TO7/70 compatible */
- case 0xf0: bank = 0; break;
- case 0xe8: bank = 1; break;
- case 0x18: bank = 2; break;
- case 0x98: bank = 3; break;
- case 0x58: bank = 4; break;
- case 0xd8: bank = 5; break;
-
- /* 64 KB of virtual disk */
- case 0xf8: bank = 6 + disk ; break;
-
- /* none selected */
- case 0: return;
-
- default:
- logerror( "to9_update_ram_bank: unknown RAM bank pia=$%02X disk=%i\n", portb & 0xf8, disk );
- return;
- }
-
- if ( m_old_ram_bank != bank )
- {
- if ( m_ram->size() == 192*1024 || bank < 6 )
- {
- m_rambank->set_entry( bank );
- }
- else
- {
- space.nop_readwrite( 0xa000, 0xdfff);
- }
- m_old_ram_bank = bank;
- LOG_BANK(( "to9_update_ram_bank: bank %i selected (pia=$%02X disk=%i)\n", bank, portb & 0xf8, disk ));
- }
-}
-
-
-
-void to9_state::to9_update_ram_bank_postload()
-{
- to9_update_ram_bank();
-}
-
-
-
-/* ------------ keyboard (6850 ACIA + 6805 CPU) ------------ */
-
-/* The 6805 chip scans the keyboard and sends ASCII codes to the 6909.
- Data between the 6809 and 6805 is serialized at 9600 bauds.
- On the 6809 side, a 6850 ACIA is used.
- We do not emulate the seral line but pass bytes directly between the
- keyboard and the 6850 registers.
- Note that the keyboard protocol uses the parity bit as an extra data bit.
-*/
-
-
-
-/* normal mode: polling interval */
-#define TO9_KBD_POLL_PERIOD attotime::from_msec( 10 )
-
-/* peripheral mode: time between two bytes, and after last byte */
-#define TO9_KBD_BYTE_SPACE attotime::from_usec( 300 )
-#define TO9_KBD_END_SPACE attotime::from_usec( 9100 )
-
-/* first and subsequent repeat periods, in TO9_KBD_POLL_PERIOD units */
-#define TO9_KBD_REPEAT_DELAY 80 /* 800 ms */
-#define TO9_KBD_REPEAT_PERIOD 7 /* 70 ms */
-
-
-
-/* quick keyboard scan */
-int to9_state::to9_kbd_ktest()
-{
- int line, bit;
- uint8_t port;
-
- for ( line = 0; line < 10; line++ )
- {
- port = m_io_keyboard[line]->read();
-
- if ( line == 7 || line == 9 )
- port |= 1; /* shift & control */
-
- for ( bit = 0; bit < 8; bit++ )
- {
- if ( ! (port & (1 << bit)) )
- return 1;
- }
- }
- return 0;
-}
-
-
-
-void to9_state::to9_kbd_update_irq()
-{
- if ( (m_to9_kbd_intr & 4) && (m_to9_kbd_status & ACIA_6850_RDRF) )
- m_to9_kbd_status |= ACIA_6850_irq; /* byte received interrupt */
-
- if ( (m_to9_kbd_intr & 4) && (m_to9_kbd_status & ACIA_6850_OVRN) )
- m_to9_kbd_status |= ACIA_6850_irq; /* overrun interrupt */
-
- if ( (m_to9_kbd_intr & 3) == 1 && (m_to9_kbd_status & ACIA_6850_TDRE) )
- m_to9_kbd_status |= ACIA_6850_irq; /* ready to transmit interrupt */
-
- m_mainirq->in_w<3>( m_to9_kbd_status & ACIA_6850_irq );
-}
-
-
-
-uint8_t to9_state::to9_kbd_r(offs_t offset)
-{
- /* ACIA 6850 registers */
-
- switch ( offset )
- {
- case 0: /* get status */
- /* bit 0: data received */
- /* bit 1: ready to transmit data (always 1) */
- /* bit 2: data carrier detect (ignored) */
- /* bit 3: clear to send (ignored) */
- /* bit 4: framing error (ignored) */
- /* bit 5: overrun */
- /* bit 6: parity error */
- /* bit 7: interrupt */
-
- LOG_KBD(( "$%04x %f to9_kbd_r: status $%02X (rdrf=%i, tdre=%i, ovrn=%i, pe=%i, irq=%i)\n",
- m_maincpu->pc(), machine().time().as_double(), m_to9_kbd_status,
- (m_to9_kbd_status & ACIA_6850_RDRF) ? 1 : 0,
- (m_to9_kbd_status & ACIA_6850_TDRE) ? 1 : 0,
- (m_to9_kbd_status & ACIA_6850_OVRN) ? 1 : 0,
- (m_to9_kbd_status & ACIA_6850_PE) ? 1 : 0,
- (m_to9_kbd_status & ACIA_6850_irq) ? 1 : 0 ));
- return m_to9_kbd_status;
-
- case 1: /* get input data */
- if ( !machine().side_effects_disabled() )
- {
- m_to9_kbd_status &= ~(ACIA_6850_irq | ACIA_6850_PE);
- if ( m_to9_kbd_overrun )
- m_to9_kbd_status |= ACIA_6850_OVRN;
- else
- m_to9_kbd_status &= ~(ACIA_6850_OVRN | ACIA_6850_RDRF);
- m_to9_kbd_overrun = 0;
- LOG_KBD(( "$%04x %f to9_kbd_r: read data $%02X\n", m_maincpu->pc(), machine().time().as_double(), m_to9_kbd_in ));
- to9_kbd_update_irq();
- }
- return m_to9_kbd_in;
-
- default:
- logerror( "$%04x to9_kbd_r: invalid offset %i\n", m_maincpu->pc(), offset );
- return 0;
- }
-}
-
-
-
-void to9_state::to9_kbd_w(offs_t offset, uint8_t data)
-{
- /* ACIA 6850 registers */
-
- switch ( offset )
- {
- case 0: /* set control */
- /* bits 0-1: clock divide (ignored) or reset */
- if ( (data & 3) == 3 )
- {
- /* reset */
- m_to9_kbd_overrun = 0;
- m_to9_kbd_status = ACIA_6850_TDRE;
- m_to9_kbd_intr = 0;
- LOG_KBD(( "$%04x %f to9_kbd_w: reset (data=$%02X)\n", m_maincpu->pc(), machine().time().as_double(), data ));
- }
- else
- {
- /* bits 2-4: parity */
- if ( (data & 0x18) == 0x10 )
- m_to9_kbd_parity = 2;
- else
- m_to9_kbd_parity = (data >> 2) & 1;
- /* bits 5-6: interrupt on transmit */
- /* bit 7: interrupt on receive */
- m_to9_kbd_intr = data >> 5;
-
- LOG_KBD(( "$%04x %f to9_kbd_w: set control to $%02X (parity=%i, intr in=%i out=%i)\n",
- m_maincpu->pc(), machine().time().as_double(),
- data, m_to9_kbd_parity, m_to9_kbd_intr >> 2,
- (m_to9_kbd_intr & 3) ? 1 : 0 ));
- }
- to9_kbd_update_irq();
- break;
-
- case 1: /* output data */
- m_to9_kbd_status &= ~(ACIA_6850_irq | ACIA_6850_TDRE);
- to9_kbd_update_irq();
- /* TODO: 1 ms delay here ? */
- m_to9_kbd_status |= ACIA_6850_TDRE; /* data transmit ready again */
- to9_kbd_update_irq();
-
- switch ( data )
- {
- case 0xF8:
- /* reset */
- m_to9_kbd_caps = 1;
- m_to9_kbd_periph = 0;
- m_to9_kbd_pad = 0;
- break;
-
- case 0xF9: m_to9_kbd_caps = 1; break;
- case 0xFA: m_to9_kbd_caps = 0; break;
- case 0xFB: m_to9_kbd_pad = 1; break;
- case 0xFC: m_to9_kbd_pad = 0; break;
- case 0xFD: m_to9_kbd_periph = 1; break;
- case 0xFE: m_to9_kbd_periph = 0; break;
-
- default:
- logerror( "$%04x %f to9_kbd_w: unknown kbd command %02X\n", m_maincpu->pc(), machine().time().as_double(), data );
- }
-
- m_caps_led = !m_to9_kbd_caps;
-
- LOG(( "$%04x %f to9_kbd_w: kbd command %02X (caps=%i, pad=%i, periph=%i)\n",
- m_maincpu->pc(), machine().time().as_double(), data,
- m_to9_kbd_caps, m_to9_kbd_pad, m_to9_kbd_periph ));
-
- break;
-
- default:
- logerror( "$%04x to9_kbd_w: invalid offset %i (data=$%02X) \n", m_maincpu->pc(), offset, data );
- }
-}
-
-
-
-/* send a key to the CPU, 8-bit + parity bit (0=even, 1=odd)
- note: parity is not used as a checksum but to actually transmit a 9-th bit
- of information!
-*/
-void to9_state::to9_kbd_send( uint8_t data, int parity )
-{
- if ( m_to9_kbd_status & ACIA_6850_RDRF )
- {
- /* overrun will be set when the current valid byte is read */
- m_to9_kbd_overrun = 1;
- LOG_KBD(( "%f to9_kbd_send: overrun => drop data=$%02X, parity=%i\n", machine().time().as_double(), data, parity ));
- }
- else
- {
- /* valid byte */
- m_to9_kbd_in = data;
- m_to9_kbd_status |= ACIA_6850_RDRF; /* raise data received flag */
- if ( m_to9_kbd_parity == 2 || m_to9_kbd_parity == parity )
- m_to9_kbd_status &= ~ACIA_6850_PE; /* parity OK */
- else
- m_to9_kbd_status |= ACIA_6850_PE; /* parity error */
- LOG_KBD(( "%f to9_kbd_send: data=$%02X, parity=%i, status=$%02X\n", machine().time().as_double(), data, parity, m_to9_kbd_status ));
- }
- to9_kbd_update_irq();
-}
-
-
-
-/* keycode => TO9 code (extended ASCII), shifted and un-shifted */
-static const int to9_kbd_code[80][2] =
-{
- { 145, 150 }, { '_', '6' }, { 'Y', 'Y' }, { 'H', 'H' },
- { 11, 11 }, { 9, 9 }, { 30, 12 }, { 'N', 'N' },
-
- { 146, 151 }, { '(', '5' }, { 'T', 'T' }, { 'G', 'G' },
- { '=', '+' }, { 8, 8 }, { 28, 28 }, { 'B', 'B' },
-
- { 147, 152 }, { '\'', '4' }, { 'R', 'R' }, { 'F', 'F' },
- { 22, 22 }, { 155, 155 }, { 29, 127 }, { 'V', 'V' },
-
- { 148, 153 }, { '"', '3' }, { 'E', 'E' }, { 'D', 'D' },
- { 161, 161 }, { 158, 158 },
- { 154, 154 }, { 'C', 'C' },
-
- { 144, 149 }, { 128, '2' }, { 'Z', 'Z' }, { 'S', 'S' },
- { 162, 162 }, { 156, 156 },
- { 164, 164 }, { 'X', 'X' },
-
- { '#', '@' }, { '*', '1' }, { 'A', 'A' }, { 'Q', 'Q' },
- { '[', '{' }, { 159, 159 }, { 160, 160 }, { 'W', 'W' },
-
- { 2, 2 }, { 129, '7' }, { 'U', 'U' }, { 'J', 'J' },
- { ' ', ' ' }, { 163, 163 }, { 165, 165 },
- { ',', '?' },
-
- { 0, 0 }, { '!', '8' }, { 'I', 'I' }, { 'K', 'K' },
- { '$', '&' }, { 10, 10 }, { ']', '}' }, { ';', '.' },
-
- { 0, 0 }, { 130, '9' }, { 'O', 'O' }, { 'L', 'L' },
- { '-', '\\' }, { 132, '%' }, { 13, 13 }, { ':', '/' },
-
- { 0, 0 }, { 131, '0' }, { 'P', 'P' }, { 'M', 'M' },
- { ')', 134 }, { '^', 133 }, { 157, 157 }, { '>', '<' }
-};
-
-
-
-/* returns the ASCII code for the key, or 0 for no key */
-int to9_state::to9_kbd_get_key()
-{
- int control = ! (m_io_keyboard[7]->read() & 1);
- int shift = ! (m_io_keyboard[9]->read() & 1);
- int key = -1, line, bit;
- uint8_t port;
-
- for ( line = 0; line < 10; line++ )
- {
- port = m_io_keyboard[line]->read();
-
- if ( line == 7 || line == 9 )
- port |= 1; /* shift & control */
-
- /* TODO: correct handling of simultaneous keystokes:
- return the new key preferably & disable repeat
- */
- for ( bit = 0; bit < 8; bit++ )
- {
- if ( ! (port & (1 << bit)) )
- key = line * 8 + bit;
- }
- }
-
- if ( key == -1 )
- {
- m_to9_kbd_last_key = 0xff;
- m_to9_kbd_key_count = 0;
- return 0;
- }
- else if ( key == 64 )
- {
- /* caps lock */
- if ( m_to9_kbd_last_key == key )
- return 0; /* no repeat */
-
- m_to9_kbd_last_key = key;
- m_to9_kbd_caps = !m_to9_kbd_caps;
- m_caps_led = !m_to9_kbd_caps;
- return 0;
- }
- else
- {
- int asc;
- asc = to9_kbd_code[key][shift];
- if ( ! asc ) return 0;
-
- /* keypad */
- if ( ! m_to9_kbd_pad ) {
- if ( asc >= 154 && asc <= 163 )
- asc += '0' - 154;
- else if ( asc == 164 )
- asc = '.';
- else if ( asc == 165 )
- asc = 13;
- }
-
- /* shifted letter */
- if ( asc >= 'A' && asc <= 'Z' && ( ! m_to9_kbd_caps ) && ( ! shift ) )
- asc += 'a' - 'A';
-
- /* control */
- if ( control )
- asc &= ~0x40;
-
- if ( key == m_to9_kbd_last_key )
- {
- /* repeat */
- m_to9_kbd_key_count++;
- if ( m_to9_kbd_key_count < TO9_KBD_REPEAT_DELAY || (m_to9_kbd_key_count - TO9_KBD_REPEAT_DELAY) % TO9_KBD_REPEAT_PERIOD )
- return 0;
- LOG_KBD(( "to9_kbd_get_key: repeat key $%02X '%c'\n", asc, asc ));
- return asc;
- }
- else
- {
- m_to9_kbd_last_key = key;
- m_to9_kbd_key_count = 0;
- LOG_KBD(( "to9_kbd_get_key: key down $%02X '%c'\n", asc, asc ));
- return asc;
- }
- }
-}
-
-
-
-TIMER_CALLBACK_MEMBER(to9_state::to9_kbd_timer_cb)
-{
- if ( m_to9_kbd_periph )
- {
- /* peripheral mode: every 10 ms we send 4 bytes */
-
- switch ( m_to9_kbd_byte_count )
- {
- case 0: /* key */
- to9_kbd_send( to9_kbd_get_key(), 0 );
- break;
-
- case 1: /* x axis */
- {
- int newx = m_io_mouse_x->read();
- uint8_t data = ( (newx - m_to9_mouse_x) & 0xf ) - 8;
- to9_kbd_send( data, 1 );
- m_to9_mouse_x = newx;
- break;
- }
-
- case 2: /* y axis */
- {
- int newy = m_io_mouse_y->read();
- uint8_t data = ( (newy - m_to9_mouse_y) & 0xf ) - 8;
- to9_kbd_send( data, 1 );
- m_to9_mouse_y = newy;
- break;
- }
-
- case 3: /* axis overflow & buttons */
- {
- int b = m_io_mouse_button->read();
- uint8_t data = 0;
- if ( b & 1 ) data |= 1;
- if ( b & 2 ) data |= 4;
- to9_kbd_send( data, 1 );
- break;
- }
-
- }
-
- m_to9_kbd_byte_count = ( m_to9_kbd_byte_count + 1 ) & 3;
- m_to9_kbd_timer->adjust(m_to9_kbd_byte_count ? TO9_KBD_BYTE_SPACE : TO9_KBD_END_SPACE);
- }
- else
- {
- int key = to9_kbd_get_key();
- /* keyboard mode: send a byte only if a key is down */
- if ( key )
- to9_kbd_send( key, 0 );
- m_to9_kbd_timer->adjust(TO9_KBD_POLL_PERIOD);
- }
-}
-
-
-
-void to9_state::to9_kbd_reset()
-{
- LOG(( "to9_kbd_reset called\n" ));
- m_to9_kbd_overrun = 0; /* no byte lost */
- m_to9_kbd_status = ACIA_6850_TDRE; /* clear to transmit */
- m_to9_kbd_intr = 0; /* interrupt disabled */
- m_to9_kbd_caps = 1;
- m_to9_kbd_periph = 0;
- m_to9_kbd_pad = 0;
- m_to9_kbd_byte_count = 0;
- m_caps_led = !m_to9_kbd_caps;
- m_to9_kbd_key_count = 0;
- m_to9_kbd_last_key = 0xff;
- to9_kbd_update_irq();
- m_to9_kbd_timer->adjust(TO9_KBD_POLL_PERIOD);
-}
-
-
-
-void to9_state::to9_kbd_init()
-{
- LOG(( "to9_kbd_init called\n" ));
- m_to9_kbd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(to9_state::to9_kbd_timer_cb),this));
- save_item(NAME(m_to9_kbd_parity));
- save_item(NAME(m_to9_kbd_intr));
- save_item(NAME(m_to9_kbd_in));
- save_item(NAME(m_to9_kbd_status));
- save_item(NAME(m_to9_kbd_overrun));
- save_item(NAME(m_to9_kbd_last_key));
- save_item(NAME(m_to9_kbd_key_count));
- save_item(NAME(m_to9_kbd_caps));
- save_item(NAME(m_to9_kbd_periph));
- save_item(NAME(m_to9_kbd_pad));
- save_item(NAME(m_to9_kbd_byte_count));
- save_item(NAME(m_to9_mouse_x));
- save_item(NAME(m_to9_mouse_y));
-}
-
-
-/* ------------ system PIA 6821 ------------ */
-
-uint8_t to9_state::to9_sys_porta_in()
-{
- uint8_t ktest = to9_kbd_ktest();
-
- LOG_KBD(( "to9_sys_porta_in: ktest=%i\n", ktest ));
-
- // PB1-7 are not connected, and are pulled hi internally
- return ktest | 0xfe;
-}
-
-
-
-void to9_state::to9_sys_porta_out(uint8_t data)
-{
- m_centronics->write_data1(BIT(data, 1));
- m_centronics->write_data2(BIT(data, 2));
- m_centronics->write_data3(BIT(data, 3));
- m_centronics->write_data4(BIT(data, 4));
- m_centronics->write_data5(BIT(data, 5));
- m_centronics->write_data6(BIT(data, 6));
- m_centronics->write_data7(BIT(data, 7));
-}
-
-
-
-void to9_state::to9_sys_portb_out(uint8_t data)
-{
- m_centronics->write_data0(BIT(data, 0));
- m_centronics->write_strobe(BIT(data, 1));
-
- to9_update_ram_bank();
-
- if ( data & 4 ) /* bit 2: video overlay (TODO) */
- LOG(( "to9_sys_portb_out: video overlay not handled\n" ));
-}
-
-
-
-/* ------------ 6846 (timer, I/O) ------------ */
-
-
-
-void to9_state::to9_timer_port_out(uint8_t data)
-{
- thom_set_mode_point( data & 1 ); /* bit 0: video bank */
- to9_update_ram_bank();
- to9_update_cart_bank();
-}
-
-
-/* ------------ init / reset ------------ */
-
-
-
-MACHINE_RESET_MEMBER( to9_state, to9 )
-{
- LOG (( "to9: machine reset called\n" ));
-
- /* subsystems */
- thom_irq_reset();
- to7_game_reset();
- to9_kbd_reset();
- to7_modem_reset();
- to7_midi_reset();
-
- m_extension->rom_map(m_maincpu->space(AS_PROGRAM), 0xe000, 0xe7bf);
- m_extension->io_map (m_maincpu->space(AS_PROGRAM), 0xe7d0, 0xe7df);
-
- /* video */
- thom_set_video_mode( THOM_VMODE_TO9 );
- m_thom_lightpen_cb = std::bind(&to9_state::to7_lightpen_cb, this, std::placeholders::_1);
- thom_set_lightpen_callback( 3 );
- thom_set_border_color( 8 );
- thom_set_mode_point( 0 );
- m_pia_sys->cb1_w( 0 );
-
- /* memory */
- m_old_ram_bank = -1;
- m_old_cart_bank = -1;
- m_to9_soft_bank = 0;
- to9_update_cart_bank();
- to9_update_ram_bank();
- /* thom_cart_bank not reset */
-
- /* lightpen */
- m_to7_lightpen = 0;
-}
-
-
-
-MACHINE_START_MEMBER( to9_state, to9 )
-{
- uint8_t* cartmem = &m_cart_rom[0];
- uint8_t* ram = m_ram->pointer();
-
- LOG (( "to9: machine start called\n" ));
-
- /* subsystems */
- to7_game_init();
- to9_kbd_init();
- to9_palette_init();
- to7_modem_init();
- to7_midi_init();
-
- m_extension->rom_map(m_maincpu->space(AS_PROGRAM), 0xe000, 0xe7bf);
- m_extension->io_map (m_maincpu->space(AS_PROGRAM), 0xe7d0, 0xe7df);
-
- /* memory */
- m_thom_vram = ram;
- m_thom_cart_bank = 0;
- m_vrambank->configure_entries( 0, 2, m_thom_vram, 0x2000 );
- m_cartbank->configure_entries( 0, 12, cartmem, 0x4000 );
- m_basebank->configure_entry( 0, ram + 0x4000);
- m_rambank->configure_entries( 0, 10, ram + 0x8000, 0x4000 );
- m_vrambank->set_entry( 0 );
- m_cartbank->set_entry( 0 );
- m_basebank->set_entry( 0 );
- m_rambank->set_entry( 0 );
-
- /* save-state */
- save_item(NAME(m_thom_cart_nb_banks));
- save_item(NAME(m_thom_cart_bank));
- save_item(NAME(m_to7_lightpen));
- save_item(NAME(m_to7_lightpen_step));
- save_item(NAME(m_to9_soft_bank));
- save_pointer(NAME(cartmem), 0x10000 );
- machine().save().register_postload(save_prepost_delegate(FUNC(to9_state::to9_update_ram_bank_postload), this));
- machine().save().register_postload(save_prepost_delegate(FUNC(to9_state::to9_update_cart_bank_postload), this));
-}
-
-
-
-/***************************** TO8 *************************/
-
-
-/* ------------ keyboard (6804) ------------ */
-
-/* The 6804 chip scans the keyboard and sends keycodes to the 6809.
- Data is serialized using variable pulse length encoding.
- Unlike the TO9, there is no decoding chip on the 6809 side, only
- 1-bit PIA ports (6821 & 6846). The 6809 does the decoding.
-
- We do not emulate the 6804 but pass serialized data directly through the
- PIA ports.
-
- Note: if we conform to the (scarce) documentation the CPU tend to lock
- waitting for keyboard input.
- The protocol documentation is pretty scarce and does not account for these
- behaviors!
- The emulation code contains many hacks (delays, timeouts, spurious
- pulses) to improve the stability.
- This works well, but is not very accurate.
-*/
-
-
-
-/* polling interval */
-#define TO8_KBD_POLL_PERIOD attotime::from_msec( 1 )
-
-/* first and subsequent repeat periods, in TO8_KBD_POLL_PERIOD units */
-#define TO8_KBD_REPEAT_DELAY 800 /* 800 ms */
-#define TO8_KBD_REPEAT_PERIOD 70 /* 70 ms */
-
-/* timeout waiting for CPU */
-#define TO8_KBD_TIMEOUT attotime::from_msec( 100 )
-
-
-
-/* quick keyboard scan */
-int to9_state::to8_kbd_ktest()
-{
- int line, bit;
- uint8_t port;
-
- if ( m_io_config->read() & 2 )
- return 0; /* disabled */
-
- for ( line = 0; line < 10; line++ )
- {
- port = m_io_keyboard[line]->read();
-
- if ( line == 7 || line == 9 )
- port |= 1; /* shift & control */
-
- for ( bit = 0; bit < 8; bit++ )
- {
- if ( ! (port & (1 << bit)) )
- return 1;
- }
- }
-
- return 0;
-}
-
-
-
-/* keyboard scan & return keycode (or -1) */
-int to9_state::to8_kbd_get_key()
-{
- int control = (m_io_keyboard[7]->read() & 1) ? 0 : 0x100;
- int shift = (m_io_keyboard[9]->read() & 1) ? 0 : 0x080;
- int key = -1, line, bit;
- uint8_t port;
-
- if ( m_io_config->read() & 2 )
- return -1; /* disabled */
-
- for ( line = 0; line < 10; line++ )
- {
- port = m_io_keyboard[line]->read();
-
- if ( line == 7 || line == 9 )
- port |= 1; /* shift & control */
-
- /* TODO: correct handling of simultaneous keystokes:
- return the new key preferably & disable repeat
- */
- for ( bit = 0; bit < 8; bit++ )
- {
- if ( ! (port & (1 << bit)) )
- key = line * 8 + bit;
- }
- }
-
- if ( key == -1 )
- {
- m_to8_kbd_last_key = 0xff;
- m_to8_kbd_key_count = 0;
- return -1;
- }
- else if ( key == 64 )
- {
- /* caps lock */
- if ( m_to8_kbd_last_key == key )
- return -1; /* no repeat */
- m_to8_kbd_last_key = key;
- m_to8_kbd_caps = !m_to8_kbd_caps;
- if ( m_to8_kbd_caps )
- key |= 0x080; /* auto-shift */
- m_caps_led = !m_to8_kbd_caps;
- return key;
- }
- else if ( key == m_to8_kbd_last_key )
- {
- /* repeat */
- m_to8_kbd_key_count++;
- if ( m_to8_kbd_key_count < TO8_KBD_REPEAT_DELAY || (m_to8_kbd_key_count - TO8_KBD_REPEAT_DELAY) % TO8_KBD_REPEAT_PERIOD )
- return -1;
- return key | shift | control;
- }
- else
- {
- m_to8_kbd_last_key = key;
- m_to8_kbd_key_count = 0;
- return key | shift | control;
- }
-}
-
-
-/* steps:
- 0 = idle, key polling
- 1 = wait for ack to go down (key to send)
- 99-117 = key data transmit
- 91-117 = signal
- 255 = timeout
-*/
-
-/* keyboard automaton */
-void to9_state::to8_kbd_timer_func()
-{
- attotime d;
-
- LOG_KBD(( "%f to8_kbd_timer_cb: step=%i ack=%i data=$%03X\n", machine().time().as_double(), m_to8_kbd_step, m_to8_kbd_ack, m_to8_kbd_data ));
-
- if( ! m_to8_kbd_step )
- {
- /* key polling */
- int k = to8_kbd_get_key();
- /* if not in transfer, send pulse from time to time
- (helps avoiding CPU lock)
- */
- if ( ! m_to8_kbd_ack )
- m_mc6846->set_input_cp1(0);
- m_mc6846->set_input_cp1(1);
-
- if ( k == -1 )
- d = TO8_KBD_POLL_PERIOD;
- else
- {
- /* got key! */
- LOG_KBD(( "to8_kbd_timer_cb: got key $%03X\n", k ));
- m_to8_kbd_data = k;
- m_to8_kbd_step = 1;
- d = attotime::from_usec( 100 );
- }
- }
- else if ( m_to8_kbd_step == 255 )
- {
- /* timeout */
- m_to8_kbd_last_key = 0xff;
- m_to8_kbd_key_count = 0;
- m_to8_kbd_step = 0;
- m_mc6846->set_input_cp1(1);
- d = TO8_KBD_POLL_PERIOD;
- }
- else if ( m_to8_kbd_step == 1 )
- {
- /* schedule timeout waiting for ack to go down */
- m_mc6846->set_input_cp1(0);
- m_to8_kbd_step = 255;
- d = TO8_KBD_TIMEOUT;
- }
- else if ( m_to8_kbd_step == 117 )
- {
- /* schedule timeout waiting for ack to go up */
- m_mc6846->set_input_cp1(0);
- m_to8_kbd_step = 255;
- d = TO8_KBD_TIMEOUT;
- }
- else if ( m_to8_kbd_step & 1 )
- {
- /* send silence between bits */
- m_mc6846->set_input_cp1(0);
- d = attotime::from_usec( 100 );
- m_to8_kbd_step++;
- }
- else
- {
- /* send bit */
- int bpos = 8 - ( (m_to8_kbd_step - 100) / 2);
- int bit = (m_to8_kbd_data >> bpos) & 1;
- m_mc6846->set_input_cp1(1);
- d = attotime::from_usec( bit ? 56 : 38 );
- m_to8_kbd_step++;
- }
- m_to8_kbd_timer->adjust(d);
-}
-
-
-
-TIMER_CALLBACK_MEMBER(to9_state::to8_kbd_timer_cb)
-{
- to8_kbd_timer_func();
-}
-
-
-
-/* cpu <-> keyboard hand-check */
-void to9_state::to8_kbd_set_ack( int data )
-{
- if ( data == m_to8_kbd_ack )
- return;
- m_to8_kbd_ack = data;
-
- if ( data )
- {
- double len = m_to8_kbd_signal->elapsed( ).as_double() * 1000. - 2.;
- LOG_KBD(( "%f to8_kbd_set_ack: CPU end ack, len=%f\n", machine().time().as_double(), len ));
- if ( m_to8_kbd_data == 0xfff )
- {
- /* end signal from CPU */
- if ( len >= 0.6 && len <= 0.8 )
- {
- LOG (( "%f to8_kbd_set_ack: INIT signal\n", machine().time().as_double() ));
- m_to8_kbd_last_key = 0xff;
- m_to8_kbd_key_count = 0;
- m_to8_kbd_caps = 1;
- /* send back signal: TODO returned codes ? */
- m_to8_kbd_data = 0;
- m_to8_kbd_step = 0;
- m_to8_kbd_timer->adjust(attotime::from_msec( 1 ));
- }
- else
- {
- m_to8_kbd_step = 0;
- m_to8_kbd_timer->adjust(TO8_KBD_POLL_PERIOD);
- if ( len >= 1.2 && len <= 1.4 )
- {
- LOG (( "%f to8_kbd_set_ack: CAPS on signal\n", machine().time().as_double() ));
- m_to8_kbd_caps = 1;
- }
- else if ( len >= 1.8 && len <= 2.0 )
- {
- LOG (( "%f to8_kbd_set_ack: CAPS off signal\n", machine().time().as_double() ));
- m_to8_kbd_caps = 0;
- }
- }
- m_caps_led = !m_to8_kbd_caps;
- }
- else
- {
- /* end key transmission */
- m_to8_kbd_step = 0;
- m_to8_kbd_timer->adjust(TO8_KBD_POLL_PERIOD);
- }
- }
-
- else
- {
- if ( m_to8_kbd_step == 255 )
- {
- /* CPU accepts key */
- m_to8_kbd_step = 99;
- m_to8_kbd_timer->adjust(attotime::from_usec( 400 ));
- }
- else
- {
- /* start signal from CPU */
- m_to8_kbd_data = 0xfff;
- m_to8_kbd_step = 91;
- m_to8_kbd_timer->adjust(attotime::from_usec( 400 ));
- m_to8_kbd_signal->adjust(attotime::never);
- }
- LOG_KBD(( "%f to8_kbd_set_ack: CPU ack, data=$%03X\n", machine().time().as_double(), m_to8_kbd_data ));
- }
-}
-
-
-
-void to9_state::to8_kbd_reset()
-{
- m_to8_kbd_last_key = 0xff;
- m_to8_kbd_key_count = 0;
- m_to8_kbd_step = 0;
- m_to8_kbd_data = 0;
- m_to8_kbd_ack = 1;
- m_to8_kbd_caps = 1;
- m_caps_led = !m_to8_kbd_caps;
- to8_kbd_timer_func();
-}
-
-
-
-void to9_state::to8_kbd_init()
-{
- m_to8_kbd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(to9_state::to8_kbd_timer_cb),this));
- m_to8_kbd_signal = machine().scheduler().timer_alloc(timer_expired_delegate());
- save_item(NAME(m_to8_kbd_ack));
- save_item(NAME(m_to8_kbd_data));
- save_item(NAME(m_to8_kbd_step));
- save_item(NAME(m_to8_kbd_last_key));
- save_item(NAME(m_to8_kbd_key_count));
- save_item(NAME(m_to8_kbd_caps));
-}
-
-
-
-/* ------------ RAM / ROM banking ------------ */
-
-void to9_state::to8_update_ram_bank()
-{
- address_space& space = m_maincpu->space(AS_PROGRAM);
- uint8_t bank = 0;
-
- if ( m_to8_reg_sys1 & 0x10 )
- {
- bank = m_to8_reg_ram & 31;
- }
- else
- {
- uint8_t portb = m_pia_sys->port_b_z_mask();
-
- switch ( portb & 0xf8 )
- {
- /* in compatibility mode, banks 5 and 6 are reversed wrt TO7/70 */
- case 0xf0: bank = 2; break;
- case 0xe8: bank = 3; break;
- case 0x18: bank = 4; break;
- case 0x58: bank = 5; break;
- case 0x98: bank = 6; break;
- case 0xd8: bank = 7; break;
- case 0xf8: return;
- default:
- logerror( "to8_update_ram_bank: unknown RAM bank=$%02X\n", portb & 0xf8 );
- return;
- }
- }
-
- /* due to addressing distortion, the 16 KB banked memory space is
- split into two 8 KB spaces:
- - 0xa000-0xbfff maps to 0x2000-0x3fff in 16 KB bank
- - 0xc000-0xdfff maps to 0x0000-0x1fff in 16 KB bank
- this is important if we map a bank that is also reachable by another,
- undistorted space, such as cartridge, page 0 (video), or page 1
- */
- if ( bank != m_old_ram_bank)
- {
- if (m_ram->size() == 512*1024 || m_to8_data_vpage < 16)
- {
- m_datalobank->set_entry( bank );
- m_datahibank->set_entry( bank );
- }
- else
- {
- /* RAM size is 256 KB only and unavailable
- * bank requested */
- space.nop_readwrite( 0xa000, 0xbfff);
- space.nop_readwrite( 0xc000, 0xdfff);
- }
- m_to8_data_vpage = bank;
- m_old_ram_bank = bank;
- LOG_BANK(( "to8_update_ram_bank: select bank %i (%s style)\n", bank, (m_to8_reg_sys1 & 0x10) ? "new" : "old"));
- }
-}
-
-
-
-void to9_state::to8_update_ram_bank_postload()
-{
- to8_update_ram_bank();
-}
-
-
-
-void to9_state::to8_update_cart_bank()
-{
- address_space& space = m_maincpu->space(AS_PROGRAM);
- int bank = 0;
- int bank_is_read_only = 0;
-
- if ( m_to8_reg_cart & 0x20 )
- {
- /* RAM space */
- m_to8_cart_vpage = m_to8_reg_cart & 31;
- bank = 8 + m_to8_cart_vpage;
- bank_is_read_only = (( m_to8_reg_cart & 0x40 ) == 0);
- if ( bank != m_old_cart_bank )
- {
- /* mapping to VRAM */
- if (m_ram->size() == 512*1024 || m_to8_cart_vpage < 16)
- {
- if (m_to8_cart_vpage < 4)
- {
- if (m_old_cart_bank < 8 || m_old_cart_bank > 11)
- {
- space.install_read_bank( 0x0000, 0x3fff, m_cartbank );
- if ( bank_is_read_only )
- {
- space.nop_write( 0x0000, 0x3fff);
- }
- else
- {
- space.install_write_handler( 0x0000, 0x3fff, write8sm_delegate(*this, FUNC(to9_state::to8_vcart_w)));
- }
- }
- }
- else
- {
- if (m_old_cart_bank < 12)
- {
- if ( bank_is_read_only )
- {
- space.install_read_bank( 0x0000, 0x3fff, m_cartbank );
- space.nop_write( 0x0000, 0x3fff);
- }
- else
- {
- space.install_readwrite_bank(0x0000, 0x3fff, m_cartbank);
- }
- }
- }
- }
- else
- {
- /* RAM size is 256 KB only and unavailable
- * bank requested */
- space.nop_readwrite( 0x0000, 0x3fff);
- }
- LOG_BANK(( "to8_update_cart_bank: CART is RAM bank %i (%s)\n",
- m_to8_cart_vpage,
- bank_is_read_only ? "read-only":"read-write"));
- }
- else
- {
- if ( bank_is_read_only != m_old_cart_bank_was_read_only )
- {
- if ( bank_is_read_only )
- {
- space.nop_write( 0x0000, 0x3fff);
- }
- else
- {
- if (m_to8_cart_vpage < 4)
- {
- space.install_write_handler( 0x0000, 0x3fff, write8sm_delegate(*this, FUNC(to9_state::to8_vcart_w)));
- }
- else
- {
- space.install_readwrite_bank( 0x0000, 0x3fff, m_cartbank );
- }
- }
- LOG_BANK(( "to8_update_cart_bank: update CART bank %i write status to %s\n",
- m_to8_cart_vpage,
- bank_is_read_only ? "read-only":"read-write"));
- }
- }
- m_old_cart_bank_was_read_only = bank_is_read_only;
- }
- else
- {
- if ( m_to8_soft_select )
- {
- /* internal software ROM space */
- bank = 4 + m_to8_soft_bank;
- if ( bank != m_old_cart_bank )
- {
- if ( m_old_cart_bank < 4 || m_old_cart_bank > 7 )
- {
- space.install_read_bank( 0x0000, 0x3fff, m_cartbank );
- space.install_write_handler( 0x0000, 0x3fff, write8sm_delegate(*this, FUNC(to9_state::to8_cartridge_w)) );
- }
- LOG_BANK(( "to8_update_cart_bank: CART is internal bank %i\n", m_to8_soft_bank ));
- }
- }
- else
- {
- /* external cartridge ROM space */
- if ( m_thom_cart_nb_banks )
- {
- bank = m_thom_cart_bank % m_thom_cart_nb_banks;
- if ( bank != m_old_cart_bank )
- {
- if ( m_old_cart_bank < 0 || m_old_cart_bank > 3 )
- {
- space.install_read_bank( 0x0000, 0x3fff, m_cartbank );
- space.install_write_handler( 0x0000, 0x3fff, write8sm_delegate(*this, FUNC(to9_state::to8_cartridge_w)) );
- space.install_read_handler( 0x0000, 0x0003, read8sm_delegate(*this, FUNC(to9_state::to8_cartridge_r)) );
- }
- LOG_BANK(( "to8_update_cart_bank: CART is external cartridge bank %i\n", bank ));
- }
- }
- else
- {
- if ( m_old_cart_bank != 0 )
- {
- space.nop_read( 0x0000, 0x3fff);
- LOG_BANK(( "to8_update_cart_bank: CART is unmapped\n"));
- }
- }
- }
- }
- if ( bank != m_old_cart_bank )
- {
- m_cartbank->set_entry( bank );
- m_old_cart_bank = bank;
- }
-}
-
-
-
-void to9_state::to8_update_cart_bank_postload()
-{
- to8_update_cart_bank();
-}
-
-
-
-/* ROM bank switch */
-void to9_state::to8_cartridge_w(offs_t offset, uint8_t data)
-{
- if ( offset >= 0x2000 )
- return;
-
- if ( m_to8_soft_select )
- m_to8_soft_bank = offset & 3;
- else
- m_thom_cart_bank = offset & 3;
-
- to8_update_cart_bank();
-}
-
-
-
-/* read signal to 0000-0003 generates a bank switch */
-uint8_t to9_state::to8_cartridge_r(offs_t offset)
-{
- uint8_t data = m_cart_rom[offset + (m_thom_cart_bank % m_thom_cart_nb_banks) * 0x4000];
- if ( !machine().side_effects_disabled() )
- {
- m_thom_cart_bank = offset & 3;
- to8_update_cart_bank();
- }
- return data;
-}
-
-
-/* ------------ system gate-array ------------ */
-
-
-
-#define TO8_LIGHTPEN_DECAL 16
-
-
-
-uint8_t to9_state::to8_gatearray_r(offs_t offset)
-{
- struct thom_vsignal v = thom_get_vsignal();
- struct thom_vsignal l = thom_get_lightpen_vsignal( TO8_LIGHTPEN_DECAL, m_to7_lightpen_step - 1, 6 );
- int count, inil, init, lt3;
- uint8_t res;
- count = m_to7_lightpen ? l.count : v.count;
- inil = m_to7_lightpen ? l.inil : v.inil;
- init = m_to7_lightpen ? l.init : v.init;
- lt3 = m_to7_lightpen ? l.lt3 : v.lt3;
-
- switch ( offset )
- {
- case 0: /* system 2 / lightpen register 1 */
- if ( m_to7_lightpen )
- res = (count >> 8) & 0xff;
- else
- res = m_to8_reg_sys2 & 0xf0;
- break;
-
- case 1: /* ram register / lightpen register 2 */
- if ( m_to7_lightpen )
- {
- if ( !machine().side_effects_disabled() )
- {
- m_mainfirq->in_w<2>(0);
- m_to8_lightpen_intr = 0;
- }
- res = count & 0xff;
- }
- else
- res = m_to8_reg_ram & 0x1f;
- break;
-
- case 2: /* cartrige register / lightpen register 3 */
- if ( m_to7_lightpen )
- res = (lt3 << 7) | (inil << 6);
- else
- res = m_to8_reg_cart;
- break;
-
- case 3: /* lightpen register 4 */
- res = (v.init << 7) | (init << 6) | (v.inil << 5) | (m_to8_lightpen_intr << 1) | m_to7_lightpen;
- break;
-
- default:
- logerror( "$%04x to8_gatearray_r: invalid offset %i\n", m_maincpu->pc(), offset );
- res = 0;
- }
-
- LOG_VIDEO(( "$%04x %f to8_gatearray_r: off=%i ($%04X) res=$%02X lightpen=%i\n",
- m_maincpu->pc(), machine().time().as_double(),
- offset, 0xe7e4 + offset, res, m_to7_lightpen ));
-
- return res;
-}
-
-
-
-void to9_state::to8_gatearray_w(offs_t offset, uint8_t data)
-{
- LOG_VIDEO(( "$%04x %f to8_gatearray_w: off=%i ($%04X) data=$%02X\n",
- m_maincpu->pc(), machine().time().as_double(),
- offset, 0xe7e4 + offset, data ));
-
- switch ( offset )
- {
- case 0: /* switch */
- m_to7_lightpen = data & 1;
- break;
-
- case 1: /* ram register */
- if ( m_to8_reg_sys1 & 0x10 )
- {
- m_to8_reg_ram = data;
- to8_update_ram_bank();
- }
- break;
-
- case 2: /* cartridge register */
- m_to8_reg_cart = data;
- to8_update_cart_bank();
- break;
-
- case 3: /* system register 1 */
- m_to8_reg_sys1 = data;
- to8_update_ram_bank();
- to8_update_cart_bank();
- break;
-
- default:
- logerror( "$%04x to8_gatearray_w: invalid offset %i (data=$%02X)\n",
- m_maincpu->pc(), offset, data );
- }
-}
-
-
-
-/* ------------ video gate-array ------------ */
-
-
-
-uint8_t to9_state::to8_vreg_r(offs_t offset)
-{
- /* 0xe7dc from external floppy drive aliases the video gate-array */
- if ( ( offset == 3 ) && ( m_to8_reg_ram & 0x80 ) && ( m_to8_reg_sys1 & 0x80 ) )
- {
- if ( machine().side_effects_disabled() )
- return 0;
-
- abort(); // return to7_floppy_r( 0xc );
- }
-
- switch ( offset )
- {
- case 0: /* palette data */
- {
- uint8_t c = m_to9_palette_data[ m_to9_palette_idx ];
- if ( !machine().side_effects_disabled() )
- {
- m_to9_palette_idx = ( m_to9_palette_idx + 1 ) & 31;
- }
- return c;
- }
-
- case 1: /* palette address */
- return m_to9_palette_idx;
-
- case 2:
- case 3:
- return 0;
-
- default:
- logerror( "to8_vreg_r: invalid read offset %i\n", offset );
- return 0;
- }
-}
-
-
-
-void to9_state::to8_vreg_w(offs_t offset, uint8_t data)
-{
- LOG_VIDEO(( "$%04x %f to8_vreg_w: off=%i ($%04X) data=$%02X\n",
- m_maincpu->pc(), machine().time().as_double(),
- offset, 0xe7da + offset, data ));
-
- switch ( offset )
- {
- case 0: /* palette data */
- {
- uint16_t color, idx;
- m_to9_palette_data[ m_to9_palette_idx ] = data;
- idx = m_to9_palette_idx / 2;
- color = m_to9_palette_data[ 2 * idx + 1 ];
- color = m_to9_palette_data[ 2 * idx ] | (color << 8);
- thom_set_palette( idx, color & 0x1fff );
- m_to9_palette_idx = ( m_to9_palette_idx + 1 ) & 31;
- }
- break;
-
- case 1: /* palette address */
- m_to9_palette_idx = data & 31;
- break;
-
- case 2: /* display register */
- to9_set_video_mode( data, 1 );
- break;
-
- case 3: /* system register 2 */
- /* 0xe7dc from external floppy drive aliases the video gate-array */
- if ( ( offset == 3 ) && ( m_to8_reg_ram & 0x80 ) && ( m_to8_reg_sys1 & 0x80 ) )
- {
- abort(); // to7_floppy_w( 0xc, data );
- }
- else
- {
- m_to8_reg_sys2 = data;
- thom_set_video_page( data >> 6 );
- thom_set_border_color( data & 15 );
- }
- break;
-
- default:
- logerror( "to8_vreg_w: invalid write offset %i data=$%02X\n", offset, data );
- }
-}
-
-
-
-/* ------------ system PIA 6821 ------------ */
-
-
-uint8_t to9_state::to8_sys_porta_in()
-{
- int ktest = to8_kbd_ktest();
-
- LOG_KBD(( "$%04x %f: to8_sys_porta_in ktest=%i\n", m_maincpu->pc(), machine().time().as_double(), ktest ));
-
- // PB1-7 are not connected, and are pulled hi internally
- return ktest | 0xfe;
-}
-
-
-
-void to9_state::to8_sys_portb_out(uint8_t data)
-{
- m_centronics->write_data0(BIT(data, 0));
- m_centronics->write_strobe(BIT(data, 1));
-
- to8_update_ram_bank();
-
- if ( data & 4 ) /* bit 2: video overlay (TODO) */
- LOG(( "to8_sys_portb_out: video overlay not handled\n" ));
-}
-
-
-
-/* ------------ 6846 (timer, I/O) ------------ */
-
-
-WRITE_LINE_MEMBER(to9_state::write_centronics_busy )
-{
- m_centronics_busy = state;
-}
-
-uint8_t to9_state::to8_timer_port_in()
-{
- int lightpen = (m_io_lightpen_button->read() & 1) ? 2 : 0;
- int cass = to7_get_cassette() ? 0x80 : 0;
- int dtr = m_centronics_busy << 6;
- int lock = m_to8_kbd_caps ? 0 : 8; /* undocumented! */
- return lightpen | cass | dtr | lock;
-}
-
-
-
-void to9_state::to8_timer_port_out(uint8_t data)
-{
- int ack = (data & 0x20) ? 1 : 0; /* bit 5: keyboard ACK */
- m_to8_bios_bank = (data & 0x10) ? 1 : 0; /* bit 4: BIOS bank*/
- thom_set_mode_point( data & 1 ); /* bit 0: video bank switch */
- m_biosbank->set_entry( m_to8_bios_bank );
- m_to8_soft_select = (data & 0x04) ? 1 : 0; /* bit 2: internal ROM select */
- to8_update_cart_bank();
- to8_kbd_set_ack(ack);
-}
-
-
-
-WRITE_LINE_MEMBER( to9_state::to8_timer_cp2_out )
-{
- /* mute */
- m_to7_game_mute = state;
- to7_game_sound_update();
-}
-
-/* ------------ lightpen ------------ */
-
-
-
-/* direct connection to interrupt line instead of through a PIA */
-void to9_state::to8_lightpen_cb( int step )
-{
- if ( ! m_to7_lightpen )
- return;
-
- m_mainfirq->in_w<2>(1);
- m_to7_lightpen_step = step;
- m_to8_lightpen_intr = 1;
-}
-
-
-
-/* ------------ init / reset ------------ */
-
-
-
-MACHINE_RESET_MEMBER( to9_state, to8 )
-{
- LOG (( "to8: machine reset called\n" ));
-
- /* subsystems */
- thom_irq_reset();
- to7_game_reset();
- to8_kbd_reset();
- to7_modem_reset();
- to7_midi_reset();
-
- /* gate-array */
- m_to7_lightpen = 0;
- m_to8_reg_ram = 0;
- m_to8_reg_cart = 0;
- m_to8_reg_sys1 = 0;
- m_to8_reg_sys2 = 0;
- m_to8_lightpen_intr = 0;
- m_to8_soft_select = 0;
-
- /* video */
- thom_set_video_mode( THOM_VMODE_TO770 );
- m_thom_lightpen_cb = std::bind(&to9_state::to8_lightpen_cb, this, std::placeholders::_1);
- thom_set_lightpen_callback( 4 );
- thom_set_border_color( 0 );
- thom_set_mode_point( 0 );
- m_pia_sys->cb1_w( 0 );
-
- /* memory */
- m_old_ram_bank = -1;
- m_old_cart_bank = -1;
- m_old_cart_bank_was_read_only = 0;
- m_to8_cart_vpage = 0;
- m_to8_data_vpage = 0;
- m_to8_soft_bank = 0;
- m_to8_bios_bank = 0;
- to8_update_ram_bank();
- to8_update_cart_bank();
- m_biosbank->set_entry( 0 );
- /* thom_cart_bank not reset */
-}
-
-
-
-MACHINE_START_MEMBER( to9_state, to8 )
-{
- uint8_t* mem = memregion("maincpu")->base();
- uint8_t* cartmem = &m_cart_rom[0];
- uint8_t* ram = m_ram->pointer();
-
- LOG (( "to8: machine start called\n" ));
-
- /* subsystems */
- to7_game_init();
- to8_kbd_init();
- to9_palette_init();
- to7_modem_init();
- to7_midi_init();
-
- m_extension->rom_map(m_maincpu->space(AS_PROGRAM), 0xe000, 0xe7bf);
- m_extension->io_map (m_maincpu->space(AS_PROGRAM), 0xe7d0, 0xe7df);
-
- /* memory */
- m_thom_cart_bank = 0;
- m_thom_vram = ram;
- m_cartbank->configure_entries( 0, 4, cartmem, 0x4000 );
- m_cartbank->configure_entries( 4, 4, mem + 0x10000, 0x4000 );
- if ( m_ram->size() == 256*1024 )
- {
- m_cartbank->configure_entries( 8, 16, ram, 0x4000 );
- m_cartbank->configure_entries( 8+16, 16, ram, 0x4000 );
- m_datalobank->configure_entries( 0, 16, ram + 0x2000, 0x4000 );
- m_datalobank->configure_entries( 16, 16, ram + 0x2000, 0x4000 );
- m_datahibank->configure_entries( 0, 16, ram + 0x0000, 0x4000 );
- m_datahibank->configure_entries( 16, 16, ram + 0x0000, 0x4000 );
- }
- else
- {
- m_cartbank->configure_entries( 8, 32, ram, 0x4000 );
- m_datalobank->configure_entries( 0, 32, ram + 0x2000, 0x4000 );
- m_datahibank->configure_entries( 0, 32, ram + 0x0000, 0x4000 );
- }
- m_vrambank->configure_entries( 0, 2, ram, 0x2000 );
- m_syslobank->configure_entry( 0, ram + 0x6000);
- m_syshibank->configure_entry( 0, ram + 0x4000);
- m_biosbank->configure_entries( 0, 2, mem + 0x20800, 0x2000 );
- m_cartbank->set_entry( 0 );
- m_vrambank->set_entry( 0 );
- m_syslobank->set_entry( 0 );
- m_syshibank->set_entry( 0 );
- m_datalobank->set_entry( 0 );
- m_datahibank->set_entry( 0 );
- m_biosbank->set_entry( 0 );
-
- /* save-state */
- save_item(NAME(m_thom_cart_nb_banks));
- save_item(NAME(m_thom_cart_bank));
- save_item(NAME(m_to7_lightpen));
- save_item(NAME(m_to7_lightpen_step));
- save_item(NAME(m_to8_reg_ram));
- save_item(NAME(m_to8_reg_cart));
- save_item(NAME(m_to8_reg_sys1));
- save_item(NAME(m_to8_reg_sys2));
- save_item(NAME(m_to8_soft_select));
- save_item(NAME(m_to8_soft_bank));
- save_item(NAME(m_to8_bios_bank));
- save_item(NAME(m_to8_lightpen_intr));
- save_item(NAME(m_to8_data_vpage));
- save_item(NAME(m_to8_cart_vpage));
- save_pointer(NAME(cartmem), 0x10000 );
- machine().save().register_postload(save_prepost_delegate(FUNC(to9_state::to8_update_ram_bank_postload), this));
- machine().save().register_postload(save_prepost_delegate(FUNC(to9_state::to8_update_cart_bank_postload), this));
-}
-
-
-
-/***************************** TO9+ *************************/
-
-
-
-/* ------------ system PIA 6821 ------------ */
-
-
-
-/* ------------ 6846 (timer, I/O) ------------ */
-
-
-
-uint8_t to9_state::to9p_timer_port_in()
-{
- int lightpen = (m_io_lightpen_button->read() & 1) ? 2 : 0;
- int cass = to7_get_cassette() ? 0x80 : 0;
- int dtr = m_centronics_busy << 6;
- return lightpen | cass | dtr;
-}
-
-
-
-void to9_state::to9p_timer_port_out(uint8_t data)
-{
- int bios_bank = (data & 0x10) ? 1 : 0; /* bit 4: BIOS bank */
- thom_set_mode_point( data & 1 ); /* bit 0: video bank switch */
- m_biosbank->set_entry( bios_bank );
- m_to8_soft_select = (data & 0x04) ? 1 : 0; /* bit 2: internal ROM select */
- to8_update_cart_bank();
-}
-
-/* ------------ init / reset ------------ */
-
-MACHINE_RESET_MEMBER( to9_state, to9p )
-{
- LOG (( "to9p: machine reset called\n" ));
-
- /* subsystems */
- thom_irq_reset();
- to7_game_reset();
- to9_kbd_reset();
- to7_modem_reset();
- to7_midi_reset();
-
- /* gate-array */
- m_to7_lightpen = 0;
- m_to8_reg_ram = 0;
- m_to8_reg_cart = 0;
- m_to8_reg_sys1 = 0;
- m_to8_reg_sys2 = 0;
- m_to8_lightpen_intr = 0;
- m_to8_soft_select = 0;
-
- /* video */
- thom_set_video_mode( THOM_VMODE_TO770 );
- m_thom_lightpen_cb = std::bind(&to9_state::to8_lightpen_cb, this, std::placeholders::_1);
- thom_set_lightpen_callback( 4 );
- thom_set_border_color( 0 );
- thom_set_mode_point( 0 );
- m_pia_sys->cb1_w( 0 );
-
- /* memory */
- m_old_ram_bank = -1;
- m_old_cart_bank = -1;
- m_to8_cart_vpage = 0;
- m_to8_data_vpage = 0;
- m_to8_soft_bank = 0;
- m_to8_bios_bank = 0;
- to8_update_ram_bank();
- to8_update_cart_bank();
- m_biosbank->set_entry( 0 );
- /* thom_cart_bank not reset */
-}
-
-
-
-MACHINE_START_MEMBER( to9_state, to9p )
-{
- uint8_t* mem = memregion("maincpu")->base();
- uint8_t* cartmem = &m_cart_rom[0];
- uint8_t* ram = m_ram->pointer();
-
- LOG (( "to9p: machine start called\n" ));
-
- /* subsystems */
- to7_game_init();
- to9_kbd_init();
- to9_palette_init();
- to7_modem_init();
- to7_midi_init();
-
- m_extension->rom_map(m_maincpu->space(AS_PROGRAM), 0xe000, 0xe7bf);
- m_extension->io_map (m_maincpu->space(AS_PROGRAM), 0xe7d0, 0xe7df);
-
- /* memory */
- m_thom_cart_bank = 0;
- m_thom_vram = ram;
- m_cartbank->configure_entries( 0, 4, cartmem, 0x4000 );
- m_cartbank->configure_entries( 4, 4, mem + 0x10000, 0x4000 );
- m_cartbank->configure_entries( 8, 32, ram, 0x4000 );
- m_vrambank->configure_entries( 0, 2, ram, 0x2000 );
- m_syslobank->configure_entry( 0, ram + 0x6000 );
- m_syshibank->configure_entry( 0, ram + 0x4000 );
- m_datalobank->configure_entries( 0, 32, ram + 0x2000, 0x4000 );
- m_datahibank->configure_entries( 0, 32, ram + 0x0000, 0x4000 );
- m_biosbank->configure_entries( 0, 2, mem + 0x20800, 0x2000 );
- m_cartbank->set_entry( 0 );
- m_vrambank->set_entry( 0 );
- m_syslobank->set_entry( 0 );
- m_syshibank->set_entry( 0 );
- m_datalobank->set_entry( 0 );
- m_datahibank->set_entry( 0 );
- m_biosbank->set_entry( 0 );
-
- /* save-state */
- save_item(NAME(m_thom_cart_nb_banks));
- save_item(NAME(m_thom_cart_bank));
- save_item(NAME(m_to7_lightpen));
- save_item(NAME(m_to7_lightpen_step));
- save_item(NAME(m_to8_reg_ram));
- save_item(NAME(m_to8_reg_cart));
- save_item(NAME(m_to8_reg_sys1));
- save_item(NAME(m_to8_reg_sys2));
- save_item(NAME(m_to8_soft_select));
- save_item(NAME(m_to8_soft_bank));
- save_item(NAME(m_to8_bios_bank));
- save_item(NAME(m_to8_lightpen_intr));
- save_item(NAME(m_to8_data_vpage));
- save_item(NAME(m_to8_cart_vpage));
- save_pointer(NAME(cartmem), 0x10000 );
- machine().save().register_postload(save_prepost_delegate(FUNC(to9_state::to8_update_ram_bank_postload), this));
- machine().save().register_postload(save_prepost_delegate(FUNC(to9_state::to8_update_cart_bank_postload), this));
-}
-
-
-
-/****************** MO6 / Olivetti Prodest PC 128 *******************/
-
-
-
-/* ------------ RAM / ROM banking ------------ */
-
-
-
-void mo6_state::mo6_update_ram_bank()
-{
- uint8_t bank = 0;
-
- if ( m_to8_reg_sys1 & 0x10 )
- {
- bank = m_to8_reg_ram & 7; /* 128 KB RAM only = 8 pages */
- }
- if ( bank != m_to8_data_vpage ) {
- m_datalobank->set_entry( bank );
- m_datahibank->set_entry( bank );
- m_to8_data_vpage = bank;
- m_old_ram_bank = bank;
- LOG_BANK(( "mo6_update_ram_bank: select bank %i (new style)\n", bank ));
- }
-}
-
-
-
-void mo6_state::mo6_update_ram_bank_postload()
-{
- mo6_update_ram_bank();
-}
-
-
-
-void mo6_state::mo6_update_cart_bank()
-{
- address_space& space = m_maincpu->space(AS_PROGRAM);
- int b = (m_pia_sys->a_output() >> 5) & 1;
- int bank = 0;
- int bank_is_read_only = 0;
-
- if ( ( ( m_to8_reg_sys1 & 0x40 ) && ( m_to8_reg_cart & 0x20 ) ) || ( ! ( m_to8_reg_sys1 & 0x40 ) && ( m_mo5_reg_cart & 4 ) ) )
- {
- /* RAM space */
- if ( m_to8_reg_sys1 & 0x40 )
- {
- /* use a7e6 */
- m_to8_cart_vpage = m_to8_reg_cart & 7; /* 128 KB RAM only = 8 pages */
- bank = 8 + m_to8_cart_vpage;
- bank_is_read_only = (( m_to8_reg_cart & 0x40 ) == 0);
- if ( bank != m_old_cart_bank )
- {
- if (m_to8_cart_vpage < 4)
- {
- if (m_old_cart_bank < 8 || m_old_cart_bank > 11)
- {
- space.install_read_bank( 0xb000, 0xbfff, m_cartlobank );
- space.install_read_bank( 0xc000, 0xefff, m_carthibank );
- if ( bank_is_read_only )
- {
- space.nop_write( 0xb000, 0xefff);
- }
- else
- {
- space.install_write_handler( 0xb000, 0xbfff, write8sm_delegate(*this, FUNC(mo6_state::mo6_vcart_lo_w)));
- space.install_write_handler( 0xc000, 0xefff, write8sm_delegate(*this, FUNC(mo6_state::mo6_vcart_hi_w)));
- }
- }
- }
- else
- {
- if (m_old_cart_bank < 12)
- {
- if ( bank_is_read_only )
- {
- space.install_read_bank( 0xb000, 0xbfff, m_cartlobank );
- space.install_read_bank( 0xc000, 0xefff, m_carthibank );
- space.nop_write( 0xb000, 0xefff);
- }
- else
- {
- space.install_readwrite_bank( 0xb000, 0xbfff, m_cartlobank );
- space.install_readwrite_bank( 0xc000, 0xefff, m_carthibank );
- }
- }
- }
- LOG_BANK(( "mo6_update_cart_bank: CART is RAM bank %i (%s)\n",
- m_to8_cart_vpage,
- bank_is_read_only ? "read-only":"read-write"));
- }
- else if ( bank_is_read_only != m_old_cart_bank_was_read_only )
- {
- if ( bank_is_read_only )
- {
- space.nop_write( 0xb000, 0xefff);
- }
- else
- {
- if (m_to8_cart_vpage < 4)
- {
- space.install_write_handler( 0xb000, 0xbfff, write8sm_delegate(*this, FUNC(mo6_state::mo6_vcart_lo_w)));
- space.install_write_handler( 0xc000, 0xefff, write8sm_delegate(*this, FUNC(mo6_state::mo6_vcart_hi_w)));
- }
- else
- {
- space.install_readwrite_bank( 0xb000, 0xbfff, m_cartlobank );
- space.install_readwrite_bank( 0xc000, 0xefff, m_carthibank );
- }
- }
- LOG_BANK(( "mo6_update_cart_bank: update CART bank %i write status to %s\n",
- m_to8_cart_vpage,
- bank_is_read_only ? "read-only":"read-write"));
- }
- m_old_cart_bank_was_read_only = bank_is_read_only;
- }
- else if ( m_thom_cart_nb_banks == 4 )
- {
- /* "JANE"-style cartridge bank switching */
- bank = m_mo5_reg_cart & 3;
- if ( bank != m_old_cart_bank )
- {
- if ( m_old_cart_bank < 0 || m_old_cart_bank > 3 )
- {
- space.install_read_bank( 0xb000, 0xbfff, m_cartlobank );
- space.install_read_bank( 0xc000, 0xefff, m_carthibank );
- space.nop_write( 0xb000, 0xefff);
- }
- LOG_BANK(( "mo6_update_cart_bank: CART is external cartridge bank %i (A7CB style)\n", bank ));
- }
- }
- else
- {
- /* RAM from MO5 network extension */
- int bank_is_read_only = (( m_mo5_reg_cart & 8 ) == 0);
- m_to8_cart_vpage = (m_mo5_reg_cart & 3) | 4;
- bank = 8 + m_to8_cart_vpage;
- if ( bank != m_old_cart_bank )
- {
- if ( m_old_cart_bank < 12 )
- {
- if ( bank_is_read_only )
- {
- space.install_read_bank( 0xb000, 0xbfff, m_cartlobank );
- space.install_read_bank( 0xc000, 0xefff, m_carthibank );
- space.nop_write( 0xb000, 0xefff);
- }
- else
- {
- space.install_readwrite_bank( 0xb000, 0xbfff, m_cartlobank );
- space.install_readwrite_bank( 0xc000, 0xefff, m_carthibank );
- }
- }
- LOG_BANK(( "mo6_update_cart_bank: CART is RAM bank %i (MO5 compat.) (%s)\n",
- m_to8_cart_vpage,
- bank_is_read_only ? "read-only":"read-write"));
- }
- else if ( bank_is_read_only != m_old_cart_bank_was_read_only )
- {
- if ( bank_is_read_only )
- {
- space.install_read_bank( 0xb000, 0xbfff, m_cartlobank );
- space.install_read_bank( 0xc000, 0xefff, m_carthibank );
- space.nop_write( 0xb000, 0xefff);
- }
- else
- {
- space.install_readwrite_bank( 0xb000, 0xbfff, m_cartlobank );
- space.install_readwrite_bank( 0xc000, 0xefff, m_carthibank );
- }
- LOG_BANK(( "mo5_update_cart_bank: update CART bank %i write status to %s\n",
- m_to8_cart_vpage,
- bank_is_read_only ? "read-only":"read-write"));
- }
- m_old_cart_bank_was_read_only = bank_is_read_only;
- }
- }
- else
- {
- /* ROM space */
- if ( m_to8_reg_sys2 & 0x20 )
- {
- /* internal ROM */
- if ( m_to8_reg_sys2 & 0x10)
- {
- bank = b + 6; /* BASIC 128 */
- }
- else
- {
- bank = b + 4; /* BASIC 1 */
- }
- if ( bank != m_old_cart_bank )
- {
- if ( m_old_cart_bank < 4 || m_old_cart_bank > 7 )
- {
- space.install_read_bank( 0xb000, 0xbfff, m_cartlobank );
- space.install_read_bank( 0xc000, 0xefff, m_carthibank );
- space.install_write_handler( 0xb000, 0xefff, write8sm_delegate(*this, FUNC(mo6_state::mo6_cartridge_w)) );
- }
- LOG_BANK(( "mo6_update_cart_bank: CART is internal ROM bank %i\n", b ));
- }
- }
- else
- {
- /* cartridge */
- if ( m_thom_cart_nb_banks )
- {
- bank = m_thom_cart_bank % m_thom_cart_nb_banks;
- if ( bank != m_old_cart_bank )
- {
- if ( m_old_cart_bank < 0 || m_old_cart_bank > 3 )
- {
- space.install_read_bank( 0xb000, 0xbfff, m_cartlobank );
- space.install_read_bank( 0xc000, 0xefff, m_carthibank );
- space.install_write_handler( 0xb000, 0xefff, write8sm_delegate(*this, FUNC(mo6_state::mo6_cartridge_w)) );
- space.install_read_handler( 0xbffc, 0xbfff, read8sm_delegate(*this, FUNC(mo6_state::mo6_cartridge_r)) );
- }
- LOG_BANK(( "mo6_update_cart_bank: CART is external cartridge bank %i\n", bank ));
- }
- }
- else
- {
- if ( m_old_cart_bank != 0 )
- {
- space.nop_read( 0xb000, 0xefff );
- LOG_BANK(( "mo6_update_cart_bank: CART is unmapped\n"));
- }
- }
- }
- }
- if ( bank != m_old_cart_bank )
- {
- m_cartlobank->set_entry( bank );
- m_carthibank->set_entry( bank );
- m_biosbank->set_entry( b );
- m_old_cart_bank = bank;
- }
-}
-
-
-
-void mo6_state::mo6_update_cart_bank_postload()
-{
- mo6_update_cart_bank();
-}
-
-
-
-/* write signal generates a bank switch */
-void mo6_state::mo6_cartridge_w(offs_t offset, uint8_t data)
-{
- if ( offset >= 0x2000 )
- return;
-
- m_thom_cart_bank = offset & 3;
- mo6_update_cart_bank();
-}
-
-
-
-/* read signal generates a bank switch */
-uint8_t mo6_state::mo6_cartridge_r(offs_t offset)
-{
- uint8_t data = m_cart_rom[offset + 0x3ffc + (m_thom_cart_bank % m_thom_cart_nb_banks) * 0x4000];
- if ( !machine().side_effects_disabled() )
- {
- m_thom_cart_bank = offset & 3;
- mo6_update_cart_bank();
- }
- return data;
-}
-
-
-
-void mo6_state::mo6_ext_w(uint8_t data)
-{
- /* MO5 network extension compatible */
- m_mo5_reg_cart = data;
- mo6_update_cart_bank();
-}
-
-
-
-/* ------------ game 6821 PIA ------------ */
-
-/* similar to SX 90-018, but with a few differences: mute, printer */
-
-
-WRITE_LINE_MEMBER( mo6_state::mo6_centronics_busy )
-{
- m_pia_game->cb1_w(state);
-}
-
-
-void mo6_state::mo6_game_porta_out(uint8_t data)
-{
- LOG (( "$%04x %f mo6_game_porta_out: CENTRONICS set data=$%02X\n", m_maincpu->pc(), machine().time().as_double(), data ));
-
- /* centronics data */
- m_cent_data_out->write(data);
-}
-
-
-
-WRITE_LINE_MEMBER( mo6_state::mo6_game_cb2_out )
-{
- LOG (( "$%04x %f mo6_game_cb2_out: CENTRONICS set strobe=%i\n", m_maincpu->pc(), machine().time().as_double(), state ));
-
- /* centronics strobe */
- m_centronics->write_strobe(state);
-}
-
-
-
-TIMER_CALLBACK_MEMBER(mo6_state::mo6_game_update_cb)
-{
- /* unlike the TO8, CB1 & CB2 are not connected to buttons */
- if ( m_io_config->read() & 1 )
- {
- uint8_t mouse = to7_get_mouse_signal();
- m_pia_game->ca1_w( BIT(mouse, 0) ); /* XA */
- m_pia_game->ca2_w( BIT(mouse, 1) ); /* YA */
- }
- else
- {
- /* joystick */
- uint8_t in = m_io_game_port_buttons->read();
- m_pia_game->ca1_w( BIT(in, 2) ); /* P1 action B */
- m_pia_game->ca2_w( BIT(in, 6) ); /* P1 action A */
- }
-}
-
-
-
-void mo6_state::mo6_game_init()
-{
- LOG (( "mo6_game_init called\n" ));
- m_to7_game_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mo6_state::mo6_game_update_cb),this));
- m_to7_game_timer->adjust(TO7_GAME_POLL_PERIOD, 0, TO7_GAME_POLL_PERIOD);
- save_item(NAME(m_to7_game_sound));
- save_item(NAME(m_to7_game_mute));
-}
-
-
-
-void mo6_state::mo6_game_reset()
-{
- LOG (( "mo6_game_reset called\n" ));
- m_pia_game->ca1_w( 0 );
- m_to7_game_sound = 0;
- m_to7_game_mute = 0;
- to7_game_sound_update();
-}
-
-
-
-/* ------------ system PIA 6821 ------------ */
-
-
-
-uint8_t mo6_state::mo6_sys_porta_in()
-{
- return
- ((m_io_lightpen_button->read() & 1) ? 2 : 0) | /* bit 1: lightpen button */
- 8 | /* bit 3: kbd-line float up to 1 */
- (mo5_get_cassette() ? 0x80 : 0) | /* bit 7: cassette input */
- 0x75; /* other bits are unconnected and pulled hi internally */
-}
-
-
-
-uint8_t mo6_state::mo6_sys_portb_in()
-{
- /* keyboard: 9 lines of 8 keys */
- uint8_t porta = m_pia_sys->a_output();
- uint8_t portb = m_pia_sys->b_output();
- int col = (portb >> 4) & 7; /* B bits 4-6: kbd column */
- int lin = (portb >> 1) & 7; /* B bits 1-3: kbd line */
-
- if ( ! (porta & 8) )
- lin = 8; /* A bit 3: 9-th kbd line select */
-
- return
- ( m_io_keyboard[lin]->read() & (1 << col) ) ? 0x80 : 0;
- /* bit 7: key up */
-}
-
-
-
-void mo6_state::mo6_sys_porta_out(uint8_t data)
-{
- thom_set_mode_point( data & 1 ); /* bit 0: video bank switch */
- m_to7_game_mute = data & 4; /* bit 2: sound mute */
- m_caps_led = (data & 16) ? 0 : 1; /* bit 4: keyboard led */
- mo5_set_cassette( (data & 0x40) ? 1 : 0 ); /* bit 6: cassette output */
- mo6_update_cart_bank(); /* bit 5: rom bank */
- to7_game_sound_update();
-}
-
-
-
-WRITE_LINE_MEMBER( mo6_state::mo6_sys_cb2_out )
-{
- /* SCART pin 8 = slow switch (?) */
- LOG(( "mo6_sys_cb2_out: SCART slow switch set to %i\n", state ));
-}
-
-
-
-/* ------------ system gate-array ------------ */
-
-#define MO6_LIGHTPEN_DECAL 12
-
-
-
-uint8_t mo6_state::mo6_gatearray_r(offs_t offset)
-{
- struct thom_vsignal v = thom_get_vsignal();
- struct thom_vsignal l = thom_get_lightpen_vsignal( MO6_LIGHTPEN_DECAL, m_to7_lightpen_step - 1, 6 );
- int count, inil, init, lt3;
- uint8_t res;
- count = m_to7_lightpen ? l.count : v.count;
- inil = m_to7_lightpen ? l.inil : v.inil;
- init = m_to7_lightpen ? l.init : v.init;
- lt3 = m_to7_lightpen ? l.lt3 : v.lt3;
-
- switch ( offset )
- {
- case 0: /* system 2 / lightpen register 1 */
- if ( m_to7_lightpen )
- res = (count >> 8) & 0xff;
- else
- res = m_to8_reg_sys2 & 0xf0;
- break;
-
- case 1: /* ram register / lightpen register 2 */
- if ( m_to7_lightpen )
- {
- if ( !machine().side_effects_disabled() )
- {
- m_mainfirq->in_w<2>(0);
- m_to8_lightpen_intr = 0;
- }
- res = count & 0xff;
- }
- else
- res = m_to8_reg_ram & 0x1f;
- break;
-
- case 2: /* cartrige register / lightpen register 3 */
- if ( m_to7_lightpen )
- res = (lt3 << 7) | (inil << 6);
- else
- res = 0;
- break;
-
- case 3: /* lightpen register 4 */
- res = (v.init << 7) | (init << 6) | (v.inil << 5) | (m_to8_lightpen_intr << 1) | m_to7_lightpen;
- break;
-
- default:
- logerror( "$%04x mo6_gatearray_r: invalid offset %i\n", m_maincpu->pc(), offset );
- res = 0;
- }
-
- LOG_VIDEO(( "$%04x %f mo6_gatearray_r: off=%i ($%04X) res=$%02X lightpen=%i\n",
- m_maincpu->pc(), machine().time().as_double(),
- offset, 0xa7e4 + offset, res, m_to7_lightpen ));
-
- return res;
-}
-
-
-
-void mo6_state::mo6_gatearray_w(offs_t offset, uint8_t data)
-{
- LOG_VIDEO(( "$%04x %f mo6_gatearray_w: off=%i ($%04X) data=$%02X\n",
- m_maincpu->pc(), machine().time().as_double(),
- offset, 0xa7e4 + offset, data ));
-
- switch ( offset )
- {
- case 0: /* switch */
- m_to7_lightpen = data & 1;
- break;
-
- case 1: /* ram register */
- if ( m_to8_reg_sys1 & 0x10 )
- {
- m_to8_reg_ram = data;
- mo6_update_ram_bank();
- }
- break;
-
- case 2: /* cartridge register */
- m_to8_reg_cart = data;
- mo6_update_cart_bank();
- break;
-
- case 3: /* system register 1 */
- m_to8_reg_sys1 = data;
- mo6_update_ram_bank();
- mo6_update_cart_bank();
- break;
-
- default:
- logerror( "$%04x mo6_gatearray_w: invalid offset %i (data=$%02X)\n", m_maincpu->pc(), offset, data );
- }
-}
-
-
-/* ------------ video gate-array ------------ */
-
-
-
-uint8_t mo6_state::mo6_vreg_r(offs_t offset)
-{
- /* 0xa7dc from external floppy drive aliases the video gate-array */
- if ( ( offset == 3 ) && ( m_to8_reg_ram & 0x80 ) )
- {
- if ( !machine().side_effects_disabled() )
- abort(); // return to7_floppy_r( 0xc );
- }
-
- switch ( offset )
- {
- case 0: /* palette data */
- case 1: /* palette address */
- return to8_vreg_r( offset );
-
- case 2:
- case 3:
- return 0;
-
- default:
- logerror( "mo6_vreg_r: invalid read offset %i\n", offset );
- return 0;
- }
-}
-
-
-
-void mo6_state::mo6_vreg_w(offs_t offset, uint8_t data)
-{
- LOG_VIDEO(( "$%04x %f mo6_vreg_w: off=%i ($%04X) data=$%02X\n",
- m_maincpu->pc(), machine().time().as_double(),
- offset, 0xa7da + offset, data ));
-
- switch ( offset )
- {
- case 0: /* palette data */
- case 1: /* palette address */
- to8_vreg_w( offset, data );
- return;
-
- case 2: /* display / external floppy register */
- if ( ( m_to8_reg_sys1 & 0x80 ) && ( m_to8_reg_ram & 0x80 ) )
- abort(); // to7_floppy_w( 0xc, data );
- else
- to9_set_video_mode( data, 2 );
- break;
-
- case 3: /* system register 2 */
- /* 0xa7dc from external floppy drive aliases the video gate-array */
- if ( ( offset == 3 ) && ( m_to8_reg_ram & 0x80 ) )
- abort(); // to7_floppy_w( 0xc, data );
- else
- {
- m_to8_reg_sys2 = data;
- thom_set_video_page( data >> 6 );
- thom_set_border_color( data & 15 );
- mo6_update_cart_bank();
- }
- break;
-
- default:
- logerror( "mo6_vreg_w: invalid write offset %i data=$%02X\n", offset, data );
- }
-}
-
-
-
-/* ------------ init / reset ------------ */
-
-
-
-MACHINE_RESET_MEMBER( mo6_state, mo6 )
-{
- LOG (( "mo6: machine reset called\n" ));
-
- /* subsystems */
- thom_irq_reset();
- mo6_game_reset();
- to7_modem_reset();
- to7_midi_reset();
- mo5_init_timer();
-
- /* gate-array */
- m_to7_lightpen = 0;
- m_to8_reg_ram = 0;
- m_to8_reg_cart = 0;
- m_to8_reg_sys1 = 0;
- m_to8_reg_sys2 = 0;
- m_to8_lightpen_intr = 0;
-
- /* video */
- thom_set_video_mode( THOM_VMODE_MO5 );
- m_thom_lightpen_cb = std::bind(&mo6_state::to8_lightpen_cb, this, std::placeholders::_1);
- thom_set_lightpen_callback( 3 );
- thom_set_border_color( 0 );
- thom_set_mode_point( 0 );
- m_pia_sys->ca1_w( 0 );
-
- /* memory */
- m_old_ram_bank = -1;
- m_old_cart_bank = -1;
- m_to8_cart_vpage = 0;
- m_to8_data_vpage = 0;
- mo6_update_ram_bank();
- mo6_update_cart_bank();
- /* mo5_reg_cart not reset */
- /* thom_cart_bank not reset */
-}
-
-
-
-MACHINE_START_MEMBER( mo6_state, mo6 )
-{
- uint8_t* mem = memregion("maincpu")->base();
- uint8_t* cartmem = &m_cart_rom[0];
- uint8_t* ram = m_ram->pointer();
-
- LOG (( "mo6: machine start called\n" ));
-
- /* subsystems */
- mo6_game_init();
- to9_palette_init();
- to7_modem_init();
- to7_midi_init();
- m_mo5_periodic_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mo6_state::mo5_periodic_cb),this));
-
- m_extension->rom_map(m_maincpu->space(AS_PROGRAM), 0xa000, 0xa7bf);
- m_extension->io_map (m_maincpu->space(AS_PROGRAM), 0xa7d0, 0xa7df);
-
- /* memory */
- m_thom_cart_bank = 0;
- m_mo5_reg_cart = 0;
- m_thom_vram = ram;
- m_cartlobank->configure_entries( 0, 4, cartmem, 0x4000 );
- m_cartlobank->configure_entry( 4, cartmem + 0xf000 ); // FIXME: this is wrong
- m_cartlobank->configure_entry( 5, mem + 0x13000 ); // FIXME: this is wrong
- m_cartlobank->configure_entries( 6, 2, mem + 0x18000, 0x4000 );
- m_cartlobank->configure_entries( 8, 8, ram + 0x3000, 0x4000 );
- m_carthibank->configure_entries( 0, 4, cartmem + 0x1000, 0x4000 );
- m_carthibank->configure_entries( 4, 2, mem + 0x10000, 0x4000 );
- m_carthibank->configure_entries( 6, 2, mem + 0x18000 + 0x1000, 0x4000 );
- m_carthibank->configure_entries( 8, 8, ram, 0x4000 );
- m_vrambank->configure_entries( 0, 2, ram, 0x2000 );
- m_syslobank->configure_entry( 0, ram + 0x6000);
- m_syshibank->configure_entry( 0, ram + 0x4000);
- m_datalobank->configure_entries( 0, 8, ram + 0x2000, 0x4000 );
- m_datahibank->configure_entries( 0, 8, ram + 0x0000, 0x4000 );
- m_biosbank->configure_entries( 0, 2, mem + 0x13000, 0x4000 );
- m_cartlobank->set_entry( 0 );
- m_carthibank->set_entry( 0 );
- m_vrambank->set_entry( 0 );
- m_syslobank->set_entry( 0 );
- m_syshibank->set_entry( 0 );
- m_datalobank->set_entry( 0 );
- m_datahibank->set_entry( 0 );
- m_biosbank->set_entry( 0 );
-
- /* save-state */
- save_item(NAME(m_thom_cart_nb_banks));
- save_item(NAME(m_thom_cart_bank));
- save_item(NAME(m_to7_lightpen));
- save_item(NAME(m_to7_lightpen_step));
- save_item(NAME(m_to8_reg_ram));
- save_item(NAME(m_to8_reg_cart));
- save_item(NAME(m_to8_reg_sys1));
- save_item(NAME(m_to8_reg_sys2));
- save_item(NAME(m_to8_lightpen_intr));
- save_item(NAME(m_to8_data_vpage));
- save_item(NAME(m_to8_cart_vpage));
- save_item(NAME(m_mo5_reg_cart));
- save_pointer(NAME(cartmem), 0x10000 );
- machine().save().register_postload(save_prepost_delegate(FUNC(mo6_state::mo6_update_ram_bank_postload), this));
- machine().save().register_postload(save_prepost_delegate(FUNC(mo6_state::mo6_update_cart_bank_postload), this));
-}
-
-
-
-/***************************** MO5 NR *************************/
-
-
-
-/* ------------ printer ------------ */
-
-/* Unlike the TO8, TO9, TO9+, MO6, the printer has its own ports and does not
- go through the 6821 PIA.
-*/
-
-
-uint8_t mo5nr_state::mo5nr_prn_r()
-{
- uint8_t result = 0;
-
- result |= m_centronics_busy << 7;
-
- return result;
-}
-
-
-void mo5nr_state::mo5nr_prn_w(uint8_t data)
-{
- /* TODO: understand other bits */
- m_centronics->write_strobe(BIT(data, 3));
-}
-
-
-
-/* ------------ system PIA 6821 ------------ */
-
-
-
-uint8_t mo5nr_state::mo5nr_sys_portb_in()
-{
- /* keyboard: only 8 lines of 8 keys (MO6 has 9 lines) */
- uint8_t portb = m_pia_sys->b_output();
- int col = (portb >> 4) & 7; /* B bits 4-6: kbd column */
- int lin = (portb >> 1) & 7; /* B bits 1-3: kbd line */
-
- return ( m_io_keyboard[lin]->read() & (1 << col) ) ? 0x80 : 0;
- /* bit 7: key up */
-}
-
-
-
-void mo5nr_state::mo5nr_sys_porta_out(uint8_t data)
-{
- /* no keyboard LED */
- thom_set_mode_point( data & 1 ); /* bit 0: video bank switch */
- m_to7_game_mute = data & 4; /* bit 2: sound mute */
- mo5_set_cassette( (data & 0x40) ? 1 : 0 ); /* bit 6: cassette output */
- mo6_update_cart_bank(); /* bit 5: rom bank */
- to7_game_sound_update();
-}
-
-
-
-/* ------------ game 6821 PIA ------------ */
-
-/* similar to the MO6, without the printer */
-
-
-
-void mo5nr_state::mo5nr_game_init()
-{
- LOG (( "mo5nr_game_init called\n" ));
- m_to7_game_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mo5nr_state::mo6_game_update_cb),this));
- m_to7_game_timer->adjust( TO7_GAME_POLL_PERIOD, 0, TO7_GAME_POLL_PERIOD );
- save_item(NAME(m_to7_game_sound));
- save_item(NAME(m_to7_game_mute));
-}
-
-
-
-void mo5nr_state::mo5nr_game_reset()
-{
- LOG (( "mo5nr_game_reset called\n" ));
- m_pia_game->ca1_w( 0 );
- m_to7_game_sound = 0;
- m_to7_game_mute = 0;
- to7_game_sound_update();
-}
-
-
-
-/* ------------ init / reset ------------ */
-
-
-uint8_t mo5nr_state::id_r()
-{
- return (m_nanoreseau_config->read() >> 1) & 0x1f;
-}
-
-MACHINE_RESET_MEMBER( mo5nr_state, mo5nr )
-{
- LOG (( "mo5nr: machine reset called\n" ));
-
- m_extension_view.select(m_nanoreseau_config->read() & 1);
-
- /* subsystems */
- thom_irq_reset();
- mo5nr_game_reset();
- to7_modem_reset();
- to7_midi_reset();
- mo5_init_timer();
-
- /* gate-array */
- m_to7_lightpen = 0;
- m_to8_reg_ram = 0;
- m_to8_reg_cart = 0;
- m_to8_reg_sys1 = 0;
- m_to8_reg_sys2 = 0;
- m_to8_lightpen_intr = 0;
-
- /* video */
- thom_set_video_mode( THOM_VMODE_MO5 );
- m_thom_lightpen_cb = std::bind(&mo5nr_state::to8_lightpen_cb, this, std::placeholders::_1);
- thom_set_lightpen_callback( 3 );
- thom_set_border_color( 0 );
- thom_set_mode_point( 0 );
- m_pia_sys->ca1_w( 0 );
-
- /* memory */
- m_old_ram_bank = -1;
- m_old_cart_bank = -1;
- m_to8_cart_vpage = 0;
- m_to8_data_vpage = 0;
- mo6_update_ram_bank();
- mo6_update_cart_bank();
- /* mo5_reg_cart not reset */
- /* thom_cart_bank not reset */
-}
-
-
-
-MACHINE_START_MEMBER( mo5nr_state, mo5nr )
-{
- uint8_t* mem = memregion("maincpu")->base();
- uint8_t* cartmem = &m_cart_rom[0];
- uint8_t* ram = m_ram->pointer();
-
- LOG (( "mo5nr: machine start called\n" ));
-
- /* subsystems */
- mo5nr_game_init();
- to9_palette_init();
- to7_modem_init();
- to7_midi_init();
- m_mo5_periodic_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mo5nr_state::mo5_periodic_cb),this));
-
- m_extension->rom_map(m_extension_view[0], 0xa000, 0xa7bf);
- m_extension->io_map (m_extension_view[0], 0xa7d0, 0xa7df);
- m_extension_view[1].install_device(0xa000, 0xa7bf, *m_nanoreseau, &nanoreseau_device::rom_map );
- m_extension_view[1].install_device(0xa7d0, 0xa7df, *m_nanoreseau, &nanoreseau_device::io_map );
-
- /* memory */
- m_thom_cart_bank = 0;
- m_mo5_reg_cart = 0;
- m_thom_vram = ram;
-
- m_cartlobank->configure_entries( 0, 4, cartmem, 0x4000 );
- m_cartlobank->configure_entry( 4, cartmem + 0xf000 ); // FIXME: this is wrong
- m_cartlobank->configure_entry( 5, mem + 0x13000 ); // FIXME: this is wrong
- m_cartlobank->configure_entries( 6, 2, mem + 0x18000, 0x4000 );
- m_cartlobank->configure_entries( 8, 8, ram + 0x3000, 0x4000 );
- m_carthibank->configure_entries( 0, 4, cartmem + 0x1000, 0x4000 );
- m_carthibank->configure_entries( 4, 2, mem + 0x10000, 0x4000 );
- m_carthibank->configure_entries( 6, 2, mem + 0x18000 + 0x1000, 0x4000 );
- m_carthibank->configure_entries( 8, 8, ram, 0x4000 );
- m_vrambank->configure_entries( 0, 2, ram, 0x2000 );
- m_syslobank->configure_entry( 0, ram + 0x6000);
- m_syshibank->configure_entry( 0, ram + 0x4000);
- m_datalobank->configure_entries( 0, 8, ram + 0x2000, 0x4000 );
- m_datahibank->configure_entries( 0, 8, ram + 0x0000, 0x4000 );
- m_biosbank->configure_entries( 0, 2, mem + 0x13000, 0x4000 );
- m_cartlobank->set_entry( 0 );
- m_carthibank->set_entry( 0 );
- m_vrambank->set_entry( 0 );
- m_syslobank->set_entry( 0 );
- m_syshibank->set_entry( 0 );
- m_datalobank->set_entry( 0 );
- m_datahibank->set_entry( 0 );
- m_biosbank->set_entry( 0 );
-
- /* save-state */
- save_item(NAME(m_thom_cart_nb_banks));
- save_item(NAME(m_thom_cart_bank));
- save_item(NAME(m_to7_lightpen));
- save_item(NAME(m_to7_lightpen_step));
- save_item(NAME(m_to8_reg_ram));
- save_item(NAME(m_to8_reg_cart));
- save_item(NAME(m_to8_reg_sys1));
- save_item(NAME(m_to8_reg_sys2));
- save_item(NAME(m_to8_lightpen_intr));
- save_item(NAME(m_to8_data_vpage));
- save_item(NAME(m_to8_cart_vpage));
- save_item(NAME(m_mo5_reg_cart));
- save_pointer(NAME(cartmem), 0x10000 );
- machine().save().register_postload(save_prepost_delegate(FUNC(mo5nr_state::mo6_update_ram_bank_postload), this));
- machine().save().register_postload(save_prepost_delegate(FUNC(mo5nr_state::mo6_update_cart_bank_postload), this));
-}