mirror of
https://github.com/holub/mame
synced 2025-06-06 21:03:47 +03:00
1579 lines
50 KiB
C
1579 lines
50 KiB
C
/******************************************************************************
|
|
|
|
nc.c
|
|
|
|
NC100/NC150/NC200 Notepad computer
|
|
|
|
system driver
|
|
|
|
|
|
Thankyou to:
|
|
Cliff Lawson, Russell Marks and Tim Surtel
|
|
|
|
Documentation:
|
|
|
|
NC100:
|
|
NC100 I/O Specification by Cliff Lawson,
|
|
NC100EM by Russell Marks
|
|
NC200:
|
|
Dissassembly of the NC200 ROM + e-mail
|
|
exchange with Russell Marks
|
|
|
|
|
|
NC100:
|
|
|
|
Hardware:
|
|
- Z80 CPU, 6 MHz
|
|
- memory powered by lithium batterys!
|
|
- 2 channel tone (programmable frequency beep's)
|
|
- LCD screen
|
|
- laptop/portable computer
|
|
- qwerty keyboard
|
|
- serial/parallel connection
|
|
- Amstrad custom ASIC chip
|
|
- tc8521 real time clock
|
|
- intel 8251 compatible uart
|
|
- PCMCIA Memory cards supported, up to 1mb!
|
|
|
|
NC200:
|
|
|
|
Hardware:
|
|
- Z80 CPU
|
|
- Intel 8251 compatible uart
|
|
- upd765 compatible floppy disc controller
|
|
- mc146818 real time clock?
|
|
- 720k floppy disc drive (compatible with MS-DOS)
|
|
(disc drive can be not ready).
|
|
- PCMCIA Memory cards supported, up to 1mb!
|
|
|
|
TODO:
|
|
- find out what the unused key bits are for
|
|
(checked all unused bits on nc200! - do not seem to have any use!)
|
|
- complete serial (xmodem protocol!)
|
|
- overlay would be nice!
|
|
- finish NC200 disc drive emulation (closer!)
|
|
- add NC150 driver - ROM needed!!!
|
|
- on/off control
|
|
- check values read from other ports that are not described!
|
|
- what is read from unmapped ports?
|
|
- what is read from uart when it is off?
|
|
- check if uart ints are generated when it is off?
|
|
- are ints cancelled if uart is turned off after int has been caused?
|
|
- check keyboard ints - are these regular or what??
|
|
|
|
PCMCIA memory cards are stored as a direct dump of the contents. There is no header
|
|
information. No distinction is made between RAM and ROM cards.
|
|
|
|
Memory card sizes are a power of 2 in size (e.g. 1mb, 512k, 256k etc),
|
|
however the code allows any size, but it limits access to power of 2 sizes, with
|
|
minimum access being 16k. If a file which is less than 16k is used, no memory card
|
|
will be present. If a file which is greater than 1mb is used, only 1mb will be accessed.
|
|
|
|
Interrupt system of NC100:
|
|
|
|
The IRQ mask is used to control the interrupt sources that can interrupt.
|
|
|
|
The IRQ status can be read to determine which devices are interrupting.
|
|
Some devices, e.g. serial, cannot be cleared by writing to the irq status
|
|
register. These can only be cleared by performing an operation on the
|
|
device (e.g. reading a data register).
|
|
|
|
Self Test:
|
|
|
|
- requires memory save and real time clock save to be working!
|
|
(i.e. for MESS nc100 driver, nc100.nv can be created)
|
|
- turn off nc (use NMI button)
|
|
- reset+FUNCTION+SYMBOL must be pressed together.
|
|
|
|
Note: NC200 Self test does not test disc hardware :(
|
|
|
|
|
|
|
|
Kevin Thacker [MESS driver]
|
|
|
|
******************************************************************************/
|
|
|
|
#include "emu.h"
|
|
#include "emuopts.h"
|
|
#include "cpu/z80/z80.h"
|
|
#include "includes/nc.h"
|
|
#include "machine/mc146818.h" /* for NC200 real time clock */
|
|
#include "machine/rp5c01.h" /* for NC100 real time clock */
|
|
#include "machine/upd765.h" /* for NC200 disk drive interface */
|
|
#include "formats/pc_dsk.h" /* for NC200 disk image */
|
|
#include "imagedev/cartslot.h"
|
|
#include "sound/beep.h"
|
|
#include "machine/ram.h"
|
|
#include "rendlay.h"
|
|
#include "mcfglgcy.h"
|
|
|
|
#define VERBOSE 0
|
|
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
|
|
|
|
#define NC200_DEBUG 1
|
|
#define LOG_DEBUG(x) do { if (NC200_DEBUG) logerror x; } while (0)
|
|
|
|
|
|
/* the serial clock is generated by the nc hardware and connected to the i8251
|
|
receive clock and transmit clock inputs */
|
|
|
|
/*
|
|
Port 0x00:
|
|
==========
|
|
|
|
Display memory start:
|
|
|
|
NC100:
|
|
bit 7 A15
|
|
bit 6 A14
|
|
bit 5 A13
|
|
bit 4 A12
|
|
bits 3-0 Not Used
|
|
NC200:
|
|
bit 7 A15
|
|
bit 6 A14
|
|
bit 5 A13
|
|
bits 4-0 Not Used
|
|
|
|
Port 0x010-0x013:
|
|
=================
|
|
|
|
Memory management control:
|
|
|
|
NC100 & NC200:
|
|
|
|
10 controls 0000-3FFF
|
|
11 controls 4000-7FFF
|
|
12 controls 8000-BFFF
|
|
13 controls C000-FFFF
|
|
|
|
Port 0x030:
|
|
===========
|
|
|
|
NC100:
|
|
bit 7 select card register 1=common, 0=attribute
|
|
bit 6 parallel interface Strobe signal
|
|
bit 5 Not Used
|
|
bit 4 uPD4711 line driver, 1=off, 0=on
|
|
bit 3 UART clock and reset, 1=off, 0=on
|
|
|
|
bits 2-0 set the baud rate as follows
|
|
|
|
000 = 150
|
|
001 = 300
|
|
010 = 600
|
|
011 = 1200
|
|
100 = 2400
|
|
101 = 4800
|
|
110 = 9600
|
|
111 = 19200
|
|
NC200:
|
|
bit 7 select card register 1=common, 0=attribute
|
|
bit 6 parallel interface Strobe signal
|
|
|
|
bit 5 used in disc interface; (set to 0)
|
|
|
|
bit 4 uPD4711 line driver, 1=off, 0=on
|
|
bit 3 UART clock and reset, 1=off, 0=on
|
|
|
|
bits 2-0 set the baud rate as follows
|
|
|
|
000 = 150
|
|
001 = 300
|
|
010 = 600
|
|
011 = 1200
|
|
100 = 2400
|
|
101 = 4800
|
|
110 = 9600
|
|
111 = 19200
|
|
|
|
|
|
Port 0x0a0:
|
|
===========
|
|
|
|
NC100:
|
|
bit 7: memory card present 0 = yes, 1 = no
|
|
bit 6: memory card write protected 1 = yes, 0 = no
|
|
bit 5: input voltage = 1, if >= to 4 volts
|
|
bit 4: mem card battery: 0 = battery low
|
|
bit 3: alkaline batteries. 0 if >=3.2 volts
|
|
bit 2: lithium battery 0 if >= 2.7 volts
|
|
bit 1: parallel interface busy (0 if busy)
|
|
bit 0: parallel interface ack (1 if ack)
|
|
|
|
NC200:
|
|
|
|
bit 7: memory card present 0 = yes, 1 = no
|
|
bit 6: memory card write protected 1 = yes, 0 = no
|
|
bit 5: lithium battery 0 if >= 2.7 volts
|
|
bit 4: input voltage = 1, if >= to 4 volts
|
|
bit 3: ??
|
|
bit 2: alkaline batteries. 0 if >=3.2 volts
|
|
bit 1: ??
|
|
bit 0: battery power: if 1: batteries are too low for disk usage, if 0: batteries ok for disc usage
|
|
|
|
|
|
Port 0x060 (IRQ MASK), Port 0x090 (IRQ STATUS):
|
|
===============================================
|
|
|
|
NC100:
|
|
bit 7: not used
|
|
bit 6: not used
|
|
bit 5: not used
|
|
bit 4: not used
|
|
Bit 3: Key scan interrupt (10ms)
|
|
Bit 2: ACK from parallel interface
|
|
Bit 1: Tx Ready
|
|
Bit 0: Rx Ready
|
|
|
|
NC200:
|
|
bit 7: ???
|
|
bit 6: RTC alarm?
|
|
bit 5: FDC interrupt
|
|
bit 4: Power off interrupt
|
|
Bit 3: Key scan interrupt (10ms)
|
|
Bit 2: serial interrupt (tx ready/rx ready combined)
|
|
Bit 1: not used
|
|
Bit 0: ACK from parallel interface
|
|
|
|
Port 0x070: On/off control
|
|
|
|
NC200:
|
|
bit 7: nc200 power on/off: 1 = on, 0=off
|
|
bit 2: backlight: 1=off, 0=on
|
|
bit 1: disk motor: 1=off, 0=disk motor???
|
|
bit 0: upd765 terminal count input
|
|
*/
|
|
|
|
|
|
|
|
/* this is not a real register, it is used to record card status */
|
|
/* ==0, card not inserted, !=0 card is inserted */
|
|
|
|
/* set pcmcia card present state */
|
|
void nc_state::nc_set_card_present_state(int state)
|
|
{
|
|
m_card_status = state;
|
|
}
|
|
|
|
|
|
/* latched interrupts are interrupts that cannot be cleared by writing to the irq
|
|
mask. latched interrupts can only be cleared by accessing the interrupting
|
|
device e.g. serial chip, fdc */
|
|
/* this is a mask of irqs that are latched, and it is different for nc100 and
|
|
nc200 */
|
|
|
|
void nc_state::nc_update_interrupts()
|
|
{
|
|
m_irq_status &= ~m_irq_latch_mask;
|
|
m_irq_status |= m_irq_latch;
|
|
|
|
/* any ints set and they are not masked? */
|
|
if (
|
|
(((m_irq_status & m_irq_mask) & 0x3f)!=0)
|
|
)
|
|
{
|
|
logerror("int set %02x\n", m_irq_status & m_irq_mask);
|
|
/* set int */
|
|
m_maincpu->set_input_line(0, HOLD_LINE);
|
|
}
|
|
else
|
|
{
|
|
/* clear int */
|
|
m_maincpu->set_input_line(0, CLEAR_LINE);
|
|
}
|
|
}
|
|
|
|
TIMER_CALLBACK_MEMBER(nc_state::nc_keyboard_timer_callback)
|
|
{
|
|
LOG(("keyboard int\n"));
|
|
|
|
/* set int */
|
|
m_irq_status |= (1<<3);
|
|
|
|
/* update ints */
|
|
nc_update_interrupts();
|
|
|
|
/* don't trigger again, but don't free it */
|
|
m_keyboard_timer->reset();
|
|
}
|
|
|
|
|
|
static const char *const nc_bankhandler_r[]={
|
|
"bank1", "bank2", "bank3", "bank4"};
|
|
|
|
static const char *const nc_bankhandler_w[]={
|
|
"bank5", "bank6", "bank7", "bank8"};
|
|
|
|
void nc_state::nc_refresh_memory_bank_config(int bank)
|
|
{
|
|
address_space &space = m_maincpu->space(AS_PROGRAM);
|
|
int mem_type;
|
|
int mem_bank;
|
|
char bank1[10];
|
|
char bank5[10];
|
|
sprintf(bank1,"bank%d",bank+1);
|
|
sprintf(bank5,"bank%d",bank+5);
|
|
|
|
mem_type = (m_memory_config[bank]>>6) & 0x03;
|
|
mem_bank = m_memory_config[bank] & 0x03f;
|
|
|
|
space.install_read_bank((bank * 0x4000), (bank * 0x4000) + 0x3fff, nc_bankhandler_r[bank]);
|
|
|
|
switch (mem_type)
|
|
{
|
|
/* ROM */
|
|
case 3:
|
|
case 0:
|
|
{
|
|
unsigned char *addr;
|
|
|
|
mem_bank = mem_bank & m_membank_rom_mask;
|
|
|
|
addr = (memregion("maincpu")->base()+0x010000) + (mem_bank<<14);
|
|
|
|
membank(bank1)->set_base(addr);
|
|
|
|
space.nop_write((bank * 0x4000), (bank * 0x4000) + 0x3fff);
|
|
LOG(("BANK %d: ROM %d\n",bank,mem_bank));
|
|
}
|
|
break;
|
|
|
|
/* internal RAM */
|
|
case 1:
|
|
{
|
|
unsigned char *addr;
|
|
|
|
mem_bank = mem_bank & m_membank_internal_ram_mask;
|
|
|
|
addr = m_ram->pointer() + (mem_bank<<14);
|
|
|
|
membank(bank1)->set_base(addr);
|
|
membank(bank5)->set_base(addr);
|
|
|
|
space.install_write_bank((bank * 0x4000), (bank * 0x4000) + 0x3fff, nc_bankhandler_w[bank]);
|
|
LOG(("BANK %d: RAM\n",bank));
|
|
}
|
|
break;
|
|
|
|
/* card RAM */
|
|
case 2:
|
|
{
|
|
/* card connected? */
|
|
if ((m_card_status) && (m_card_ram!=NULL))
|
|
{
|
|
unsigned char *addr;
|
|
|
|
mem_bank = mem_bank & m_membank_card_ram_mask;
|
|
addr = m_card_ram + (mem_bank<<14);
|
|
|
|
membank(bank1)->set_base(addr);
|
|
|
|
/* write enabled? */
|
|
if (ioport("EXTRA")->read() & 0x02)
|
|
{
|
|
/* yes */
|
|
membank(bank5)->set_base(addr);
|
|
|
|
space.install_write_bank((bank * 0x4000), (bank * 0x4000) + 0x3fff, nc_bankhandler_w[bank]);
|
|
}
|
|
else
|
|
{
|
|
/* no */
|
|
space.nop_write((bank * 0x4000), (bank * 0x4000) + 0x3fff);
|
|
}
|
|
|
|
LOG(("BANK %d: CARD-RAM\n",bank));
|
|
}
|
|
else
|
|
{
|
|
/* if no card connected, then writes fail */
|
|
space.nop_readwrite((bank * 0x4000), (bank * 0x4000) + 0x3fff);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void nc_state::nc_refresh_memory_config()
|
|
{
|
|
nc_refresh_memory_bank_config(0);
|
|
nc_refresh_memory_bank_config(1);
|
|
nc_refresh_memory_bank_config(2);
|
|
nc_refresh_memory_bank_config(3);
|
|
}
|
|
|
|
|
|
static NVRAM_HANDLER( nc )
|
|
{
|
|
nc_state *state = machine.driver_data<nc_state>();
|
|
|
|
if (read_or_write)
|
|
{
|
|
file->write(state->m_ram->pointer(), state->m_ram->size());
|
|
}
|
|
else if (file)
|
|
{
|
|
file->read(state->m_ram->pointer(), state->m_ram->size());
|
|
}
|
|
else
|
|
{
|
|
// leave whatever ram device defaulted to
|
|
}
|
|
}
|
|
|
|
|
|
TIMER_DEVICE_CALLBACK_MEMBER(nc_state::dummy_timer_callback)
|
|
{
|
|
int inputport_10_state;
|
|
int changed_bits;
|
|
|
|
inputport_10_state = ioport("EXTRA")->read();
|
|
|
|
changed_bits = inputport_10_state^m_previous_inputport_10_state;
|
|
|
|
/* on/off button changed state? */
|
|
if (changed_bits & 0x01)
|
|
{
|
|
if (inputport_10_state & 0x01)
|
|
{
|
|
/* on NC100 on/off button causes a nmi, on
|
|
nc200 on/off button causes an int */
|
|
switch (m_type)
|
|
{
|
|
case NC_TYPE_1xx:
|
|
{
|
|
LOG(("nmi triggered\n"));
|
|
m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
|
|
}
|
|
break;
|
|
|
|
case NC_TYPE_200:
|
|
{
|
|
m_irq_status |= (1 << 4);
|
|
nc_update_interrupts();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* memory card write enable/disable state changed? */
|
|
if (changed_bits & 0x02)
|
|
{
|
|
/* yes refresh memory config */
|
|
nc_refresh_memory_config();
|
|
}
|
|
|
|
m_previous_inputport_10_state = inputport_10_state;
|
|
}
|
|
|
|
|
|
|
|
void nc_state::nc_common_init_machine()
|
|
{
|
|
/* setup reset state */
|
|
m_display_memory_start = 0;
|
|
|
|
/* setup reset state */
|
|
m_memory_config[0] = 0;
|
|
m_memory_config[1] = 0;
|
|
m_memory_config[2] = 0;
|
|
m_memory_config[3] = 0;
|
|
|
|
m_previous_inputport_10_state = ioport("EXTRA")->read();
|
|
|
|
/* setup reset state ints are masked */
|
|
m_irq_mask = 0;
|
|
/* setup reset state no ints wanting servicing */
|
|
m_irq_status = 0;
|
|
/* at reset set to 0x0ffff */
|
|
|
|
m_irq_latch = 0;
|
|
m_irq_latch_mask = 0;
|
|
|
|
/* setup reset state */
|
|
m_sound_channel_periods[0] = (m_sound_channel_periods[1] = 0x0ffff);
|
|
|
|
/* at reset set to 1 */
|
|
m_poweroff_control = 1;
|
|
|
|
nc_refresh_memory_config();
|
|
nc_update_interrupts();
|
|
|
|
/* at reset set to 0x0ff */
|
|
m_uart_control = 0x0ff;
|
|
}
|
|
|
|
static ADDRESS_MAP_START(nc_map, AS_PROGRAM, 8, nc_state )
|
|
AM_RANGE(0x0000, 0x3fff) AM_READ_BANK("bank1") AM_WRITE_BANK("bank5")
|
|
AM_RANGE(0x4000, 0x7fff) AM_READ_BANK("bank2") AM_WRITE_BANK("bank6")
|
|
AM_RANGE(0x8000, 0xbfff) AM_READ_BANK("bank3") AM_WRITE_BANK("bank7")
|
|
AM_RANGE(0xc000, 0xffff) AM_READ_BANK("bank4") AM_WRITE_BANK("bank8")
|
|
ADDRESS_MAP_END
|
|
|
|
|
|
READ8_MEMBER(nc_state::nc_memory_management_r)
|
|
{
|
|
return m_memory_config[offset];
|
|
}
|
|
|
|
WRITE8_MEMBER(nc_state::nc_memory_management_w)
|
|
{
|
|
LOG(("Memory management W: %02x %02x\n",offset,data));
|
|
m_memory_config[offset] = data;
|
|
|
|
nc_refresh_memory_config();
|
|
}
|
|
|
|
WRITE8_MEMBER(nc_state::nc_irq_mask_w)
|
|
{
|
|
LOG(("irq mask w: %02x\n", data));
|
|
LOG_DEBUG(("irq mask nc200 w: %02x\n",data & ((1<<4) | (1<<5) | (1<<6) | (1<<7))));
|
|
|
|
/* writing mask clears ints that are to be masked? */
|
|
m_irq_mask = data;
|
|
|
|
nc_update_interrupts();
|
|
}
|
|
|
|
WRITE8_MEMBER(nc_state::nc_irq_status_w)
|
|
{
|
|
LOG(("irq status w: %02x\n", data));
|
|
data = data^0x0ff;
|
|
|
|
if (m_type == NC_TYPE_200)
|
|
{
|
|
/* Russell Marks confirms that on the NC200, the key scan interrupt must be explicitly
|
|
cleared. It is not automatically cleared when reading 0x0b9 */
|
|
if ((data & (1<<3))!=0)
|
|
{
|
|
/* set timer to occur again */
|
|
m_keyboard_timer->reset(attotime::from_msec(10));
|
|
|
|
nc_update_interrupts();
|
|
}
|
|
}
|
|
|
|
|
|
/* writing to status will clear int, will this re-start the key-scan? */
|
|
#if 0
|
|
if (
|
|
/* clearing keyboard int? */
|
|
((data & (1<<3))!=0) &&
|
|
/* keyboard int request? */
|
|
((m_irq_status & (1<<3))!=0)
|
|
)
|
|
{
|
|
/* set timer to occur again */
|
|
m_keyboard_timer->reset(attotime::from_msec(10));
|
|
}
|
|
#endif
|
|
m_irq_status &=~data;
|
|
|
|
nc_update_interrupts();
|
|
}
|
|
|
|
READ8_MEMBER(nc_state::nc_irq_status_r)
|
|
{
|
|
return ~((m_irq_status & (~m_irq_latch_mask)) | m_irq_latch);
|
|
}
|
|
|
|
|
|
READ8_MEMBER(nc_state::nc_key_data_in_r)
|
|
{
|
|
static const char *const keynames[] = {
|
|
"LINE0", "LINE1", "LINE2", "LINE3", "LINE4",
|
|
"LINE5", "LINE6", "LINE7", "LINE8", "LINE9"
|
|
};
|
|
|
|
if (offset==9)
|
|
{
|
|
/* reading 0x0b9 will clear int and re-start scan procedure! */
|
|
m_irq_status &= ~(1<<3);
|
|
|
|
/* set timer to occur again */
|
|
m_keyboard_timer->reset(attotime::from_msec(10));
|
|
|
|
nc_update_interrupts();
|
|
}
|
|
|
|
return ioport(keynames[offset])->read();
|
|
}
|
|
|
|
|
|
void nc_state::nc_sound_update(int channel)
|
|
{
|
|
int on;
|
|
int frequency;
|
|
int period;
|
|
beep_device *beeper_device = NULL;
|
|
|
|
switch(channel)
|
|
{
|
|
case 0:
|
|
beeper_device = m_beeper1;
|
|
break;
|
|
case 1:
|
|
beeper_device = m_beeper2;
|
|
break;
|
|
}
|
|
|
|
period = m_sound_channel_periods[channel];
|
|
|
|
/* if top bit is 0, sound is on */
|
|
on = ((period & (1<<15))==0);
|
|
|
|
/* calculate frequency from period */
|
|
frequency = (int)(1000000.0f/((float)((period & 0x07fff)<<1) * 1.6276f));
|
|
|
|
/* set state */
|
|
beeper_device->set_state(on);
|
|
/* set frequency */
|
|
beeper_device->set_frequency(frequency);
|
|
}
|
|
|
|
WRITE8_MEMBER(nc_state::nc_sound_w)
|
|
{
|
|
LOG(("sound w: %04x %02x\n", offset, data));
|
|
|
|
switch (offset)
|
|
{
|
|
case 0x0:
|
|
{
|
|
/* update period value */
|
|
m_sound_channel_periods[0] =
|
|
(m_sound_channel_periods[0] & 0x0ff00) | (data & 0x0ff);
|
|
|
|
nc_sound_update(0);
|
|
}
|
|
break;
|
|
|
|
case 0x01:
|
|
{
|
|
m_sound_channel_periods[0] =
|
|
(m_sound_channel_periods[0] & 0x0ff) | ((data & 0x0ff)<<8);
|
|
|
|
nc_sound_update(0);
|
|
}
|
|
break;
|
|
|
|
case 0x02:
|
|
{
|
|
/* update period value */
|
|
m_sound_channel_periods[1] =
|
|
(m_sound_channel_periods[1] & 0x0ff00) | (data & 0x0ff);
|
|
|
|
nc_sound_update(1);
|
|
}
|
|
break;
|
|
|
|
case 0x03:
|
|
{
|
|
m_sound_channel_periods[1] =
|
|
(m_sound_channel_periods[1] & 0x0ff) | ((data & 0x0ff)<<8);
|
|
|
|
nc_sound_update(1);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static const int baud_rate_table[]=
|
|
{
|
|
128, //150
|
|
64, //300
|
|
32, //600
|
|
16, //1200
|
|
8, //2400
|
|
4, //4800
|
|
2, //9600
|
|
1, //19200
|
|
};
|
|
|
|
WRITE_LINE_MEMBER(nc_state::write_uart_clock)
|
|
{
|
|
m_uart->write_txc(state);
|
|
m_uart->write_rxc(state);
|
|
}
|
|
|
|
WRITE8_MEMBER(nc_state::nc_uart_control_w)
|
|
{
|
|
/* same for nc100 and nc200 */
|
|
m_centronics->write_strobe(BIT(data, 6));
|
|
|
|
/* on/off changed state? */
|
|
if (((m_uart_control ^ data) & (1<<3))!=0)
|
|
{
|
|
/* changed uart from off to on */
|
|
if ((data & (1<<3))==0)
|
|
{
|
|
machine().device("uart")->reset();
|
|
}
|
|
}
|
|
|
|
m_uart_clock->set_clock_scale((double)1 / baud_rate_table[(data & 0x07)]);
|
|
|
|
m_uart_control = data;
|
|
}
|
|
|
|
/* NC100 printer emulation */
|
|
/* port 0x040 (write only) = 8-bit printer data */
|
|
/* port 0x030 bit 6 = printer strobe */
|
|
|
|
|
|
|
|
/********************************************************************************************************/
|
|
/* NC100 hardware */
|
|
|
|
|
|
|
|
WRITE8_MEMBER(nc_state::nc100_display_memory_start_w)
|
|
{
|
|
/* bit 7: A15 */
|
|
/* bit 6: A14 */
|
|
/* bit 5: A13 */
|
|
/* bit 4: A12 */
|
|
/* bit 3-0: not used */
|
|
m_display_memory_start = (data & 0x0f0)<<(12-4);
|
|
|
|
LOG(("disp memory w: %04x\n", (int) m_display_memory_start));
|
|
}
|
|
|
|
|
|
WRITE8_MEMBER(nc_state::nc100_uart_control_w)
|
|
{
|
|
nc_uart_control_w(space, offset,data);
|
|
|
|
// /* is this correct?? */
|
|
// if (data & (1<<3))
|
|
// {
|
|
// /* clear latched irq's */
|
|
// m_irq_latch &= ~3;
|
|
// nc_update_interrupts(machine);
|
|
// }
|
|
}
|
|
|
|
|
|
WRITE_LINE_MEMBER(nc_state::nc100_tc8521_alarm_callback)
|
|
{
|
|
// TODO
|
|
}
|
|
|
|
WRITE_LINE_MEMBER(nc_state::nc100_txrdy_callback)
|
|
{
|
|
m_irq_latch &= ~(1 << 1);
|
|
|
|
/* uart on? */
|
|
if ((m_uart_control & (1 << 3)) == 0)
|
|
{
|
|
if (state)
|
|
{
|
|
logerror("tx ready\n");
|
|
m_irq_latch |= (1 << 1);
|
|
}
|
|
}
|
|
|
|
nc_update_interrupts();
|
|
}
|
|
|
|
WRITE_LINE_MEMBER(nc_state::nc100_rxrdy_callback)
|
|
{
|
|
m_irq_latch &= ~(1<<0);
|
|
|
|
if ((m_uart_control & (1<<3))==0)
|
|
{
|
|
if (state)
|
|
{
|
|
logerror("rx ready\n");
|
|
m_irq_latch |= (1<<0);
|
|
}
|
|
}
|
|
|
|
nc_update_interrupts();
|
|
}
|
|
|
|
|
|
static RP5C01_INTERFACE( rtc_intf )
|
|
{
|
|
DEVCB_DRIVER_LINE_MEMBER(nc_state,nc100_tc8521_alarm_callback)
|
|
};
|
|
|
|
WRITE_LINE_MEMBER(nc_state::write_nc100_centronics_ack)
|
|
{
|
|
m_centronics_ack = state;
|
|
|
|
if (state)
|
|
m_irq_status |= 0x04;
|
|
else
|
|
m_irq_status &= ~0x04;
|
|
|
|
/* trigger an int if the irq is set */
|
|
nc_update_interrupts();
|
|
}
|
|
|
|
WRITE_LINE_MEMBER(nc_state::write_centronics_busy)
|
|
{
|
|
m_centronics_busy = state;
|
|
}
|
|
|
|
void nc_state::machine_reset()
|
|
{
|
|
/* 256k of rom */
|
|
m_membank_rom_mask = 0x0f;
|
|
|
|
m_membank_internal_ram_mask = 3;
|
|
|
|
m_membank_card_ram_mask = 0x03f;
|
|
|
|
nc_common_init_machine();
|
|
|
|
/* serial */
|
|
m_irq_latch_mask = (1<<0) | (1<<1);
|
|
}
|
|
|
|
void nc_state::machine_start()
|
|
{
|
|
m_type = NC_TYPE_1xx;
|
|
|
|
/* keyboard timer */
|
|
m_keyboard_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(nc_state::nc_keyboard_timer_callback),this));
|
|
m_keyboard_timer->adjust(attotime::from_msec(10));
|
|
}
|
|
|
|
|
|
WRITE8_MEMBER(nc_state::nc100_poweroff_control_w)
|
|
{
|
|
/* bits 7-1: not used */
|
|
/* bit 0: 1 = no effect, 0 = power off */
|
|
m_poweroff_control = data;
|
|
LOG(("nc poweroff control: %02x\n",data));
|
|
}
|
|
|
|
|
|
/* nc100 version of card/battery status */
|
|
READ8_MEMBER(nc_state::nc100_card_battery_status_r)
|
|
{
|
|
int nc_card_battery_status = 0x0fc;
|
|
|
|
/* printer */
|
|
nc_card_battery_status |= m_centronics_ack;
|
|
nc_card_battery_status |= m_centronics_busy << 1;
|
|
|
|
if (m_card_status)
|
|
{
|
|
/* card present */
|
|
nc_card_battery_status &=~(1<<7);
|
|
}
|
|
|
|
if (ioport("EXTRA")->read() & 0x02)
|
|
{
|
|
/* card write enable */
|
|
nc_card_battery_status &=~(1<<6);
|
|
}
|
|
|
|
/* enough power - see bit assignments where
|
|
nc card battery status is defined */
|
|
nc_card_battery_status |= (1<<5);
|
|
nc_card_battery_status &= ~((1<<2) | (1<<3));
|
|
|
|
return nc_card_battery_status;
|
|
}
|
|
|
|
WRITE8_MEMBER(nc_state::nc100_memory_card_wait_state_w)
|
|
{
|
|
LOG(("nc100 memory card wait state: %02x\n",data));
|
|
}
|
|
|
|
|
|
|
|
static ADDRESS_MAP_START(nc100_io, AS_IO, 8, nc_state )
|
|
ADDRESS_MAP_GLOBAL_MASK(0xff)
|
|
ADDRESS_MAP_UNMAP_HIGH
|
|
AM_RANGE(0x00, 0x0f) AM_WRITE(nc100_display_memory_start_w)
|
|
AM_RANGE(0x10, 0x13) AM_READWRITE(nc_memory_management_r, nc_memory_management_w)
|
|
AM_RANGE(0x20, 0x20) AM_WRITE(nc100_memory_card_wait_state_w)
|
|
AM_RANGE(0x30, 0x30) AM_WRITE(nc100_uart_control_w)
|
|
AM_RANGE(0x40, 0x40) AM_DEVWRITE("cent_data_out", output_latch_device, write)
|
|
AM_RANGE(0x50, 0x53) AM_WRITE(nc_sound_w)
|
|
AM_RANGE(0x60, 0x60) AM_WRITE(nc_irq_mask_w)
|
|
AM_RANGE(0x70, 0x70) AM_WRITE(nc100_poweroff_control_w)
|
|
AM_RANGE(0x90, 0x90) AM_READWRITE(nc_irq_status_r, nc_irq_status_w)
|
|
AM_RANGE(0x91, 0x9f) AM_READ(nc_irq_status_r)
|
|
AM_RANGE(0xa0, 0xaf) AM_READ(nc100_card_battery_status_r)
|
|
AM_RANGE(0xb0, 0xb9) AM_READ(nc_key_data_in_r)
|
|
AM_RANGE(0xc0, 0xc0) AM_DEVREADWRITE("uart",i8251_device, data_r, data_w)
|
|
AM_RANGE(0xc1, 0xc1) AM_DEVREADWRITE("uart", i8251_device, status_r, control_w)
|
|
AM_RANGE(0xd0, 0xdf) AM_DEVREADWRITE("rtc", rp5c01_device, read, write)
|
|
ADDRESS_MAP_END
|
|
|
|
|
|
/* 2008-05 FP:
|
|
Small note about natural keyboard support (both for nc100 and nc200): currently,
|
|
- "Shift" (both L & R) and "Caps Lock" do not work in natural mode (to be investigated)
|
|
- "Function" is mapped to 'Left Control'
|
|
- "Control" is mapped to 'Right Control'
|
|
- "Caps Lock" is mapped to 'Right Alt'
|
|
- "On" is mapped to 'F1'
|
|
- "Stop" is mapped to 'F2'
|
|
- "Symbol" is mapped to 'F3'
|
|
- "Menu" is mapped to 'F4'
|
|
*/
|
|
|
|
static INPUT_PORTS_START(nc100)
|
|
PORT_START("LINE0")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Shift (Left)") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_MAMEKEY(LSHIFT))
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Shift (Right)") PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT))
|
|
PORT_BIT(0x04, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Cursor Left (Red)") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
|
|
PORT_BIT(0x20, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x40, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x80, 0x00, IPT_UNUSED)
|
|
|
|
PORT_START("LINE1")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Function (Yellow)") PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) // 5th row, 1st key on left (where 'fn' is on mac keyboards)
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Control") PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_MAMEKEY(RCONTROL))
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Stop") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(F2))
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
|
|
PORT_BIT(0x10, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x20, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
|
|
PORT_BIT(0x80, 0x00, IPT_UNUSED)
|
|
|
|
PORT_START("LINE2")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Caps Lock") PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT))
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Symbol") PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(F3)) // 5th row, 3rd key (where 'Alt' usually stays)
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t')
|
|
PORT_BIT(0x10, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x20, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x40, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x80, 0x00, IPT_UNUSED)
|
|
|
|
PORT_START("LINE3")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('\xA3')
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
|
|
PORT_BIT(0x20, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
|
|
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
|
|
|
|
PORT_START("LINE4")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
|
|
PORT_BIT(0x02, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
|
|
PORT_BIT(0x20, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
|
|
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
|
|
|
|
PORT_START("LINE5")
|
|
PORT_BIT(0x01, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x02, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
|
|
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('c') PORT_CHAR('C')
|
|
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('g') PORT_CHAR('G')
|
|
|
|
PORT_START("LINE6")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Cursor Down (Blue)") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Del>") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Cursor Right (Green)") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('#') PORT_CHAR('~')
|
|
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
|
|
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
|
|
|
|
PORT_START("LINE7")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('\\') PORT_CHAR('|')
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Menu") PORT_CODE(KEYCODE_PGUP) PORT_CHAR(UCHAR_MAMEKEY(F4))
|
|
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
|
|
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
|
|
|
|
PORT_START("LINE8")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('@')
|
|
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
|
|
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
|
|
|
|
PORT_START("LINE9")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Del<") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR('8')
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
|
|
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
|
|
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
|
|
|
|
/* these are not part of the nc100 keyboard */
|
|
/* extra */
|
|
PORT_START("EXTRA")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("On Button") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(F1))
|
|
/* pcmcia memory card setting */
|
|
PORT_DIPNAME( 0x02, 0x002, "PCMCIA Memory card write enable")
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x02, DEF_STR( On ) )
|
|
INPUT_PORTS_END
|
|
|
|
/**********************************************************************************************************/
|
|
/* NC150 hardware */
|
|
/* to be completed! */
|
|
|
|
#if 0
|
|
void nc_state::nc150_init_machine()
|
|
{
|
|
m_membank_internal_ram_mask = 7;
|
|
|
|
m_membank_card_ram_mask = 0x03f;
|
|
|
|
nc_common_init_machine(machine);
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
/**********************************************************************************************************/
|
|
/* NC200 hardware */
|
|
|
|
#ifdef UNUSED_FUNCTION
|
|
WRITE8_MEMBER(nc_state::nc200_display_memory_start_w)
|
|
{
|
|
/* bit 7: A15 */
|
|
/* bit 6: A14 */
|
|
/* bit 5: A13 */
|
|
/* bit 4-0: not used */
|
|
m_display_memory_start = (data & 0x0e0)<<(12-4);
|
|
|
|
LOG(("disp memory w: %04x\n", (int) m_display_memory_start));
|
|
}
|
|
#endif
|
|
|
|
|
|
WRITE_LINE_MEMBER(nc_state::write_nc200_centronics_ack)
|
|
{
|
|
if (state)
|
|
m_irq_status |= 0x01;
|
|
else
|
|
m_irq_status &= ~0x01;
|
|
|
|
/* trigger an int if the irq is set */
|
|
nc_update_interrupts();
|
|
}
|
|
|
|
/* assumption. nc200 uses the same uart chip. The rxrdy and txrdy are combined
|
|
together with a or to generate a single interrupt */
|
|
|
|
void nc_state::nc200_refresh_uart_interrupt()
|
|
{
|
|
m_irq_latch &=~(1<<2);
|
|
|
|
/* uart enabled? */
|
|
if ((m_uart_control & (1<<3))==0)
|
|
{
|
|
if ((m_nc200_uart_interrupt_irq & 0x03)!=0)
|
|
{
|
|
m_irq_latch |= (1<<2);
|
|
}
|
|
}
|
|
nc_update_interrupts();
|
|
}
|
|
|
|
WRITE_LINE_MEMBER(nc_state::nc200_txrdy_callback)
|
|
{
|
|
//nc_state *drvstate = machine().driver_data<nc_state>();
|
|
// m_nc200_uart_interrupt_irq &=~(1<<0);
|
|
//
|
|
// if (state)
|
|
// {
|
|
// m_nc200_uart_interrupt_irq |=(1<<0);
|
|
// }
|
|
//
|
|
// nc200_refresh_uart_interrupt(machine());
|
|
}
|
|
|
|
WRITE_LINE_MEMBER(nc_state::nc200_rxrdy_callback)
|
|
{
|
|
m_nc200_uart_interrupt_irq &=~(1<<1);
|
|
|
|
if (state)
|
|
{
|
|
m_nc200_uart_interrupt_irq |=(1<<1);
|
|
}
|
|
|
|
nc200_refresh_uart_interrupt();
|
|
}
|
|
|
|
void nc_state::nc200_fdc_interrupt(bool state)
|
|
{
|
|
#if 0
|
|
m_irq_latch &=~(1<<5);
|
|
|
|
if (state)
|
|
{
|
|
m_irq_latch |=(1<<5);
|
|
}
|
|
#endif
|
|
m_irq_status &=~(1<<5);
|
|
|
|
if (state)
|
|
{
|
|
m_irq_status |=(1<<5);
|
|
}
|
|
|
|
nc_update_interrupts();
|
|
}
|
|
|
|
#ifdef UNUSED_FUNCTION
|
|
void nc_state::nc200_floppy_drive_index_callback(int drive_id)
|
|
{
|
|
LOG_DEBUG(("nc200 index pulse\n"));
|
|
// m_irq_status |= (1<<4);
|
|
|
|
// nc_update_interrupts(Machine);
|
|
}
|
|
#endif
|
|
|
|
MACHINE_RESET_MEMBER(nc_state,nc200)
|
|
{
|
|
/* 512k of rom */
|
|
m_membank_rom_mask = 0x1f;
|
|
|
|
m_membank_internal_ram_mask = 7;
|
|
|
|
m_membank_card_ram_mask = 0x03f;
|
|
|
|
nc_common_init_machine();
|
|
|
|
m_nc200_uart_interrupt_irq = 0;
|
|
|
|
/* fdc, serial */
|
|
m_irq_latch_mask = /*(1<<5) |*/ (1<<2);
|
|
|
|
nc200_video_set_backlight(0);
|
|
}
|
|
|
|
MACHINE_START_MEMBER(nc_state,nc200)
|
|
{
|
|
m_type = NC_TYPE_200;
|
|
|
|
/* keyboard timer */
|
|
m_keyboard_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(nc_state::nc_keyboard_timer_callback),this));
|
|
m_keyboard_timer->adjust(attotime::from_msec(10));
|
|
|
|
/* serial timer */
|
|
machine().device<upd765a_device>("upd765")->setup_intrq_cb(upd765a_device::line_cb(FUNC(nc_state::nc200_fdc_interrupt), this));
|
|
}
|
|
|
|
/*
|
|
NC200:
|
|
|
|
bit 7: memory card present 0 = yes, 1 = no
|
|
bit 6: memory card write protected 1=yes 0=no
|
|
bit 5: lithium battery 0 if >= 2.7 volts
|
|
bit 4: input voltage = 1, if >= to 4 volts
|
|
bit 3: ??
|
|
bit 2: alkaline batteries. 0 if >=3.2 volts
|
|
bit 1: ??
|
|
bit 0: battery power: if 1: batteries are too low for disk usage, if 0: batteries ok for disc usage
|
|
*/
|
|
|
|
|
|
/* nc200 version of card/battery status */
|
|
READ8_MEMBER(nc_state::nc200_card_battery_status_r)
|
|
{
|
|
int nc_card_battery_status = 0x0ff;
|
|
|
|
/* enough power */
|
|
|
|
/* input voltage ok */
|
|
nc_card_battery_status |=(1<<4);
|
|
/* lithium batteries and alkaline batteries have enough power,
|
|
and there is enough power for disk usage */
|
|
nc_card_battery_status &=~((1<<5) | (1<<2) | (1<<0));
|
|
|
|
if (m_card_status)
|
|
{
|
|
/* card present */
|
|
nc_card_battery_status&=~(1<<7);
|
|
}
|
|
|
|
if (ioport("EXTRA")->read() & 0x02)
|
|
{
|
|
/* card write enable */
|
|
nc_card_battery_status &=~(1<<6);
|
|
}
|
|
|
|
return nc_card_battery_status;
|
|
}
|
|
|
|
|
|
/* port &80:
|
|
|
|
bit 0: Parallel interface BUSY
|
|
*/
|
|
|
|
READ8_MEMBER(nc_state::nc200_printer_status_r)
|
|
{
|
|
UINT8 result = 0;
|
|
|
|
result |= m_centronics_busy;
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
WRITE8_MEMBER(nc_state::nc200_uart_control_w)
|
|
{
|
|
/* int reset_fdc = (m_uart_control^data) & (1<<5); */
|
|
|
|
nc_uart_control_w(space, offset,data);
|
|
|
|
if (data & (1<<3))
|
|
{
|
|
m_nc200_uart_interrupt_irq &=~3;
|
|
|
|
nc200_refresh_uart_interrupt();
|
|
}
|
|
|
|
/* bit 5 is used in disk interface */
|
|
LOG_DEBUG(("bit 5: PC: %04x %02x\n", m_maincpu->pc(), data & (1 << 5)));
|
|
}
|
|
|
|
|
|
/* bit 7: same as nc100 */
|
|
/* bit 2: ?? */
|
|
/* bit 1: ?? */
|
|
/* %10000110 = 0x086 */
|
|
/* %10000010 = 0x082 */
|
|
/* %10000011 = 0x083 */
|
|
/* writes 86,82 */
|
|
|
|
/* bit 7: nc200 power control: 1=on, 0=off */
|
|
/* bit 1: disk motor?? */
|
|
/* bit 0: UPD765 Terminal Count input */
|
|
|
|
WRITE8_MEMBER(nc_state::nc200_memory_card_wait_state_w)
|
|
{
|
|
upd765a_device *fdc = machine().device<upd765a_device>("upd765");
|
|
LOG_DEBUG(("nc200 memory card wait state: PC: %04x %02x\n", m_maincpu->pc(), data));
|
|
#if 0
|
|
floppy_drive_set_motor_state(0, 1);
|
|
floppy_drive_set_ready_state(0, 1, 1);
|
|
#endif
|
|
fdc->tc_w(data & 0x01);
|
|
}
|
|
|
|
/* bit 2: backlight: 1=off, 0=on */
|
|
/* bit 1 cleared to zero in disk code */
|
|
/* bit 0 seems to be the same as nc100 */
|
|
WRITE8_MEMBER(nc_state::nc200_poweroff_control_w)
|
|
{
|
|
LOG_DEBUG(("nc200 power off: PC: %04x %02x\n", m_maincpu->pc(), data));
|
|
|
|
nc200_video_set_backlight(((data ^ (1 << 2)) >> 2) & 0x01);
|
|
}
|
|
|
|
static ADDRESS_MAP_START(nc200_io, AS_IO, 8, nc_state )
|
|
ADDRESS_MAP_GLOBAL_MASK(0xff)
|
|
AM_RANGE(0x00, 0x0f) AM_WRITE(nc100_display_memory_start_w)
|
|
AM_RANGE(0x10, 0x13) AM_READWRITE(nc_memory_management_r, nc_memory_management_w)
|
|
AM_RANGE(0x20, 0x20) AM_WRITE(nc200_memory_card_wait_state_w)
|
|
AM_RANGE(0x30, 0x30) AM_WRITE(nc200_uart_control_w)
|
|
AM_RANGE(0x40, 0x40) AM_DEVWRITE("cent_data_out", output_latch_device, write)
|
|
AM_RANGE(0x50, 0x53) AM_WRITE(nc_sound_w)
|
|
AM_RANGE(0x60, 0x60) AM_WRITE(nc_irq_mask_w)
|
|
AM_RANGE(0x70, 0x70) AM_WRITE(nc200_poweroff_control_w)
|
|
AM_RANGE(0x80, 0x80) AM_READ(nc200_printer_status_r)
|
|
AM_RANGE(0x90, 0x90) AM_READWRITE(nc_irq_status_r, nc_irq_status_w)
|
|
AM_RANGE(0xa0, 0xa0) AM_READ(nc200_card_battery_status_r)
|
|
AM_RANGE(0xb0, 0xb9) AM_READ(nc_key_data_in_r)
|
|
AM_RANGE(0xc0, 0xc0) AM_DEVREADWRITE("uart",i8251_device, data_r, data_w)
|
|
AM_RANGE(0xc1, 0xc1) AM_DEVREADWRITE("uart", i8251_device, status_r, control_w)
|
|
AM_RANGE(0xd0, 0xd1) AM_DEVREADWRITE("mc", mc146818_device, read, write)
|
|
AM_RANGE(0xe0, 0xe1) AM_DEVICE("upd765", upd765a_device, map)
|
|
ADDRESS_MAP_END
|
|
|
|
static INPUT_PORTS_START(nc200)
|
|
PORT_START("LINE0")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Shift (Left)") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_MAMEKEY(LSHIFT))
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Shift (Right)") PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT))
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Cursor Left (Red)") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
|
|
PORT_BIT(0x20, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x40, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x80, 0x00, IPT_UNUSED)
|
|
|
|
PORT_START("LINE1")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Function (Yellow)") PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) // 5th row, 1st key on left (where 'fn' is on mac keyboards)
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Control") PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_MAMEKEY(RCONTROL))
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Stop") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(F2))
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
|
|
PORT_BIT(0x10, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x20, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x40, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
|
|
|
|
PORT_START("LINE2")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Caps Lock") PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT))
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Symbol") PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(F3)) // 5th row, 3rd key (where 'Alt' usually stays)
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t')
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
|
|
PORT_BIT(0x20, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
|
|
PORT_BIT(0x80, 0x00, IPT_UNUSED)
|
|
|
|
PORT_START("LINE3")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('\xA3')
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
|
|
PORT_BIT(0x20, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
|
|
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
|
|
|
|
PORT_START("LINE4")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
|
|
PORT_BIT(0x20, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
|
|
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
|
|
|
|
PORT_START("LINE5")
|
|
PORT_BIT(0x01, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x02, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
|
|
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('c') PORT_CHAR('C')
|
|
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('g') PORT_CHAR('G')
|
|
|
|
PORT_START("LINE6")
|
|
PORT_BIT(0x01, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Cursor Down (Blue)") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Del>") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Cursor Right (Green)") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('#') PORT_CHAR('~')
|
|
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
|
|
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
|
|
|
|
PORT_START("LINE7")
|
|
PORT_BIT(0x01, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('\\') PORT_CHAR('|')
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Cursor Up (White)") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Menu") PORT_CODE(KEYCODE_PGUP) PORT_CHAR(UCHAR_MAMEKEY(F4))
|
|
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
|
|
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
|
|
|
|
PORT_START("LINE8")
|
|
PORT_BIT(0x01, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('@')
|
|
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
|
|
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
|
|
|
|
PORT_START("LINE9")
|
|
PORT_BIT(0x01, 0x00, IPT_UNUSED)
|
|
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
|
|
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Del<") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR('8')
|
|
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
|
|
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
|
|
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
|
|
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
|
|
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
|
|
|
|
/* not part of the nc200 keyboard */
|
|
PORT_START("EXTRA")
|
|
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("On Button") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(F1))
|
|
/* pcmcia memory card setting */
|
|
PORT_DIPNAME( 0x02, 0x002, "PCMCIA Memory card write enable")
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off) )
|
|
PORT_DIPSETTING( 0x02, DEF_STR( On) )
|
|
INPUT_PORTS_END
|
|
|
|
/**********************************************************************************************************/
|
|
|
|
static MACHINE_CONFIG_START( nc100, nc_state )
|
|
/* basic machine hardware */
|
|
MCFG_CPU_ADD("maincpu", Z80, /*6000000*/ 4606000) /* Russell Marks says this is more accurate */
|
|
MCFG_CPU_PROGRAM_MAP(nc_map)
|
|
MCFG_CPU_IO_MAP(nc100_io)
|
|
MCFG_QUANTUM_TIME(attotime::from_hz(60))
|
|
|
|
/* video hardware */
|
|
MCFG_SCREEN_ADD("screen", LCD)
|
|
MCFG_SCREEN_REFRESH_RATE(50)
|
|
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
|
|
MCFG_SCREEN_SIZE(480, 64)
|
|
MCFG_SCREEN_VISIBLE_AREA(0, 480-1, 0, 64-1)
|
|
MCFG_SCREEN_UPDATE_DRIVER(nc_state, screen_update_nc)
|
|
|
|
MCFG_PALETTE_LENGTH(NC_NUM_COLOURS)
|
|
MCFG_DEFAULT_LAYOUT(layout_lcd)
|
|
|
|
/* sound hardware */
|
|
MCFG_SPEAKER_STANDARD_MONO("mono")
|
|
MCFG_SOUND_ADD("beep.1", BEEP, 0)
|
|
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
|
|
MCFG_SOUND_ADD("beep.2", BEEP, 0)
|
|
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
|
|
|
|
/* printer */
|
|
MCFG_CENTRONICS_ADD("centronics", centronics_printers, "image")
|
|
MCFG_CENTRONICS_ACK_HANDLER(WRITELINE(nc_state, write_nc100_centronics_ack))
|
|
MCFG_CENTRONICS_BUSY_HANDLER(WRITELINE(nc_state, write_centronics_busy))
|
|
|
|
MCFG_CENTRONICS_OUTPUT_LATCH_ADD("cent_data_out", "centronics")
|
|
|
|
/* uart */
|
|
MCFG_DEVICE_ADD("uart", I8251, 0)
|
|
MCFG_I8251_RXRDY_HANDLER(WRITELINE(nc_state,nc100_rxrdy_callback))
|
|
MCFG_I8251_TXRDY_HANDLER(WRITELINE(nc_state,nc100_txrdy_callback))
|
|
|
|
MCFG_DEVICE_ADD("uart_clock", CLOCK, 19200)
|
|
MCFG_CLOCK_SIGNAL_HANDLER(WRITELINE(nc_state, write_uart_clock))
|
|
|
|
/* rtc */
|
|
MCFG_RP5C01_ADD("rtc", XTAL_32_768kHz, rtc_intf)
|
|
|
|
/* cartridge */
|
|
MCFG_CARTSLOT_ADD("cart")
|
|
MCFG_CARTSLOT_EXTENSION_LIST("crd,card")
|
|
MCFG_CARTSLOT_NOT_MANDATORY
|
|
MCFG_CARTSLOT_LOAD(nc_state,nc_pcmcia_card)
|
|
MCFG_CARTSLOT_UNLOAD(nc_state,nc_pcmcia_card)
|
|
|
|
/* internal ram */
|
|
MCFG_RAM_ADD(RAM_TAG)
|
|
MCFG_RAM_DEFAULT_SIZE("64K")
|
|
MCFG_NVRAM_HANDLER(nc)
|
|
|
|
/* dummy timer */
|
|
MCFG_TIMER_DRIVER_ADD_PERIODIC("dummy_timer", nc_state, dummy_timer_callback, attotime::from_hz(50))
|
|
MACHINE_CONFIG_END
|
|
|
|
static const floppy_format_type ibmpc_floppy_formats[] = {
|
|
FLOPPY_PC_FORMAT,
|
|
FLOPPY_MFI_FORMAT,
|
|
NULL
|
|
};
|
|
|
|
static SLOT_INTERFACE_START( ibmpc_floppies )
|
|
SLOT_INTERFACE( "525dd", FLOPPY_525_DD )
|
|
SLOT_INTERFACE_END
|
|
|
|
static MACHINE_CONFIG_DERIVED( nc200, nc100 )
|
|
|
|
MCFG_CPU_MODIFY( "maincpu" )
|
|
MCFG_CPU_IO_MAP(nc200_io)
|
|
|
|
MCFG_MACHINE_START_OVERRIDE(nc_state, nc200 )
|
|
MCFG_MACHINE_RESET_OVERRIDE(nc_state, nc200 )
|
|
|
|
/* video hardware */
|
|
MCFG_SCREEN_MODIFY("screen")
|
|
MCFG_SCREEN_SIZE(NC200_SCREEN_WIDTH, NC200_SCREEN_HEIGHT)
|
|
MCFG_SCREEN_VISIBLE_AREA(0, NC200_SCREEN_WIDTH-1, 0, NC200_SCREEN_HEIGHT-1)
|
|
MCFG_PALETTE_LENGTH(NC200_NUM_COLOURS)
|
|
|
|
/* printer */
|
|
MCFG_DEVICE_MODIFY("centronics")
|
|
MCFG_CENTRONICS_ACK_HANDLER(WRITELINE(nc_state, write_nc200_centronics_ack))
|
|
|
|
/* uart */
|
|
MCFG_DEVICE_MODIFY("uart")
|
|
MCFG_I8251_RXRDY_HANDLER(WRITELINE(nc_state,nc200_rxrdy_callback))
|
|
MCFG_I8251_TXRDY_HANDLER(WRITELINE(nc_state,nc200_txrdy_callback))
|
|
|
|
/* no rtc */
|
|
MCFG_DEVICE_REMOVE("rtc")
|
|
|
|
MCFG_UPD765A_ADD("upd765", true, true)
|
|
MCFG_FLOPPY_DRIVE_ADD("upd765:0", ibmpc_floppies, "525dd", ibmpc_floppy_formats)
|
|
MCFG_FLOPPY_DRIVE_ADD("upd765:1", ibmpc_floppies, "525dd", ibmpc_floppy_formats)
|
|
|
|
MCFG_MC146818_ADD( "mc", XTAL_4_194304Mhz )
|
|
|
|
/* internal ram */
|
|
MCFG_RAM_MODIFY(RAM_TAG)
|
|
MCFG_RAM_DEFAULT_SIZE("128K")
|
|
|
|
MACHINE_CONFIG_END
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
Game driver(s)
|
|
|
|
***************************************************************************/
|
|
|
|
ROM_START(nc100)
|
|
ROM_REGION(((64*1024)+(256*1024)), "maincpu",0)
|
|
ROM_SYSTEM_BIOS(0, "106", "ROM v1.06")
|
|
ROMX_LOAD("nc100a.rom", 0x010000, 0x040000, CRC(849884f9) SHA1(ff030dd334ca867d620ee4a94b142ef0d93b69b6), ROM_BIOS(1))
|
|
ROM_SYSTEM_BIOS(1, "102dk", "ROM v1.02 Danish")
|
|
ROMX_LOAD("nc100_dk_a1.rom", 0x010000, 0x040000, CRC(ebb54923) SHA1(30321011384c5e10204b9a837430c36fc63580d2), ROM_BIOS(2))
|
|
ROM_SYSTEM_BIOS(2, "102de", "ROM v1.02 German")
|
|
ROMX_LOAD("nc100_de_a1.rom", 0x010000, 0x040000, CRC(bd9ce223) SHA1(2efb26911832bf1456d76d2508e24c0733dc216d), ROM_BIOS(3))
|
|
ROM_SYSTEM_BIOS(3, "100", "ROM v1.00")
|
|
ROMX_LOAD("nc100.rom", 0x010000, 0x040000, CRC(a699eca3) SHA1(ce217d5a298b959ccc3d7bc5c93b1dba043f1339), ROM_BIOS(4))
|
|
ROM_END
|
|
|
|
|
|
ROM_START(dw225)
|
|
ROM_REGION(((64*1024)+(512*1024)), "maincpu",0)
|
|
ROM_LOAD("dr (1.06).ic303", 0x010000, 0x080000, CRC(fcf2f7bd) SHA1(a69951618b24e97154cb4284d215cbf4aa9fb34f))
|
|
ROM_END
|
|
|
|
|
|
ROM_START(nc150)
|
|
ROM_REGION(((64*1024)+(512*1024)), "maincpu",0)
|
|
ROM_SYSTEM_BIOS(0, "b2", "French B2")
|
|
ROMX_LOAD("nc150_fr_b2.rom", 0x010000, 0x080000, CRC(be442d14) SHA1(f141d409dc72dc1e6662c21a147231c4df3be6b8), ROM_BIOS(1)) /* French */
|
|
ROM_SYSTEM_BIOS(1, "b1", "Italian B1")
|
|
ROMX_LOAD("nc150_it_b1.rom", 0x010000, 0x080000, CRC(1b2fe2fd) SHA1(67eb6bce0b0d4668401d9c8f5a900dc6bd135c21), ROM_BIOS(2)) /* Italian */
|
|
ROM_END
|
|
|
|
|
|
ROM_START(nc200)
|
|
ROM_REGION(((64*1024)+(512*1024)), "maincpu",0)
|
|
ROM_LOAD("nc200.rom", 0x010000, 0x080000, CRC(bb8180e7) SHA1(fb5c93b0a3e199202c6a12548d2617f7a09bae47))
|
|
ROM_END
|
|
|
|
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */
|
|
COMP( 1992, nc100, 0, 0, nc100, nc100, nc_state, nc, "Amstrad plc", "NC100", 0 )
|
|
COMP( 1992, dw225, nc100, 0, nc100, nc100, nc_state, nc, "NTS Computer Systems", "DreamWriter 225", 0 )
|
|
COMP( 1992, nc150, nc100, 0, nc100, nc100, nc_state, nc, "Amstrad plc", "NC150", 0 )
|
|
COMP( 1993, nc200, 0, 0, nc200, nc200, nc_state, nc, "Amstrad plc", "NC200", GAME_NOT_WORKING ) // boot hangs while checking the MC146818 UIP (update in progress) bit
|