diff --git a/src/devices/cpu/i386/i386.cpp b/src/devices/cpu/i386/i386.cpp index b10ae99b59b..be86d21afd8 100644 --- a/src/devices/cpu/i386/i386.cpp +++ b/src/devices/cpu/i386/i386.cpp @@ -2445,6 +2445,7 @@ void i386_device::zero_state() m_opcode_bytes_length = 0; memset(m_opcode_addrs, 0, sizeof(m_opcode_addrs)); m_opcode_addrs_index = 0; + m_dri_changed_active = false; } void i386_device::device_reset() diff --git a/src/devices/cpu/i386/i386.h b/src/devices/cpu/i386/i386.h index 07522e0fb9d..5c769994699 100644 --- a/src/devices/cpu/i386/i386.h +++ b/src/devices/cpu/i386/i386.h @@ -276,6 +276,7 @@ protected: memory_passthrough_handler m_dr_breakpoints[4]; util::notifier_subscription m_notifier; + bool m_dri_changed_active; //386 Debug Register change handlers. inline void dri_changed(); diff --git a/src/devices/cpu/i386/i386ops.hxx b/src/devices/cpu/i386/i386ops.hxx index 4a192738458..debd26ce224 100644 --- a/src/devices/cpu/i386/i386ops.hxx +++ b/src/devices/cpu/i386/i386ops.hxx @@ -736,9 +736,10 @@ void i386_device::i386_mov_dr_r32() // Opcode 0x0f 23 case 6: CYCLES(CYCLES_MOV_DR6_7_REG); m_dr[dr] = LOAD_RM32(modrm); break; case 7: { - dr7_changed(m_dr[7], rm32); - CYCLES(CYCLES_MOV_DR6_7_REG); + uint32_t old_dr7 = m_dr[7]; m_dr[dr] = rm32; + dr7_changed(old_dr7, m_dr[7]); + CYCLES(CYCLES_MOV_DR6_7_REG); break; } default: diff --git a/src/devices/cpu/i386/i386segs.hxx b/src/devices/cpu/i386/i386segs.hxx index 9015d0a3209..5bc3e0c903d 100644 --- a/src/devices/cpu/i386/i386segs.hxx +++ b/src/devices/cpu/i386/i386segs.hxx @@ -2479,7 +2479,11 @@ void i386_device::i386_protected_mode_iret(int operand32) inline void i386_device::dri_changed() { int dr; - if(!(m_dr[7] & 0xff)) return; + + if(m_dri_changed_active) + return; + m_dri_changed_active = true; + for(dr = 0; dr < 4; dr++) { m_dr_breakpoints[dr].remove(); @@ -2490,48 +2494,65 @@ inline void i386_device::dri_changed() int breakpoint_length = (m_dr[7] >> ((dr << 2) + 16 + 2)) & 3; uint32_t phys_addr = m_dr[dr]; uint32_t error; - phys_addr = translate_address(m_CPL, TRANSLATE_READ, &phys_addr, &error); - phys_addr &= ~3; // According to CUP386, data breakpoints are only reliable on dword-aligned addresses, so align this to a dword. - uint32_t true_mask = 0; - switch(breakpoint_length) + if(translate_address(m_CPL, TRANSLATE_READ, &phys_addr, &error)) { - case 0: true_mask = 0xff; break; - case 1: true_mask = 0xffff; break; - // Case 2 is invalid on a real 386. - case 3: true_mask = 0xffffffff; break; + phys_addr &= ~3; // According to CUP386, data breakpoints are only reliable on dword-aligned addresses, so align this to a dword. + uint32_t true_mask = 0; + switch(breakpoint_length) + { + case 0: true_mask = 0xff; break; + case 1: true_mask = 0xffff; break; + // Case 2 is invalid on a real 386. + case 3: true_mask = 0xffffffff; break; + } + if(true_mask == 0) + { + logerror("i386: Unknown breakpoint length value\n"); + } + else if(breakpoint_type == 1) + { + m_dr_breakpoints[dr] = m_program->install_write_tap( + phys_addr, + phys_addr + 3, + "i386_debug_write_breakpoint", + [this, dr, true_mask](offs_t offset, u32& data, u32 mem_mask) + { + if(true_mask & mem_mask) + { + m_dr[6] |= 1 << dr; + i386_trap(1,1,0); + } + }, + &m_dr_breakpoints[dr]); + } + else if(breakpoint_type == 3) + { + m_dr_breakpoints[dr] = m_program->install_readwrite_tap( + phys_addr, + phys_addr + 3, + "i386_debug_readwrite_breakpoint", + [this, dr, true_mask](offs_t offset, u32& data, u32 mem_mask) + { + if(true_mask & mem_mask) + { + m_dr[6] |= 1 << dr; + i386_trap(1,1,0); + } + }, + [this, dr, true_mask](offs_t offset, u32& data, u32 mem_mask) + { + if(true_mask & mem_mask) + { + m_dr[6] |= 1 << dr; + i386_trap(1,1,0); + } + }, + &m_dr_breakpoints[dr]); + } } - if(true_mask == 0) - { - logerror("i386: Unknown breakpoint length value\n"); - } - else if(breakpoint_type == 1) m_dr_breakpoints[dr] = m_program->install_write_tap(phys_addr, phys_addr + 3, "i386_debug_write_breakpoint", - [&, dr, true_mask](offs_t offset, u32& data, u32 mem_mask) - { - if(true_mask & mem_mask) - { - m_dr[6] |= 1 << dr; - i386_trap(1,0,0); - } - }, &m_dr_breakpoints[dr]); - else if(breakpoint_type == 3) m_dr_breakpoints[dr] = m_program->install_readwrite_tap(phys_addr, phys_addr + 3, "i386_debug_readwrite_breakpoint", - [this, dr, true_mask](offs_t offset, u32& data, u32 mem_mask) - { - if(true_mask & mem_mask) - { - m_dr[6] |= 1 << dr; - i386_trap(1,0,0); - } - }, - [this, dr, true_mask](offs_t offset, u32& data, u32 mem_mask) - { - if(true_mask & mem_mask) - { - m_dr[6] |= 1 << dr; - i386_trap(1,0,0); - } - }, &m_dr_breakpoints[dr]); } } + m_dri_changed_active = false; } inline void i386_device::dr7_changed(uint32_t old_val, uint32_t new_val) diff --git a/src/devices/machine/53c7xx.cpp b/src/devices/machine/53c7xx.cpp index 00d111f54e9..a99b9d797cb 100644 --- a/src/devices/machine/53c7xx.cpp +++ b/src/devices/machine/53c7xx.cpp @@ -292,7 +292,8 @@ uint32_t ncr53c7xx_device::read(offs_t offset, uint32_t mem_mask) if (ACCESSING_BITS_0_7) { ret = m_dstat; - m_dstat = 0; + // DFE isn't cleared on read + m_dstat &= DSTAT_DFE; update_irqs(); } if (ACCESSING_BITS_8_15) diff --git a/src/devices/machine/z80scc.cpp b/src/devices/machine/z80scc.cpp index 81a35652df5..be9d4d6f86d 100644 --- a/src/devices/machine/z80scc.cpp +++ b/src/devices/machine/z80scc.cpp @@ -1077,6 +1077,9 @@ void z80scc_channel::device_start() m_tx_fifo_sz = (m_uart->m_variant & z80scc_device::SET_ESCC) ? 4 : 1; m_tx_fifo_wp = m_tx_fifo_rp = 0; + m_rxc = 0x00; + m_txc = 0x00; + #if Z80SCC_USE_LOCAL_BRG // baudrate clocks and timers baudtimer = timer_alloc(TIMER_ID_BAUD); @@ -1137,6 +1140,11 @@ void z80scc_channel::device_start() save_item(NAME(m_rts)); save_item(NAME(m_tx_int_disarm)); save_item(NAME(m_sync_pattern)); + save_item(NAME(m_rxd)); + save_item(NAME(m_rcv_mode)); + save_item(NAME(m_index)); + save_item(NAME(m_brg_rate)); + save_item(NAME(m_delayed_tx_brg_change)); } diff --git a/src/mame/drivers/rastersp.cpp b/src/mame/drivers/rastersp.cpp index 59e4c3c37bc..a5c9eaf267b 100644 --- a/src/mame/drivers/rastersp.cpp +++ b/src/mame/drivers/rastersp.cpp @@ -8,21 +8,26 @@ Games supported: * Rise of the Robots (prototype) + * Football Crazy ROMs wanted: * Zool (prototype) - * Football Crazy (need HDD/CD image) + * Wiggle ****************************************************************************/ #include "emu.h" +#include "bus/nscsi/cd.h" #include "bus/nscsi/hd.h" #include "cpu/i386/i386.h" #include "cpu/tms32031/tms32031.h" #include "machine/53c7xx.h" +#include "machine/bacta_datalogger.h" #include "machine/mc146818.h" #include "machine/nvram.h" #include "machine/timer.h" +#include "machine/watchdog.h" +#include "machine/z80scc.h" #include "sound/dac.h" #include "emupal.h" #include "screen.h" @@ -54,17 +59,49 @@ public: : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") , m_dsp(*this, "dsp") + , m_duart(*this, "duart") , m_dram(*this, "dram") , m_ldac(*this, "ldac") , m_rdac(*this, "rdac") , m_palette(*this, "palette") , m_nvram(*this, "nvram") + , m_watchdog(*this, "watchdog") , m_tms_timer1(nullptr) , m_tms_tx_timer(nullptr) { } void rastersp(machine_config &config); + void rs_config_base(machine_config &config); + +protected: + virtual void machine_reset() override; + virtual void machine_start() override; + virtual void video_start() override; + + uint8_t interrupt_ctrl_r(offs_t offset); + void interrupt_ctrl_w(offs_t offset, uint8_t data); + uint8_t nvram_r(offs_t offset); + void nvram_w(offs_t offset, uint8_t data); + + void cpu_map_base(address_map &map); + void io_map(address_map &map); + void dsp_map_base(address_map &map); + + required_device m_maincpu; + required_device m_dsp; + required_device m_duart; + + void update_irq(uint32_t which, uint32_t state); + + enum irq_status + { + IRQ_RTC = 1, + IRQ_UART = 2, + IRQ_SCSI = 3, + IRQ_DSP = 4, + IRQ_VBLANK = 5, + }; private: #define VIDEO_ADDR_MASK 0x3fffffff @@ -94,29 +131,17 @@ private: SPORT_DATA_RX = 0x4c }; - enum irq_status - { - IRQ_RTC = 1, - IRQ_UART = 2, - IRQ_DSP = 4, - IRQ_VBLANK = 5, - IRQ_SCSI = 7 - }; - - required_device m_maincpu; - required_device m_dsp; required_shared_ptr m_dram; required_device m_ldac; required_device m_rdac; required_device m_palette; required_device m_nvram; + required_device m_watchdog; emu_timer *m_tms_timer1; emu_timer *m_tms_tx_timer; void cyrix_cache_w(uint32_t data); - uint8_t nvram_r(offs_t offset); - void nvram_w(offs_t offset, uint8_t data); void port1_w(uint32_t data); void port2_w(uint32_t data); void port3_w(uint32_t data); @@ -135,31 +160,77 @@ private: TIMER_CALLBACK_MEMBER(tms_timer1); TIMER_CALLBACK_MEMBER(tms_tx_timer); DECLARE_WRITE_LINE_MEMBER(vblank_irq); - - std::unique_ptr m_nvram8; - uint8_t m_irq_status = 0; - uint32_t m_dpyaddr = 0; - std::unique_ptr m_paletteram; - uint32_t m_speedup_count = 0; - uint32_t m_tms_io_regs[0x80]{}; - bitmap_ind16 m_update_bitmap; + DECLARE_WRITE_LINE_MEMBER(duart_irq); uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - void update_irq(uint32_t which, uint32_t state); void upload_palette(uint32_t word1, uint32_t word2); IRQ_CALLBACK_MEMBER(irq_callback); nscsi_connector &add_rastersp_scsi_slot(machine_config &config, const char *tag, const char *default_slot); static void ncr53c700_config(device_t *device); void cpu_map(address_map &map); void dsp_map(address_map &map); - void io_map(address_map &map); + uint8_t interrupt_status_r(offs_t offset); - // driver_device overrides - virtual void machine_reset() override; - virtual void machine_start() override; - virtual void video_start() override; + std::unique_ptr m_nvram8; + uint8_t m_irq_status; + uint32_t m_dlba; + std::unique_ptr m_paletteram; + uint8_t m_palette_number; + uint32_t m_speedup_count; + uint32_t m_tms_io_regs[0x80]; + bitmap_ind16 m_update_bitmap; + + uint8_t m_port2_data; + uint32_t m_last_watchdog; + int m_left_volume; + int m_right_volume; + uint8_t m_interrupt_mask; + uint8_t m_dsp_ctrl_data; }; +class fbcrazy_state : public rastersp_state +{ +public: + fbcrazy_state(const machine_config &mconfig, device_type type, const char *tag) + : rastersp_state(mconfig, type, tag) + , m_io_track_x(*this, "TRACK_X") + , m_io_track_y(*this, "TRACK_Y") + , m_trackball_timer(nullptr) + { + } + + void fbcrazy(machine_config &config); + + DECLARE_READ_LINE_MEMBER(meter_pulse_r); + +protected: + virtual void machine_reset() override; + virtual void machine_start() override; + +private: + required_ioport m_io_track_x; + required_ioport m_io_track_y; + emu_timer *m_trackball_timer; + + void aux_port0_w(offs_t offset, uint8_t data); + void aux_port1_w(offs_t offset, uint8_t data); + void aux_port2_w(offs_t offset, uint8_t data); + void aux_port3_w(offs_t offset, uint8_t data); + void aux_port4_w(offs_t offset, uint8_t data); + + void cpu_map(address_map &map); + void dsp_map(address_map &map); + + TIMER_CALLBACK_MEMBER(trackball_timer); + DECLARE_WRITE_LINE_MEMBER(trackball_rts); + + uint8_t m_aux_port3_data; + uint8_t m_trackball_ctr; + uint8_t m_trackball_data[3]; + uint16_t m_oldxpos; + uint16_t m_oldypos; + uint8_t m_trackball_enabled; +}; /************************************* @@ -176,7 +247,7 @@ void rastersp_state::machine_start() membank("bank1")->set_base(m_dram); membank("bank2")->set_base(&m_dram[0x10000/4]); - membank("bank3")->set_base(&m_dram[0x300000/4]); + //membank("bank3")->set_base(&m_dram[0x300000/4]); if (!m_tms_timer1) m_tms_timer1 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(rastersp_state::tms_timer1), this)); @@ -188,13 +259,49 @@ void rastersp_state::machine_start() m_dsp->space(AS_PROGRAM).install_read_handler(0x809923, 0x809923, read32smo_delegate(*this, FUNC(rastersp_state::dsp_speedup_r))); m_dsp->space(AS_PROGRAM).install_write_handler(0x809923, 0x809923, write32smo_delegate(*this, FUNC(rastersp_state::dsp_speedup_w))); #endif + + save_item(NAME(m_irq_status)); + save_item(NAME(m_dlba)); + save_pointer(NAME(m_paletteram), 0x8000); + save_item(NAME(m_palette_number)); + save_item(NAME(m_speedup_count)); + save_item(NAME(m_tms_io_regs)); + save_item(NAME(m_port2_data)); + save_item(NAME(m_last_watchdog)); + save_item(NAME(m_left_volume)); + save_item(NAME(m_right_volume)); + save_item(NAME(m_interrupt_mask)); + save_item(NAME(m_dsp_ctrl_data)); } +void fbcrazy_state::machine_start() +{ + rastersp_state::machine_start(); + + m_trackball_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(fbcrazy_state::trackball_timer), this)); + + save_item(NAME(m_aux_port3_data)); + save_item(NAME(m_trackball_ctr)); + save_item(NAME(m_trackball_data)); + save_item(NAME(m_oldxpos)); + save_item(NAME(m_oldypos)); + save_item(NAME(m_trackball_enabled)); +} void rastersp_state::machine_reset() { m_irq_status = 0; - m_dpyaddr = 0; + m_dlba = 0; + m_palette_number = 0; + + m_last_watchdog = 0; + m_port2_data = 0; + m_left_volume = 0; + m_right_volume = 0; + m_interrupt_mask = 0; + + m_dsp_ctrl_data = 0; + // Halt the 486 on reset - the DSP will release it from reset m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); @@ -210,6 +317,23 @@ void rastersp_state::machine_reset() m_tms_tx_timer->adjust(attotime::never); } +void fbcrazy_state::machine_reset() +{ + attotime period; + + rastersp_state::machine_reset(); + + m_aux_port3_data = 0; + + m_trackball_ctr = 0; + m_trackball_data[0] = m_trackball_data[1] = m_trackball_data[2] = 0; + m_oldxpos = 0; + m_oldypos = 0; + m_trackball_enabled = 0; + + period = attotime::from_hz(1200); // 1200 baud + m_trackball_timer->adjust(period, 0, period); +} /************************************* @@ -226,50 +350,57 @@ void rastersp_state::video_start() void rastersp_state::dpylist_w(uint32_t data) { - m_dpyaddr = data; + uint32_t word1 = 0; + m_dlba = data; // Update the video now // TODO: This should probably be done in sync with the video scan - if (m_dpyaddr == 0) + if (!BIT(m_dlba, 7)) { m_update_bitmap.fill(m_palette->black_pen()); return; } - uint32_t dpladdr = (m_dpyaddr & ~0xff) >> 6; - - if ((m_dpyaddr & 0xff) != 0xb2 && (m_dpyaddr & 0xff) != 0xf2) - logerror("Unusual display list data: %x\n", m_dpyaddr); + uint32_t dpladdr = (m_dlba & ~0xff) >> 6; int y = 0; int x = 0; uint16_t *bmpptr = &m_update_bitmap.pix(0, 0); + // Note that you can have a control word (top bit setp) without an address if the control word doesn't need data + // You can also have a single address word which is used by multiple control words. while (y < 240) { - uint32_t word1 = m_dram[dpladdr/4]; + uint32_t word2 = m_dram[dpladdr/4]; + dpladdr += 4; - if (word1 & 0x80000000) + if (!(word2 & 0x80000000)) { - // TODO: What does this signify? - dpladdr += 4; + // Not a control word so it's the data address + word1 = word2; } else { - uint32_t word2 = m_dram[(dpladdr + 4)/4]; - - dpladdr += 8; - - if (word2 & 0x10000000) + // You're allowed to change the palette for 8 bit pixels even if the + // control word is for 16 bit pixels! + if (word2 & 0x40000000) { - if ((word2 & 0xfe000000) != 0x94000000) - logerror("Unusual display list entry: %x %x\n", word1, word2); + m_palette_number &= 0x0f; + m_palette_number |= ((word2 >> 8) & 0xf0); + } + else + { + m_palette_number &= 0xf0; + m_palette_number |= ((word2 >> 12) & 0x0f); + } + if ((word2 & 0xbe000000) == 0x94000000) + { + // 8 bit pixels using palette uint32_t srcaddr = word1 >> 8; uint32_t pixels = (word2 >> 16) & 0x1ff; - uint32_t palbase = (word2 >> 4) & 0xf00; - uint16_t* palptr = &m_paletteram[palbase]; + uint16_t* palptr = &m_paletteram[m_palette_number*256]; uint8_t* srcptr = reinterpret_cast(&m_dram[0]); uint32_t acc = srcaddr << 8; @@ -279,7 +410,6 @@ void rastersp_state::dpylist_w(uint32_t data) // Sign extend for our convenience incr |= ~((incr & 0x800) - 1) & ~0xff; - // TODO: Assumes 8-bit palettized mode - the hardware also supports 16-bit direct while (y < 240 && pixels) { while (x < 320 && pixels) @@ -299,12 +429,47 @@ void rastersp_state::dpylist_w(uint32_t data) } } } + else if ((word2 & 0xbe000000) == 0x84000000) + { + // 16-bit pixels + uint32_t srcaddr = word1 >> 8; + uint32_t pixels = (word2 >> 16) & 0x1ff; + + uint16_t* srcptr = reinterpret_cast(&m_dram[0]); + + uint32_t acc = srcaddr << 8; + + int32_t incr = word2 & 0xfff; + + // Sign extend for our convenience + incr |= ~((incr & 0x800) - 1) & ~0xff; + + while (y < 240 && pixels) + { + while (x < 320 && pixels) + { + *bmpptr++ = srcptr[WORD_XOR_LE(acc >> 9)]; + acc = (acc + incr) & VIDEO_ADDR_MASK; + + --pixels; + ++x; + } + + // Advance to the next scanline + if (x >= 320) + { + x = 0; + ++y; + } + } + } + else if ((word2 & 0xbe000000) == 0x8c000000) + { + upload_palette(word1, word2); + } else { - if ((word2 & 0x0c000000) != 0x0c000000) - logerror("Unknown palette upload: %.8x %.8x\n", word1, word2); - - upload_palette(word1, word2); + fatalerror("Unknown control words! (%x, %x)\n", word1, word2); } } } @@ -313,19 +478,24 @@ void rastersp_state::dpylist_w(uint32_t data) void rastersp_state::upload_palette(uint32_t word1, uint32_t word2) { + /* + Palette entry format: + ........ ........ ........ ...xxxxx - Blue + ........ ........ .....xxx xxx..... - Green + ........ ........ xxxxx... ........ - Red + .......x xxxxxxxx ........ ........ - Entry number + */ if (word1 & 3) fatalerror("Unalligned palette address! (%x, %x)\n", word1, word2); uint32_t addr = word1 >> 8; uint32_t entries = (word2 >> 16) & 0x1ff; - uint32_t index = ((word2 >> 12) & 0x1f) * 256; + uint32_t index = m_palette_number * 256; - // The third byte of each entry in RAM appears to contain an index - // but appears to be discared when written to palette RAM while (entries--) { uint32_t data = m_dram[addr / 4]; - m_paletteram[index++] = data & 0xffff; + m_paletteram[index + ((data >> 16) & 0xff)] = data & 0xffff; addr += 4; } } @@ -333,40 +503,44 @@ void rastersp_state::upload_palette(uint32_t word1, uint32_t word2) /******************************************************************************* - Display list register: + Display pointer word: - ..xxxxxx xxxxxxxx xxxxxxxx ........ Display list base (DWORD granularity) - ........ ........ ........ xxxxxxxx ? (number of entries? Only seems to be valid for basic stuff) + xxxxxxxx xxxxxxxx xxxxxxxx ........ DLBA pointer (DWORD aligned) + ........ ........ ........ x....... Display enable + ........ ........ ........ ......xx Mode: + 00: 384x288 50Hz overscan + 01: 320x240 64Hz overscan + 02: 320x240 50Hz underscan + 03: invalid + + Control words: + + Set address + 0.xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Address - Display list format: - -[0] ..xxxxxx xxxxxxxx xxxxxxxx ........ Source address (4MB mask?) - -Palette update: (8d000400) -[1] 1....... ........ ........ ........ ? - ...0.... ........ ........ ........ 0 for palette upload? - ....11.. ........ ........ ........ ? + Palette update: + 1P0..... ........ ........ ........ P specifies whether palette entry is the bottom (when 0) or top (when 1) 4 bits of palette number + ...01... ........ ........ ........ Palette upload + .....10. ........ ........ ........ X address only .......x xxxxxxxx ........ ........ Entry count - ........ ........ .....1.. ........ ? (Usually 1) + ........ ........ xxxx.... ........ Palette (top 4 bits if 'P' is 1 or bottom 4 bits if 'P' is 0 + ........ ........ ....xxxx xxxxxxxx Scale (4.8 signed fixed point) -Pixel data: (94040100) -[2] 1....... ........ ........ ........ ? - ...1.... ........ ........ ........ 1 for video update? - .....1.. ........ ........ ........ ? + Pixel data, 8-bit palettized: + 1P0..... ........ ........ ........ P specifies whether palette entry is the bottom (when 0) or top (when 1) 4 bits of palette number + ...10... ........ ........ ........ 8 bit pixels with palette + .....10. ........ ........ ........ X address only .......x xxxxxxxx ........ ........ Pixel count - ........ ........ xxxx.... ........ Palette + ........ ........ xxxx.... ........ Palette (top 4 bits if 'P' is 1 or bottom 4 bits if 'P' is 0) ........ ........ ....xxxx xxxxxxxx Scale (4.8 signed fixed point) -Unknown: (D4000100) - Present at start of a list -[3] 1....... ........ ........ ......... - .1...... ........ ........ ......... ? - ..1..... ........ ........ ......... - .....1.. ........ ........ ......... ? - ........ ........ .......1 ......... ? - - - TODO: I'm not sure about bit 28. When creating the display list if it's 0, - 0x1000 is added to the source address. + Pixel data, 16-bit: + 1P0..... ........ ........ ........ P specifies whether palette entry is the bottom (when 0) or top (when 1) 4 bits of palette number + ...00... ........ ........ ........ 8 bit pixels with palette + .....10. ........ ........ ........ X address only + .......x xxxxxxxx ........ ........ Pixel count + ........ ........ xxxx.... ........ Unused + ........ ........ ....xxxx xxxxxxxx Scale (4.8 signed fixed point) *******************************************************************************/ @@ -388,7 +562,11 @@ IRQ_CALLBACK_MEMBER(rastersp_state::irq_callback) { uint8_t vector = 0; - if (m_irq_status & (1 << IRQ_SCSI)) + if (m_irq_status & (1 << IRQ_UART)) + { + vector = 10; + } + else if (m_irq_status & (1 << IRQ_SCSI)) { vector = 11; } @@ -427,6 +605,12 @@ void rastersp_state::update_irq(uint32_t which, uint32_t state) WRITE_LINE_MEMBER( rastersp_state::scsi_irq ) { update_irq(IRQ_SCSI, state); + + if (state && BIT(m_dsp_ctrl_data, 5)) + { + m_dsp->set_input_line(TMS3203X_IRQ0, ASSERT_LINE); + m_dsp->set_input_line(TMS3203X_IRQ0, CLEAR_LINE); + } } @@ -436,8 +620,122 @@ WRITE_LINE_MEMBER( rastersp_state::vblank_irq ) update_irq(IRQ_VBLANK, ASSERT_LINE); } +WRITE_LINE_MEMBER( rastersp_state::duart_irq ) +{ + update_irq(IRQ_UART, state); +} +WRITE_LINE_MEMBER( fbcrazy_state::trackball_rts ) +{ + m_trackball_enabled = state; +} + +/* + Mimic trackball unit. This uses a small PIC based interface board + which converts the trackball movement into RS232 data. + The data format is as follows: + Byte 0 : 0100abAB bits 7 & 6 = 01 signifies 1st byte + Byte 1 : 00CDEFGH bits 7 & 6 = 00 signifies 2 or 3rd byte (not identified) + Byte 2 : 00cdefgh + + The trackball X movement is ABCDEFGH and Y movement abcdefgh + We do not have a PCB nor a dump of the PIC :( +*/ +TIMER_CALLBACK_MEMBER(fbcrazy_state::trackball_timer) +{ + if (m_trackball_enabled) + { + if (m_trackball_ctr == 0) + { + uint16_t newxpos, newypos; + + newxpos = m_io_track_x->read(); + newypos = m_io_track_y->read(); + + int diffx, diffy; + diffx = newxpos - m_oldxpos; + diffy = newypos - m_oldypos; + + if (diffx<-3900) + { + diffx += 4096; + } + else if (diffx>3900) + { + diffx -= 4096; + } + if (diffx>127) + { + diffx = 127; + } + else if (diffx <-127) + { + diffx = -127; + } + + if (diffy<-3900) + { + diffy += 4096; + } + else if (diffy>3900) + { + diffy -= 4096; + } + if (diffy>127) + { + diffy = 127; + } + else if (diffy <-127) + { + diffy = -127; + } + + m_oldxpos = newxpos; + m_oldypos = newypos; + + //Format movement into 3 bytes as described above for tx + m_trackball_data[0] = 0x40 | ((diffy>>4)&0x0c) | ((diffx>>6)&0x03); + m_trackball_data[1] = diffx & 0x3f; + m_trackball_data[2] = diffy & 0x3f; + } + + if (m_trackball_ctr < 36) + { + //Transmitting data + uint8_t bitnum = m_trackball_ctr % 12 ; + if (bitnum == 0) + { + //start bit + m_duart->rxb_w(0); + } + else if (bitnum < 9) + { + //Data bits + m_duart->rxb_w(BIT(m_trackball_data[m_trackball_ctr / 12], bitnum - 1)); + } + else + { + //Stop bit and small gap + m_duart->rxb_w(1); + } + m_trackball_ctr++; + } + else + { + m_trackball_ctr = 0; + } + } + else + { + m_trackball_ctr = 0; + m_trackball_data[0] = 0; + m_trackball_data[1] = 0; + m_trackball_data[2] = 0; + m_duart->rxb_w(1); + } +} + /************************************* * * 486 I/O @@ -446,24 +744,65 @@ WRITE_LINE_MEMBER( rastersp_state::vblank_irq ) void rastersp_state::port1_w(uint32_t data) { - // x... .... - LED? - // ..x. .... - DSP IRQ2 line - // .... ..xx - LEDs? - - if (data & 0x20) + /* + x... .... - Watchdog kick + ..x. .... - DSP IRQ2 line + .... x... - Coin lockout A on ROTR and payout on Football Crazy + .... .x.. - Coin lockout B + .... ..x. - Coin meter A + .... ...x - Coin meter B + */ + if (BIT(data, 5) && BIT(m_dsp_ctrl_data, 5)) { m_dsp->set_input_line(TMS3203X_IRQ2, ASSERT_LINE); m_dsp->set_input_line(TMS3203X_IRQ2, CLEAR_LINE); } + + if (BIT(data, 7) != m_last_watchdog) + { + m_last_watchdog = BIT(data, 7); + + if (BIT(data, 7)) + m_watchdog->watchdog_reset(); + } } void rastersp_state::port2_w(uint32_t data) { - // .x.. .... - X9313WP /INC - // ..x. .... - X9313WP U/#D -} + /* + .x.. .... - X9313WP /INC + ..x. .... - X9313WP U/#D + ...x .... - Left audio volume CS (X9313) + .... x... - Right audio volume CS (X9313) + .... .xxx - Audio bitrate select + */ + uint8_t changed = m_port2_data ^ data; + m_port2_data = data; + + if (changed & 0x40) + { + // Digital volume clock line changed + if (!(data & 0x40)) + { + if (data & 0x20) + { + if (!(data & 0x10) && (m_left_volume < 31)) m_left_volume++; + if (!(data & 0x08) && (m_right_volume < 31)) m_right_volume++; + } + else + { + if (!(data & 0x10) && (m_left_volume > 0)) m_left_volume--; + if (!(data & 0x08) && (m_right_volume > 0)) m_right_volume--; + } + + m_ldac->set_output_gain(ALL_OUTPUTS, m_left_volume / 32.0f); + m_rdac->set_output_gain(ALL_OUTPUTS, m_right_volume / 32.0f); + } + } + +} void rastersp_state:: port3_w(uint32_t data) { @@ -511,12 +850,81 @@ uint8_t rastersp_state::nvram_r(offs_t offset) return m_nvram8[addr]; } +void fbcrazy_state::aux_port0_w(offs_t offset, uint8_t data) +{ + // Lamps 1-8 on bits 0-7 + // Bit 6, lamp 6, is Start lamp +} + +void fbcrazy_state::aux_port1_w(offs_t offset, uint8_t data) +{ + // Lamps 9-16 on bits 0-7 + // Bit 3, lamp 12, is SELECT button lamp +} + +void fbcrazy_state::aux_port2_w(offs_t offset, uint8_t data) +{ + // Lamps 17-22 on bits 0-5 + // Bit 6 Coin Validator lamp ? + // Bit 7 unused +} + +void fbcrazy_state::aux_port3_w(offs_t offset, uint8_t data) +{ + m_aux_port3_data = data; + // Bit 0 - unused + // Bit 1 - unused + // Bit 2 - Meter 3 + // Bit 3 - Meter 1 + // Bit 4 - Meter 2 + // Bit 5 - unused + // Bit 6 - unused + // Bit 7 - unused +} + +void fbcrazy_state::aux_port4_w(offs_t offset, uint8_t data) +{ + // Bit 0 - unused + // Bit 1 - unused + // Bit 2 - unused + // Bit 3 - 10p lockout + // Bit 4 - 20p lockout + // Bit 5 - 50p lockout + // Bit 6 - £1 lockout + // Bit 7 - 5p lockout +} + +READ_LINE_MEMBER(fbcrazy_state::meter_pulse_r) +{ + return m_aux_port3_data & 0xbc ? 1 : 0; +} + + void rastersp_state::cyrix_cache_w(uint32_t data) { // TODO? } +uint8_t rastersp_state::interrupt_ctrl_r(offs_t offset) +{ + return m_interrupt_mask; +} + +void rastersp_state::interrupt_ctrl_w(offs_t offset, uint8_t data) +{ + m_interrupt_mask = data;; +} + +uint8_t rastersp_state::interrupt_status_r(offs_t offset) +{ + // TODO: This returns something to do with interrupts + // Is it a bit pattern of the current interupt or a + // bit pattern of all interrupts pending? + // Either way, 0 works anyway! + return 0; +} + /************************************* @@ -654,10 +1062,13 @@ void rastersp_state::dsp_486_int_w(uint32_t data) void rastersp_state::dsp_ctrl_w(uint32_t data) { - // x... .... LED? - // .xx. .... 486 reset control? + // x... .... - Something to do with 486 bus access? + // .x.. .... - 486 reset control + // ..x. .... - Enable SCSI, UART, and 486 int to DSP - m_maincpu->set_input_line(INPUT_LINE_RESET, (data & 0x60) == 0x60 ? CLEAR_LINE : ASSERT_LINE); + m_maincpu->set_input_line(INPUT_LINE_RESET, (data & 0x40) ? CLEAR_LINE : ASSERT_LINE); + + m_dsp_ctrl_data = data; } @@ -685,22 +1096,43 @@ uint32_t rastersp_state::dsp_speedup_r() * * Memory maps * + * The FPGA limits access to the 1st 1MB of DRAM + * when A25 and A24 are both high + * *************************************/ +void rastersp_state::cpu_map_base(address_map &map) +{ + map(0x02200000, 0x022fffff).rw(FUNC(rastersp_state::nvram_r), FUNC(rastersp_state::nvram_w)).umask32(0x000000ff); + map(0x02200800, 0x02200803).rw(FUNC(rastersp_state::interrupt_ctrl_r),FUNC(rastersp_state::interrupt_ctrl_w)); + map(0x02208000, 0x02208fff).rw("scsibus:7:ncr53c700", FUNC(ncr53c7xx_device::read), FUNC(ncr53c7xx_device::write)); + map(0x0220e000, 0x0220e003).w(FUNC(rastersp_state::dpylist_w)); + map(0xfff00000, 0xffffffff).bankrw("bank1");//was 3 +} + void rastersp_state::cpu_map(address_map &map) { - map(0x00000000, 0x003fffff).ram().share("dram"); + cpu_map_base(map); + map(0x00000000, 0x003fffff).ram().share("dram"); // 4MB DRAM on original board map(0x01000000, 0x010bffff).noprw(); // External ROM - map(0x010c0000, 0x010cffff).rom().region("bios", 0); - map(0x02200000, 0x022fffff).rw(FUNC(rastersp_state::nvram_r), FUNC(rastersp_state::nvram_w)).umask32(0x000000ff); - map(0x02200800, 0x02200803).nopw(); // ? - map(0x02208000, 0x02208fff).rw("scsibus:7:ncr53c700", FUNC(ncr53c7xx_device::read), FUNC(ncr53c7xx_device::write)); - map(0x0220e000, 0x0220e003).w(FUNC(rastersp_state::dpylist_w)); - map(0xfff00000, 0xffffffff).bankrw("bank3"); +} + +void fbcrazy_state::cpu_map(address_map &map) +{ + cpu_map_base(map); + map(0x00000000, 0x007fffff).ram().share("dram"); // 8MB DRAM on Football Crazy board + map(0x01000000, 0x01000003).w( FUNC(fbcrazy_state::aux_port0_w)).umask32(0x000000ff); + map(0x01000000, 0x01000003).portr("AUX_PORT0"); + map(0x01000004, 0x01000007).w( FUNC(fbcrazy_state::aux_port1_w)).umask32(0x000000ff); + map(0x01000004, 0x01000007).portr("AUX_PORT1"); + map(0x01000008, 0x0100000b).w( FUNC(fbcrazy_state::aux_port2_w)).umask32(0x000000ff); + map(0x0100000c, 0x0100000f).w( FUNC(fbcrazy_state::aux_port3_w)).umask32(0x000000ff); + map(0x01000010, 0x01000013).w( FUNC(fbcrazy_state::aux_port4_w)).umask32(0x000000ff); } void rastersp_state::io_map(address_map &map) { + map(0x0000, 0x0000).r(FUNC(rastersp_state::interrupt_status_r)); map(0x0020, 0x0023).w(FUNC(rastersp_state::cyrix_cache_w)); map(0x1000, 0x1003).portr("P1").w(FUNC(rastersp_state::port1_w)); map(0x1004, 0x1007).portr("P2").w(FUNC(rastersp_state::port2_w)); @@ -709,22 +1141,34 @@ void rastersp_state::io_map(address_map &map) map(0x1010, 0x1013).portr("DSW1"); map(0x1014, 0x1017).portr("EXTRA"); map(0x4000, 0x4007).rw("rtc", FUNC(mc146818_device::read), FUNC(mc146818_device::write)).umask32(0x000000ff); - map(0x6008, 0x600b).nopr().nopw(); // RS232 + map(0x6000, 0x6000).rw( m_duart, FUNC(z80scc_device::cb_r), FUNC(z80scc_device::cb_w)); + map(0x6004, 0x6004).rw( m_duart, FUNC(z80scc_device::db_r), FUNC(z80scc_device::db_w)); + map(0x6008, 0x6008).rw( m_duart, FUNC(z80scc_device::ca_r), FUNC(z80scc_device::ca_w)); + map(0x600c, 0x600c).rw( m_duart, FUNC(z80scc_device::da_r), FUNC(z80scc_device::da_w)); } - -void rastersp_state::dsp_map(address_map &map) +void rastersp_state::dsp_map_base(address_map &map) { - map(0x000000, 0x0fffff).bankrw("bank1"); map(0x400000, 0x40ffff).rom().region("dspboot", 0); map(0x808000, 0x80807f).rw(FUNC(rastersp_state::tms32031_control_r), FUNC(rastersp_state::tms32031_control_w)); map(0x880402, 0x880402).w(FUNC(rastersp_state::dsp_unk_w)); map(0x883c00, 0x883c00).w(FUNC(rastersp_state::dsp_486_int_w)); map(0xc00000, 0xc03fff).bankrw("bank2"); map(0xc80000, 0xc80000).w(FUNC(rastersp_state::dsp_ctrl_w)); - map(0xfc0000, 0xffffff).bankrw("bank3"); + map(0xfc0000, 0xffffff).bankrw("bank1");//was3 } +void rastersp_state::dsp_map(address_map &map) +{ + dsp_map_base(map); + map(0x000000, 0x0fffff).bankrw("bank1");//4 meg +} + +void fbcrazy_state::dsp_map(address_map &map) +{ + rastersp_state::dsp_map_base(map); + map(0x000000, 0x1fffff).bankrw("bank1");//8 meg +} /************************************* @@ -833,6 +1277,139 @@ static INPUT_PORTS_START( rotr ) PORT_DIPSETTING( 0x80, DEF_STR( No ) ) INPUT_PORTS_END +static INPUT_PORTS_START( fbcrazy ) + PORT_START("P1") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("P2") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("COMMON") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Select") PORT_CODE(KEYCODE_S) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("EXTRA") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_SERVICE_NO_TOGGLE( 0x02, IP_ACTIVE_LOW ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Refill Key") PORT_CODE(KEYCODE_R) PORT_TOGGLE + PORT_DIPNAME( 0x20, 0x00, "4 6 Cashbox Door" ) + PORT_DIPSETTING( 0x00, "CLOSED" ) + PORT_DIPSETTING( 0x20, "OPEN" ) + PORT_DIPNAME( 0x40, 0x00, "4 7 Back Door" ) + PORT_DIPSETTING( 0x00, "CLOSED" ) + PORT_DIPSETTING( 0x40, "OPEN" ) + PORT_DIPNAME( 0x80, 0x00, "4 8 Front Door" ) + PORT_DIPSETTING( 0x00, "CLOSED" ) + PORT_DIPSETTING( 0x80, "OPEN" ) + + PORT_START("DSW1") + PORT_DIPNAME( 0x01, 0x01, "Setup Disk" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) + + PORT_DIPNAME( 0x02, 0x00, DEF_STR( Service_Mode ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x02, DEF_STR( On ) ) + + PORT_DIPNAME( 0x3c, 0x00, "Load PROG" ) + PORT_DIPSETTING( 0x00, "0" ) + PORT_DIPSETTING( 0x04, "1" ) + PORT_DIPSETTING( 0x08, "2" ) + PORT_DIPSETTING( 0x0c, "3" ) + PORT_DIPSETTING( 0x10, "4" ) + PORT_DIPSETTING( 0x14, "5" ) + PORT_DIPSETTING( 0x18, "6" ) + PORT_DIPSETTING( 0x1c, "7" ) + PORT_DIPSETTING( 0x20, "8" ) + PORT_DIPSETTING( 0x24, "9" ) + PORT_DIPSETTING( 0x28, "A" ) + PORT_DIPSETTING( 0x2c, "B" ) + PORT_DIPSETTING( 0x30, "C" ) + PORT_DIPSETTING( 0x34, "D" ) + PORT_DIPSETTING( 0x38, "E" ) + PORT_DIPSETTING( 0x3c, "F" ) + + PORT_DIPNAME( 0x40, 0x00, "Reserved" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x40, DEF_STR( On ) ) + + PORT_DIPNAME( 0x80, 0x00, "Enable Cache" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + + PORT_START("DSW2") + PORT_DIPNAME( 0x01, 0x00, "Debug Screen" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) + + PORT_DIPNAME( 0x0e, 0x00, "FPGA File Source" ) + PORT_DIPSETTING( 0x00, "Serial PROMs" ) + PORT_DIPSETTING( 0x0e, "Cable" ) + + PORT_DIPNAME( 0x70, 0x50, "Clock speed" ) + PORT_DIPSETTING( 0x00, "4" ) + PORT_DIPSETTING( 0x10, "8" ) + PORT_DIPSETTING( 0x20, "16" ) + PORT_DIPSETTING( 0x30, "20" ) + PORT_DIPSETTING( 0x40, "25" ) + PORT_DIPSETTING( 0x50, "33" ) + PORT_DIPSETTING( 0x60, "40" ) + PORT_DIPSETTING( 0x70, "50" ) + + PORT_DIPNAME( 0x80, 0x00, "SCSI bus terminated" ) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) + PORT_DIPSETTING( 0x80, DEF_STR( No ) ) + + PORT_START("AUX_PORT0") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_IMPULSE(3) PORT_NAME("10p") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_IMPULSE(3) PORT_NAME("20p") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_COIN3 ) PORT_IMPULSE(3) PORT_NAME("50p") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_COIN4 ) PORT_IMPULSE(3) PORT_NAME("1 Pound") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_COIN5 ) PORT_IMPULSE(3) PORT_NAME("5P") + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Pay tube level") PORT_CODE(KEYCODE_T) PORT_TOGGLE + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("AUX_PORT1") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_DIPNAME( 0x08, 0x00, "Pay unit fitted" ) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) + PORT_DIPSETTING( 0x08, DEF_STR( No ) ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(fbcrazy_state, meter_pulse_r) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("TRACK_X") // Fake trackball input port + PORT_BIT( 0xfff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(70) PORT_KEYDELTA(10) + + PORT_START("TRACK_Y") // Fake trackball input port + PORT_BIT( 0xfff, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(70) PORT_KEYDELTA(10) +INPUT_PORTS_END /************************************* @@ -855,27 +1432,19 @@ void rastersp_state::ncr53c700_config(device_t *device) { auto *state = device->subdevice(":"); ncr53c7xx_device &scsictrl = downcast(*device); - scsictrl.set_clock(66000000); + scsictrl.set_clock(66'000'000); scsictrl.irq_handler().set(*state, FUNC(rastersp_state::scsi_irq)); scsictrl.host_read().set(*state, FUNC(rastersp_state::ncr53c700_read)); scsictrl.host_write().set(*state, FUNC(rastersp_state::ncr53c700_write)); } -/************************************* - * - * Machine driver - * - *************************************/ - -void rastersp_state::rastersp(machine_config &config) +void rastersp_state::rs_config_base(machine_config &config) { - I486(config, m_maincpu, 33330000); - m_maincpu->set_addrmap(AS_PROGRAM, &rastersp_state::cpu_map); - m_maincpu->set_addrmap(AS_IO, &rastersp_state::io_map); + I486(config, m_maincpu, 33'330'000); m_maincpu->set_irq_acknowledge_callback(FUNC(rastersp_state::irq_callback)); + m_maincpu->set_addrmap(AS_IO, &rastersp_state::io_map); - TMS32031(config, m_dsp, 33330000); - m_dsp->set_addrmap(AS_PROGRAM, &rastersp_state::dsp_map); + TMS32031(config, m_dsp, 33'330'000); m_dsp->set_mcbl_mode(true); // Boot-loader mode MC146818(config, "rtc", 32.768_kHz_XTAL); @@ -883,12 +1452,8 @@ void rastersp_state::rastersp(machine_config &config) NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); NSCSI_BUS(config, "scsibus", 0); - - nscsi_connector &connector0(NSCSI_CONNECTOR(config, "scsibus:0", 0)); - connector0.option_add("harddisk", NSCSI_HARDDISK); - connector0.option_add_internal("ncr53c700", NCR53C7XX); - connector0.set_default_option("harddisk"); - connector0.set_fixed(true); + + WATCHDOG_TIMER(config, m_watchdog).set_time(attotime::from_seconds(1)); nscsi_connector &connector7(NSCSI_CONNECTOR(config, "scsibus:7", 0)); connector7.option_add("harddisk", NSCSI_HARDDISK); @@ -917,9 +1482,53 @@ void rastersp_state::rastersp(machine_config &config) DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_rdac, 0); m_ldac->add_route(ALL_OUTPUTS, "lspeaker", 0.5); // unknown DAC m_rdac->add_route(ALL_OUTPUTS, "rspeaker", 0.5); // unknown DAC + + SCC85C30(config, m_duart, 8'000'000); + m_duart->configure_channels(1'843'200, 0, 1'843'200, 0); + m_duart->out_int_callback().set(FUNC(rastersp_state::duart_irq)); +} + +/************************************* + * + * Machine driver + * + *************************************/ + +void rastersp_state::rastersp(machine_config &config) +{ + rs_config_base(config); + m_maincpu->set_addrmap(AS_PROGRAM, &rastersp_state::cpu_map); + + m_dsp->set_addrmap(AS_PROGRAM, &rastersp_state::dsp_map); + + nscsi_connector &connector0(NSCSI_CONNECTOR(config, "scsibus:0", 0)); + connector0.option_add("harddisk", NSCSI_HARDDISK); + connector0.option_add_internal("ncr53c700", NCR53C7XX); + connector0.set_default_option("harddisk"); + connector0.set_fixed(true); } +void fbcrazy_state::fbcrazy(machine_config &config) +{ + rs_config_base(config); + m_maincpu->set_addrmap(AS_PROGRAM, &fbcrazy_state::cpu_map); + + m_dsp->set_addrmap(AS_PROGRAM, &fbcrazy_state::dsp_map); + + nscsi_connector &connector3(NSCSI_CONNECTOR(config, "scsibus:3", 0)); + connector3.option_add("cdrom", NSCSI_CDROM); + connector3.option_add_internal("ncr53c700", NCR53C7XX); + connector3.set_default_option("cdrom"); + connector3.set_fixed(true); + + bacta_datalogger_device &bacta(BACTA_DATALOGGER(config, "bacta", 0)); + + m_duart->out_txda_callback().set("bacta", FUNC(bacta_datalogger_device::write_txd)); + bacta.rxd_handler().set(m_duart, FUNC(z80scc_device::rxa_w)); + m_duart->out_rtsa_callback().set(FUNC(fbcrazy_state::trackball_rts)); + +} /************************************* * @@ -928,9 +1537,6 @@ void rastersp_state::rastersp(machine_config &config) *************************************/ ROM_START( rotr ) - ROM_REGION32_LE(0x100000, "bios", 0) - ROM_LOAD( "rasterspeed2.1_bootrom4.u10", 0x00000, 0x10000, CRC(6da142d1) SHA1(e2dbd479034677726fc26fd1ba85c4458d89286c) ) - ROM_REGION32_LE(0x1000000, "dspboot", 0) ROM_LOAD32_BYTE( "rasterspeed2.1_bootrom4.u10", 0x00000, 0x10000, CRC(6da142d1) SHA1(e2dbd479034677726fc26fd1ba85c4458d89286c) ) @@ -947,9 +1553,6 @@ ROM_END ROM_START( rotra ) - ROM_REGION32_LE(0x100000, "bios", 0) - ROM_LOAD( "rasterspeed2.1_bootrom4.u10", 0x00000, 0x10000, CRC(6da142d1) SHA1(e2dbd479034677726fc26fd1ba85c4458d89286c) ) - ROM_REGION32_LE(0x1000000, "dspboot", 0) ROM_LOAD32_BYTE( "rasterspeed2.1_bootrom4.u10", 0x00000, 0x10000, CRC(6da142d1) SHA1(e2dbd479034677726fc26fd1ba85c4458d89286c) ) @@ -966,33 +1569,36 @@ ROM_END /* Football Crazy runs on the (c)1997 "RASTERSPEED 2.1 31-599-001 ISS 4" PCB, which seems to be a more modern production version. - a PCB photo with the rom sticker showing the text below has also been seen + a PCB photo with the ROM sticker showing the text below has also been seen Football Crazy Cashflow 95 750 956 STANDARD UK 64K VER. FOOT 3.2 BFM - + Bell Fruit issue roms in pairs. + Roms with the 5th digit 0 do not require a Bacta Dataport unit to operate although they still send out the data + Roms with the 5th digit 1 do required a Dataport unit and the machine will lock if one isn't fitted when the doors are closed. + Football Crazy is wrong in that 95751937 still requires the Dataport unit even when the doors are open :( + 95751937 shows RS Mk 2.16 P Uk Boot ROM on power up while 95750937 shows RS Mk 2.16 N Uk Boot ROM + The 'N' and 'P' referring to non-protocol and protocol. */ // the rom also exists in some odd hex format like this // ROM_LOAD( "95751937.hex", 0x0000, 0x025f91, CRC(8f412e97) SHA1(a5ff924fbc327114e59d75de644ed0d5cd7fa6b3) ) ROM_START( fbcrazy ) - ROM_REGION32_LE(0x100000, "bios", 0) - ROM_LOAD( "95751937.bin", 0x0000, 0x010000, CRC(4a99ee11) SHA1(335398ebc64bbfe86e2652ac080a5943dd413928) ) - ROM_REGION32_LE(0x1000000, "dspboot", 0) ROM_LOAD32_BYTE( "95751937.bin", 0x0000, 0x010000, CRC(4a99ee11) SHA1(335398ebc64bbfe86e2652ac080a5943dd413928) ) + //ROM_LOAD32_BYTE( "95750937.bin", 0x0000, 0x010000, CRC(15364c8b) SHA1(c36903fd18ff8abfccca5dbbad8acda25d78e8f6) ) ROM_REGION(0x8000, "proms", ROMREGION_ERASEFF ) - /* not on this PCB type? */ + // Not on this PCB type? ROM_REGION(0x8000, "nvram", ROMREGION_ERASEFF ) - DISK_REGION( "scsibus:0:harddisk:image" ) - DISK_IMAGE( "fbcrazy_hdd", 0, NO_DUMP ) + DISK_REGION( "scsibus:3:cdrom" ) + DISK_IMAGE_READONLY( "95100303", 0, SHA1(9ba47c96de27ec2bea9c6624d78d309b67705406) ) ROM_END /************************************* @@ -1001,6 +1607,6 @@ ROM_END * *************************************/ -GAME( 1994, rotr, 0, rastersp, rotr, rastersp_state, empty_init, ROT0, "BFM/Mirage", "Rise of the Robots (prototype)", 0 ) -GAME( 1994, rotra, rotr, rastersp, rotr, rastersp_state, empty_init, ROT0, "BFM/Mirage", "Rise of the Robots (prototype, older)", 0 ) -GAME( 1997, fbcrazy, 0, rastersp, rotr, rastersp_state, empty_init, ROT0, "BFM", "Football Crazy (Video Quiz)", MACHINE_NOT_WORKING ) +GAME( 1994, rotr, 0, rastersp, rotr, rastersp_state, empty_init, ROT0, "BFM/Mirage", "Rise of the Robots (prototype)", MACHINE_SUPPORTS_SAVE ) +GAME( 1994, rotra, rotr, rastersp, rotr, rastersp_state, empty_init, ROT0, "BFM/Mirage", "Rise of the Robots (prototype, older)", MACHINE_SUPPORTS_SAVE ) +GAME( 1997, fbcrazy, 0, fbcrazy, fbcrazy, fbcrazy_state, empty_init, ROT0, "BFM", "Football Crazy (Video Quiz)", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/machine/bacta_datalogger.cpp b/src/mame/machine/bacta_datalogger.cpp index beae2f8883e..43f9855bfd9 100644 --- a/src/mame/machine/bacta_datalogger.cpp +++ b/src/mame/machine/bacta_datalogger.cpp @@ -68,11 +68,11 @@ void bacta_datalogger_device::tx_queue() { if (is_transmit_register_empty()) { - if (m_output_char != -1) + if (m_output_char != 255) { set_tra_rate(1200); transmit_register_setup(m_output_char); - m_output_char = -1; + m_output_char = 255; } } }