diff options
Diffstat (limited to 'src/mame/drivers/newbrain.c')
-rw-r--r-- | src/mame/drivers/newbrain.c | 1493 |
1 files changed, 1493 insertions, 0 deletions
diff --git a/src/mame/drivers/newbrain.c b/src/mame/drivers/newbrain.c new file mode 100644 index 00000000000..84699034a75 --- /dev/null +++ b/src/mame/drivers/newbrain.c @@ -0,0 +1,1493 @@ +// license:BSD-3-Clause +// copyright-holders:Curt Coder +#include "includes/newbrain.h" +#include "formats/mfi_dsk.h" + +/* + + NewBrain + Grundy Business Systems Ltd. + + 32K RAM + 28K ROM + + Z80 @ 2MHz + COP420 @ 2MHz + + Z80 @ 4MHz (416): INT/NMI=+5V, WAIT=EXTBUSRQ|BUSAKD, RESET=_FDC RESET, + NEC 765AC @ 4 MHz (418) + MC6850 ACIA (459) + Z80CTC (458) + ADC0809 (427) + DAC0808 (461) + + Models according to the Software Technical Manual: + + Model M: 'Page Register', Expansion Port onto Z80 bus, Video, ACIA/CTC, User Port + Model A: Expansion Port, Video, no User Port but has software driver serial port - s/w Printer, s/w V24 + Model V: ACIA/CTC, User Port + +*/ + +/* + + TODO: + + - bitmapped graphics mode + - COP420 microbus access + - escape key is missing + - CP/M 2.2 ROMs + - floppy disc controller + - convert FDC into a device + - convert EIM into a device + + - Micropage ROM/RAM card + - Z80 PIO board + - peripheral (PI) box + - sound card + +*/ + +void newbrain_state::check_interrupt() +{ + int level = (!m_clkint || !m_copint) ? ASSERT_LINE : CLEAR_LINE; + + m_maincpu->set_input_line(INPUT_LINE_IRQ0, level); +} + +/* Bank Switching */ + +#define memory_install_unmapped(program, bank, bank_start, bank_end) \ + program.unmap_readwrite(bank_start, bank_end); + +#define memory_install_rom_helper(program, bank, bank_start, bank_end) \ + program.install_read_bank(bank_start, bank_end, bank); \ + program.unmap_write(bank_start, bank_end); + +#define memory_install_ram_helper(program, bank, bank_start, bank_end) \ + program.install_readwrite_bank(bank_start, bank_end, bank); + +void newbrain_eim_state::bankswitch() +{ + address_space &program = m_maincpu->space(AS_PROGRAM); + int bank; + + for (bank = 1; bank < 9; bank++) + { + int page = (m_a16 << 3) | bank; + UINT8 data = ~m_pr[page]; + int ch = (data >> 3) & 0x03; + int eim_bank = data & 0x07; + + UINT16 eim_bank_start = eim_bank * 0x2000; + UINT16 bank_start = (bank - 1) * 0x2000; + UINT16 bank_end = bank_start + 0x1fff; + char bank_name[10]; + sprintf(bank_name,"bank%d",bank); + switch (ch) + { + case 0: + /* ROM */ + memory_install_rom_helper(program, bank_name, bank_start, bank_end); + membank(bank_name)->configure_entry(0, m_eim_rom->base() + eim_bank_start); + break; + + case 2: + /* RAM */ + memory_install_ram_helper(program, bank_name, bank_start, bank_end); + membank(bank_name)->configure_entry(0, m_eim_ram + eim_bank_start); + break; + + default: + logerror("Invalid memory channel %u!\n", ch); + break; + } + } +} + +void newbrain_state::bankswitch() +{ + address_space &program = m_maincpu->space(AS_PROGRAM); + int bank; + + for (bank = 1; bank < 9; bank++) + { + UINT16 bank_start = (bank - 1) * 0x2000; + UINT16 bank_end = bank_start + 0x1fff; + char bank_name[10]; + sprintf(bank_name,"bank%d",bank); + + if (m_pwrup) + { + /* all banks point to ROM at 0xe000 */ + memory_install_rom_helper(program, bank_name, bank_start, bank_end); + membank(bank_name)->configure_entry(0, m_rom->base() + 0xe000); + } + else + { + membank(bank_name)->configure_entry(0, m_rom->base() + bank_start); + + if (bank < 5) + { + /* bank is RAM */ + memory_install_ram_helper(program, bank_name, bank_start, bank_end); + } + else if (bank == 5) + { + /* 0x8000-0x9fff */ + if (m_eim_rom) + { + /* expansion interface ROM */ + memory_install_rom_helper(program, bank_name, bank_start, bank_end); + membank(bank_name)->configure_entry(0, m_eim_rom->base() + 0x4000); + } + else + { + /* mirror of 0xa000-0xbfff */ + if (m_rom->base()[0xa001] == 0) + { + /* unmapped on the M model */ + memory_install_unmapped(program, bank_name, bank_start, bank_end); + } + else + { + /* bank is ROM on the A model */ + memory_install_rom_helper(program, bank_name, bank_start, bank_end); + } + + membank(bank_name)->configure_entry(0, m_rom->base() + 0xa000); + } + } + else if (bank == 6) + { + /* 0xa000-0xbfff */ + if (m_rom->base()[0xa001] == 0) + { + /* unmapped on the M model */ + memory_install_unmapped(program, bank_name, bank_start, bank_end); + } + else + { + /* bank is ROM on the A model */ + memory_install_rom_helper(program, bank_name, bank_start, bank_end); + } + } + else + { + /* bank is ROM */ + memory_install_rom_helper(program, bank_name, bank_start, bank_end); + } + } + + membank(bank_name)->set_entry(0); + } +} + +/* Enable/Status */ + +WRITE8_MEMBER( newbrain_state::enrg1_w ) +{ + /* + + bit signal description + + 0 _CLK enable frame frequency clock interrupts + 1 enable user interrupt + 2 TVP enable video display + 3 enable V24 + 4 V24 Select Receive Bit 0 + 5 V24 Select Receive Bit 1 + 6 V24 Select Transmit Bit 0 + 7 V24 Select Transmit Bit 1 + + */ + + m_enrg1 = data; +} + +WRITE8_MEMBER( newbrain_state::a_enrg1_w ) +{ + /* + + bit signal description + + 0 _CLK Clock Enable + 1 + 2 TVP TV Enable + 3 IOPOWER + 4 _CTS Clear to Send V24 + 5 DO Transmit Data V24 + 6 + 7 PO Transmit Data Printer + + */ + + m_enrg1 = data; +} + +READ8_MEMBER( newbrain_state::ust_r ) +{ + /* + + bit signal description + + 0 variable + 1 variable + 2 MNS mains present + 3 _USRINT0 user status + 4 _USRINT user interrupt + 5 _CLKINT clock interrupt + 6 _ACINT ACIA interrupt + 7 _COPINT COP interrupt + + */ + + UINT8 data = (m_copint << 7) | (m_aciaint << 6) | (m_clkint << 5) | (m_userint << 4) | 0x04; + + switch ((m_enrg1 & NEWBRAIN_ENRG1_UST_BIT_0_MASK) >> 6) + { + case 0: + // excess, 1=24, 0=4 + if (m_tvctl & NEWBRAIN_VIDEO_32_40) + { + data |= 0x01; + } + break; + + case 1: + // characters per line, 1=40, 0=80 + if (m_tvctl & NEWBRAIN_VIDEO_80L) + { + data |= 0x01; + } + break; + + case 2: + // tape in + break; + + case 3: + // calling indicator + break; + } + + switch ((m_enrg1 & NEWBRAIN_ENRG1_UST_BIT_1_MASK) >> 4) + { + case 0: + // PWRUP, if set indicates that power is supplied to Z80 and memory + if (m_pwrup) + { + data |= 0x02; + } + break; + + case 1: + // TVCNSL, if set then processor has video device as primary console output + if (m_tvcnsl) + { + data |= 0x02; + } + break; + + case 2: + // _BEE, if set then processor is Model A type + if (m_bee) + { + data |= 0x02; + } + break; + + case 3: + // _CALLIND, calling indicator + data |= 0x02; + break; + } + + return data; +} + +READ8_MEMBER( newbrain_state::a_ust_r ) +{ + /* + + bit signal description + + 0 +5V + 1 PWRUP + 2 + 3 + 4 + 5 _CLKINT clock interrupt + 6 + 7 _COPINT COP interrupt + + */ + + return (m_copint << 7) | (m_clkint << 5) | (m_pwrup << 1) | 0x01; +} + +READ8_MEMBER( newbrain_state::user_r ) +{ + /* + + bit signal description + + 0 RDDK Received Data V24 + 1 _CTSD _Clear to Send V24 + 2 + 3 + 4 + 5 TPIN Tape in + 6 + 7 _CTSP _Clear to Send Printer + + */ + + m_user = 0; + + return 0xff; +} + +WRITE8_MEMBER( newbrain_state::user_w ) +{ + m_user = data; +} + +/* Interrupts */ + +READ8_MEMBER( newbrain_state::clclk_r ) +{ + m_clkint = 1; + check_interrupt(); + + return 0xff; +} + +WRITE8_MEMBER( newbrain_state::clclk_w ) +{ + m_clkint = 1; + check_interrupt(); +} + +READ8_MEMBER( newbrain_state::clusr_r ) +{ + m_userint = 1; + + return 0xff; +} + +WRITE8_MEMBER( newbrain_state::clusr_w ) +{ + m_userint = 1; +} + +/* COP420 */ + +READ8_MEMBER( newbrain_state::cop_l_r ) +{ + // connected to the Z80 data bus + return m_cop_bus; +} + +WRITE8_MEMBER( newbrain_state::cop_l_w ) +{ + // connected to the Z80 data bus + m_cop_bus = data; +} + +WRITE8_MEMBER( newbrain_state::cop_g_w ) +{ + /* + + bit description + + G0 _COPINT + G1 _TM1 + G2 not connected + G3 _TM2 + + */ + + m_copint = BIT(data, 0); + check_interrupt(); + + /* tape motor enable */ + + m_cassette1->change_state(BIT(data,1) ? CASSETTE_MOTOR_DISABLED : CASSETTE_MOTOR_ENABLED, CASSETTE_MASK_MOTOR); + m_cassette2->change_state(BIT(data,3) ? CASSETTE_MOTOR_DISABLED : CASSETTE_MOTOR_ENABLED, CASSETTE_MASK_MOTOR); +} + +READ8_MEMBER( newbrain_state::cop_g_r ) +{ + /* + + bit description + + G0 not connected + G1 K9 + G2 K7 + G3 K3 + + */ + + return (BIT(m_keydata, 3) << 3) | (BIT(m_keydata, 0) << 2) | (BIT(m_keydata, 1) << 1); +} + +WRITE8_MEMBER( newbrain_state::cop_d_w ) +{ + /* + bit description + + D0 inverted to K4 -> CD4024 pin 2 (reset) + D1 TDO + D2 inverted to K6 -> CD4024 pin 1 (clock), CD4076 pin 7 (clock), inverted to DS8881 pin 3 (enable) + D3 not connected + + */ + + /* keyboard row reset */ + + if (!BIT(data, 0)) + { + m_keylatch = 0; + } + + /* tape data output */ + + m_cop_tdo = BIT(data, 1); + + m_cassette1->output(m_cop_tdo ? -1.0 : +1.0); + m_cassette2->output(m_cop_tdo ? -1.0 : +1.0); + + /* keyboard and display clock */ + + if (!BIT(data, 2)) + { + m_keylatch++; + + if (m_keylatch == 16) + { + m_keylatch = 0; + } + + m_keydata = m_key_row[m_keylatch]->read(); + + output_set_digit_value(m_keylatch, m_segment_data[m_keylatch]); + } +} + +READ8_MEMBER( newbrain_state::cop_in_r ) +{ + /* + + bit description + + IN0 K8 + IN1 _RD + IN2 _COP + IN3 _WR + + */ + + return (m_cop_wr << 3) | (m_cop_access << 2) | (m_cop_rd << 1) | BIT(m_keydata, 2); +} + +WRITE_LINE_MEMBER( newbrain_state::cop_so_w ) +{ + // connected to K1 + m_cop_so = state; +} + +WRITE_LINE_MEMBER( newbrain_state::cop_sk_w ) +{ + // connected to K2 + m_segment_data[m_keylatch] >>= 1; + m_segment_data[m_keylatch] = (m_cop_so << 15) | (m_segment_data[m_keylatch] & 0x7fff); +} + +READ_LINE_MEMBER( newbrain_state::cop_si_r ) +{ + // connected to TDI + m_cop_tdi = (((m_cassette1)->input() > +1.0) || ((m_cassette2)->input() > +1.0)) ^ m_cop_tdo; + + return m_cop_tdi; +} + +/* Video */ + +void newbrain_state::tvram_w(UINT8 data, int a6) +{ + /* latch video address counter bits A5-A0 */ + m_tvram = (m_tvctl & NEWBRAIN_VIDEO_80L) ? 0x04 : 0x02; + + /* latch video address counter bit A6 */ + m_tvram |= a6 << 6; + + /* latch data to video address counter bits A14-A7 */ + m_tvram = (data << 7); +} + +READ8_MEMBER( newbrain_state::tvl_r ) +{ + UINT8 data = 0xff; + + tvram_w(data, !offset); + + return data; +} + +WRITE8_MEMBER( newbrain_state::tvl_w ) +{ + tvram_w(data, !offset); +} + +WRITE8_MEMBER( newbrain_state::tvctl_w ) +{ + /* + + bit signal description + + 0 RV 1 reverses video over entire field, ie. black on white + 1 FS 0 generates 128 characters and 128 reverse field characters from 8 bit character code. 1 generates 256 characters from 8 bit character code + 2 32/_40 0 generates 320 or 640 horizontal dots in pixel graphics mode. 1 generates 256 or 512 horizontal dots in pixel graphics mode + 3 UCR 0 selects 256 characters expressed in an 8x10 matrix, and 25 lines (max) displayed. 1 selects 256 characters in an 8x8 matrix, and 31 lines (max) displayed + 4 + 5 + 6 80L 0 selects 40 character line length. 1 selects 80 character line length + 7 + + */ + + m_tvctl = data; +} + +/* Disc Controller */ + +WRITE8_MEMBER( newbrain_eim_state::fdc_auxiliary_w ) +{ + /* + + bit description + + 0 MOTON + 1 765 RESET + 2 TC + 3 + 4 + 5 PA15 + 6 + 7 + + */ + + m_floppy->mon_w(!BIT(data, 0)); + + if(BIT(data, 1)) + m_fdc->reset(); + + m_fdc->tc_w(BIT(data, 2)); +} + +READ8_MEMBER( newbrain_eim_state::fdc_control_r ) +{ + /* + + bit description + + 0 + 1 + 2 + 3 + 4 + 5 FDC INT + 6 PAGING + 7 FDC ATT + + */ + + return (m_fdc_att << 7) | (m_paging << 6) | (m_fdc_int << 5); +} + +READ8_MEMBER( newbrain_eim_state::ust2_r ) +{ + /* + + bit description + + 0 RDDK (V24 RxD) + 1 _CTSD (V24 Clear to Send) + 2 + 3 + 4 + 5 TPIN + 6 + 7 _CTSP (Printer Clear to Send) + + */ + + return 0; +} + +#define NEWBRAIN_COPCMD_NULLCOM 0xd0 +#define NEWBRAIN_COPCMD_DISPCOM 0xa0 +//#define NEWBRAIN_COPCMD_TIMCOM 0x +#define NEWBRAIN_COPCMD_PDNCOM 0xb8 +#define NEWBRAIN_COPCMD_TAPECOM 0x80 + +#define NEWBRAIN_COP_TAPE_RECORD 0x00 +#define NEWBRAIN_COP_TAPE_PLAYBK 0x04 +#define NEWBRAIN_COP_TAPE_MOTOR1 0x08 +#define NEWBRAIN_COP_TAPE_MOTOR2 0x02 + +#define NEWBRAIN_COP_TIMER0 0x01 + +#define NEWBRAIN_COP_NO_DATA 0x01 +#define NEWBRAIN_COP_BREAK_PRESSED 0x02 + +#define NEWBRAIN_COP_REGINT 0x00 +/*#define NEWBRAIN_COP_CASSERR 0x +#define NEWBRAIN_COP_CASSIN 0x +#define NEWBRAIN_COP_KBD 0x +#define NEWBRAIN_COP_CASSOUT 0x*/ + +enum +{ + NEWBRAIN_COP_STATE_COMMAND = 0, + NEWBRAIN_COP_STATE_DATA +}; + + +READ8_MEMBER( newbrain_state::cop_r ) +{ + m_copint = 1; + check_interrupt(); + + return m_copdata; +} + +WRITE8_MEMBER( newbrain_state::cop_w ) +{ + m_copdata = data; + + switch (m_copstate) + { + case NEWBRAIN_COP_STATE_COMMAND: + logerror("COP command %02x\n", data); + + switch (data) + { + case NEWBRAIN_COPCMD_NULLCOM: + break; + + case NEWBRAIN_COPCMD_DISPCOM: + m_copregint = 0; + m_copbytes = 18; + m_copstate = NEWBRAIN_COP_STATE_DATA; + + m_copdata = NEWBRAIN_COP_NO_DATA; + m_copint = 0; + check_interrupt(); + + break; + +#if 0 + case NEWBRAIN_COPCMD_TIMCOM: + m_copregint = 0; + m_copbytes = 6; + m_copstate = NEWBRAIN_COP_STATE_DATA; + break; +#endif + case NEWBRAIN_COPCMD_PDNCOM: + /* power down */ + m_copregint = 0; + break; + + default: + if (data & NEWBRAIN_COPCMD_TAPECOM) + { + m_copregint = 0; + } + } + break; + + case NEWBRAIN_COP_STATE_DATA: + logerror("COP data %02x\n", data); + m_copbytes--; + + if (m_copbytes == 0) + { + m_copstate = NEWBRAIN_COP_STATE_COMMAND; + m_copregint = 1; + } + + m_copdata = NEWBRAIN_COP_NO_DATA; + m_copint = 0; + check_interrupt(); + + break; + } +} + +TIMER_DEVICE_CALLBACK_MEMBER(newbrain_state::cop_regint_tick) +{ + if (m_copregint) + { + logerror("COP REGINT\n"); + m_copint = 0; + check_interrupt(); + } +} + +/* Expansion Interface Module */ + +WRITE8_MEMBER( newbrain_eim_state::enrg2_w ) +{ + /* + + bit signal description + + 0 _USERP 0 enables user data bus interrupt and also parallel latched data output (or centronics printer) interrupt + 1 ANP 1 enables ADC conversion complete interrupt and also calling indicator interrupt + 2 MLTMD 1 enables serial receive clock into multiplier input of DAC and signals data terminal not ready + 3 MSPD 1 enables 50K Baud serial data rate to be obtained ie. CTC input clock of 800 kHz. 0 selects xxx.692 kHz + 4 ENOR 1 enables serial receive clock to sound output summer, and also selects serial input from the printer port. 0 selects serial input from the comms port + 5 ANSW 1 enables second bank of 4 analogue inputs (voltage, non-ratiometric), ie. ch4-7, and enabled sound output, 0 selects ch03 + 6 ENOT 1 enables serial transmit clock to sound ouput summer, and also selects serial output to the printer port. 0 selects serial output to the comms port + 7 9th output bit for centronics printer port + + */ + + m_enrg2 = data; +} + +WRITE8_MEMBER( newbrain_eim_state::pr_w ) +{ + /* + + bit signal description + + 0 HP0 + 1 HP1 + 2 HP2 + 3 HP3 + 4 HP4 + 5 HP5 + 6 HP6 + 7 HP11 + + HP0-HP2 are decoded to _ROM0..._ROM7 signals + HP3-HP4 are decoded to _CH0..._CH3 signals + + */ + + int page = (BIT(offset, 12) >> 9) | (BIT(offset, 15) >> 13) | (BIT(offset, 14) >> 13) | (BIT(offset, 13) >> 13); + int bank = (BIT(offset, 11) >> 3) | (data & 0x7f); + + m_pr[page] = bank; + + bankswitch(); +} + +READ8_MEMBER( newbrain_eim_state::user_r ) +{ + m_user = 0xff; + + return 0xff; +} + +WRITE8_MEMBER( newbrain_eim_state::user_w ) +{ + m_user = data; +} + +READ8_MEMBER( newbrain_eim_state::anout_r ) +{ + return 0xff; +} + +WRITE8_MEMBER( newbrain_eim_state::anout_w ) +{ +} + +READ8_MEMBER( newbrain_eim_state::anin_r ) +{ +// int channel = offset & 0x03; + + return 0; +} + +WRITE8_MEMBER( newbrain_eim_state::anio_w ) +{ +// int channel = offset & 0x03; +} + +READ8_MEMBER( newbrain_eim_state::st0_r ) +{ + /* + + bit signal description + + 0 fixed at 1 - indicates excess of 24 or 48, obsolete + 1 PWRUP 1 indicates power up from 'cold' - necessary in battery machines with power switching + 2 1 indicates analogue or calling indicator interrupts + 3 _USRINT0 0 indicates centronics printer (latched output data) port interrupt + 4 _USRINT 0 indicates parallel data bus port interrupt + 5 _CLKINT 0 indicates frame frequency clock interrupt + 6 _ACINT 0 indicates ACIA interrupt + 7 _COPINT 0 indicates interrupt from micro-controller COP420M + + */ + + return (m_copint << 7) | (m_aciaint << 6) | (m_clkint << 5) | (m_userint << 4) | (m_userint0 << 3) | (m_pwrup) << 1 | 0x01; +} + +READ8_MEMBER( newbrain_eim_state::st1_r ) +{ + /* + + bit signal description + + 0 + 1 + 2 N/_RV 1 selects normal video on power up (white on black), 0 selects reversed video (appears as D0 on the first 200 EI's) + 3 ANCH 1 indicates power is being taken from the mains supply + 4 40/_80 1 indicates that 40 column video is selected on power up. 0 selects 80 column video + 5 + 6 TVCNSL 1 indicates that a video display is required on power up + 7 + + */ + + return (m_tvcnsl << 6) | 0x10 | 0x08 | 0x04; +} + +READ8_MEMBER( newbrain_eim_state::st2_r ) +{ + /* + + bit signal description + + 0 received serial data from communications port + 1 0 indicates 'clear-to-send' condition at communications port + 2 + 3 + 4 + 5 logic level tape input + 6 + 7 0 indicates 'clear-to-send' condition at printer port + + */ + + return 0; +} + +READ8_MEMBER( newbrain_eim_state::usbs_r ) +{ + return 0xff; +} + +WRITE8_MEMBER( newbrain_eim_state::usbs_w ) +{ +} + +WRITE8_MEMBER( newbrain_eim_state::paging_w ) +{ + if (BIT(offset, 8)) + { + // expansion interface module + + /* + + bit signal description + + 0 PG 1 enables paging circuits + 1 WPL unused + 2 A16 1 sets local A16 to 1 (ie. causes second set of 8 page registers to select addressed memory) + 3 _MPM 0 selects multi-processing mode. among other effects this extends the page registers from 8 to 12 bits in length + 4 HISLT 1 isolates the local machine. this is used in multi-processing mode + 5 + 6 + 7 + + */ + + m_paging = BIT(data, 0); + m_a16 = BIT(data, 2); + m_mpm = BIT(data, 3); + } + else if (BIT(offset, 9)) + { + // disc controller + + /* + + bit signal description + + 0 PAGING 1 enables paging circuits + 1 + 2 HA16 1 sets local A16 to 1 (ie. causes second set of 8 page registers to select addressed memory) + 3 MPM 0 selects multi-processing mode. among other effects this extends the page registers from 8 to 12 bits in length + 4 + 5 _FDC RESET + 6 + 7 FDC ATT + + */ + + m_fdccpu->set_input_line(INPUT_LINE_RESET, BIT(data, 5) ? HOLD_LINE : CLEAR_LINE); + + m_paging = BIT(data, 0); + m_a16 = BIT(data, 2); + m_mpm = BIT(data, 3); + m_fdc_att = BIT(data, 7); + } + else if (BIT(offset, 10)) + { + // network controller + } +} + +/* A/D Converter */ + +WRITE_LINE_MEMBER( newbrain_eim_state::adc_eoc_w ) +{ + m_anint = state; +} + +ADC0808_ANALOG_READ_CB( newbrain_eim_state::adc_vref_pos_r ) +{ + return 5.0; +} + +ADC0808_ANALOG_READ_CB( newbrain_eim_state::adc_vref_neg_r ) +{ + return 0.0; +} + +ADC0808_ANALOG_READ_CB( newbrain_eim_state::adc_input_r ) +{ + return 0.0; +} + +/* Memory Maps */ + +static ADDRESS_MAP_START( newbrain_map, AS_PROGRAM, 8, newbrain_state ) + ADDRESS_MAP_UNMAP_HIGH + AM_RANGE(0x0000, 0x1fff) AM_RAMBANK("bank1") + AM_RANGE(0x2000, 0x3fff) AM_RAMBANK("bank2") + AM_RANGE(0x4000, 0x5fff) AM_RAMBANK("bank3") + AM_RANGE(0x6000, 0x7fff) AM_RAMBANK("bank4") + AM_RANGE(0x8000, 0x9fff) AM_RAMBANK("bank5") + AM_RANGE(0xa000, 0xbfff) AM_RAMBANK("bank6") + AM_RANGE(0xc000, 0xdfff) AM_RAMBANK("bank7") + AM_RANGE(0xe000, 0xffff) AM_RAMBANK("bank8") +ADDRESS_MAP_END + +static ADDRESS_MAP_START( newbrain_ei_io_map, AS_IO, 8, newbrain_eim_state ) + ADDRESS_MAP_UNMAP_HIGH + AM_RANGE(0x00, 0x00) AM_MIRROR(0xff00) AM_READWRITE(clusr_r, clusr_w) + AM_RANGE(0x01, 0x01) AM_MIRROR(0xff00) AM_WRITE(enrg2_w) + AM_RANGE(0x02, 0x02) AM_MIRROR(0xff00) AM_MASK(0xff00) AM_WRITE(pr_w) + AM_RANGE(0x03, 0x03) AM_MIRROR(0xff00) AM_READWRITE(user_r, user_w) + AM_RANGE(0x04, 0x04) AM_MIRROR(0xff00) AM_READWRITE(clclk_r, clclk_w) + AM_RANGE(0x05, 0x05) AM_MIRROR(0xff00) AM_READWRITE(anout_r, anout_w) + AM_RANGE(0x06, 0x06) AM_MIRROR(0xff00) AM_READWRITE(cop_r, cop_w) + AM_RANGE(0x07, 0x07) AM_MIRROR(0xff00) AM_WRITE(enrg1_w) + AM_RANGE(0x08, 0x09) AM_MIRROR(0xff02) AM_READWRITE(tvl_r, tvl_w) + AM_RANGE(0x0c, 0x0c) AM_MIRROR(0xff03) AM_WRITE(tvctl_w) + AM_RANGE(0x10, 0x13) AM_MIRROR(0xff00) AM_READWRITE(anin_r, anio_w) + AM_RANGE(0x14, 0x14) AM_MIRROR(0xff00) AM_READ(st0_r) + AM_RANGE(0x15, 0x15) AM_MIRROR(0xff00) AM_READ(st1_r) + AM_RANGE(0x16, 0x16) AM_MIRROR(0xff00) AM_READ(st2_r) + AM_RANGE(0x17, 0x17) AM_MIRROR(0xff00) AM_READWRITE(usbs_r, usbs_w) + AM_RANGE(0x18, 0x18) AM_MIRROR(0xff00) AM_DEVREADWRITE(MC6850_TAG, acia6850_device, status_r, control_w) + AM_RANGE(0x19, 0x19) AM_MIRROR(0xff00) AM_DEVREADWRITE(MC6850_TAG, acia6850_device, data_r, data_w) + AM_RANGE(0x1c, 0x1f) AM_MIRROR(0xff00) AM_DEVREADWRITE(Z80CTC_TAG, z80ctc_device, read, write) + AM_RANGE(0xff, 0xff) AM_MIRROR(0xff00) AM_MASK(0xff00) AM_WRITE(paging_w) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( newbrain_a_io_map, AS_IO, 8, newbrain_state ) + ADDRESS_MAP_UNMAP_HIGH + AM_RANGE(0x00, 0x00) AM_MIRROR(0xffc0) AM_READWRITE(clusr_r, clusr_w) + AM_RANGE(0x03, 0x03) AM_MIRROR(0xffc0) AM_WRITE(user_w) + AM_RANGE(0x04, 0x04) AM_MIRROR(0xffc0) AM_READWRITE(clclk_r, clclk_w) + AM_RANGE(0x06, 0x06) AM_MIRROR(0xffc0) AM_READWRITE(cop_r, cop_w) + AM_RANGE(0x07, 0x07) AM_MIRROR(0xffc0) AM_WRITE(a_enrg1_w) + AM_RANGE(0x08, 0x09) AM_MIRROR(0xffc2) AM_READWRITE(tvl_r, tvl_w) + AM_RANGE(0x0c, 0x0c) AM_MIRROR(0xffc3) AM_WRITE(tvctl_w) + AM_RANGE(0x14, 0x14) AM_MIRROR(0xffc3) AM_READ(a_ust_r) + AM_RANGE(0x16, 0x16) AM_MIRROR(0xffc0) AM_READ(user_r) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( newbrain_fdc_map, AS_PROGRAM, 8, newbrain_eim_state ) + ADDRESS_MAP_UNMAP_HIGH + AM_RANGE(0x0000, 0x1fff) AM_ROM +ADDRESS_MAP_END + +static ADDRESS_MAP_START( newbrain_fdc_io_map, AS_IO, 8, newbrain_eim_state ) + ADDRESS_MAP_UNMAP_HIGH + ADDRESS_MAP_GLOBAL_MASK(0xff) + AM_RANGE(0x00, 0x01) AM_DEVICE(UPD765_TAG, upd765a_device, map) + AM_RANGE(0x20, 0x20) AM_WRITE(fdc_auxiliary_w) + AM_RANGE(0x40, 0x40) AM_READ(fdc_control_r) +ADDRESS_MAP_END + +/* Input Ports */ + +static INPUT_PORTS_START( newbrain ) + PORT_START("Y0") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("STOP") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(END)) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("Y1") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_DOWN) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) + + PORT_START("Y2") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') + + PORT_START("Y3") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') + + PORT_START("Y4") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') + + PORT_START("Y5") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('(') PORT_CHAR('[') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') + + PORT_START("Y6") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(')') PORT_CHAR(']') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') + + PORT_START("Y7") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("* \xC2\xA3") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('*') PORT_CHAR(0x00A3) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') + + PORT_START("Y8") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("VIDEO TEXT") PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT)) // Vd + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') + + PORT_START("Y9") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') + + PORT_START("Y10") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('@') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') + + PORT_START("Y11") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('-') PORT_CHAR('\\') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') + + PORT_START("Y12") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('+') PORT_CHAR('^') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("INSERT") PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT)) + + PORT_START("Y13") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("NEW LINE") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) // NL + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') + + PORT_START("Y14") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("HOME") PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME)) // CH + + PORT_START("Y15") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) // SH + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("GRAPHICS") PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT)) // GR + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("REPEAT") // RPT + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CONTROL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) // GL +INPUT_PORTS_END + +/* Machine Initialization */ + +WRITE_LINE_MEMBER( newbrain_eim_state::acia_tx ) +{ + m_acia_txd = state; +} + +WRITE_LINE_MEMBER( newbrain_eim_state::acia_interrupt ) +{ + m_aciaint = state; +} + +WRITE_LINE_MEMBER( newbrain_eim_state::fdc_interrupt ) +{ + m_fdc_int = state; +} + +WRITE_LINE_MEMBER( newbrain_eim_state::ctc_z2_w ) +{ + /* connected to CTC channel 0/1 clock inputs */ + m_ctc->trg0(state); + m_ctc->trg1(state); +} + +TIMER_DEVICE_CALLBACK_MEMBER(newbrain_eim_state::ctc_c2_tick) +{ + m_ctc->trg2(1); + m_ctc->trg2(0); +} + +inline int newbrain_state::get_reset_t() +{ + return RES_K(220) * CAP_U(10) * 1000; // t = R128 * C125 = 2.2s +} + +inline int newbrain_state::get_pwrup_t() +{ + return RES_K(560) * CAP_U(10) * 1000; // t = R129 * C127 = 5.6s +} + +//------------------------------------------------- +// device_timer - handler timer events +//------------------------------------------------- + +void newbrain_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch (id) + { + case TIMER_ID_RESET: + m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); + m_copcpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); + break; + + case TIMER_ID_PWRUP: + m_pwrup = 0; + bankswitch(); + break; + } +} + +void newbrain_state::machine_start() +{ + m_copregint = 1; + + /* set power up timer */ + timer_set(attotime::from_usec(get_pwrup_t()), TIMER_ID_PWRUP); + + /* initialize variables */ + m_pwrup = 1; + m_userint = 1; + m_userint0 = 1; + m_clkint = 1; + m_aciaint = 1; + m_copint = 1; + m_bee = 1; + m_tvcnsl = 1; + + /* set up memory banking */ + bankswitch(); + + // find keyboard rows + m_key_row[0] = m_y0; + m_key_row[1] = m_y1; + m_key_row[2] = m_y2; + m_key_row[3] = m_y3; + m_key_row[4] = m_y4; + m_key_row[5] = m_y5; + m_key_row[6] = m_y6; + m_key_row[7] = m_y7; + m_key_row[8] = m_y8; + m_key_row[9] = m_y9; + m_key_row[10] = m_y10; + m_key_row[11] = m_y11; + m_key_row[12] = m_y12; + m_key_row[13] = m_y13; + m_key_row[14] = m_y14; + m_key_row[15] = m_y15; + + /* register for state saving */ + save_item(NAME(m_pwrup)); + save_item(NAME(m_userint)); + save_item(NAME(m_userint0)); + save_item(NAME(m_clkint)); + save_item(NAME(m_aciaint)); + save_item(NAME(m_copint)); + save_item(NAME(m_anint)); + save_item(NAME(m_bee)); + save_item(NAME(m_enrg1)); + save_item(NAME(m_enrg2)); + save_item(NAME(m_cop_bus)); + save_item(NAME(m_cop_so)); + save_item(NAME(m_cop_tdo)); + save_item(NAME(m_cop_tdi)); + save_item(NAME(m_cop_rd)); + save_item(NAME(m_cop_wr)); + save_item(NAME(m_cop_access)); + save_item(NAME(m_keylatch)); + save_item(NAME(m_keydata)); + save_item(NAME(m_user)); +} + +void newbrain_eim_state::machine_start() +{ + newbrain_state::machine_start(); + + /* allocate expansion RAM */ + m_eim_ram.allocate(NEWBRAIN_EIM_RAM_SIZE); + + /* register for state saving */ + save_item(NAME(m_mpm)); + save_item(NAME(m_a16)); + save_item(NAME(m_pr)); + save_item(NAME(m_fdc_int)); + save_item(NAME(m_fdc_att)); + save_item(NAME(m_paging)); +} + +void newbrain_state::machine_reset() +{ + timer_set(attotime::from_usec(get_reset_t()), TIMER_ID_RESET); +} + +INTERRUPT_GEN_MEMBER(newbrain_state::newbrain_interrupt) +{ + if (!(m_enrg1 & NEWBRAIN_ENRG1_CLK)) + { + m_clkint = 0; + check_interrupt(); + } +} + +/* Machine Drivers */ + +/* F4 Character Displayer */ +static const gfx_layout newbrain_charlayout = +{ + 8, 10, /* 8 x 10 characters */ + 256, /* 256 characters */ + 1, /* 1 bits per pixel */ + { 0 }, /* no bitplanes */ + /* x offsets */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, + /* y offsets */ + { 0*256*8, 1*256*8, 2*256*8, 3*256*8, 4*256*8, 5*256*8, 6*256*8, 7*256*8, 8*256*8, 9*256*8, 10*256*8, 11*256*8, 12*256*8, 13*256*8, 14*256*8, 15*256*8 }, + 8 /* every char takes 16 x 1 bytes */ +}; + +static GFXDECODE_START( newbrain ) + GFXDECODE_ENTRY( "chargen", 0x0000, newbrain_charlayout, 0, 1 ) +GFXDECODE_END + +static MACHINE_CONFIG_START( newbrain_a, newbrain_state ) + // basic system hardware + MCFG_CPU_ADD(Z80_TAG, Z80, XTAL_16MHz/8) + MCFG_CPU_PROGRAM_MAP(newbrain_map) + MCFG_CPU_IO_MAP(newbrain_a_io_map) + MCFG_CPU_VBLANK_INT_DRIVER(SCREEN_TAG, newbrain_state, newbrain_interrupt) + + MCFG_CPU_ADD(COP420_TAG, COP420, XTAL_16MHz/8) // COP420-GUW/N + MCFG_COP400_CONFIG( COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, COP400_MICROBUS_ENABLED ) + MCFG_COP400_READ_L_CB(READ8(newbrain_state, cop_l_r)) + MCFG_COP400_WRITE_L_CB(WRITE8(newbrain_state, cop_l_w)) + MCFG_COP400_READ_G_CB(READ8(newbrain_state, cop_g_r)) + MCFG_COP400_WRITE_G_CB(WRITE8(newbrain_state, cop_g_w)) + MCFG_COP400_WRITE_D_CB(WRITE8(newbrain_state, cop_d_w)) + MCFG_COP400_READ_IN_CB(READ8(newbrain_state, cop_in_r)) + MCFG_COP400_WRITE_SK_CB(WRITELINE(newbrain_state, cop_sk_w)) + MCFG_COP400_READ_SI_CB(READLINE(newbrain_state, cop_si_r)) + MCFG_COP400_WRITE_SO_CB(WRITELINE(newbrain_state, cop_so_w)) + + MCFG_GFXDECODE_ADD("gfxdecode", "palette", newbrain) + + MCFG_TIMER_DRIVER_ADD_PERIODIC("cop_regint", newbrain_state, cop_regint_tick, attotime::from_usec(12500)) + + // video hardware + MCFG_FRAGMENT_ADD(newbrain_video) + + // devices + MCFG_CASSETTE_ADD("cassette") + MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_MUTED) + + MCFG_CASSETTE_ADD("cassette2") + MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_MUTED) + + // internal ram + MCFG_RAM_ADD(RAM_TAG) + MCFG_RAM_DEFAULT_SIZE("32K") +MACHINE_CONFIG_END + +static SLOT_INTERFACE_START( newbrain_floppies ) + SLOT_INTERFACE( "525dd", FLOPPY_525_DD ) +SLOT_INTERFACE_END + +static MACHINE_CONFIG_DERIVED_CLASS( newbrain_eim, newbrain_a, newbrain_eim_state ) + // basic system hardware + MCFG_CPU_MODIFY(Z80_TAG) + MCFG_CPU_IO_MAP(newbrain_ei_io_map) + + MCFG_CPU_ADD(FDC_Z80_TAG, Z80, XTAL_4MHz) + MCFG_CPU_PROGRAM_MAP(newbrain_fdc_map) + MCFG_CPU_IO_MAP(newbrain_fdc_io_map) + + // devices + MCFG_DEVICE_ADD(Z80CTC_TAG, Z80CTC, XTAL_16MHz/8) + MCFG_Z80CTC_ZC0_CB(DEVWRITELINE(MC6850_TAG, acia6850_device, write_rxc)) + MCFG_Z80CTC_ZC1_CB(DEVWRITELINE(MC6850_TAG, acia6850_device, write_txc)) + MCFG_Z80CTC_ZC2_CB(WRITELINE(newbrain_eim_state, ctc_z2_w)) + + MCFG_TIMER_DRIVER_ADD_PERIODIC("z80ctc_c2", newbrain_eim_state, ctc_c2_tick, attotime::from_hz(XTAL_16MHz/4/13)) + MCFG_DEVICE_ADD(ADC0809_TAG, ADC0808, 500000) + MCFG_ADC0808_OUT_EOC_CB(WRITELINE(newbrain_eim_state, adc_eoc_w)) + MCFG_ADC0808_IN_VREF_POS_CB(newbrain_eim_state, adc_vref_pos_r) + MCFG_ADC0808_IN_VREF_NEG_CB(newbrain_eim_state, adc_vref_neg_r) + MCFG_ADC0808_IN_IN_0_CB(newbrain_eim_state, adc_input_r) + MCFG_ADC0808_IN_IN_1_CB(newbrain_eim_state, adc_input_r) + MCFG_ADC0808_IN_IN_2_CB(newbrain_eim_state, adc_input_r) + MCFG_ADC0808_IN_IN_3_CB(newbrain_eim_state, adc_input_r) + MCFG_ADC0808_IN_IN_4_CB(newbrain_eim_state, adc_input_r) + MCFG_ADC0808_IN_IN_5_CB(newbrain_eim_state, adc_input_r) + MCFG_ADC0808_IN_IN_6_CB(newbrain_eim_state, adc_input_r) + MCFG_ADC0808_IN_IN_7_CB(newbrain_eim_state, adc_input_r) + + MCFG_DEVICE_ADD(MC6850_TAG, ACIA6850, 0) + MCFG_ACIA6850_TXD_HANDLER(WRITELINE(newbrain_eim_state, acia_tx)) + MCFG_ACIA6850_IRQ_HANDLER(WRITELINE(newbrain_eim_state, acia_interrupt)) + + MCFG_UPD765A_ADD(UPD765_TAG, false, true) + MCFG_FLOPPY_DRIVE_ADD(UPD765_TAG ":0", newbrain_floppies, "525dd", floppy_image_device::default_floppy_formats) + MCFG_FLOPPY_DRIVE_ADD(UPD765_TAG ":1", newbrain_floppies, "525dd", floppy_image_device::default_floppy_formats) + + // internal ram + MCFG_RAM_MODIFY(RAM_TAG) + MCFG_RAM_DEFAULT_SIZE("96K") +MACHINE_CONFIG_END + +/* ROMs */ + +ROM_START( newbrain ) + ROM_REGION( 0x10000, Z80_TAG, 0 ) + ROM_DEFAULT_BIOS( "rom20" ) + + ROM_SYSTEM_BIOS( 0, "issue1", "Issue 1 (v?)" ) + ROMX_LOAD( "aben.ic6", 0xa000, 0x2000, CRC(308f1f72) SHA1(a6fd9945a3dca47636887da2125fde3f9b1d4e25), ROM_BIOS(1) ) + ROMX_LOAD( "cd iss 1.ic7", 0xc000, 0x2000, CRC(6b4d9429) SHA1(ef688be4e75aced61f487c928258c8932a0ae00a), ROM_BIOS(1) ) + ROMX_LOAD( "ef iss 1.ic8", 0xe000, 0x2000, CRC(20dd0b49) SHA1(74b517ca223cefb588e9f49e72ff2d4f1627efc6), ROM_BIOS(1) ) + + ROM_SYSTEM_BIOS( 1, "issue2", "Issue 2 (v1.9)" ) + ROMX_LOAD( "aben19.ic6", 0xa000, 0x2000, CRC(d0283eb1) SHA1(351d248e69a77fa552c2584049006911fb381ff0), ROM_BIOS(2) ) + ROMX_LOAD( "cdi2.ic7", 0xc000, 0x2000, CRC(6b4d9429) SHA1(ef688be4e75aced61f487c928258c8932a0ae00a), ROM_BIOS(2) ) + ROMX_LOAD( "ef iss 1.ic8", 0xe000, 0x2000, CRC(20dd0b49) SHA1(74b517ca223cefb588e9f49e72ff2d4f1627efc6), ROM_BIOS(2) ) + + ROM_SYSTEM_BIOS( 2, "issue3", "Issue 3 (v1.91)" ) + ROMX_LOAD( "aben191.ic6", 0xa000, 0x2000, CRC(b7be8d89) SHA1(cce8d0ae7aa40245907ea38b7956c62d039d45b7), ROM_BIOS(3) ) + ROMX_LOAD( "cdi3.ic7", 0xc000, 0x2000, CRC(6b4d9429) SHA1(ef688be4e75aced61f487c928258c8932a0ae00a), ROM_BIOS(3) ) + ROMX_LOAD( "ef iss 1.ic8", 0xe000, 0x2000, CRC(20dd0b49) SHA1(74b517ca223cefb588e9f49e72ff2d4f1627efc6), ROM_BIOS(3) ) + + ROM_SYSTEM_BIOS( 3, "series2", "Series 2 (v?)" ) + ROMX_LOAD( "abs2.ic6", 0xa000, 0x2000, CRC(9a042acb) SHA1(80d83a2ea3089504aa68b6cf978d80d296cd9bda), ROM_BIOS(4) ) + ROMX_LOAD( "cds2.ic7", 0xc000, 0x2000, CRC(6b4d9429) SHA1(ef688be4e75aced61f487c928258c8932a0ae00a), ROM_BIOS(4) ) + ROMX_LOAD( "efs2.ic8", 0xe000, 0x2000, CRC(b222d798) SHA1(c0c816b4d4135b762f2c5f1b24209d0096f22e56), ROM_BIOS(4) ) + + ROM_SYSTEM_BIOS( 4, "rom20", "? (v2.0)" ) + ROMX_LOAD( "aben20.rom", 0xa000, 0x2000, CRC(3d76d0c8) SHA1(753b4530a518ad832e4b81c4e5430355ba3f62e0), ROM_BIOS(5) ) + ROMX_LOAD( "cd20tci.rom", 0xc000, 0x4000, CRC(f65b2350) SHA1(1ada7fbf207809537ec1ffb69808524300622ada), ROM_BIOS(5) ) + + ROM_REGION( 0x400, COP420_TAG, 0 ) + ROM_LOAD( "cop420.419", 0x000, 0x400, NO_DUMP ) + + ROM_REGION( 0x1000, "chargen", ROMREGION_ERASE00 ) + ROM_LOAD( "char eprom iss 1.ic453", 0x0000, 0x0a01, BAD_DUMP CRC(46ecbc65) SHA1(3fe064d49a4de5e3b7383752e98ad35a674e26dd) ) // 8248R7 +ROM_END + +#define rom_newbraina rom_newbrain + +ROM_START( newbraineim ) + ROM_REGION( 0x10000, Z80_TAG, 0 ) + ROM_DEFAULT_BIOS( "rom20" ) + + ROM_SYSTEM_BIOS( 0, "issue1", "Issue 1 (v?)" ) + ROMX_LOAD( "aben.ic6", 0xa000, 0x2000, CRC(308f1f72) SHA1(a6fd9945a3dca47636887da2125fde3f9b1d4e25), ROM_BIOS(1) ) + ROMX_LOAD( "cd iss 1.ic7", 0xc000, 0x2000, CRC(6b4d9429) SHA1(ef688be4e75aced61f487c928258c8932a0ae00a), ROM_BIOS(1) ) + ROMX_LOAD( "ef iss 1.ic8", 0xe000, 0x2000, CRC(20dd0b49) SHA1(74b517ca223cefb588e9f49e72ff2d4f1627efc6), ROM_BIOS(1) ) + + ROM_SYSTEM_BIOS( 1, "issue2", "Issue 2 (v1.9)" ) + ROMX_LOAD( "aben19.ic6", 0xa000, 0x2000, CRC(d0283eb1) SHA1(351d248e69a77fa552c2584049006911fb381ff0), ROM_BIOS(2) ) + ROMX_LOAD( "cdi2.ic7", 0xc000, 0x2000, CRC(6b4d9429) SHA1(ef688be4e75aced61f487c928258c8932a0ae00a), ROM_BIOS(2) ) + ROMX_LOAD( "ef iss 1.ic8", 0xe000, 0x2000, CRC(20dd0b49) SHA1(74b517ca223cefb588e9f49e72ff2d4f1627efc6), ROM_BIOS(2) ) + + ROM_SYSTEM_BIOS( 2, "issue3", "Issue 3 (v1.91)" ) + ROMX_LOAD( "aben191.ic6", 0xa000, 0x2000, CRC(b7be8d89) SHA1(cce8d0ae7aa40245907ea38b7956c62d039d45b7), ROM_BIOS(3) ) + ROMX_LOAD( "cdi3.ic7", 0xc000, 0x2000, CRC(6b4d9429) SHA1(ef688be4e75aced61f487c928258c8932a0ae00a), ROM_BIOS(3) ) + ROMX_LOAD( "ef iss 1.ic8", 0xe000, 0x2000, CRC(20dd0b49) SHA1(74b517ca223cefb588e9f49e72ff2d4f1627efc6), ROM_BIOS(3) ) + + ROM_SYSTEM_BIOS( 3, "series2", "Series 2 (v?)" ) + ROMX_LOAD( "abs2.ic6", 0xa000, 0x2000, CRC(9a042acb) SHA1(80d83a2ea3089504aa68b6cf978d80d296cd9bda), ROM_BIOS(4) ) + ROMX_LOAD( "cds2.ic7", 0xc000, 0x2000, CRC(6b4d9429) SHA1(ef688be4e75aced61f487c928258c8932a0ae00a), ROM_BIOS(4) ) + ROMX_LOAD( "efs2.ic8", 0xe000, 0x2000, CRC(b222d798) SHA1(c0c816b4d4135b762f2c5f1b24209d0096f22e56), ROM_BIOS(4) ) + + ROM_SYSTEM_BIOS( 4, "rom20", "? (v2.0)" ) + ROMX_LOAD( "aben20.rom", 0xa000, 0x2000, CRC(3d76d0c8) SHA1(753b4530a518ad832e4b81c4e5430355ba3f62e0), ROM_BIOS(5) ) + ROMX_LOAD( "cd20tci.rom", 0xc000, 0x4000, CRC(f65b2350) SHA1(1ada7fbf207809537ec1ffb69808524300622ada), ROM_BIOS(5) ) + + ROM_REGION( 0x400, COP420_TAG, 0 ) + ROM_LOAD( "cop420.419", 0x000, 0x400, NO_DUMP ) + + ROM_REGION( 0x1000, "chargen", 0 ) + ROM_LOAD( "char eprom iss 1.ic453", 0x0000, 0x0a01, BAD_DUMP CRC(46ecbc65) SHA1(3fe064d49a4de5e3b7383752e98ad35a674e26dd) ) // 8248R7 + + ROM_REGION( 0x10000, "eim", 0 ) // Expansion Interface Module + ROM_LOAD( "e415-2.rom", 0x4000, 0x2000, CRC(5b0e390c) SHA1(0f99cae57af2e64f3f6b02e5325138d6ba015e72) ) + ROM_LOAD( "e415-3.rom", 0x4000, 0x2000, CRC(2f88bae5) SHA1(04e03f230f4b368027442a7c2084dae877f53713) ) // 18/8/83.aci + ROM_LOAD( "e416-3.rom", 0x6000, 0x2000, CRC(8b5099d8) SHA1(19b0cfce4c8b220eb1648b467f94113bafcb14e0) ) // 10/8/83.mtv + ROM_LOAD( "e417-2.rom", 0x8000, 0x2000, CRC(6a7afa20) SHA1(f90db4f8318777313a862b3d5bab83c2fd260010) ) + + ROM_REGION( 0x10000, FDC_Z80_TAG, 0 ) // Floppy Disk Controller + ROM_LOAD( "d413-2.rom", 0x0000, 0x2000, CRC(097591f1) SHA1(c2aa1d27d4f3a24ab0c8135df746a4a44201a7f4) ) + ROM_LOAD( "d417-1.rom", 0x0000, 0x2000, CRC(40fad31c) SHA1(5137be4cc026972c0ffd4fa6990e8583bdfce163) ) + ROM_LOAD( "d417-2.rom", 0x0000, 0x2000, CRC(e8bda8b9) SHA1(c85a76a5ff7054f4ef4a472ce99ebaed1abd269c) ) +ROM_END + +ROM_START( newbrainmd ) + ROM_REGION( 0x10000, Z80_TAG, 0 ) + ROM_LOAD( "cdmd.rom", 0xc000, 0x2000, CRC(6b4d9429) SHA1(ef688be4e75aced61f487c928258c8932a0ae00a) ) + ROM_LOAD( "efmd.rom", 0xe000, 0x2000, CRC(20dd0b49) SHA1(74b517ca223cefb588e9f49e72ff2d4f1627efc6) ) + + ROM_REGION( 0x400, COP420_TAG, 0 ) + ROM_LOAD( "cop420.419", 0x000, 0x400, NO_DUMP ) + + ROM_REGION( 0x1000, "chargen", 0 ) + ROM_LOAD( "char eprom iss 1.ic453", 0x0000, 0x0a01, BAD_DUMP CRC(46ecbc65) SHA1(3fe064d49a4de5e3b7383752e98ad35a674e26dd) ) // 8248R7 +ROM_END + +/* System Drivers */ + +// YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS +COMP( 1981, newbrain, 0, 0, newbrain_a, newbrain, driver_device, 0, "Grundy Business Systems Ltd", "NewBrain AD", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) +COMP( 1981, newbraineim,newbrain, 0, newbrain_eim, newbrain, driver_device, 0, "Grundy Business Systems Ltd", "NewBrain AD with Expansion Interface", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) +COMP( 1981, newbraina, newbrain, 0, newbrain_a, newbrain, driver_device, 0, "Grundy Business Systems Ltd", "NewBrain A", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) +COMP( 1981, newbrainmd, newbrain, 0, newbrain_a, newbrain, driver_device, 0, "Grundy Business Systems Ltd", "NewBrain MD", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) |