summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/hp48.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/machine/hp48.c')
-rw-r--r--src/mess/machine/hp48.c1176
1 files changed, 0 insertions, 1176 deletions
diff --git a/src/mess/machine/hp48.c b/src/mess/machine/hp48.c
deleted file mode 100644
index 6c6ad253001..00000000000
--- a/src/mess/machine/hp48.c
+++ /dev/null
@@ -1,1176 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Antoine Mine
-/**********************************************************************
-
- Copyright (C) Antoine Mine' 2008
-
- Hewlett Packard HP48 S/SX & G/GX/G+ and HP49 G
-
-**********************************************************************/
-
-#include "emu.h"
-#include "sound/dac.h"
-#include "cpu/saturn/saturn.h"
-
-#include "machine/nvram.h"
-
-#include "includes/hp48.h"
-
-
-/***************************************************************************
- DEBUGGING
-***************************************************************************/
-
-
-#define VERBOSE 0
-#define VERBOSE_SERIAL 0
-
-#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
-#define LOG_SERIAL(x) do { if (VERBOSE_SERIAL) logerror x; } while (0)
-
-
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-/* state field in hp48_module */
-#define HP48_MODULE_UNCONFIGURED 0
-#define HP48_MODULE_MASK_KNOWN 1
-#define HP48_MODULE_CONFIGURED 2
-
-/***************************************************************************
- GLOBAL VARIABLES & CONSTANTS
-***************************************************************************/
-
-/* current HP48 model */
-
-#define HP48_G_SERIES ((m_model==HP48_G) || (m_model==HP48_GX) || (m_model==HP48_GP))
-#define HP48_S_SERIES ((m_model==HP48_S) || (m_model==HP48_SX))
-#define HP48_X_SERIES ((m_model==HP48_SX) || (m_model==HP48_GX))
-#define HP48_GX_MODEL ((m_model==HP48_GX) || (m_model==HP48_GP))
-#define HP49_G_MODEL ((m_model==HP49_G))
-
-static const char *const hp48_module_names[6] =
-{ "HDW (I/O)", "NCE2 (RAM)", "CE1", "CE2", "NCE3", "NCE1 (ROM)" };
-
-/* values returned by C=ID */
-static const UINT8 hp48_module_mask_id[6] = { 0x00, 0x03, 0x05, 0x07, 0x01, 0x00 };
-static const UINT8 hp48_module_addr_id[6] = { 0x19, 0xf4, 0xf6, 0xf8, 0xf2, 0x00 };
-
-
-
-
-
-/***************************************************************************
- FUNCTIONS
-***************************************************************************/
-
-void hp48_state::hp48_pulse_irq( int irq_line)
-{
- m_maincpu->set_input_line(irq_line, ASSERT_LINE );
- m_maincpu->set_input_line(irq_line, CLEAR_LINE );
-}
-
-
-/* ---------------- serial --------------------- */
-
-#define RS232_DELAY attotime::from_usec( 300 )
-
-/* end of receive event */
-TIMER_CALLBACK_MEMBER(hp48_state::hp48_rs232_byte_recv_cb)
-{
- LOG_SERIAL(( "%f hp48_rs232_byte_recv_cb: end of receive, data=%02x\n",
- machine().time().as_double(), param ));
-
- m_io[0x14] = param & 0xf; /* receive zone */
- m_io[0x15] = param >> 4;
- m_io[0x11] &= ~2; /* clear byte receiving */
- m_io[0x11] |= 1; /* set byte received */
-
- /* interrupt */
- if ( m_io[0x10] & 2 )
- {
- hp48_pulse_irq( SATURN_IRQ_LINE );
- }
-}
-
-/* outside world initiates a receive event */
-void hp48_state::hp48_rs232_start_recv_byte( UINT8 data )
-{
- LOG_SERIAL(( "%f hp48_rs232_start_recv_byte: start receiving, data=%02x\n",
- machine().time().as_double(), data ));
-
- m_io[0x11] |= 2; /* set byte receiving */
-
- /* interrupt */
- if ( m_io[0x10] & 1 )
- {
- hp48_pulse_irq( SATURN_IRQ_LINE );
- }
-
- /* schedule end of reception */
- machine().scheduler().timer_set( RS232_DELAY, timer_expired_delegate(FUNC(hp48_state::hp48_rs232_byte_recv_cb),this), data);
-}
-
-
-/* end of send event */
-TIMER_CALLBACK_MEMBER(hp48_state::hp48_rs232_byte_sent_cb)
-{
- //device_image_interface *xmodem = dynamic_cast<device_image_interface *>(machine().device("rs232_x"));
- //device_image_interface *kermit = dynamic_cast<device_image_interface *>(machine().device("rs232_k"));
-
- LOG_SERIAL(( "%f hp48_rs232_byte_sent_cb: end of send, data=%02x\n",
- machine().time().as_double(), param ));
-
- m_io[0x12] &= ~3; /* clear byte sending and buffer full */
-
- /* interrupt */
- if ( m_io[0x10] & 4 )
- {
- hp48_pulse_irq( SATURN_IRQ_LINE );
- }
-
- /* protocol action */
- //if ( xmodem && xmodem->exists() ) xmodem_receive_byte( &xmodem->device(), param );
- //else if ( kermit && kermit->exists() ) kermit_receive_byte( &kermit->device(), param );
-}
-
-/* CPU initiates a send event */
-void hp48_state::hp48_rs232_send_byte( )
-{
- UINT8 data = HP48_IO_8(0x16); /* byte to send */
-
- LOG_SERIAL(( "%s %f hp48_rs232_send_byte: start sending, data=%02x\n",
- machine().describe_context(), machine().time().as_double(), data ));
-
- /* set byte sending and send buffer full */
- m_io[0x12] |= 3;
-
- /* schedule transmission */
- machine().scheduler().timer_set( RS232_DELAY, timer_expired_delegate(FUNC(hp48_state::hp48_rs232_byte_sent_cb),this), data);
-}
-
-
-
-
-/* ------ Saturn's IN / OUT registers ---------- */
-
-
-/* CPU sets OUT register (keyboard + beeper) */
-WRITE32_MEMBER( hp48_state::hp48_reg_out )
-{
- LOG(( "%s %f hp48_reg_out: %03x\n",
- machine().describe_context(), machine().time().as_double(), data ));
-
- /* bits 0-8: keyboard lines */
- m_out = data & 0x1ff;
-
- /* bits 9-10: unused */
-
- /* bit 11: beeper */
- m_dac->write_unsigned8((data & 0x800) ? 0x80 : 00 );
-}
-
-int hp48_state::hp48_get_in( )
-{
- int in = 0;
-
- /* regular keys */
- if ( (m_out >> 0) & 1 ) in |= ioport( "LINE0" )->read();
- if ( (m_out >> 1) & 1 ) in |= ioport( "LINE1" )->read();
- if ( (m_out >> 2) & 1 ) in |= ioport( "LINE2" )->read();
- if ( (m_out >> 3) & 1 ) in |= ioport( "LINE3" )->read();
- if ( (m_out >> 4) & 1 ) in |= ioport( "LINE4" )->read();
- if ( (m_out >> 5) & 1 ) in |= ioport( "LINE5" )->read();
- if ( (m_out >> 6) & 1 ) in |= ioport( "LINE6" )->read();
- if ( (m_out >> 7) & 1 ) in |= ioport( "LINE7" )->read();
- if ( (m_out >> 8) & 1 ) in |= ioport( "LINE8" )->read();
-
- /* on key */
- in |= ioport( "ON" )->read();
-
- return in;
-}
-
-/* CPU reads IN register (keyboard) */
-READ32_MEMBER( hp48_state::hp48_reg_in )
-{
- int in = hp48_get_in();
- LOG(( "%s %f hp48_reg_in: %04x\n",
- machine().describe_context(), machine().time().as_double(), in ));
- return in;
-}
-
-/* key detect */
-void hp48_state::hp48_update_kdn( )
-{
- int in = hp48_get_in();
-
- /* interrupt on raising edge */
- if ( in && !m_kdn )
- {
- LOG(( "%f hp48_update_kdn: interrupt\n", machine().time().as_double() ));
- m_io[0x19] |= 8; /* service request */
- hp48_pulse_irq( SATURN_WAKEUP_LINE );
- hp48_pulse_irq( SATURN_IRQ_LINE );
- }
-
- m_kdn = (in!=0);
-}
-
-/* periodic keyboard polling, generates an interrupt */
-TIMER_CALLBACK_MEMBER(hp48_state::hp48_kbd_cb)
-{
- /* NMI for ON key */
- if ( ioport( "ON" )->read() )
- {
- LOG(( "%f hp48_kbd_cb: keyboard interrupt, on key\n",
- machine().time().as_double() ));
- m_io[0x19] |= 8; /* set service request */
- hp48_pulse_irq( SATURN_WAKEUP_LINE );
- hp48_pulse_irq( SATURN_NMI_LINE );
- return;
- }
-
- /* regular keys */
- hp48_update_kdn();
-}
-
-/* RSI opcode */
-WRITE_LINE_MEMBER( hp48_state::hp48_rsi )
-{
- LOG(( "%s %f hp48_rsi\n", machine().describe_context(), machine().time().as_double() ));
-
- /* enables interrupts on key repeat
- (normally, there is only one interrupt, when the key is pressed)
- */
- m_kdn = 0;
-}
-
-
-/* ------------- annonciators ------------ */
-
-void hp48_state::hp48_update_annunciators()
-{
- /* bit 0: left shift
- bit 1: right shift
- bit 2: alpha
- bit 3: alert
- bit 4: busy
- bit 5: transmit
- bit 7: master enable
- */
- int markers = HP48_IO_8(0xb);
- output_set_value( "lshift0", (markers & 0x81) == 0x81 );
- output_set_value( "rshift0", (markers & 0x82) == 0x82 );
- output_set_value( "alpha0", (markers & 0x84) == 0x84 );
- output_set_value( "alert0", (markers & 0x88) == 0x88 );
- output_set_value( "busy0", (markers & 0x90) == 0x90 );
- output_set_value( "transmit0", (markers & 0xb0) == 0xb0 );
-}
-
-
-/* ------------- I/O registers ----------- */
-
-/* Some part of the I/O registers are simple r/w registers. We store them in hp48_io.
- Special cases are registers that:
- - have a different meaning on read and write
- - perform some action on read / write
- */
-
-WRITE8_MEMBER(hp48_state::hp48_io_w)
-{
- LOG(( "%s %f hp48_io_w: off=%02x data=%x\n",
- space.machine().describe_context(), space.machine().time().as_double(), offset, data ));
-
- switch( offset )
- {
- /* CRC register */
- case 0x04: m_crc = (m_crc & 0xfff0) | data; break;
- case 0x05: m_crc = (m_crc & 0xff0f) | (data << 4); break;
- case 0x06: m_crc = (m_crc & 0xf0ff) | (data << 8); break;
- case 0x07: m_crc = (m_crc & 0x0fff) | (data << 12); break;
-
- /* annunciators */
- case 0x0b:
- case 0x0c:
- m_io[offset] = data;
- hp48_update_annunciators();
- break;
-
- /* cntrl ROM */
- case 0x29:
- {
- int old_cntrl = m_io[offset] & 8;
- m_io[offset] = data;
- if ( old_cntrl != (data & 8) )
- {
- hp48_apply_modules();
- }
- break;
- }
-
- /* timers */
- case 0x37: m_timer1 = data; break;
- case 0x38: m_timer2 = (m_timer2 & 0xfffffff0) | data; break;
- case 0x39: m_timer2 = (m_timer2 & 0xffffff0f) | (data << 4); break;
- case 0x3a: m_timer2 = (m_timer2 & 0xfffff0ff) | (data << 8); break;
- case 0x3b: m_timer2 = (m_timer2 & 0xffff0fff) | (data << 12); break;
- case 0x3c: m_timer2 = (m_timer2 & 0xfff0ffff) | (data << 16); break;
- case 0x3d: m_timer2 = (m_timer2 & 0xff0fffff) | (data << 20); break;
- case 0x3e: m_timer2 = (m_timer2 & 0xf0ffffff) | (data << 24); break;
- case 0x3f: m_timer2 = (m_timer2 & 0x0fffffff) | (data << 28); break;
-
- /* cards */
- case 0x0e:
- LOG(( "%s: card control write %02x\n", space.machine().describe_context(), data ));
-
- /* bit 0: software interrupt */
- if ( data & 1 )
- {
- LOG(( "%f hp48_io_w: software interrupt requested\n",
- space.machine().time().as_double() ));
- hp48_pulse_irq( SATURN_IRQ_LINE );
- data &= ~1;
- }
-
- /* XXX not implemented
- bit 1: card test?
- */
-
- m_io[0x0e] = data;
- break;
-
- case 0x0f:
- LOG(( "%s: card info write %02x\n", space.machine().describe_context(), data ));
- m_io[0x0f] = data;
- break;
-
- /* serial */
- case 0x13:
- m_io[0x11] &= ~4; /* clear error status */
- break;
- case 0x16:
- /* first nibble of sent data */
- m_io[offset] = data;
- break;
- case 0x17:
- /* second nibble of sent data */
- m_io[offset] = data;
- hp48_rs232_send_byte();
- break;
-
- /* XXX not implemented:
-
- - 0x0d: RS232c speed:
- bits 0-2: speed
- 000 = 1200 bauds
- 010 = 2400 bauds
- 100 = 4800 bauds
- 110 = 9600 bauds
- bit 3: ?
-
- - 0x1a: I/R input
- bit 0: irq
- bit 1: irq enable
- bit 2: 1=RS232c mode 0=direct mode
- bit 3: receiving
-
- - 0x1c: I/R output control
- bit 0: buffer full
- bit 1: transmitting
- bit 2: irq enable on buffer empty
- bit 3: led on (direct mode)
- on HP49 G, flash ROM write enable
-
- - 0x1d: I/R output buffer
- */
-
- default: m_io[offset] = data;
- }
-
-}
-
-
-READ8_MEMBER(hp48_state::hp48_io_r)
-{
- UINT8 data = 0;
-
- switch( offset )
- {
- /* CRC register */
- case 0x04: data = m_crc & 0xf; break;
- case 0x05: data = (m_crc >> 4) & 0xf; break;
- case 0x06: data = (m_crc >> 8) & 0xf; break;
- case 0x07: data = (m_crc >> 12) & 0xf; break;
-
- /* battery test */
- case 0x08:
- data = 0;
- if ( m_io[0x9] & 8 ) /* test enable */
- {
- /* XXX not implemented:
- bit 3: battery in port 2
- bit 2: battery in port 1
- */
- switch ( ioport( "BATTERY" )->read() )
- {
- case 1: data = 2; break; /* low */
- case 2: data = 3; break; /* low | critical */
- }
- }
- break;
-
- /* remaining lines in main bitmap */
- case 0x28:
- case 0x29:
- {
- int last_line = HP48_IO_8(0x28) & 0x3f; /* last line of main bitmap before menu */
- int cur_line = space.machine().first_screen()->vpos();
- if ( last_line <= 1 ) last_line = 0x3f;
- data = ( cur_line >= 0 && cur_line <= last_line ) ? last_line - cur_line : 0;
- if ( offset == 0x29 )
- {
- data >>= 4;
- data |= HP48_IO_4(0x29) & 0xc;
- }
- else
- {
- data &= 0xf;
- }
- break;
- }
-
- /* timers */
- case 0x37: data = m_timer1; break;
- case 0x38: data = m_timer2 & 0xf; break;
- case 0x39: data = (m_timer2 >> 4) & 0xf; break;
- case 0x3a: data = (m_timer2 >> 8) & 0xf; break;
- case 0x3b: data = (m_timer2 >> 12) & 0xf; break;
- case 0x3c: data = (m_timer2 >> 16) & 0xf; break;
- case 0x3d: data = (m_timer2 >> 20) & 0xf; break;
- case 0x3e: data = (m_timer2 >> 24) & 0xf; break;
- case 0x3f: data = (m_timer2 >> 28) & 0xf; break;
-
- /* serial */
- case 0x15:
- {
- /* second nibble of received data */
-
- //device_image_interface *xmodem = dynamic_cast<device_image_interface *>(space.machine().device("rs232_x"));
- //device_image_interface *kermit = dynamic_cast<device_image_interface *>(space.machine().device("rs232_k"));
-
- m_io[0x11] &= ~1; /* clear byte received */
- data = m_io[offset];
-
- /* protocol action */
- //if ( xmodem && xmodem->exists() ) xmodem_byte_transmitted( &xmodem->device() );
- //else if ( kermit && kermit->exists() ) kermit_byte_transmitted( &kermit->device() );
- break;
- }
-
- /* cards */
- case 0x0e: /* detection */
- data = m_io[0x0e];
- LOG(( "%s: card control read %02x\n", space.machine().describe_context(), data ));
- break;
- case 0x0f: /* card info */
- data = 0;
- if ( HP48_G_SERIES )
- {
- if ( m_port_size[1] ) data |= 1;
- if ( m_port_size[0] ) data |= 2;
- if ( m_port_size[1] && m_port_write[1] ) data |= 4;
- if ( m_port_size[0] && m_port_write[0] ) data |= 8;
- }
- else
- {
- if ( m_port_size[0] ) data |= 1;
- if ( m_port_size[1] ) data |= 2;
- if ( m_port_size[0] && m_port_write[0] ) data |= 4;
- if ( m_port_size[1] && m_port_write[1] ) data |= 8;
- }
- LOG(( "%s: card info read %02x\n", space.machine().describe_context(), data ));
- break;
-
-
- default: data = m_io[offset];
- }
-
- LOG(( "%s %f hp48_io_r: off=%02x data=%x\n",
- space.machine().describe_context(), space.machine().time().as_double(), offset, data ));
- return data;
-}
-
-
-/* ---------- bank switcher --------- */
-
-READ8_MEMBER(hp48_state::hp48_bank_r)
-{
- /* HP48 GX
- bit 0: ignored
- bits 2-5: bank number
- bit 6: enable
- */
-
- /* HP49 G
- bit 0: ignored
- bits 1-2: select bank 0x00000-0x3ffff
- bits 3-6: select bank 0x40000-0x7ffff
- */
- offset &= 0x7e;
- if ( m_bank_switch != offset )
- {
- LOG(( "%s %f hp48_bank_r: off=%03x\n", space.machine().describe_context(), space.machine().time().as_double(), offset ));
- m_bank_switch = offset;
- hp48_apply_modules();
- }
- return 0;
-}
-
-
-WRITE8_MEMBER(hp48_state::hp49_bank_w)
-{
- offset &= 0x7e;
- if ( m_bank_switch != offset )
- {
- LOG(( "%05x %f hp49_bank_w: off=%03x\n", space.device().safe_pcbase(), space.machine().time().as_double(), offset ));
- m_bank_switch = offset;
- hp48_apply_modules();
- }
-}
-
-
-
-/* ---------------- timers --------------- */
-
-TIMER_CALLBACK_MEMBER(hp48_state::hp48_timer1_cb)
-{
- if ( !(m_io[0x2f] & 1) ) return; /* timer enable */
-
- m_timer1 = (m_timer1 - 1) & 0xf;
-
- /* wake-up on carry */
- if ( (m_io[0x2e] & 4) && (m_timer1 == 0xf) )
- {
- LOG(( "wake-up on timer1\n" ));
- m_io[0x2e] |= 8; /* set service request */
- m_io[0x18] |= 4; /* set service request */
- hp48_pulse_irq( SATURN_WAKEUP_LINE );
- }
- /* interrupt on carry */
- if ( (m_io[0x2e] & 2) && (m_timer1 == 0xf) )
- {
- LOG(( "generate timer1 interrupt\n" ));
- m_io[0x2e] |= 8; /* set service request */
- m_io[0x18] |= 4; /* set service request */
- hp48_pulse_irq( SATURN_NMI_LINE );
- }
-}
-
-TIMER_CALLBACK_MEMBER(hp48_state::hp48_timer2_cb)
-{
- if ( !(m_io[0x2f] & 1) ) return; /* timer enable */
-
- m_timer2 = (m_timer2 - 1) & 0xffffffff;
-
- /* wake-up on carry */
- if ( (m_io[0x2f] & 4) && (m_timer2 == 0xffffffff) )
- {
- LOG(( "wake-up on timer2\n" ));
- m_io[0x2f] |= 8; /* set service request */
- m_io[0x18] |= 4; /* set service request */
- hp48_pulse_irq( SATURN_WAKEUP_LINE );
- }
- /* interrupt on carry */
- if ( (m_io[0x2f] & 2) && (m_timer2 == 0xffffffff) )
- {
- LOG(( "generate timer2 interrupt\n" ));
- m_io[0x2f] |= 8; /* set service request */
- m_io[0x18] |= 4; /* set service request */
- hp48_pulse_irq( SATURN_NMI_LINE );
- }
-}
-
-
-
-
-/* --------- memory controller ----------- */
-
-/*
- Clark (S series) and York (G series) CPUs have 6 daisy-chained modules
-
-
- <-- highest --------- priority ------------- lowest -->
-
- CPU ---------------------------------------------------
- | | | | | |
- HDW NCE2 CE1 CE2 NCE3 NCE1
-
-
- However, controller usage is different in both series:
-
-
- controller 48 S series 48 G series 49 G series
- (Clark CPU) (York CPU) (York CPU)
-
- HDW 32B I/O RAM 32B I/O RAM 32B I/O RAM
- NCE2 32KB RAM 32/128KB RAM 256KB RAM
- CE1 port1 bank switcher bank switcher
- CE2 port2 port1 128KB RAM
- NCE3 unused port2 128KB RAM
- NCE1 256KB ROM 512KB ROM 2MB flash ROM
-
-
- - NCE1 (ROM) cannot be configured, it is always visible at addresses
- 00000-7ffff not covered by higher priority modules.
-
- - only the address of HDW (I/O) can be configured, its size is constant
- (64 nibbles)
-
- - other modules can have their address & size set
-
- */
-
-
-/* remap all modules according to hp48_modules */
-void hp48_state::hp48_apply_modules()
-{
- int i;
- int nce3_enable = 1;
- address_space& space = m_maincpu->space(AS_PROGRAM);
-
- m_io_addr = 0x100000;
-
- /* NCE1 (ROM) is a bit special, so treat it separately */
- space.unmap_readwrite( 0, 0xfffff, 0, 0 );
- if ( HP49_G_MODEL )
- {
- int bank_lo = (m_bank_switch >> 5) & 3;
- int bank_hi = (m_bank_switch >> 1) & 15;
- LOG(( "hp48_apply_modules: low ROM bank is %i\n", bank_lo ));
- LOG(( "hp48_apply_modules: high ROM bank is %i\n", bank_hi ));
- space.install_read_bank( 0x00000, 0x3ffff, 0, 0x80000, "bank5" );
- space.install_read_bank( 0x40000, 0x7ffff, 0, 0x80000, "bank6" );
- if ( m_rom )
- {
- membank("bank5")->set_base( m_rom + bank_lo * 0x40000 );
- membank("bank6")->set_base( m_rom + bank_hi * 0x40000 );
- }
- }
- else if ( HP48_G_SERIES )
- {
- /* port 2 bank switch */
- if ( m_port_size[1] > 0 )
- {
- int off = (m_bank_switch << 16) % m_port_size[1];
- LOG(( "hp48_apply_modules: port 2 offset is %i\n", off ));
- m_modules[HP48_NCE3].data = m_port_data[1] + off;
- }
-
- /* ROM A19 (hi 256 KB) / NCE3 (port 2) control switch */
- if ( m_io[0x29] & 8 )
- {
- /* A19 */
- LOG(( "hp48_apply_modules: A19 enabled, NCE3 disabled\n" ));
- nce3_enable = 0;
- space.install_read_bank( 0, 0xfffff, 0, 0, "bank5" );
- }
- else
- {
- /* NCE3 */
- nce3_enable = m_bank_switch >> 6;
- LOG(( "hp48_apply_modules: A19 disabled, NCE3 %s\n", nce3_enable ? "enabled" : "disabled" ));
- space.install_read_bank( 0, 0x7ffff, 0, 0x80000, "bank5" );
- }
- if ( m_rom )
- membank("bank5")->set_base( m_rom );
- }
- else
- {
- space.install_read_bank( 0, 0x7ffff, 0, 0x80000, "bank5" );
- if ( m_rom )
- membank("bank5")->set_base( m_rom );
- }
-
-
- /* from lowest to highest priority */
- for ( i = 4; i >= 0; i-- )
- {
- UINT32 select_mask = m_modules[i].mask;
- UINT32 nselect_mask = ~select_mask & 0xfffff;
- UINT32 base = m_modules[i].base;
- UINT32 off_mask = m_modules[i].off_mask;
- UINT32 mirror = nselect_mask & ~off_mask;
- UINT32 end = base + (off_mask & nselect_mask);
- char bank[10];
- sprintf(bank,"bank%d",i);
-
- if ( m_modules[i].state != HP48_MODULE_CONFIGURED ) continue;
-
- if ( (i == 4) && !nce3_enable ) continue;
-
- /* our code assumes that the 20-bit select_mask is all 1s followed by all 0s */
- if ( nselect_mask & (nselect_mask+1) )
- {
- logerror( "hp48_apply_modules: invalid mask %05x for module %s\n",
- select_mask, hp48_module_names[i] );
- continue;
- }
-
- if (m_modules[i].data)
- space.install_read_bank( base, end, 0, mirror, bank );
- else
- {
- if (!m_modules[i].read.isnull())
- space.install_read_handler( base, end, 0, mirror, m_modules[i].read );
- }
-
- if (m_modules[i].isnop)
- space.nop_write(base, end, 0, mirror);
- else
- {
- if (m_modules[i].data)
- {
- space.install_write_bank( base, end, 0, mirror, bank );
- }
- else
- {
- if (!m_modules[i].write.isnull())
- space.install_write_handler( base, end, 0, mirror, m_modules[i].write );
- }
- }
-
- LOG(( "hp48_apply_modules: module %s configured at %05x-%05x, mirror %05x\n",
- hp48_module_names[i], base, end, mirror ));
-
- if ( m_modules[i].data )
- {
- membank( bank )->set_base( m_modules[i].data );
- }
-
- if ( i == 0 )
- {
- m_io_addr = base;
- }
- }
-}
-
-
-/* reset the configuration */
-void hp48_state::hp48_reset_modules( )
-{
- int i;
- /* fixed size for HDW */
- m_modules[HP48_HDW].state = HP48_MODULE_MASK_KNOWN;
- m_modules[HP48_HDW].mask = 0xfffc0;
- /* unconfigure NCE2, CE1, CE2, NCE3 */
- for ( i = 1; i < 5; i++ )
- {
- m_modules[i].state = HP48_MODULE_UNCONFIGURED;
- }
-
- /* fixed configuration for NCE1 */
- m_modules[HP48_NCE1].state = HP48_MODULE_CONFIGURED;
- m_modules[HP48_NCE1].base = 0;
- m_modules[HP48_NCE1].mask = 0;
-
- hp48_apply_modules();
-}
-
-
-/* RESET opcode */
-WRITE_LINE_MEMBER( hp48_state::hp48_mem_reset )
-{
- LOG(( "%s %f hp48_mem_reset\n", machine().describe_context(), machine().time().as_double() ));
- hp48_reset_modules();
-}
-
-
-/* CONFIG opcode */
-WRITE32_MEMBER( hp48_state::hp48_mem_config )
-{
- int i;
-
- LOG(( "%s %f hp48_mem_config: %05x\n", machine().describe_context(), machine().time().as_double(), data ));
-
- /* find the highest priority unconfigured module (except non-configurable NCE1)... */
- for ( i = 0; i < 5; i++ )
- {
- /* ... first call sets the address mask */
- if ( m_modules[i].state == HP48_MODULE_UNCONFIGURED )
- {
- m_modules[i].mask = data & 0xff000;
- m_modules[i].state = HP48_MODULE_MASK_KNOWN;
- break;
- }
-
- /* ... second call sets the base address */
- if ( m_modules[i].state == HP48_MODULE_MASK_KNOWN )
- {
- m_modules[i].base = data & m_modules[i].mask;
- m_modules[i].state = HP48_MODULE_CONFIGURED;
- LOG(( "hp48_mem_config: module %s configured base=%05x, mask=%05x\n",
- hp48_module_names[i], m_modules[i].base, m_modules[i].mask ));
- hp48_apply_modules();
- break;
- }
- }
-}
-
-
-/* UNCFG opcode */
-WRITE32_MEMBER( hp48_state::hp48_mem_unconfig )
-{
- int i;
- LOG(( "%s %f hp48_mem_unconfig: %05x\n", machine().describe_context(), machine().time().as_double(), data ));
-
- /* find the highest priority fully configured module at address v (except NCE1)... */
- for ( i = 0; i < 5; i++ )
- {
- /* ... and unconfigure it */
- if ( m_modules[i].state == HP48_MODULE_CONFIGURED &&
- (m_modules[i].base == (data & m_modules[i].mask)) )
- {
- m_modules[i].state = i> 0 ? HP48_MODULE_UNCONFIGURED : HP48_MODULE_MASK_KNOWN;
- LOG(( "hp48_mem_unconfig: module %s\n", hp48_module_names[i] ));
- hp48_apply_modules();
- break;
- }
- }
-}
-
-
-/* C=ID opcode */
-READ32_MEMBER( hp48_state::hp48_mem_id )
-{
- int i;
- int data = 0; /* 0 = everything is configured */
-
- /* find the highest priority unconfigured module (except NCE1)... */
- for ( i = 0; i < 5; i++ )
- {
- /* ... mask need to be configured */
- if ( m_modules[i].state == HP48_MODULE_UNCONFIGURED )
- {
- data = hp48_module_mask_id[i] | (m_modules[i].mask & ~0xff);
- break;
- }
-
- /* ... address need to be configured */
- if ( m_modules[i].state == HP48_MODULE_MASK_KNOWN )
- {
- data = hp48_module_addr_id[i] | (m_modules[i].base & ~0x3f);
- break;
- }
- }
-
- LOG(( "%s %f hp48_mem_id = %02x\n",
- machine().describe_context(), machine().time().as_double(), data ));
-
- return data; /* everything is configured */
-}
-
-
-
-/* --------- CRC ---------- */
-
-/* each memory read by the CPU updates the internal CRC state */
-WRITE32_MEMBER( hp48_state::hp48_mem_crc )
-{
- /* no CRC for I/O RAM */
- if ( offset >= m_io_addr && offset < m_io_addr + 0x40 ) return;
-
- m_crc = (m_crc >> 4) ^ (((m_crc ^ data) & 0xf) * 0x1081);
-}
-
-
-
-/* ------ utilities ------- */
-
-
-/* decodes size bytes into 2*size nibbles (least significant first) */
-void hp48_state::hp48_decode_nibble( UINT8* dst, UINT8* src, int size )
-{
- int i;
- for ( i=size-1; i >= 0; i-- )
- {
- dst[2*i+1] = src[i] >> 4;
- dst[2*i] = src[i] & 0xf;
- }
-}
-
-/* inverse of hp48_decode_nibble */
-void hp48_state::hp48_encode_nibble( UINT8* dst, UINT8* src, int size )
-{
- int i;
- for ( i=0; i < size; i++ )
- {
- dst[i] = (src[2*i] & 0xf) | (src[2*i+1] << 4);
- }
-}
-
-
-
-/* ----- card images ------ */
-const device_type HP48_PORT = &device_creator<hp48_port_image_device>;
-
-/* helper for load and create */
-void hp48_port_image_device::hp48_fill_port()
-{
- hp48_state *state = machine().driver_data<hp48_state>();
- int size = state->m_port_size[m_port];
- LOG(( "hp48_fill_port: %s module=%i size=%i rw=%i\n", tag(), m_module, size, state->m_port_write[m_port] ));
- state->m_port_data[m_port] = global_alloc_array(UINT8, 2 * size);
- memset( state->m_port_data[m_port], 0, 2 * size );
- state->m_modules[m_module].off_mask = 2 * (( size > 128 * 1024 ) ? 128 * 1024 : size) - 1;
- state->m_modules[m_module].read = read8_delegate();
- state->m_modules[m_module].write = write8_delegate();
- state->m_modules[m_module].isnop = state->m_port_write[m_port] ? 0 : 1;
- state->m_modules[m_module].data = state->m_port_data[m_port];
- state->hp48_apply_modules();
-}
-
-/* helper for start and unload */
-void hp48_port_image_device::hp48_unfill_port()
-{
- hp48_state *state = machine().driver_data<hp48_state>();
- LOG(( "hp48_unfill_port\n" ));
- state->m_modules[m_module].off_mask = 0x00fff; /* 2 KB */
- state->m_modules[m_module].read = read8_delegate();
- state->m_modules[m_module].write = write8_delegate();
- state->m_modules[m_module].data = NULL;
- state->m_modules[m_module].isnop = 1;
- state->m_port_size[m_port] = 0;
-}
-
-
-bool hp48_port_image_device::call_load()
-{
- hp48_state *state = machine().driver_data<hp48_state>();
- int size = length();
- if ( size == 0 ) size = m_max_size; /* default size */
- LOG(( "hp48_port_image load: size=%i\n", size ));
-
- /* check size */
- if ( (size < 32*1024) || (size > m_max_size) || (size & (size-1)) )
- {
- logerror( "hp48: image size for %s should be a power of two between %i and %i\n", tag(), 32*1024, m_max_size );
- return IMAGE_INIT_FAIL;
- }
-
- state->m_port_size[m_port] = size;
- state->m_port_write[m_port] = !is_readonly();
- hp48_fill_port( );
- fread(state->m_port_data[m_port], state->m_port_size[m_port] );
- state->hp48_decode_nibble( state->m_port_data[m_port], state->m_port_data[m_port], state->m_port_size[m_port] );
- return IMAGE_INIT_PASS;
-}
-
-bool hp48_port_image_device::call_create(int format_type, option_resolution *format_options)
-{
- hp48_state *state = machine().driver_data<hp48_state>();
- int size = m_max_size;
- LOG(( "hp48_port_image create: size=%i\n", size ));
- /* XXX defaults to max_size; get user-specified size instead */
-
- /* check size */
- /* size must be a power of 2 between 32K and max_size */
- if ( (size < 32*1024) || (size > m_max_size) || (size & (size-1)) )
- {
- logerror( "hp48: image size for %s should be a power of two between %i and %i\n", tag(), 32*1024, m_max_size );
- return IMAGE_INIT_FAIL;
- }
-
- state->m_port_size[m_port] = size;
- state->m_port_write[m_port] = 1;
- hp48_fill_port();
- return IMAGE_INIT_PASS;
-}
-
-void hp48_port_image_device::call_unload()
-{
- hp48_state *state = machine().driver_data<hp48_state>();
- LOG(( "hp48_port image unload: %s size=%i rw=%i\n",
- tag(), state->m_port_size[m_port], state->m_port_write[m_port] ));
- if ( state->m_port_write[m_port] )
- {
- state->hp48_encode_nibble( state->m_port_data[m_port], state->m_port_data[m_port], state->m_port_size[m_port] );
- fseek( 0, SEEK_SET );
- fwrite( state->m_port_data[m_port], state->m_port_size[m_port] );
- }
- global_free_array( state->m_port_data[m_port] );
- hp48_unfill_port();
- state->hp48_apply_modules();
-}
-
-void hp48_port_image_device::device_start()
-{
- LOG(("hp48_port_image start\n"));
- hp48_unfill_port();
-}
-
-hp48_port_image_device::hp48_port_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : device_t(mconfig, HP48_PORT, "HP48 memory card", tag, owner, clock, "hp48_port_image", __FILE__),
- device_image_interface(mconfig, *this)
-{
-}
-
-void hp48_port_image_device::device_config_complete()
-{
- update_names(HP48_PORT, "port", "p");
-}
-
-/***************************************************************************
- MACHINES
-***************************************************************************/
-
-DRIVER_INIT_MEMBER(hp48_state,hp48)
-{
- int i;
- LOG(( "hp48: driver init called\n" ));
- for ( i = 0; i < 6; i++ )
- {
- m_modules[i].off_mask = 0x00fff; /* 2 KB */
- m_modules[i].read = read8_delegate();
- m_modules[i].write = write8_delegate();
- m_modules[i].data = NULL;
- m_modules[i].isnop = 0;
- }
- m_port_size[0] = 0;
- m_port_size[1] = 0;
- m_rom = NULL;
-}
-
-void hp48_state::machine_reset()
-{
- LOG(( "hp48: machine reset called\n" ));
- m_bank_switch = 0;
- hp48_reset_modules();
- hp48_update_annunciators();
-}
-
-void hp48_state::hp48_machine_start( hp48_models model )
-{
- UINT8 *ram;
- int ram_size, rom_size, i;
-
- LOG(( "hp48_machine_start: model %i\n", model ));
-
- m_model = model;
-
- /* internal RAM */
- ram_size =
- HP49_G_MODEL ? (512 * 1024) :
- HP48_GX_MODEL ? (128 * 1024) : (32 * 1024);
-
- ram = auto_alloc_array(machine(), UINT8, 2 * ram_size);
- machine().device<nvram_device>("nvram")->set_base(ram, 2 * ram_size);
-
-
- /* ROM load */
- rom_size =
- HP49_G_MODEL ? (2048 * 1024) :
- HP48_S_SERIES ? (256 * 1024) : (512 * 1024);
- m_rom = auto_alloc_array(machine(), UINT8, 2 * rom_size);
- hp48_decode_nibble( m_rom, memregion( "maincpu" )->base(), rom_size );
-
- /* init state */
- memset( ram, 0, 2 * ram_size );
- memset( m_io, 0, sizeof( m_io ) );
- m_out = 0;
- m_kdn = 0;
- m_crc = 0;
- m_timer1 = 0;
- m_timer2 = 0;
- m_bank_switch = 0;
-
- /* I/O RAM */
- m_modules[HP48_HDW].off_mask = 0x0003f; /* 32 B */
- m_modules[HP48_HDW].read = read8_delegate(FUNC(hp48_state::hp48_io_r),this);
- m_modules[HP48_HDW].write = write8_delegate(FUNC(hp48_state::hp48_io_w),this);
-
- /* internal RAM */
- if ( HP49_G_MODEL )
- {
- m_modules[HP48_NCE2].off_mask = 2 * 256 * 1024 - 1;
- m_modules[HP48_NCE2].data = ram;
- m_modules[HP48_CE2].off_mask = 2 * 128 * 1024 - 1;
- m_modules[HP48_CE2].data = ram + 2 * 256 * 1024;
- m_modules[HP48_NCE3].off_mask = 2 * 128 * 1024 - 1;
- m_modules[HP48_NCE3].data = ram + 2 * (128+256) * 1024;
- }
- else
- {
- m_modules[HP48_NCE2].off_mask = 2 * ram_size - 1;
- m_modules[HP48_NCE2].data = ram;
- }
-
- /* bank switcher */
- if ( HP48_G_SERIES )
- {
- m_modules[HP48_CE1].off_mask = 0x00fff; /* 2 KB */
- m_modules[HP48_CE1].read = read8_delegate(FUNC(hp48_state::hp48_bank_r),this);
- m_modules[HP48_CE1].write = HP49_G_MODEL ? write8_delegate(FUNC(hp48_state::hp49_bank_w),this) : write8_delegate();
- }
-
- /* timers */
- machine().scheduler().timer_pulse(attotime::from_hz( 16 ), timer_expired_delegate(FUNC(hp48_state::hp48_timer1_cb),this));
- machine().scheduler().timer_pulse(attotime::from_hz( 8192 ), timer_expired_delegate(FUNC(hp48_state::hp48_timer2_cb),this));
-
- /* 1ms keyboard polling */
- machine().scheduler().timer_pulse(attotime::from_msec( 1 ), timer_expired_delegate(FUNC(hp48_state::hp48_kbd_cb),this));
-
- /* save state */
- save_item(NAME(m_out) );
- save_item(NAME(m_kdn) );
- save_item(NAME(m_io_addr) );
- save_item(NAME(m_crc) );
- save_item(NAME(m_timer1) );
- save_item(NAME(m_timer2) );
- save_item(NAME(m_bank_switch) );
- for ( i = 0; i < 6; i++ )
- {
- save_item(m_modules[i].state, "globals/m_modules[i].state", i);
- save_item(m_modules[i].base, "globals/m_modules[i].base", i);
- save_item(m_modules[i].mask, "globals/m_modules[i].mask", i);
- }
- save_item(NAME(m_io) );
- machine().save().register_postload( save_prepost_delegate(FUNC(hp48_state::hp48_update_annunciators), this ));
- machine().save().register_postload( save_prepost_delegate(FUNC(hp48_state::hp48_apply_modules), this ));
-
-}
-
-
-MACHINE_START_MEMBER(hp48_state,hp48s)
-{
- hp48_machine_start( HP48_S );
-}
-
-
-MACHINE_START_MEMBER(hp48_state,hp48sx)
-{
- hp48_machine_start( HP48_SX );
-}
-
-
-MACHINE_START_MEMBER(hp48_state,hp48g)
-{
- hp48_machine_start( HP48_G );
-}
-
-MACHINE_START_MEMBER(hp48_state,hp48gx)
-{
- hp48_machine_start( HP48_GX );
-}
-
-MACHINE_START_MEMBER(hp48_state,hp48gp)
-{
- hp48_machine_start( HP48_GP );
-}
-
-MACHINE_START_MEMBER(hp48_state,hp49g)
-{
- hp48_machine_start( HP49_G );
-}