// license:BSD-3-Clause // copyright-holders:Olivier Galibert #include "emu.h" #include "cpu/i86/i186.h" #include "cpu/mcs48/mcs48.h" #include "imagedev/floppy.h" #include "machine/upd765.h" #include "formats/pc_dsk.h" #include "sound/dac.h" #include "sound/volt_reg.h" #include "machine/ins8250.h" #include "bus/rs232/rs232.h" #include "screen.h" #include "speaker.h" #include "mindset.lh" // Missing: // - Correct video timings // * screen_device does not handle interlaced screens yet // - Correct timing of the specific-video-position interrupt // * see previous (so that partial screen update is correct) plus there's no "interrupt at a (x, y) position" interface // - Interrupt from modules // * no use example, serial maybe? And may be going through the system mcu // - HD support module // * can't find the software that uses it. Hand-drawn schematic at http://bitsavers.org/pdf/mindset/video_input/video_input_module_schematic.jpg (it's the same) // - Modem modules // * no information on them, probably no software to use them either // - Cartridges // * no dump of the rom ones, no users for the nvram ones. gwbasic could use the nvram ones maybe? // - Graphics CoProcessor timings // * need to count the accesses and estimate the mean access duration // - GCP right-to-left blitting // * need to find a user, otherwise no way to know if the implementation is correct // - GCP collision detection // * need to find a user, or at least a way to distinguish between the mask and the comparison value // - GCP interrupt // * need to find a user, especially since it interacts with the system mcu // - Genlock // * no osd support for video input // - Capture card // * no osd support for video input. Could try with the picture image device maybe? // - Digitizing tablet // * no osd support, and a relatively rare device in the real world which is also hard to simulate on something else // - Power control // * the system mcu controls the power to the system (some bit of p2 is seems), rocker switch on the keyboard resets the keyboard mcu for "on" and pretends sending a byte for "off". Can be annoying UI-wise, and pretty much requires autosave. class mindset_module_interface: public device_t { public: virtual void map(address_map &map) = 0; virtual void idmap(address_map &map) = 0; auto irq_cb() { return m_irq_cb.bind(); } bool irq_r() const; protected: bool m_irq_state; void irq_w(int state); mindset_module_interface(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); virtual void device_start() override; virtual void device_reset() override; private: devcb_write_line m_irq_cb; }; void mindset_module_interface::device_start() { m_irq_cb.resolve_safe(); save_item(NAME(m_irq_state)); } void mindset_module_interface::device_reset() { m_irq_state = false; m_irq_cb(m_irq_state); } mindset_module_interface::mindset_module_interface(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock), m_irq_cb(*this) { } void mindset_module_interface::irq_w(int state) { m_irq_state = state; m_irq_cb(m_irq_state); } class mindset_module: public device_t, public device_slot_interface { public: template mindset_module(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt, bool fixed = false) : mindset_module(mconfig, tag, owner, 0) { option_reset(); opts(*this); set_default_option(dflt); set_fixed(fixed); } mindset_module(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); virtual ~mindset_module() = default; void map(address_space &space, offs_t base, bool id); protected: virtual void device_validity_check(validity_checker &valid) const override; virtual void device_start() override; }; DEFINE_DEVICE_TYPE(MINDSET_MODULE, mindset_module, "mindset_module", "MINDSET module") mindset_module::mindset_module(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, MINDSET_MODULE, tag, owner, clock), device_slot_interface(mconfig, *this) { } void mindset_module::device_validity_check(validity_checker &valid) const { device_t *const carddev = get_card_device(); if (carddev && !dynamic_cast(carddev)) osd_printf_error("Card device %s (%s) does not implement mindset_module_interface\n", carddev->tag(), carddev->name()); } void mindset_module::device_start() { } void mindset_module::map(address_space &space, offs_t base, bool id) { mindset_module_interface *module = dynamic_cast(get_card_device()); if(module) space.install_device(base, base+0x3f, *module, id ? &mindset_module_interface::idmap : &mindset_module_interface::map); } class mindset_sound_module: public mindset_module_interface { public: mindset_sound_module(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); virtual ~mindset_sound_module() = default; virtual void map(address_map &map) override; virtual void idmap(address_map &map) override; protected: virtual const tiny_rom_entry *device_rom_region() const override; virtual void device_add_mconfig(machine_config &config) override; virtual void device_start() override; virtual void device_reset() override; private: u8 m_p1, m_p2; required_device m_soundcpu; required_device m_dac; void p1_w(u8 data); void p2_w(u8 data); void update_dac(); }; DEFINE_DEVICE_TYPE(MINDSET_SOUND_MODULE, mindset_sound_module, "mindset_sound_module", "MINDSET stereo sound module") mindset_sound_module::mindset_sound_module(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : mindset_module_interface(mconfig, MINDSET_SOUND_MODULE, tag, owner, clock), m_soundcpu(*this, "soundcpu"), m_dac(*this, "dac") { } void mindset_sound_module::device_start() { mindset_module_interface::device_start(); save_item(NAME(m_p1)); save_item(NAME(m_p2)); } void mindset_sound_module::device_reset() { mindset_module_interface::device_reset(); m_p1 = 0x80; m_p2 = 0; m_dac->write(0x80); } void mindset_sound_module::update_dac() { // The p1 dac has the waveform (idle at 0x80), while the p2 one is used for the global volume (mute at 0x00, max at 0xff) m_dac->write((s8(m_p1-0x80)*m_p2/255 + 0x80) & 0xff); } void mindset_sound_module::p1_w(u8 data) { m_p1 = data; update_dac(); } void mindset_sound_module::p2_w(u8 data) { m_p2 = data; update_dac(); } void mindset_sound_module::map(address_map &map) { map(0x00, 0x03).rw(m_soundcpu, FUNC(i8042_device::upi41_master_r), FUNC(i8042_device::upi41_master_w)).umask16(0x00ff).mirror(0x3c); } void mindset_sound_module::idmap(address_map &map) { map(0x00, 0x3f).lr8(NAME([]() -> u8 { return 0x13; })).umask16(0x00ff); } ROM_START(mindset_sound_module) ROM_REGION(0x0800, "soundcpu", 0) ROM_LOAD("253006-001.u16", 0, 0x800, CRC(7bea5edd) SHA1(30cdc0dedaa5246f4952df452a99ca22e3cd0636)) ROM_END const tiny_rom_entry *mindset_sound_module::device_rom_region() const { return ROM_NAME(mindset_sound_module); } void mindset_sound_module::device_add_mconfig(machine_config &config) { I8042(config, m_soundcpu, 12_MHz_XTAL/2); m_soundcpu->p1_out_cb().set(FUNC(mindset_sound_module::p1_w)); m_soundcpu->p2_out_cb().set(FUNC(mindset_sound_module::p2_w)); SPEAKER(config, "rspeaker").front_right(); DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "rspeaker", 0.5); voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref")); vref.add_route(0, m_dac, 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, m_dac, -1.0, DAC_VREF_NEG_INPUT); } class mindset_rs232_module: public mindset_module_interface { public: mindset_rs232_module(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); virtual ~mindset_rs232_module() = default; virtual void map(address_map &map) override; virtual void idmap(address_map &map) override; protected: virtual void device_add_mconfig(machine_config &config) override; private: required_device m_ins8250; required_device m_rs232; }; DEFINE_DEVICE_TYPE(MINDSET_RS232_MODULE, mindset_rs232_module, "mindset_rs232_module", "MINDSET RS232 module") mindset_rs232_module::mindset_rs232_module(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : mindset_module_interface(mconfig, MINDSET_RS232_MODULE, tag, owner, clock), m_ins8250(*this, "ins8250"), m_rs232(*this, "rs232") { } void mindset_rs232_module::map(address_map &map) { map(0x00, 0x0f).rw(m_ins8250, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)).umask16(0x00ff).mirror(0x30); } void mindset_rs232_module::idmap(address_map &map) { map(0x00, 0x3f).lr8(NAME([this]() -> u8 { return 0x73 | (m_irq_state ? 0x80 : 0x00); })).umask16(0x00ff); } void mindset_rs232_module::device_add_mconfig(machine_config &config) { INS8250(config, m_ins8250, 12_MHz_XTAL/2/4); // Weird since there's no divider in the module m_ins8250->out_tx_callback().set(m_rs232, FUNC(rs232_port_device::write_txd)); m_ins8250->out_int_callback().set(FUNC(mindset_rs232_module::irq_w)); RS232_PORT(config, m_rs232, default_rs232_devices, nullptr); m_rs232->rxd_handler().set(m_ins8250, FUNC(ins8250_device::rx_w)); m_rs232->dsr_handler().set(m_ins8250, FUNC(ins8250_device::dsr_w)); } class mindset_state: public driver_device { public: mindset_state(const machine_config &mconfig, device_type type, const char *tag); virtual ~mindset_state() = default; void mindset(machine_config &config); protected: required_device m_maincpu; required_device m_syscpu, m_soundcpu; required_device m_kbdcpu; required_device m_screen; required_device m_fdc; required_device m_fdco[2]; required_shared_ptr m_vram; required_ioport_array<11> m_kbd_row; required_ioport_array<2> m_mouse_axis; required_ioport m_mouse_btn, m_joystick; output_finder<2> m_floppy_leds; output_finder<> m_red_led; output_finder<> m_yellow_led; output_finder<> m_green_led; required_device m_dac; required_device_array m_modules; memory_access_cache<1, 0, ENDIANNESS_LITTLE> *m_gcps; floppy_image_device *m_floppy[2]; u32 m_palette[16]; bool m_genlock[16]; u16 m_dispctrl, m_screenpos, m_intpos, m_intaddr, m_fdc_dma_count; u8 m_kbd_p1, m_kbd_p2, m_borderidx, m_snd_p1, m_snd_p2, m_sys_p2; u8 m_mouse_last_read[2], m_mouse_counter[2]; bool m_fdc_intext, m_fdc_int, m_fdc_drq, m_trap_int, m_trap_drq; u16 m_trap_data[8]; u32 m_trap_pos, m_trap_len; static u16 gcp_blend_0(u16, u16); static u16 gcp_blend_1(u16, u16); static u16 gcp_blend_2(u16, u16); static u16 gcp_blend_3(u16, u16); static u16 gcp_blend_4(u16, u16); static u16 gcp_blend_5(u16, u16); static u16 gcp_blend_6(u16, u16); static u16 gcp_blend_7(u16, u16); static u16 (*const gcp_blend[8])(u16, u16); static inline u16 msk(int bit) { return (1U << bit) - 1; } static inline u16 sw(u16 data) { return (data >> 8) | (data << 8); } void maincpu_mem(address_map &map); void maincpu_io(address_map &map); void display_mode(); void blit(u16 packet_seg, u16 packet_adr); void gcp_w(u16); u16 dispctrl_r(); void dispctrl_w(u16 data); u16 dispreg_r(); void dispreg_w(u16 data); int sys_t0_r(); int sys_t1_r(); u8 sys_p1_r(); u8 sys_p2_r(); void sys_p1_w(u8 data); void sys_p2_w(u8 data); void kbd_p1_w(u8 data); void kbd_p2_w(u8 data); int kbd_t1_r(); u8 kbd_d_r(); void snd_p1_w(u8 data); void snd_p2_w(u8 data); void fdc_ctrl_w(u8 data); void fdc_int_w(int state); u16 fdc_clear_interrupt(); void fdc_dma_count_w(u16 data); u8 fdc_dma_r(); void fdc_dma_w(u8 data); u16 trap_dma_r(offs_t, u16); u16 trap_r(offs_t offset); void trap_w(offs_t offset, u16 data); u16 trap_clear_interrupt(); template void floppy_led_cb(floppy_image_device *, int state); u16 keyscan(); void update_dac(); void map_modules(); u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); virtual void machine_start() override; virtual void machine_reset() override; DECLARE_FLOPPY_FORMATS(floppy_formats); }; FLOPPY_FORMATS_MEMBER(mindset_state::floppy_formats) FLOPPY_PC_FORMAT FLOPPY_FORMATS_END mindset_state::mindset_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), m_syscpu(*this, "syscpu"), m_soundcpu(*this, "soundcpu"), m_kbdcpu(*this, "kbdcpu"), m_screen(*this, "screen"), m_fdc(*this, "fdc"), m_fdco{{*this, "fdc:0"}, {*this, "fdc:1"}}, m_vram(*this, "vram"), m_kbd_row(*this, "K%02u", 0U), m_mouse_axis(*this, "MOUSEAXIS%u", 0U), m_mouse_btn(*this, "MOUSEBTN"), m_joystick(*this, "JOYSTICK"), m_floppy_leds(*this, "drive%u_led", 0U), m_red_led(*this, "red_led"), m_yellow_led(*this, "yellow_led"), m_green_led(*this, "green_led"), m_dac(*this, "dac"), m_modules(*this, "m%d", 0U) { } template void mindset_state::floppy_led_cb(floppy_image_device *, int state) { m_floppy_leds[floppy] = state; } void mindset_state::machine_start() { m_floppy_leds.resolve(); m_red_led.resolve(); m_yellow_led.resolve(); m_green_led.resolve(); m_gcps = m_maincpu->space(AS_PROGRAM).cache<1, 0, ENDIANNESS_LITTLE>(); for(int i=0; i<2; i++) m_floppy[i] = m_fdco[i]->get_device(); if(m_floppy[0]) m_floppy[0]->setup_led_cb(floppy_image_device::led_cb(&mindset_state::floppy_led_cb<0>, this)); if(m_floppy[1]) m_floppy[1]->setup_led_cb(floppy_image_device::led_cb(&mindset_state::floppy_led_cb<1>, this)); save_item(NAME(m_fdc_intext)); save_item(NAME(m_fdc_int)); save_item(NAME(m_fdc_drq)); save_item(NAME(m_trap_int)); save_item(NAME(m_trap_drq)); save_item(NAME(m_trap_pos)); save_item(NAME(m_trap_len)); save_item(NAME(m_trap_data)); save_item(NAME(m_palette)); save_item(NAME(m_genlock)); save_item(NAME(m_dispctrl)); save_item(NAME(m_screenpos)); save_item(NAME(m_intpos)); save_item(NAME(m_intaddr)); save_item(NAME(m_fdc_dma_count)); save_item(NAME(m_kbd_p1)); save_item(NAME(m_kbd_p2)); save_item(NAME(m_borderidx)); save_item(NAME(m_mouse_last_read)); save_item(NAME(m_mouse_counter)); save_item(NAME(m_snd_p1)); save_item(NAME(m_snd_p2)); save_item(NAME(m_sys_p2)); } void mindset_state::map_modules() { auto &space = m_maincpu->space(AS_IO); bool id = !(m_sys_p2 & 0x40); space.unmap_readwrite(0x8080, 0x81ff); for(int i=0; i<6; i++) m_modules[i]->map(space, 0x8080 + 0x40*i, id); } void mindset_state::machine_reset() { m_sys_p2 = 0; map_modules(); m_fdc_intext = m_fdc_int = m_trap_int = m_fdc_drq = m_trap_drq = false; m_trap_pos = m_trap_len = 0; memset(m_trap_data, 0, sizeof(m_trap_data)); memset(m_palette, 0, sizeof(m_palette)); memset(m_genlock, 0, sizeof(m_genlock)); m_dispctrl = m_screenpos = m_intpos = m_intaddr = m_fdc_dma_count = 0; m_kbd_p1 = m_kbd_p2 = m_borderidx = 0; memset(m_mouse_last_read, 0, sizeof(m_mouse_last_read)); memset(m_mouse_counter, 0, sizeof(m_mouse_counter)); m_snd_p1 = 0x80; m_snd_p2 = 0; m_dac->write(0x80); } int mindset_state::sys_t0_r() { // logerror("SYS: %d read t0 %d (%03x)\n", m_kbdcpu->total_cycles(), (m_kbd_p2 & 0x40) != 0, m_syscpu->pc()); return (m_kbd_p2 & 0x40) != 0; } int mindset_state::sys_t1_r() { logerror("SYS: read t1\n"); return !m_fdc_int; } u8 mindset_state::sys_p1_r() { // logerror("SYS: read p1\n"); return 0xff; } u8 mindset_state::sys_p2_r() { // logerror("SYS: read p2 (%03x)\n", m_syscpu->pc()); return 0xff; } void mindset_state::sys_p1_w(u8 data) { // m_maincpu->int0_w(!((data & 0x40) || m_fdc->get_irq())); logerror("SYS: fdc write p1 %02x irq %d\n", data, !!(data & 0x40)); } void mindset_state::sys_p2_w(u8 data) { u8 old = m_sys_p2; m_sys_p2 = data; m_yellow_led = !BIT(data, 0); m_green_led = !BIT(data, 1); m_red_led = !BIT(data, 2); if((m_sys_p2 ^ old) & 0x40) map_modules(); m_maincpu->int3_w(!(data & 0x80)); // logerror("SYS: write p2 %02x\n", data); } void mindset_state::kbd_p1_w(u8 data) { m_kbd_p1 = data; } void mindset_state::kbd_p2_w(u8 data) { // if((m_kbd_p2 ^ data) & 0x40) // logerror("KBD: %d output bit %d\n", m_kbdcpu->total_cycles(), (m_kbd_p2 & 0x40) != 0); m_kbd_p2 = data; } u8 mindset_state::kbd_d_r() { return keyscan(); } int mindset_state::kbd_t1_r() { return keyscan() & 0x100; } void mindset_state::update_dac() { // The p1 dac has the waveform (idle at 0x80), while the p2 one is used for the global volume (mute at 0x00, max at 0xff) m_dac->write((s8(m_snd_p1-0x80)*m_snd_p2/255 + 0x80) & 0xff); } void mindset_state::snd_p1_w(u8 data) { m_snd_p1 = data; update_dac(); } void mindset_state::snd_p2_w(u8 data) { m_snd_p2 = data; update_dac(); } u16 mindset_state::keyscan() { u16 src = (m_kbd_p2 << 8) | m_kbd_p1; u16 res = 0x1ff; for(unsigned int i=0; i<11; i++) if(!(src & (1 << i))) res &= m_kbd_row[i]->read(); if(!(src & 0x8000)) { int axis = (src >> 12) & 1; u8 aval = m_mouse_axis[axis]->read(); m_mouse_counter[axis] += aval - m_mouse_last_read[axis]; m_mouse_last_read[axis] = aval; u8 nib; if((src >> 11) & 1) { nib = m_mouse_counter[axis] & 0xf; m_mouse_counter[axis] &= 0xf0; } else { nib = m_mouse_counter[axis] >> 4; m_mouse_counter[axis] &= 0x0f; } res &= m_mouse_btn->read() & (nib | 0x1f0); } if(!(src & 0x2000)) res &= m_joystick->read(); return res; } u16 mindset_state::dispctrl_r() { return m_dispctrl; } void mindset_state::dispctrl_w(u16 data) { u16 chg = m_dispctrl ^ data; m_dispctrl = data; if(chg & 0xff88) logerror("display control %s bank=%c %s %s h=%d ppx=%d w=%s interlace=%d rreg=%d indicator=%s wreg=%d\n", m_dispctrl & 0x8000 ? "?15" : "?!15", m_dispctrl & 0x4000 ? '1' : '0', m_dispctrl & 0x2000 ? "ibm" : "native", m_dispctrl & 0x1000 ? "?12" : "?!12", m_dispctrl & 0x0800 ? "400" : "200", (m_dispctrl & 0x0600) >> 9, m_dispctrl & 0x0100 ? "320" : "640", m_dispctrl & 0x0080 ? "on" : "off", (m_dispctrl & 0x0070) >> 4, m_dispctrl & 0x0008 ? "on" : "off", m_dispctrl & 7); } u16 mindset_state::dispreg_r() { switch((m_dispctrl >> 4) & 7) { case 1: { // Read vram at interrupt position u16 v = m_vram[m_intaddr >> 1]; if(m_intaddr & 1) v >>= 8; return sw(v << 4); break; } case 5: { // wants 0080 set to be able to upload the palette // may be a field indicator return 0x0080; } } logerror("dispreg read %x\n", (m_dispctrl >> 4) & 7); return 0; } void mindset_state::dispreg_w(u16 data) { switch(m_dispctrl & 0x7) { case 0: m_screenpos = data; logerror("screen position (%d, %d)\n", (data >> 8) & 15, (data >> 12) & 15); break; case 1: m_borderidx = (data >> 8) & 0xf; logerror("border color %x\n", m_borderidx); break; case 2: { m_intpos = data; int intx = (159 - ((m_intpos >> 8) & 255)) * ((m_dispctrl & 0x100) ? 2 : 4); int inty = 199 - (m_intpos & 255); m_intaddr = 0; bool bank = m_dispctrl & 0x4000; bool ibm_mode = m_dispctrl & 0x2000; // bool interleave = m_dispctrl & 0x0800; int pixels_per_byte_order = (m_dispctrl & 0x0600) >> 9; bool large_pixels = m_dispctrl & 0x0100; if(ibm_mode) m_intaddr = (inty & 1) * 0x2000 + (inty >> 1) * 80 + (intx >> (3 - large_pixels)) ; else { int stepy = 0; if(pixels_per_byte_order == 2) stepy = 40; if(pixels_per_byte_order == 1) stepy = 80; if(pixels_per_byte_order == 0) stepy = 160; m_intaddr = inty * stepy + (intx >> (pixels_per_byte_order - large_pixels + 2)); } if(bank) m_intaddr += 16000; logerror("interrupt position (%3d, %3d) ramdac address %04x\n", intx, inty, m_intaddr); break; } case 4: { data = sw(data); u8 r = (0x49*(data & 7)) >> 1; u8 g = (0x49*((data & 0x38) >> 3)) >> 1; u8 b = (0x49*((data & 0x1c0) >> 6)) >> 1; m_palette[m_borderidx] = (r << 16) | (g << 8) | b; m_genlock[m_borderidx] = data & 0x0200; logerror("palette[%x] = %04x -> %06x.%d\n", m_borderidx, data, m_palette[m_borderidx], m_genlock[m_borderidx]); m_borderidx = (m_borderidx + 1) & 0xf; break; } case 5: { logerror("genlock %s%s, extra=%c\n", data & 0x0200 ? "on" : "off", data & 0x0100 ? " fixed" : "", data & 0x0400 ? '1' : '0'); break; } default: logerror("display reg[%x] = %04x\n", m_dispctrl & 0xf, data); } } u32 mindset_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { // Temporary gross hack if(cliprect.max_y != 479) return 0; const u16 *bank = m_dispctrl & 0x4000 ? m_vram + 8000 : m_vram; bool ibm_mode = m_dispctrl & 0x2000; bool interleave = m_dispctrl & 0x0800; int pixels_per_byte_order = (m_dispctrl & 0x0600) >> 9; bool large_pixels = m_dispctrl & 0x0100; bitmap.fill(m_palette[m_borderidx]); int dx = ((m_screenpos >> 8) & 15) * (751 - 640) / 15; int dy = ((m_screenpos >> 12) & 15) * (480 - 400) / 15; if(ibm_mode) { if(large_pixels) { static int palind[4] = { 0, 1, 4, 5 }; for(int field=0; field<2; field++) { for(u32 yy=0; yy<2; yy++) { const u16 *src = bank + 4096*yy; for(u32 y=yy; y<200; y+=2) { u32 *dest = &bitmap.pix32(2*y+field+dy, dx); for(u32 x=0; x<320; x+=8) { u16 sv = sw(*src++); for(u32 xx=0; xx<8; xx++) { u32 color = m_palette[palind[(sv >> (14-2*xx)) & 3]]; *dest++ = color; *dest++ = color; } } } } } return 0; } else { static int palind[4] = { 0, 4 }; for(int field=0; field<2; field++) { for(u32 yy=0; yy<2; yy++) { const u16 *src = bank + 4096*yy; for(u32 y=yy; y<200; y+=2) { u32 *dest = &bitmap.pix32(2*y+field+dy, dx); for(u32 x=0; x<640; x+=16) { u16 sv = sw(*src++); for(u32 xx=0; xx<16; xx++) { u32 color = m_palette[palind[(sv >> (15-xx)) & 1]]; *dest++ = color; } } } } } return 0; } } else { if(large_pixels) { if(!interleave) { switch(pixels_per_byte_order) { case 0: { const u16 *src = bank; for(u32 y=0; y<200; y++) { u32 *dest0 = &bitmap.pix32(2*y+dy, dx); u32 *dest1 = &bitmap.pix32(2*y+1+dy, dx); for(u32 x=0; x<320; x+=4) { u16 sv = sw(*src++); for(u32 xx=0; xx<4; xx++) { u32 color = m_palette[(sv >> (12-4*xx)) & 15]; *dest0++ = color; *dest0++ = color; *dest1++ = color; *dest1++ = color; } } } return 0; } case 1: { static int palind[4] = { 0, 1, 4, 5 }; const u16 *src = bank; for(u32 y=0; y<200; y++) { u32 *dest0 = &bitmap.pix32(2*y+dy, dx); u32 *dest1 = &bitmap.pix32(2*y+1+dy, dx); for(u32 x=0; x<320; x+=8) { u16 sv = sw(*src++); for(u32 xx=0; xx<8; xx++) { u32 color = m_palette[palind[(sv >> (14-2*xx)) & 3]]; *dest0++ = color; *dest0++ = color; *dest1++ = color; *dest1++ = color; } } } return 0; } case 2: { const u16 *src = bank; for(u32 y=0; y<200; y++) { u32 *dest0 = &bitmap.pix32(2*y+dy, dx); u32 *dest1 = &bitmap.pix32(2*y+1+dy, dx); for(u32 x=0; x<320; x+=16) { u16 sv = sw(*src++); for(u32 xx=0; xx<16; xx++) { u32 color = m_palette[(sv >> (15-xx)) & 1]; *dest0++ = color; *dest0++ = color; *dest1++ = color; *dest1++ = color; } } } return 0; } } } else { switch(pixels_per_byte_order) { case 0: { const u16 *src = bank; for(u32 y=0; y<400; y++) { u32 *dest = &bitmap.pix32(y+dy, dx); for(u32 x=0; x<320; x+=4) { u16 sv = sw(*src++); for(u32 xx=0; xx<4; xx++) { u32 color = m_palette[(sv >> (12-4*xx)) & 15]; *dest++ = color; *dest++ = color; } } } return 0; } case 1: { static int palind[4] = { 0, 1, 4, 5 }; const u16 *src = bank; for(u32 y=0; y<400; y++) { u32 *dest = &bitmap.pix32(y+dy, dx); for(u32 x=0; x<320; x+=8) { u16 sv = sw(*src++); for(u32 xx=0; xx<8; xx++) { u32 color = m_palette[palind[(sv >> (14-2*xx)) & 3]]; *dest++ = color; *dest++ = color; } } } return 0; } } } } else { if(!interleave) { switch(pixels_per_byte_order) { case 0: { static int palind[4] = { 0, 4, 8, 12 }; const u16 *src = bank; for(u32 y=0; y<200; y++) { u32 *dest0 = &bitmap.pix32(2*y+dy, dx); u32 *dest1 = &bitmap.pix32(2*y+1+dy, dx); for(u32 x=0; x<640; x+=8) { u16 sv = sw(*src++); for(u32 xx=0; xx<8; xx++) { u32 color = m_palette[palind[(sv >> (14-2*xx)) & 3]]; *dest0++ = color; *dest1++ = color; } } } return 0; } case 1: { static int palind[4] = { 0, 4 }; const u16 *src = bank; for(u32 y=0; y<200; y++) { u32 *dest0 = &bitmap.pix32(2*y+dy, dx); u32 *dest1 = &bitmap.pix32(2*y+1+dy, dx); for(u32 x=0; x<640; x+=16) { u16 sv = sw(*src++); for(u32 xx=0; xx<16; xx++) { u32 color = m_palette[palind[(sv >> (15-xx)) & 1]]; *dest0++ = color; *dest1++ = color; } } } return 0; } } } else { static int palind[4] = { 0, 4 }; const u16 *src = bank; for(u32 y=0; y<400; y++) { u32 *dest = &bitmap.pix32(y+dy, dx); for(u32 x=0; x<640; x+=16) { u16 sv = sw(*src++); for(u32 xx=0; xx<16; xx++) { u32 color = m_palette[palind[(sv >> (15-xx)) & 1]]; *dest++ = color; } } } return 0; } } logerror("Unimplemented native mode (%dx%d, ppb=%d)\n", large_pixels ? 320 : 640, interleave ? 400 : 200, 2 << pixels_per_byte_order); } bitmap.fill(0); return 0; } u16 mindset_state::gcp_blend_0(u16 src, u16) { return src; } u16 mindset_state::gcp_blend_1(u16 src, u16 dst) { return src & dst; } u16 mindset_state::gcp_blend_2(u16 src, u16 dst) { return src | dst; } u16 mindset_state::gcp_blend_3(u16 src, u16 dst) { return src ^ dst; } u16 mindset_state::gcp_blend_4(u16 src, u16) { return ~src; } u16 mindset_state::gcp_blend_5(u16 src, u16 dst) { return (~src) & dst; } u16 mindset_state::gcp_blend_6(u16 src, u16 dst) { return (~src) | dst; } u16 mindset_state::gcp_blend_7(u16 src, u16 dst) { return (~src) ^ dst; } u16 (*const mindset_state::gcp_blend[8])(u16, u16) = { gcp_blend_0, gcp_blend_1, gcp_blend_2, gcp_blend_3, gcp_blend_4, gcp_blend_5, gcp_blend_6, gcp_blend_7 }; void mindset_state::blit(u16 packet_seg, u16 packet_adr) { u16 mode = sw(m_gcps->read_word((packet_seg << 4) + ((packet_adr + 0) & 0xffff))); u16 src_adr = sw(m_gcps->read_word((packet_seg << 4) + ((packet_adr + 2) & 0xffff))); u16 src_sft = sw(m_gcps->read_word((packet_seg << 4) + ((packet_adr + 4) & 0xffff))); u16 dst_adr = sw(m_gcps->read_word((packet_seg << 4) + ((packet_adr + 6) & 0xffff))); u16 dst_sft = sw(m_gcps->read_word((packet_seg << 4) + ((packet_adr + 8) & 0xffff))); u16 width = sw(m_gcps->read_word((packet_seg << 4) + ((packet_adr + 10) & 0xffff))); u16 height = sw(m_gcps->read_word((packet_seg << 4) + ((packet_adr + 12) & 0xffff))); u16 sy = sw(m_gcps->read_word((packet_seg << 4) + ((packet_adr + 14) & 0xffff))); u16 dy = sw(m_gcps->read_word((packet_seg << 4) + ((packet_adr + 16) & 0xffff))); u16 rmask = sw(m_gcps->read_word((packet_seg << 4) + ((packet_adr + 18) & 0xffff))); u16 src_seg = sw(m_gcps->read_word((packet_seg << 4) + ((packet_adr + 20) & 0xffff))); u16 dst_seg = sw(m_gcps->read_word((packet_seg << 4) + ((packet_adr + 22) & 0xffff))); u16 wmask = sw(m_gcps->read_word((packet_seg << 4) + ((packet_adr + 24) & 0xffff))); u16 kmask = sw(m_gcps->read_word((packet_seg << 4) + ((packet_adr + 26) & 0xffff))); // -f-w wnpi ktxm mm-- // f = fast (pure word copy) // w = pixel width (1/2/4/8 bits) // n = invert collision flag (unimplemented) // p = pattern fill (used by fill_dest_buffer) // i/f = increment source / don't (used by blt_copy_word) // t/o = transparent/opaque // k = detect collision (unimplemented) // x = go right to left (unimplemented) // m = blending mode if(0) logerror("GCP: p src %04x:%04x.%x dst %04x:%04x.%x sz %xx%x step %x:%x mask %04x:%04x k %x:%x mode %c%d%c%c%c%c%c%c%d\n", src_seg, src_adr, src_sft, dst_seg, dst_adr, dst_sft, width, height, sy, dy, rmask, wmask, (kmask >> 8) & 15, kmask & 15, mode & 0x4000 ? 'f' : '-', (mode >> 11) & 3, mode & 0x400 ? 'n' : '-', mode & 0x200 ? 'p' : '-', mode & 0x100 ? 'i' : 'f', mode & 0x80 ? 'k' : '-', mode & 0x40 ? 't' : 'o', mode & 0x20 ? 'x' : '-', (mode >> 2) & 7); if(mode & 0x200) { // pattern fill u16 src = m_gcps->read_word((src_seg << 4) + src_adr); for(u16 w=0; w != width/2; w++) { m_gcps->write_word((dst_seg << 4) + dst_adr, src); dst_adr += 2; } } else if(mode & 0x4000) { // fast mode u32 nw = (width+15) >> 4; for(u32 y=0; ywrite_word((dst_seg << 4) + dst_cadr, m_gcps->read_word((src_seg << 4) + src_cadr)); src_cadr += 2; dst_cadr += 2; } src_adr += sy; dst_adr += dy; } } else { auto blend = gcp_blend[(mode >> 2) & 7]; // Need to rotate rmask depending on the shifts too u16 awmask = ((wmask << 16) | wmask) >> (15 - dst_sft); u16 swmask, mwmask, ewmask; if(dst_sft >= width) { swmask = msk(dst_sft+1) & ~msk(dst_sft - width + 1); mwmask = 0xffff; ewmask = swmask; } else { swmask = msk(dst_sft+1); mwmask = 0xffff; ewmask = ~msk((dst_sft - width + 1) & 15); } swmask &= awmask; mwmask &= awmask; ewmask &= awmask; bool preload = dst_sft > src_sft; int src_do_sft = 15 - src_sft; int dst_do_sft = (preload ? 31 : 15) - dst_sft; u16 nw = ((width + (15 - dst_sft)) + 15) >> 4; for(u32 y=0; yread_word((src_seg << 4) + src_cadr)) << src_do_sft; if(mode & 0x100) src_cadr += 2; } do { srcs = (srcs << 16) | (sw(m_gcps->read_word((src_seg << 4) + src_cadr)) << src_do_sft); u16 src = (srcs >> dst_do_sft) & rmask; u16 dst = sw(m_gcps->read_word((dst_seg << 4) + dst_cadr)); u16 res = blend(src, dst); if(mode & 0x40) { u16 tmask; switch((mode >> 11) & 3) { case 0: default: tmask = src; break; case 1: tmask = (src >> 1) | src; tmask = (tmask & 0x5555) * 0x3; break; case 2: tmask = (src >> 2) | src; tmask = (tmask >> 1) | tmask; tmask = (tmask & 0x1111) * 0xf; break; case 3: tmask = (src >> 4) | src; tmask = (tmask >> 2) | tmask; tmask = (tmask >> 1) | tmask; tmask = (tmask & 0x0101) * 0xff; break; } cmask &= tmask; } res = (dst & ~cmask) | (res & cmask); m_gcps->write_word((dst_seg << 4) + dst_cadr, sw(res)); if(mode & 0x100) src_cadr += 2; dst_cadr += 2; nw1 --; cmask = nw1 == 1 ? ewmask : mwmask; } while(nw1); if(mode & 0x100) src_adr += sy; dst_adr += dy; } } } void mindset_state::gcp_w(u16) { u16 packet_seg = sw(m_gcps->read_word(0xbfd7a)); u16 packet_adr = sw(m_gcps->read_word(0xbfd78)); u16 global_mode = sw(m_gcps->read_word(0xbfd76)); if(0) logerror("GCP: start %04x:%04x mode %04x (%05x)\n", packet_seg, packet_adr, global_mode, m_maincpu->pc()); switch(global_mode) { case 0x0005: case 0x0101: blit(packet_seg, packet_adr); break; } // 100 = done, 200 = done too???, 400 = collision? m_gcps->write_word(0xbfd74, m_gcps->read_word(0xbfd74) | 0x0700); // Can trigger an irq, on mode & 2 (or is it 200?) (0x40 on 8282, ack on 0x41, which means the system 8042...) } void mindset_state::fdc_ctrl_w(u8 data) { logerror("fdc control %02x\n", data); if(data & 0x04) m_fdc->reset(); m_floppy[data & 1]->mon_w(!(data & 2)); m_floppy[(data & 1)^1]->mon_w(true); } void mindset_state::fdc_int_w(int state) { if(!m_fdc_intext && state) m_fdc_int = true; m_fdc_intext = state; m_maincpu->int0_w(m_fdc_int || m_trap_int); } u16 mindset_state::fdc_clear_interrupt() { m_fdc_int = false; m_maincpu->int0_w(m_fdc_int || m_trap_int); return 0x0000; } void mindset_state::fdc_dma_count_w(u16 data) { m_fdc_dma_count = data; logerror("fdc dma count %x\n", m_fdc_dma_count); } u8 mindset_state::fdc_dma_r() { u8 res = m_fdc->dma_r(); if(!m_fdc_dma_count) { m_fdc->tc_w(1); m_fdc->tc_w(0); } else m_fdc_dma_count--; return res; } void mindset_state::fdc_dma_w(u8 data) { m_fdc->dma_w(data); if(!m_fdc_dma_count) { m_fdc->tc_w(1); m_fdc->tc_w(0); } else m_fdc_dma_count--; } u16 mindset_state::trap_clear_interrupt() { m_trap_int = false; m_maincpu->int0_w(m_fdc_int || m_trap_int); return 0x0000; } u16 mindset_state::trap_r(offs_t offset) { // machine().debug_break(); logerror("trap_r %04x\n", offset << 1); m_trap_data[m_trap_len++] = (offset << 1) | 0x8000; m_trap_data[m_trap_len++] = 0; m_trap_drq = true; m_maincpu->drq1_w(m_fdc_drq || m_trap_drq); return 0; } void mindset_state::trap_w(offs_t offset, u16 data) { // machine().debug_break(); logerror("trap_w %04x, %04x\n", offset << 1, data); m_trap_data[m_trap_len++] = offset << 1; m_trap_data[m_trap_len++] = data; m_trap_drq = true; m_maincpu->drq1_w(m_fdc_drq || m_trap_drq); } u16 mindset_state::trap_dma_r(offs_t, u16 mem_mask) { u16 res = m_trap_pos < m_trap_len ? m_trap_data[m_trap_pos++] : 0; logerror("trap dma %04x @ %04x\n", res, mem_mask); if(m_trap_pos >= m_trap_len) { m_trap_drq = false; m_trap_int = true; m_maincpu->drq1_w(m_fdc_drq || m_trap_drq); m_maincpu->int0_w(m_fdc_int || m_trap_int); m_trap_pos = m_trap_len = 0; } return res; } void mindset_state::maincpu_mem(address_map &map) { map(0x00000, 0x3ffff).ram(); map(0xb8000, 0xbffff).ram().share("vram"); map(0xf8000, 0xfffff).rom().region("maincpu", 0); } void mindset_state::maincpu_io(address_map &map) { map(0x0000, 0x7fff).rw(FUNC(mindset_state::trap_r), FUNC(mindset_state::trap_w)); map(0x8040, 0x8041).r(FUNC(mindset_state::trap_dma_r)); map(0x8048, 0x8049).r(FUNC(mindset_state::trap_clear_interrupt)); map(0x8050, 0x8050).w(FUNC(mindset_state::fdc_ctrl_w)); map(0x8054, 0x8054).rw(FUNC(mindset_state::fdc_dma_r), FUNC(mindset_state::fdc_dma_w)); map(0x8058, 0x8059).w(FUNC(mindset_state::fdc_dma_count_w)); map(0x805c, 0x805d).r(FUNC(mindset_state::fdc_clear_interrupt)); map(0x8060, 0x8060).r(m_fdc, FUNC(i8272a_device::msr_r)); map(0x8062, 0x8062).rw(m_fdc, FUNC(i8272a_device::fifo_r), FUNC(i8272a_device::fifo_w)); #if 0 map(0x8080, 0x8080).lr8("id13", []() -> u8 { return 0x13; }); // sound map(0x80c0, 0x80c0).lr8("id3f", []() -> u8 { return 0x3f; }); // serial type 1, maybe? map(0x8100, 0x8100).lr8("id5f", []() -> u8 { return 0x5f; }); // serial type 2 map(0x8140, 0x8140).lr8("id70", []() -> u8 { return 0x70; }); // parallel printer, init writes 0x82 at +6 map(0x8180, 0x8180).lr8("rs232-id", []() -> u8 { return 0x73; }); // rs232 #endif map(0x8280, 0x8283).rw(m_syscpu, FUNC(i8042_device::upi41_master_r), FUNC(i8042_device::upi41_master_w)).umask16(0x00ff); map(0x82a0, 0x82a3).rw(m_soundcpu, FUNC(i8042_device::upi41_master_r), FUNC(i8042_device::upi41_master_w)).umask16(0x00ff); map(0x8300, 0x8301).w(FUNC(mindset_state::gcp_w)); map(0x8320, 0x8321).rw(FUNC(mindset_state::dispreg_r), FUNC(mindset_state::dispreg_w)); map(0x8322, 0x8323).rw(FUNC(mindset_state::dispctrl_r), FUNC(mindset_state::dispctrl_w)); } static void pc_dd_floppies(device_slot_interface &device) { device.option_add("525dd", FLOPPY_525_DD); } static void mindset_modules(device_slot_interface &device) { device.option_add("stereo", MINDSET_SOUND_MODULE); device.option_add("rs232", MINDSET_RS232_MODULE); } void mindset_state::mindset(machine_config &config) { config.set_perfect_quantum(m_syscpu); config.set_default_layout(layout_mindset); I80186(config, m_maincpu, 12_MHz_XTAL); // Divides internally by 2 to produce a clkout of 6MHz m_maincpu->set_addrmap(AS_PROGRAM, &mindset_state::maincpu_mem); m_maincpu->set_addrmap(AS_IO, &mindset_state::maincpu_io); I8042(config, m_syscpu, 14.318181_MHz_XTAL/2); m_syscpu->p1_in_cb().set(FUNC(mindset_state::sys_p1_r)); m_syscpu->p2_in_cb().set(FUNC(mindset_state::sys_p2_r)); m_syscpu->p1_out_cb().set(FUNC(mindset_state::sys_p1_w)); m_syscpu->p2_out_cb().set(FUNC(mindset_state::sys_p2_w)); m_syscpu->t0_in_cb().set(FUNC(mindset_state::sys_t0_r)); m_syscpu->t1_in_cb().set(FUNC(mindset_state::sys_t1_r)); I8042(config, m_soundcpu, 12_MHz_XTAL/2); m_soundcpu->p1_out_cb().set(FUNC(mindset_state::snd_p1_w)); m_soundcpu->p2_out_cb().set(FUNC(mindset_state::snd_p2_w)); I8749(config, m_kbdcpu, 6_MHz_XTAL); m_kbdcpu->p1_out_cb().set(FUNC(mindset_state::kbd_p1_w)); m_kbdcpu->p2_out_cb().set(FUNC(mindset_state::kbd_p2_w)); m_kbdcpu->bus_in_cb().set(FUNC(mindset_state::kbd_d_r)); m_kbdcpu->t1_in_cb().set(FUNC(mindset_state::kbd_t1_r)); // Should be NTSC actually... we'll see // Pretty sure the pixel clock is the 14.x one, the 12MHz one would only allow 630 pixels SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_refresh_hz(60); m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(100)); m_screen->set_size(751, 480); m_screen->set_visarea(0, 750, 0, 479); m_screen->set_screen_update(FUNC(mindset_state::screen_update)); // Should be at the position indicated by display reg 2 m_screen->scanline().set([this](int scanline) { m_maincpu->int2_w(scanline == 398); }); m_screen->screen_vblank().set(m_maincpu, FUNC(i80186_cpu_device::int1_w)); I8272A(config, m_fdc, 16_MHz_XTAL/2, true); m_fdc->intrq_wr_callback().set(FUNC(mindset_state::fdc_int_w)); m_fdc->drq_wr_callback().set([this](int state) { m_fdc_drq = state; m_maincpu->drq1_w(m_fdc_drq || m_trap_drq); }); m_fdc->set_ready_line_connected(false); FLOPPY_CONNECTOR(config, m_fdco[0], pc_dd_floppies, "525dd", mindset_state::floppy_formats); FLOPPY_CONNECTOR(config, m_fdco[1], pc_dd_floppies, "525dd", mindset_state::floppy_formats); SPEAKER(config, "lspeaker").front_left(); DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "lspeaker", 0.5); voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref")); vref.add_route(0, m_dac, 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, m_dac, -1.0, DAC_VREF_NEG_INPUT); MINDSET_MODULE(config, "m0", mindset_modules, "stereo", false); MINDSET_MODULE(config, "m1", mindset_modules, "rs232", false); MINDSET_MODULE(config, "m2", mindset_modules, nullptr, false); MINDSET_MODULE(config, "m3", mindset_modules, nullptr, false); MINDSET_MODULE(config, "m4", mindset_modules, nullptr, false); MINDSET_MODULE(config, "m5", mindset_modules, nullptr, false); SOFTWARE_LIST(config, "flop_list").set_original("mindset_flop"); } static INPUT_PORTS_START(mindset) PORT_START("K00") PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("K01") PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Start") PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PAUSE) PORT_NAME("Pause") PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F11) PORT_NAME("Sys config") PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F12) PORT_NAME("Reset") PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("K02") PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("K03") PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~') PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT)) PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PGUP) PORT_CHAR(UCHAR_MAMEKEY(PGUP)) PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break") PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("K04") PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t') PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("K05") PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PGDN) PORT_CHAR(UCHAR_MAMEKEY(PGDN)) PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_NAME("Caps lock") PORT_START("K06") PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) PORT_NAME("Control") PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("K07") PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"') PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_NAME("Return") PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("K08") PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(END)) PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT)) PORT_NAME("Alt") PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_NAME("Shift (Left)") PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("K09") PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_NAME("Shift (Right)") PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PRTSCR) PORT_CHAR(UCHAR_MAMEKEY(PRTSCR)) PORT_NAME("Prt Scn") PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_START("K10") PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("MOUSEAXIS1") PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(50) PORT_KEYDELTA(1) PORT_MINMAX(0, 255) PORT_PLAYER(1) PORT_START("MOUSEAXIS0") PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(1) PORT_MINMAX(0, 255) PORT_PLAYER(1) PORT_START("MOUSEBTN") PORT_BIT(0x1cf, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1) PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(1) PORT_START("JOYSTICK") PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_PLAYER(2) PORT_8WAY PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_PLAYER(2) PORT_8WAY PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_PLAYER(2) PORT_8WAY PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_PLAYER(2) PORT_8WAY PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2) PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(2) PORT_BIT(0x1c0, IP_ACTIVE_LOW, IPT_UNUSED) INPUT_PORTS_END ROM_START(mindset) ROM_REGION(0x8000, "maincpu", 0) ROM_LOAD16_BYTE("1.7_lo.u60", 0, 0x4000, CRC(00474dc1) SHA1(676f30f170c14174dbff3b5cbf98d0f23472b7c4)) ROM_LOAD16_BYTE("1.7_hi.u59", 1, 0x4000, CRC(1434af10) SHA1(39105eacdd7ddc13e449e2c32743e828bef33595)) ROM_REGION(0x0800, "syscpu", 0) ROM_LOAD("253002-001.u17", 0, 0x800, CRC(69da82c9) SHA1(2f0bf5b134dc703cbc72e0c6df5b7beda1b39e70)) ROM_REGION(0x0800, "soundcpu", 0) ROM_LOAD("253006-001.u16", 0, 0x800, CRC(7bea5edd) SHA1(30cdc0dedaa5246f4952df452a99ca22e3cd0636)) ROM_REGION(0x0800, "kbdcpu", 0) ROM_LOAD("kbd_v3.0.bin", 0, 0x800, CRC(1c6aa433) SHA1(1d01dbda4730f26125ba2564a608c2f8ddfc05b3)) ROM_END COMP( 1984, mindset, 0, 0, mindset, mindset, mindset_state, empty_init, "Mindset Corporation", "Mindset Personal Computer", MACHINE_SUPPORTS_SAVE)