// license:GPL-2.0+ // copyright-holders:Wilbert Pol, Kevin Thacker /****************************************************************************** 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 "includes/nc.h" #include "cpu/z80/z80.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 "rendlay.h" #include "screen.h" #include "speaker.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 */ /* 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); uint8_t *ptr; 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: { mem_bank &= m_membank_rom_mask; ptr = (memregion("maincpu")->base() + 0x010000) + (mem_bank << 14); membank(bank1)->set_base(ptr); space.nop_write((bank * 0x4000), (bank * 0x4000) + 0x3fff); LOG(("BANK %d: ROM %d\n",bank,mem_bank)); } break; /* internal RAM */ case 1: { mem_bank &= m_membank_internal_ram_mask; ptr = m_ram->pointer() + (mem_bank << 14); membank(bank1)->set_base(ptr); membank(bank5)->set_base(ptr); 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) { mem_bank &= m_membank_card_ram_mask; ptr = m_card_ram->base() + (mem_bank << 14); membank(bank1)->set_base(ptr); /* write enabled? */ if (ioport("EXTRA")->read() & 0x02) { /* yes */ membank(bank5)->set_base(ptr); 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); } 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; } void nc_state::nc_map(address_map &map) { map(0x0000, 0x3fff).bankr("bank1").bankw("bank5"); map(0x4000, 0x7fff).bankr("bank2").bankw("bank6"); map(0x8000, 0xbfff).bankr("bank3").bankw("bank7"); map(0xc000, 0xffff).bankr("bank4").bankw("bank8"); } 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 = nullptr; 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_clock(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(); } 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; std::string region_tag; m_card_ram = memregion(region_tag.assign(m_card->tag()).append(GENERIC_ROM_REGION_TAG).c_str()); if (m_card_ram) m_card_size = m_card_ram->bytes(); else m_card_size = 0; /* 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)); m_nvram->set_base(m_ram->pointer(), m_ram->size()); } 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)); } void nc_state::nc100_io(address_map &map) { map.global_mask(0xff); map.unmap_value_high(); map(0x00, 0x0f).w(this, FUNC(nc_state::nc100_display_memory_start_w)); map(0x10, 0x13).rw(this, FUNC(nc_state::nc_memory_management_r), FUNC(nc_state::nc_memory_management_w)); map(0x20, 0x20).w(this, FUNC(nc_state::nc100_memory_card_wait_state_w)); map(0x30, 0x30).w(this, FUNC(nc_state::nc100_uart_control_w)); map(0x40, 0x40).w("cent_data_out", FUNC(output_latch_device::write)); map(0x50, 0x53).w(this, FUNC(nc_state::nc_sound_w)); map(0x60, 0x60).w(this, FUNC(nc_state::nc_irq_mask_w)); map(0x70, 0x70).w(this, FUNC(nc_state::nc100_poweroff_control_w)); map(0x90, 0x90).rw(this, FUNC(nc_state::nc_irq_status_r), FUNC(nc_state::nc_irq_status_w)); map(0x91, 0x9f).r(this, FUNC(nc_state::nc_irq_status_r)); map(0xa0, 0xaf).r(this, FUNC(nc_state::nc100_card_battery_status_r)); map(0xb0, 0xb9).r(this, FUNC(nc_state::nc_key_data_in_r)); map(0xc0, 0xc0).rw(m_uart, FUNC(i8251_device::data_r), FUNC(i8251_device::data_w)); map(0xc1, 0xc1).rw(m_uart, FUNC(i8251_device::status_r), FUNC(i8251_device::control_w)); map(0xd0, 0xdf).rw("rtc", FUNC(tc8521_device::read), FUNC(tc8521_device::write)); } /* 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(0xA3) 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) { // m_nc200_uart_interrupt_irq &=~(1<<0); // // if (state) // { // m_nc200_uart_interrupt_irq |=(1<<0); // } // // nc200_refresh_uart_interrupt(); } 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(); } WRITE_LINE_MEMBER( nc_state::nc200_fdc_interrupt ) { #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; std::string region_tag; m_card_ram = memregion(region_tag.assign(m_card->tag()).append(GENERIC_ROM_REGION_TAG).c_str()); if (m_card_ram) m_card_size = m_card_ram->bytes(); else m_card_size = 0; /* 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)); m_nvram->set_base(m_ram->pointer(), m_ram->size()); } /* 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_t 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("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); } void nc_state::nc200_io(address_map &map) { map.global_mask(0xff); map(0x00, 0x0f).w(this, FUNC(nc_state::nc100_display_memory_start_w)); map(0x10, 0x13).rw(this, FUNC(nc_state::nc_memory_management_r), FUNC(nc_state::nc_memory_management_w)); map(0x20, 0x20).w(this, FUNC(nc_state::nc200_memory_card_wait_state_w)); map(0x30, 0x30).w(this, FUNC(nc_state::nc200_uart_control_w)); map(0x40, 0x40).w("cent_data_out", FUNC(output_latch_device::write)); map(0x50, 0x53).w(this, FUNC(nc_state::nc_sound_w)); map(0x60, 0x60).w(this, FUNC(nc_state::nc_irq_mask_w)); map(0x70, 0x70).w(this, FUNC(nc_state::nc200_poweroff_control_w)); map(0x80, 0x80).r(this, FUNC(nc_state::nc200_printer_status_r)); map(0x90, 0x90).rw(this, FUNC(nc_state::nc_irq_status_r), FUNC(nc_state::nc_irq_status_w)); map(0xa0, 0xa0).r(this, FUNC(nc_state::nc200_card_battery_status_r)); map(0xb0, 0xb9).r(this, FUNC(nc_state::nc_key_data_in_r)); map(0xc0, 0xc0).rw(m_uart, FUNC(i8251_device::data_r), FUNC(i8251_device::data_w)); map(0xc1, 0xc1).rw(m_uart, FUNC(i8251_device::status_r), FUNC(i8251_device::control_w)); map(0xd0, 0xd1).rw("mc", FUNC(mc146818_device::read), FUNC(mc146818_device::write)); map(0xe0, 0xe1).m("upd765", FUNC(upd765a_device::map)); } 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(0xA3) 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 /**********************************************************************************************************/ MACHINE_CONFIG_START(nc_state::nc100) /* 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_SCREEN_PALETTE("palette") MCFG_PALETTE_ADD("palette", NC_NUM_COLOURS) MCFG_PALETTE_INIT_OWNER(nc_state, nc) 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_devices, "printer") 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_DEVICE_ADD("rtc", TC8521, XTAL(32'768)) MCFG_RP5C01_OUT_ALARM_CB(WRITELINE(nc_state, nc100_tc8521_alarm_callback)) /* cartridge */ MCFG_GENERIC_CARTSLOT_ADD("cardslot", generic_plain_slot, nullptr) MCFG_GENERIC_LOAD(nc_state, nc_pcmcia_card) MCFG_GENERIC_UNLOAD(nc_state, nc_pcmcia_card) /* internal ram */ MCFG_RAM_ADD(RAM_TAG) MCFG_RAM_DEFAULT_SIZE("64K") MCFG_NVRAM_ADD_NO_FILL("nvram") /* 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, nullptr }; static void ibmpc_floppies(device_slot_interface &device) { device.option_add("525dd", FLOPPY_525_DD); } MACHINE_CONFIG_START(nc_state::nc200) nc100(config); 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_MODIFY("palette") MCFG_PALETTE_ENTRIES(NC200_NUM_COLOURS) MCFG_PALETTE_INIT_OWNER(nc_state, nc) /* 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_UPD765_INTRQ_CALLBACK(WRITELINE(nc_state, nc200_fdc_interrupt)) 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'194'304) ) /* 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 STATE 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", MACHINE_NOT_WORKING ) // boot hangs while checking the MC146818 UIP (update in progress) bit