From 3be65c90a55c6446136993268231f93568b898f3 Mon Sep 17 00:00:00 2001 From: Angelo Salese Date: Thu, 6 Apr 2023 12:05:32 +0200 Subject: video/huc6272.cpp: modernize handler interface (#11077) * video/huc6272.cpp: modernize handler interface * machine/t10mmc.cpp: avoid a stack overflow if device can't read CD data, allows PC-FX menu to be useable (with CD in ...) * video/huc6272.cpp: fix m_bg save state registration, add stub logmacro.h, misc cleanups --- src/devices/machine/t10mmc.cpp | 3 +- src/devices/video/huc6272.cpp | 708 ++++++++++++++++++++++++----------------- src/devices/video/huc6272.h | 68 +++- src/mame/nec/pcfx.cpp | 2 +- 4 files changed, 478 insertions(+), 303 deletions(-) diff --git a/src/devices/machine/t10mmc.cpp b/src/devices/machine/t10mmc.cpp index 7b9fd22d0fa..a72b597fc5c 100644 --- a/src/devices/machine/t10mmc.cpp +++ b/src/devices/machine/t10mmc.cpp @@ -562,7 +562,8 @@ void t10mmc::ReadData( uint8_t *data, int dataLength ) { if (!m_cdrom->read_data(m_lba, tmp_buffer, cdrom_file::CD_TRACK_MODE1)) { - m_device->logerror("T10MMC: CD read error!\n"); + m_device->logerror("T10MMC: CD read error! (%08x)\n", m_lba); + return; } //m_device->logerror("True LBA: %d, buffer half: %d\n", m_lba, m_cur_subblock * m_sector_bytes); diff --git a/src/devices/video/huc6272.cpp b/src/devices/video/huc6272.cpp index 5f4ec6b8c7a..781bf0a2c91 100644 --- a/src/devices/video/huc6272.cpp +++ b/src/devices/video/huc6272.cpp @@ -9,12 +9,15 @@ - Convert base mapping to address_map; - Convert I/O to space address, and make it honor mem_mask; - subclass "SCSICD" into SCSI-2 "CD-ROM DRIVE:FX" - \- Crashes if CD-ROM is in, on unhandled command 0x28 "Read(10)"; + \- Crashes if CD-ROM is in, on unhandled command 0x28 "Read(10)". + Tries to LBA with 0xffff'ff7a and 0 after failing a custom mode sense, + prior TOC tests makes even less sense, CPU core bug? \- During POST it tries an unhandled 0x44 "Read Header"; \- Derivative design of PCE drive, which in turn is a derivative of PC-8801-30 (cd drive) and PC-8801-31 (interface); - Implement video routines drawing and interface: \- BIOS main menu draws BG0 only as backdrop of the PCE VDCs with 16M mode (5); + \- (check Photo CD, Audio CD & backup RAM screens); - Implement video mixing with other PCFX chips; - Implement microprogram (layer timings, sort of Sega Saturn VRAM cycle patterns); - Implement Rainbow transfers (NEC logo on POST); @@ -30,7 +33,9 @@ #include "emu.h" #include "video/huc6272.h" +#define VERBOSE (LOG_GENERAL) +#include "logmacro.h" //************************************************************************** // GLOBAL VARIABLES @@ -54,6 +59,72 @@ void huc6272_device::kram_map(address_map &map) } } +// TODO: are dword transfers supported by the chip? +void huc6272_device::amap(address_map &map) +{ + map(0x00, 0x01).rw(FUNC(huc6272_device::status_r), FUNC(huc6272_device::register_select_w)); + map(0x02, 0x03).r(FUNC(huc6272_device::status2_r)); + map(0x04, 0x07).rw(FUNC(huc6272_device::data_r), FUNC(huc6272_device::data_w)); +} + +void huc6272_device::io_map(address_map &map) +{ + map(0x00, 0x00).rw(FUNC(huc6272_device::scsi_data_r), FUNC(huc6272_device::scsi_data_w)); + map(0x01, 0x01).w(FUNC(huc6272_device::scsi_initiate_cmd_w)); +// map(0x02, 0x02) SCSI DMA mode + map(0x03, 0x03).w(FUNC(huc6272_device::scsi_target_cmd_w)); + map(0x05, 0x05).rw(FUNC(huc6272_device::scsi_bus_r), FUNC(huc6272_device::scsi_bus_w)); +// map(0x06, 0x06) SCSI input data +// map(0x07, 0x07) SCSI DMA trigger +// map(0x08, 0x08) SCSI subcode +// map(0x09, 0x09) SCSI DMA start address +// map(0x0a, 0x0a) SCSI DMA size +// map(0x0b, 0x0b) SCSI DMA control + map(0x0c, 0x0c).rw(FUNC(huc6272_device::kram_read_address_r), FUNC(huc6272_device::kram_read_address_w)); + map(0x0d, 0x0d).rw(FUNC(huc6272_device::kram_write_address_r), FUNC(huc6272_device::kram_write_address_w)); + map(0x0e, 0x0e).rw(FUNC(huc6272_device::kram_read_data_r), FUNC(huc6272_device::kram_write_data_w)); + map(0x0f, 0x0f).rw(FUNC(huc6272_device::kram_page_setup_r), FUNC(huc6272_device::kram_page_setup_w)); + + map(0x10, 0x10).w(FUNC(huc6272_device::bg_mode_w)); + map(0x12, 0x12).w(FUNC(huc6272_device::bg_priority_w)); + map(0x13, 0x13).w(FUNC(huc6272_device::microprogram_address_w)); + map(0x14, 0x14).w(FUNC(huc6272_device::microprogram_data_w)); + map(0x15, 0x15).w(FUNC(huc6272_device::microprogram_control_w)); +// map(0x16, 0x16) wrap-around enable + + map(0x20, 0x20).w(FUNC(huc6272_device::bg_bat_w<0>)); + map(0x21, 0x21).w(FUNC(huc6272_device::bg_cg_w<0>)); + map(0x22, 0x22).w(FUNC(huc6272_device::bg0sub_bat_w)); + map(0x23, 0x23).w(FUNC(huc6272_device::bg0sub_cg_w)); + + map(0x24, 0x24).w(FUNC(huc6272_device::bg_bat_w<1>)); + map(0x25, 0x25).w(FUNC(huc6272_device::bg_cg_w<1>)); + + map(0x26, 0x26).w(FUNC(huc6272_device::bg_bat_w<2>)); + map(0x27, 0x27).w(FUNC(huc6272_device::bg_cg_w<2>)); + + map(0x28, 0x28).w(FUNC(huc6272_device::bg_bat_w<3>)); + map(0x29, 0x29).w(FUNC(huc6272_device::bg_cg_w<3>)); + + map(0x2c, 0x2f).w(FUNC(huc6272_device::bg_size_w)); + + map(0x30, 0x37).w(FUNC(huc6272_device::bg_scroll_w)); +// map(0x38, 0x3b) BG affine coefficients +// map(0x3c, 0x3d) BG affine center X/Y +// map(0x40, 0x44) Rainbow regs + + map(0x50, 0x50).w(FUNC(huc6272_device::adpcm_control_w)); + map(0x51, 0x52).w(FUNC(huc6272_device::adpcm_channel_control_w)); + map(0x53, 0x53).r(FUNC(huc6272_device::adpcm_status_r)); + + map(0x58, 0x58).w(FUNC(huc6272_device::adpcm_start_address_w<0>)); + map(0x59, 0x59).w(FUNC(huc6272_device::adpcm_end_address_w<0>)); + map(0x5a, 0x5a).w(FUNC(huc6272_device::adpcm_imm_address_w<0>)); + + map(0x5c, 0x5c).w(FUNC(huc6272_device::adpcm_start_address_w<1>)); + map(0x5d, 0x5d).w(FUNC(huc6272_device::adpcm_end_address_w<1>)); + map(0x5e, 0x5e).w(FUNC(huc6272_device::adpcm_imm_address_w<1>)); +} //************************************************************************** // LIVE DEVICE @@ -71,6 +142,7 @@ huc6272_device::huc6272_device(const machine_config &mconfig, const char *tag, d m_cdda_r(*this, "cdda_r"), m_program_space_config("microprg", ENDIANNESS_LITTLE, 16, 4, 0, address_map_constructor(FUNC(huc6272_device::microprg_map), this)), m_data_space_config("kram", ENDIANNESS_LITTLE, 32, 21, 0, address_map_constructor(FUNC(huc6272_device::kram_map), this)), + m_io_space_config("io", ENDIANNESS_LITTLE, 32, 7, -2, address_map_constructor(FUNC(huc6272_device::io_map), this)), m_microprg_ram(*this, "microprg_ram"), m_kram_page0(*this, "kram_page0"), m_kram_page1(*this, "kram_page1"), @@ -110,17 +182,14 @@ void huc6272_device::device_start() save_item(NAME(m_kram_page_w)); save_item(NAME(m_page_setting)); - for (int bg = 0; bg < 4; bg++) - { - save_item(NAME(m_bg[bg].bat_address), bg); - save_item(NAME(m_bg[bg].cg_address), bg); - save_item(NAME(m_bg[bg].mode), bg); - save_item(NAME(m_bg[bg].height), bg); - save_item(NAME(m_bg[bg].width), bg); - save_item(NAME(m_bg[bg].xscroll), bg); - save_item(NAME(m_bg[bg].yscroll), bg); - save_item(NAME(m_bg[bg].priority), bg); - } + save_item(STRUCT_MEMBER(m_bg, bat_address)); + save_item(STRUCT_MEMBER(m_bg, cg_address)); + save_item(STRUCT_MEMBER(m_bg, mode)); + save_item(STRUCT_MEMBER(m_bg, height)); + save_item(STRUCT_MEMBER(m_bg, width)); + save_item(STRUCT_MEMBER(m_bg, xscroll)); + save_item(STRUCT_MEMBER(m_bg, yscroll)); + save_item(STRUCT_MEMBER(m_bg, priority)); save_item(NAME(m_bg0sub.bat_address)); save_item(NAME(m_bg0sub.cg_address)); @@ -165,7 +234,8 @@ device_memory_interface::space_config_vector huc6272_device::memory_space_config { return space_config_vector { std::make_pair(AS_PROGRAM, &m_program_space_config), - std::make_pair(AS_DATA, &m_data_space_config) + std::make_pair(AS_DATA, &m_data_space_config), + std::make_pair(AS_IO, &m_io_space_config) }; } @@ -201,311 +271,359 @@ void huc6272_device::write_microprg_data(offs_t address, uint16_t data) // READ/WRITE HANDLERS //************************************************************************** -uint32_t huc6272_device::read(offs_t offset) +/* + * -x-- ---- ---- ---- SCSI IRQ pending + * --x- ---- ---- ---- DMA IRQ pending + * ---x ---- ---- ---- CD Sub Channel IRQ pending + * ---- x--- ---- ---- Raster IRQ pending + * ---- -x-- ---- ---- ADPCM IRQ pending + * ---- ---- -xxx xxxx register read-back + */ +u16 huc6272_device::status_r(offs_t offset) +{ + u16 res = m_register & 0x7f; + res |= (m_adpcm.interrupt << 10); + // TODO: other IRQs + return res; +} + +/* + * xxxx xxxx ---- ---- Sub Channel Buffer + * ---- ---- x--- ---- SCSI RST flag + * ---- ---- -x-- ---- SCSI BUSY flag + * ---- ---- --x- ---- SCSI REQ flag + * ---- ---- ---x ---- SCSI MSG flag + * ---- ---- ---- x--- SCSI CD flag + * ---- ---- ---- -x-- SCSI IO flag + * ---- ---- ---- --x- SCSI SEL flag + * ---- ---- ^^^^ ^^^^ \- same as reg $5 + */ +u16 huc6272_device::status2_r(offs_t offset) +{ + u16 res = (m_scsi_ctrl_in->read() & 0xff); + // TODO: sub-code data + return res; +} + +void huc6272_device::register_select_w(offs_t offset, u16 data, u16 mem_mask) +{ + COMBINE_DATA(&m_register); +} + +u32 huc6272_device::data_r(offs_t offset, u32 mem_mask) +{ + return space(AS_IO).read_dword(m_register, mem_mask); +} + +void huc6272_device::data_w(offs_t offset, u32 data, u32 mem_mask) +{ + space(AS_IO).write_dword(m_register, data, mem_mask); +} + +/* + * I/O handlers + */ + +u32 huc6272_device::scsi_data_r(offs_t offset) { - uint32_t res = 0; + return m_scsi_data_in->read() & 0xff; +} + +void huc6272_device::scsi_data_w(offs_t offset, u32 data, u32 mem_mask) +{ + m_scsi_data_out->write(data & 0xff); +} - if((offset & 1) == 0) +void huc6272_device::scsi_initiate_cmd_w(offs_t offset, u32 data, u32 mem_mask) +{ + //m_scsibus->write_bsy(BIT(data, 0)); // bus? + m_scsibus->write_atn(BIT(data, 1)); + m_scsibus->write_sel(BIT(data, 2)); + m_scsibus->write_ack(BIT(data, 4)); + m_scsibus->write_rst(BIT(data, 7)); +} + +void huc6272_device::scsi_target_cmd_w(offs_t offset, u32 data, u32 mem_mask) +{ + m_scsibus->write_io(BIT(data, 0)); + m_scsibus->write_cd(BIT(data, 1)); + m_scsibus->write_msg(BIT(data, 2)); // Misc? +} + +u32 huc6272_device::scsi_bus_r(offs_t offset) +{ + u32 res = m_scsi_ctrl_in->read() & 0xff; + res |= m_scsi_data_in->read() << 16; + return res; +} + +void huc6272_device::scsi_bus_w(offs_t offset, u32 data, u32 mem_mask) +{ + if (ACCESSING_BITS_0_15) { - /* - xxxx xxxx ---- ---- ---- ---- ---- ---- Sub Channel Buffer - ---- ---- x--- ---- ---- ---- ---- ---- SCSI RST flag - ---- ---- -x-- ---- ---- ---- ---- ---- SCSI BUSY flag - ---- ---- --x- ---- ---- ---- ---- ---- SCSI REQ flag - ---- ---- ---x ---- ---- ---- ---- ---- SCSI MSG flag - ---- ---- ---- x--- ---- ---- ---- ---- SCSI CD flag - ---- ---- ---- -x-- ---- ---- ---- ---- SCSI IO flag - ---- ---- ---- --x- ---- ---- ---- ---- SCSI SEL flag - ---- ---- ---- ---- -x-- ---- ---- ---- SCSI IRQ pending - ---- ---- ---- ---- --x- ---- ---- ---- DMA IRQ pending - ---- ---- ---- ---- ---x ---- ---- ---- CD Sub Channel IRQ pending - ---- ---- ---- ---- ---- x--- ---- ---- Raster IRQ pending - ---- ---- ---- ---- ---- -x-- ---- ---- ADPCM IRQ pending - ---- ---- ---- ---- ---- ---- -xxx xxxx register read-back - */ - res = m_register & 0x7f; - res |= (m_adpcm.interrupt << 10); - res |= (m_scsi_ctrl_in->read() & 0xff) << 16; + // TODO: bits 7-0: SCSI DMA trigger? + LOG("SCSI DMA trigger %04x & %08x\n", data, mem_mask); } - else + + if (ACCESSING_BITS_16_23) + m_scsi_data_out->write((data >> 16) & 0xff); +} + +u32 huc6272_device::kram_read_address_r(offs_t offset) +{ + return (m_kram_addr_r & 0x3ffff) + | ((m_kram_inc_r & 0x1ff) << 18) + | ((m_kram_page_r & 1) << 31); +} + +void huc6272_device::kram_read_address_w(offs_t offset, u32 data, u32 mem_mask) +{ + COMBINE_DATA(&m_kram_load_reg); + m_kram_addr_r = (m_kram_load_reg & 0x0003ffff); + m_kram_inc_r = (m_kram_load_reg & 0x0ffc0000) >> 18; + m_kram_page_r = BIT(m_kram_load_reg, 31); +} + +u32 huc6272_device::kram_write_address_r(offs_t offset) +{ + return (m_kram_addr_w & 0x3ffff) + | ((m_kram_inc_w & 0x1ff) << 18) + | ((m_kram_page_w & 1) << 31); +} + +void huc6272_device::kram_write_address_w(offs_t offset, u32 data, u32 mem_mask) +{ + COMBINE_DATA(&m_kram_write_reg); + m_kram_addr_w = (m_kram_write_reg & 0x0003ffff); + m_kram_inc_w = (m_kram_write_reg & 0x0ffc0000) >> 18; + m_kram_page_w = BIT(m_kram_write_reg, 31); +} + +u32 huc6272_device::kram_read_data_r(offs_t offset) +{ + // TODO: is this always 32-bit? + u32 res = read_dword((m_kram_addr_r)|(m_kram_page_r<<18)); + m_kram_addr_r += (m_kram_inc_r & 0x200) + ? ((m_kram_inc_r & 0x1ff) - 0x200) + : (m_kram_inc_r & 0x1ff); + return res; +} + +void huc6272_device::kram_write_data_w(offs_t offset, u32 data, u32 mem_mask) +{ + write_dword( + (m_kram_addr_w) | (m_kram_page_w<<18), + data + ); + m_kram_addr_w += (m_kram_inc_w & 0x200) + ? ((m_kram_inc_w & 0x1ff) - 0x200) + : (m_kram_inc_w & 0x1ff); +} + +/* + * ---x ---- ---- ---- ADPCM page setting + * ---- ---x ---- ---- RAINBOW page setting + * ---- ---- ---x ---- BG page setting + * ---- ---- ---- ---x SCSI page setting + */ +u32 huc6272_device::kram_page_setup_r(offs_t offset) +{ + return m_page_setting; +} + +void huc6272_device::kram_page_setup_w(offs_t offset, u32 data, u32 mem_mask) +{ + // TODO: dispatch in individual bits instead + COMBINE_DATA(&m_page_setting); +} + +/* + * xxxx ---- ---- ---- BG3 mode setting + * ---- xxxx ---- ---- BG2 mode setting + * ---- ---- xxxx ---- BG1 mode setting + * ---- ---- ---- xxxx BG0 mode setting + * + * 0001 - 4 color palette + * 0010 - 16 color palette + * 0011 - 256 color palette + * 0100 - 64k color + * 0101 - 16M color + * 1001 - 4 color palette block mode + * 1010 - 16 color palette block mode + * 1011 - 256 color palette block mode + * others - unused/invalid + */ +void huc6272_device::bg_mode_w(offs_t offset, u32 data, u32 mem_mask) +{ + if (ACCESSING_BITS_0_7) { - switch(m_register) - { - case 0x00: // SCSI data in - res = m_scsi_data_in->read() & 0xff; - break; - - case 0x05: // SCSI bus status - res = m_scsi_ctrl_in->read() & 0xff; - res|= (m_scsi_data_in->read() << 8); - break; - - - /* - x--- ---- ---- ---- ---- - */ - case 0x0c: // KRAM load address - res = (m_kram_addr_r & 0x3ffff) | ((m_kram_inc_r & 0x1ff) << 18) | ((m_kram_page_r & 1) << 31); - break; - - case 0x0d: // KRAM write address - res = (m_kram_addr_w & 0x3ffff) | ((m_kram_inc_w & 0x1ff) << 18) | ((m_kram_page_w & 1) << 31); - break; - - case 0x0e: // KRAM read data - res = read_dword((m_kram_addr_r)|(m_kram_page_r<<18)); - m_kram_addr_r += (m_kram_inc_r & 0x200) ? ((m_kram_inc_r & 0x1ff) - 0x200) : (m_kram_inc_r & 0x1ff); - break; - - case 0x0f: - res = m_page_setting; - break; - - case 0x53: // ADPCM status - res = m_adpcm.status; - - m_adpcm.status = 0; - m_adpcm.interrupt = 0; - interrupt_update(); - break; - //default: printf("%04x\n",m_register); - } + for(int i = 0; i < 2; i++) + m_bg[i].mode = (data >> i*4) & 0x0f; } - return res; + if (ACCESSING_BITS_8_15) + { + for(int i = 2; i < 4; i++) + m_bg[i].mode = (data >> i*4) & 0x0f; + } } -void huc6272_device::write(offs_t offset, uint32_t data) +/* + * ---x ---- ---- ---- BG0 rotation enable + * ---- xxx- ---- ---- BG3 priority + * ---- ---x xx-- ---- BG2 priority + * ---- ---- --xx x--- BG1 priority + * ---- ---- ---- -xxx BG0 priority + * ---- ---- ---- -000 hidden + * ---- ---- ---- -001 farthest back + * ---- ---- ---- -100 farthest forward + * ---- ---- ---- -1xx + * NB: there's another priority reg in '6261, is above layer vs. layer priority? + */ +void huc6272_device::bg_priority_w(offs_t offset, u32 data, u32 mem_mask) { - if((offset & 1) == 0) - m_register = data & 0x7f; - else + // TODO: fix access + // TODO: rotation enable + + if (ACCESSING_BITS_0_15) { - switch(m_register) - { - case 0x00: // SCSI data out - m_scsi_data_out->write(data & 0xff); - break; - case 0x01: // SCSI command - //m_scsibus->write_bsy(BIT(data, 0)); // bus? - m_scsibus->write_atn(BIT(data, 1)); - m_scsibus->write_sel(BIT(data, 2)); - m_scsibus->write_ack(BIT(data, 4)); - m_scsibus->write_rst(BIT(data, 7)); - - break; - - case 0x02: // SCSI mode - break; - - case 0x03: // SCSI target command - m_scsibus->write_io(BIT(data, 0)); - m_scsibus->write_cd(BIT(data, 1)); - m_scsibus->write_msg(BIT(data, 2)); - break; - - case 0x05: // SCSI bus status - // bits 7-0: SCSI DMA trigger? - m_scsi_data_out->write((data >> 8) & 0xff); - break; - - case 0x06: // SCSI input data - case 0x07: // SCSI DMA trigger - case 0x08: // SCSI subcode - case 0x09: // SCSI DMA start address - case 0x0a: // SCSI DMA size - case 0x0b: // SCSI DMA control - break; - /* - ---- ---- ---- ---- ---- - */ - case 0x0c: // KRAM load address - m_kram_addr_r = (data & 0x0003ffff); - m_kram_inc_r = (data & 0x0ffc0000) >> 18; - m_kram_page_r = (data & 0x80000000) >> 31; - break; - - case 0x0d: // KRAM write address - m_kram_addr_w = (data & 0x0003ffff); - m_kram_inc_w = (data & 0x0ffc0000) >> 18; - m_kram_page_w = (data & 0x80000000) >> 31; - break; - - case 0x0e: // KRAM write data - // TODO: handle non-dword cases? - write_dword((m_kram_addr_w)|(m_kram_page_w<<18),data); - m_kram_addr_w += (m_kram_inc_w & 0x200) ? ((m_kram_inc_w & 0x1ff) - 0x200) : (m_kram_inc_w & 0x1ff); - break; - - /* - ---x ---- ---- ---- ADPCM page setting - ---- ---x ---- ---- RAINBOW page setting - ---- ---- ---x ---- BG page setting - ---- ---- ---- ---x SCSI page setting - */ - case 0x0f: - m_page_setting = data; - break; - - // - // xxxx ---- ---- ---- BG3 mode setting - // ---- xxxx ---- ---- BG2 mode setting - // ---- ---- xxxx ---- BG1 mode setting - // ---- ---- ---- xxxx BG0 mode setting - // - // 0001 - 4 color palette - // 0010 - 16 color palette - // 0011 - 256 color palette - // 0100 - 64k color - // 0101 - 16M color - // 1001 - 4 color palette block mode - // 1010 - 16 color palette block mode - // 1011 - 256 color palette block mode - // others - unused/invalid - case 0x10: - for(int i=0;i<4;i++) - m_bg[i].mode = (data >> i*4) & 0x0f; - - break; - - /* - ---x ---- ---- ---- BG0 rotation enable - ---- xxx- ---- ---- BG3 priority - ---- ---x xx-- ---- BG2 priority - ---- ---- --xx x--- BG1 priority - ---- ---- ---- -xxx BG0 priority - */ - case 0x12: - for(int i=0;i<4;i++) - m_bg[i].priority = (data >> i*3) & 0x07; - - // TODO: rotation enable - break; - - case 0x13: - m_micro_prg.index = data & 0xf; - break; - - case 0x14: - write_microprg_data(m_micro_prg.index,data & 0xffff); - m_micro_prg.index ++; - m_micro_prg.index &= 0xf; - break; - - case 0x15: - m_micro_prg.ctrl = data & 1; - break; - - // case 0x16: wrap-around enable - - // BAT and CG address setters - case 0x20: m_bg[0].bat_address = data * 1024; break; - case 0x21: m_bg[0].cg_address = data * 1024; break; - case 0x22: m_bg0sub.bat_address = data * 1024; break; - case 0x23: m_bg0sub.cg_address = data * 1024; break; - case 0x24: m_bg[1].bat_address = data * 1024; break; - case 0x25: m_bg[1].cg_address = data * 1024; break; - case 0x26: m_bg[2].bat_address = data * 1024; break; - case 0x27: m_bg[2].cg_address = data * 1024; break; - case 0x28: m_bg[3].bat_address = data * 1024; break; - case 0x29: m_bg[3].cg_address = data * 1024; break; - - // Height & Width setters - case 0x2c: - case 0x2d: - case 0x2e: - case 0x2f: - { - uint8_t reg_offs = m_register & 3; - m_bg[reg_offs].height = 1 << (data & 0x000f); - m_bg[reg_offs].width = 1 << ((data & 0x00f0) >> 4); - if(reg_offs == 0) - { - m_bg0sub.height = 1 << ((data & 0x0f00) >> 8); - m_bg0sub.width = 1 << ((data & 0xf000) >> 12); - } - break; - } + for(int i = 0; i < 4; i++) + m_bg[i].priority = (data >> i*3) & 0x07; + } +} - // X & Y scroll values - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - { - uint8_t reg_offs = (m_register & 6) >> 1; +void huc6272_device::microprogram_address_w(offs_t offset, u32 data, u32 mem_mask) +{ + if (ACCESSING_BITS_0_7) + m_micro_prg.index = data & 0xf; +} - if(m_register & 1) - m_bg[reg_offs].yscroll = data & 0xffff; - else - m_bg[reg_offs].xscroll = data & 0xffff; - break; - } +void huc6272_device::microprogram_data_w(offs_t offset, u32 data, u32 mem_mask) +{ + if (ACCESSING_BITS_0_15) + { + write_microprg_data(m_micro_prg.index, data & 0xffff); + m_micro_prg.index ++; + m_micro_prg.index &= 0xf; + } +} - case 0x50: // ADPCM control - { - for (int i = 0; i < 2; i++) - { - m_adpcm.playing[i] = BIT(data, i); - if (!m_adpcm.playing[i]) - { - m_adpcm.input[i] = 0; - m_adpcm.pos[i] = 0; - m_adpcm.nibble[i] = 32; - } - else - { - m_adpcm.addr[i] = m_adpcm.start[i]; - } - } +void huc6272_device::microprogram_control_w(offs_t offset, u32 data, u32 mem_mask) +{ + if (ACCESSING_BITS_0_7) + m_micro_prg.ctrl = data & 1; +} - m_adpcm.rate = (data & 0xc) >> 2; - break; - } +// TODO: limit? +template void huc6272_device::bg_bat_w(offs_t offset, u32 data, u32 mem_mask) +{ + m_bg[N].bat_address = data * 1024; +} - // ADPCM channel control - case 0x51: - case 0x52: - { - uint8_t reg_offs = 1-(m_register & 1); - m_adpcm.control[reg_offs] = data & 0x7; - if (BIT(m_adpcm.control[reg_offs], 1) == 0) - m_adpcm.status &= ~(1 << (2*reg_offs)); +template void huc6272_device::bg_cg_w(offs_t offset, u32 data, u32 mem_mask) +{ + m_bg[N].cg_address = data * 1024; +} - if (BIT(m_adpcm.control[reg_offs], 2) == 0) - m_adpcm.status &= ~(1 << (2*reg_offs+1)); +void huc6272_device::bg0sub_bat_w(offs_t offset, u32 data, u32 mem_mask) +{ + m_bg0sub.bat_address = data * 1024; +} - break; - } +void huc6272_device::bg0sub_cg_w(offs_t offset, u32 data, u32 mem_mask) +{ + m_bg0sub.cg_address = data * 1024; +} + +void huc6272_device::bg_size_w(offs_t offset, u32 data, u32 mem_mask) +{ + if (ACCESSING_BITS_0_7) + { + m_bg[offset].height = 1 << (data & 0x000f); + m_bg[offset].width = 1 << ((data & 0x00f0) >> 4); + } + + if(offset == 0 && ACCESSING_BITS_8_15) + { + m_bg0sub.height = 1 << ((data & 0x0f00) >> 8); + m_bg0sub.width = 1 << ((data & 0xf000) >> 12); + } +} - // ADPCM start address - case 0x58: - case 0x5c: - m_adpcm.start[(m_register >> 2) & 1] = (data << 8) & 0x3ffff; - break; - - // ADPCM end address - case 0x59: - case 0x5d: - m_adpcm.end[(m_register >> 2) & 1] = data & 0x3ffff; - break; - - // ADPCM intermediate address - case 0x5a: - case 0x5e: - m_adpcm.imm[(m_register >> 2) & 1] = (data << 6) & 0x3ffff; - break; - - //default: printf("%04x %04x %08x\n",m_register,data,mem_mask); +void huc6272_device::bg_scroll_w(offs_t offset, u32 data, u32 mem_mask) +{ + if (ACCESSING_BITS_0_15) + { + uint8_t layer_n = (offset & 6) >> 1; + + if(offset & 1) + m_bg[layer_n].yscroll = data & 0xffff; + else + m_bg[layer_n].xscroll = data & 0xffff; + } +} + +void huc6272_device::adpcm_control_w(offs_t offset, u32 data, u32 mem_mask) +{ + for (int i = 0; i < 2; i++) + { + m_adpcm.playing[i] = BIT(data, i); + if (!m_adpcm.playing[i]) + { + m_adpcm.input[i] = 0; + m_adpcm.pos[i] = 0; + m_adpcm.nibble[i] = 32; + } + else + { + m_adpcm.addr[i] = m_adpcm.start[i]; } } + + m_adpcm.rate = (data & 0xc) >> 2; +} + +void huc6272_device::adpcm_channel_control_w(offs_t offset, u32 data, u32 mem_mask) +{ + uint8_t channel = 1 - (offset & 1); + m_adpcm.control[channel] = data & 0x7; + if (BIT(m_adpcm.control[channel], 1) == 0) + m_adpcm.status &= ~(1 << (2 * channel)); + + if (BIT(m_adpcm.control[channel], 2) == 0) + m_adpcm.status &= ~(1 << (2 * channel + 1)); +} + +u32 huc6272_device::adpcm_status_r(offs_t offset) +{ + u32 res = m_adpcm.status; + + if (!machine().side_effects_disabled()) + { + m_adpcm.status = 0; + m_adpcm.interrupt = 0; + interrupt_update(); + } + return res; +} + +// TODO: verify mask ranges +template void huc6272_device::adpcm_start_address_w(offs_t offset, u32 data, u32 mem_mask) +{ + m_adpcm.start[N] = (data * 256) & 0x3ffff; +} + +template void huc6272_device::adpcm_end_address_w(offs_t offset, u32 data, u32 mem_mask) +{ + m_adpcm.end[N] = data & 0x3ffff; +} + +template void huc6272_device::adpcm_imm_address_w(offs_t offset, u32 data, u32 mem_mask) +{ + m_adpcm.imm[N] = (data * 64) & 0x3ffff; } -// TODO: clearly written in blind faith +// TODO: verify me // (interrupt_update fns are untested by the BIOS main menu) uint8_t huc6272_device::adpcm_update(int chan) { diff --git a/src/devices/video/huc6272.h b/src/devices/video/huc6272.h index db5087f7f0c..67a629c1299 100644 --- a/src/devices/video/huc6272.h +++ b/src/devices/video/huc6272.h @@ -27,7 +27,7 @@ class huc6272_device : public device_t, public device_memory_interface { public: - static constexpr feature_type imperfect_features() { return feature::SOUND | feature::GRAPHICS; } // Incorrect ADPCM and Graphics + static constexpr feature_type imperfect_features() { return feature::SOUND | feature::GRAPHICS; } // construction/destruction huc6272_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); @@ -35,9 +35,7 @@ public: auto irq_changed_callback() { return m_irq_changed_cb.bind(); } template void set_rainbow_tag(T &&tag) { m_huc6271.set_tag(std::forward(tag)); } - // I/O operations - void write(offs_t offset, uint32_t data); - uint32_t read(offs_t offset); + void amap(address_map &map); // ADPCM operations uint8_t adpcm_update_0(); @@ -63,8 +61,9 @@ private: uint8_t m_register; uint32_t m_kram_addr_r, m_kram_addr_w; - uint16_t m_kram_inc_r,m_kram_inc_w; - uint8_t m_kram_page_r,m_kram_page_w; + uint16_t m_kram_inc_r, m_kram_inc_w; + uint8_t m_kram_page_r, m_kram_page_w; + u32 m_kram_load_reg = 0, m_kram_write_reg = 0; uint32_t m_page_setting; struct{ @@ -107,6 +106,7 @@ private: const address_space_config m_program_space_config; const address_space_config m_data_space_config; + const address_space_config m_io_space_config; required_shared_ptr m_microprg_ram; required_shared_ptr m_kram_page0; required_shared_ptr m_kram_page1; @@ -125,8 +125,64 @@ private: uint8_t adpcm_update(int chan); void interrupt_update(); + void io_map(address_map &map); void kram_map(address_map &map); void microprg_map(address_map &map); + +// void write(offs_t offset, uint32_t data); + // host interface + u16 status_r(offs_t offset); + void register_select_w(offs_t offset, u16 data, u16 mem_mask = ~0); + u16 status2_r(offs_t offset); + // u32 mem_mask = ~0 + u32 data_r(offs_t offset, u32 mem_mask = ~0); + void data_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + // internal I/O handlers + u32 scsi_data_r(offs_t offset); + void scsi_data_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + void scsi_initiate_cmd_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + void scsi_target_cmd_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + u32 scsi_bus_r(offs_t offset); + void scsi_bus_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + u32 kram_read_address_r(offs_t offset); + void kram_read_address_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + u32 kram_write_address_r(offs_t offset); + void kram_write_address_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + u32 kram_read_data_r(offs_t offset); + void kram_write_data_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + u32 kram_page_setup_r(offs_t offset); + void kram_page_setup_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + void bg_mode_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + void bg_priority_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + void microprogram_address_w(offs_t offset, u32 data, u32 mem_mask = ~0); + void microprogram_data_w(offs_t offset, u32 data, u32 mem_mask = ~0); + void microprogram_control_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + template void bg_bat_w(offs_t offset, u32 data, u32 mem_mask = ~0); + template void bg_cg_w(offs_t offset, u32 data, u32 mem_mask = ~0); + void bg0sub_bat_w(offs_t offset, u32 data, u32 mem_mask = ~0); + void bg0sub_cg_w(offs_t offset, u32 data, u32 mem_mask = ~0); + void bg_size_w(offs_t offset, u32 data, u32 mem_mask = ~0); + void bg_scroll_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + void adpcm_control_w(offs_t offset, u32 data, u32 mem_mask = ~0); + void adpcm_channel_control_w(offs_t offset, u32 data, u32 mem_mask = ~0); + template void adpcm_start_address_w(offs_t offset, u32 data, u32 mem_mask = ~0); + template void adpcm_end_address_w(offs_t offset, u32 data, u32 mem_mask = ~0); + template void adpcm_imm_address_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + u32 adpcm_status_r(offs_t offset); }; // device type definition diff --git a/src/mame/nec/pcfx.cpp b/src/mame/nec/pcfx.cpp index c7cb3770b95..610e4d36646 100644 --- a/src/mame/nec/pcfx.cpp +++ b/src/mame/nec/pcfx.cpp @@ -186,7 +186,7 @@ void pcfx_state::pcfx_io(address_map &map) map(0x00000300, 0x000003FF).rw(m_huc6261, FUNC(huc6261_device::read), FUNC(huc6261_device::write)).umask32(0x0000ffff); /* HuC6261 */ map(0x00000400, 0x000004FF).rw("huc6270_a", FUNC(huc6270_device::read), FUNC(huc6270_device::write)).umask32(0x0000ffff); /* HuC6270-A */ map(0x00000500, 0x000005FF).rw("huc6270_b", FUNC(huc6270_device::read), FUNC(huc6270_device::write)).umask32(0x0000ffff); /* HuC6270-B */ - map(0x00000600, 0x000006FF).rw("huc6272", FUNC(huc6272_device::read), FUNC(huc6272_device::write)); /* HuC6272 */ + map(0x00000600, 0x00000607).mirror(0xf8).m("huc6272", FUNC(huc6272_device::amap)); // King // map(0x00000C80, 0x00000C83).noprw(); // backup RAM control map(0x00000E00, 0x00000EFF).rw(FUNC(pcfx_state::irq_read), FUNC(pcfx_state::irq_write)).umask32(0x0000ffff); /* Interrupt controller */ // map(0x00000F00, 0x00000FFF).noprw(); // Timer -- cgit v1.2.3