summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/huc6272.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/video/huc6272.cpp')
-rw-r--r--src/devices/video/huc6272.cpp799
1 files changed, 470 insertions, 329 deletions
diff --git a/src/devices/video/huc6272.cpp b/src/devices/video/huc6272.cpp
index 88d71542d55..256e14013f7 100644
--- a/src/devices/video/huc6272.cpp
+++ b/src/devices/video/huc6272.cpp
@@ -1,25 +1,41 @@
// license:BSD-3-Clause
// copyright-holders:Wilbert Pol, Angelo Salese
-/***************************************************************************
+/**************************************************************************************************
Hudson/NEC HuC6272 "King" device
TODO:
- - Use NSCSI instead of legacy one!
- - ADPCM Transfer is correct?
+ - Use NSCSI instead of legacy one;
+ \- SEL acknowledges with 0x84, bit 7 controller type is unknown at this time
+ (bit 2 should select the CD drive);
+ - 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"
+ \- Fails detection of PC-FX discs, detects as normal audio CDs;
+ \- 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);
+ - Verify ADPCM transfers;
ADPCM related patents:
- https://patents.google.com/patent/US5692099
- https://patents.google.com/patent/US6453286
- https://patents.google.com/patent/US5548655A
-***************************************************************************/
+**************************************************************************************************/
#include "emu.h"
+#include "huc6272.h"
-#include "video/huc6272.h"
-
+#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
//**************************************************************************
// GLOBAL VARIABLES
@@ -43,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).rw(FUNC(huc6272_device::scsi_cmd_status_r), 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
@@ -53,21 +135,23 @@ void huc6272_device::kram_map(address_map &map)
//-------------------------------------------------
huc6272_device::huc6272_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, HUC6272, tag, owner, clock),
- device_memory_interface(mconfig, *this),
- m_huc6271(*this, finder_base::DUMMY_TAG),
- m_cdda_l(*this, "cdda_l"),
- 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_microprg_ram(*this, "microprg_ram"),
- m_kram_page0(*this, "kram_page0"),
- m_kram_page1(*this, "kram_page1"),
- m_scsibus(*this, "scsi"),
- m_scsi_data_in(*this, "scsi_data_in"),
- m_scsi_data_out(*this, "scsi_data_out"),
- m_scsi_ctrl_in(*this, "scsi_ctrl_in"),
- m_irq_changed_cb(*this)
+ : device_t(mconfig, HUC6272, tag, owner, clock)
+ , device_memory_interface(mconfig, *this)
+ , m_huc6271(*this, finder_base::DUMMY_TAG)
+ , m_cdda_l(*this, "cdda_l")
+ , 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")
+ , m_scsibus(*this, "scsi")
+ , m_scsi_data_in(*this, "scsi_data_in")
+ , m_scsi_data_out(*this, "scsi_data_out")
+ , m_scsi_ctrl_in(*this, "scsi_ctrl_in")
+ , m_scsi_cmd_in(*this, "scsi_cmd_in")
+ , m_irq_changed_cb(*this)
{
}
@@ -88,8 +172,6 @@ void huc6272_device::device_validity_check(validity_checker &valid) const
void huc6272_device::device_start()
{
- m_irq_changed_cb.resolve_safe();
-
save_item(NAME(m_register));
save_item(NAME(m_kram_addr_r));
save_item(NAME(m_kram_inc_r));
@@ -99,17 +181,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));
@@ -154,7 +233,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)
};
}
@@ -190,310 +270,365 @@ void huc6272_device::write_microprg_data(offs_t address, uint16_t data)
// READ/WRITE HANDLERS
//**************************************************************************
-READ32_MEMBER( huc6272_device::read )
+/*
+ * -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)
+{
+ 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);
+}
+
+u32 huc6272_device::scsi_cmd_status_r(offs_t offset)
+{
+ return m_scsi_cmd_in->read() & 0xff;
+}
+
+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)
{
- uint32_t res = 0;
+ u32 res = m_scsi_ctrl_in->read() & 0xff;
+ res |= m_scsi_data_in->read() << 16;
+ return res;
+}
- if((offset & 1) == 0)
+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;
+ }
}
-WRITE32_MEMBER( huc6272_device::write )
+/*
+ * ---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 <prohibited>
+ * 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] = -1;
- m_adpcm.pos[i] = 0;
- }
- 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 <unsigned N> 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 <unsigned N> 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);
+ }
+}
+
+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;
+ }
+}
- // 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::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 <unsigned N> void huc6272_device::adpcm_start_address_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ m_adpcm.start[N] = (data * 256) & 0x3ffff;
+}
+
+template <unsigned N> void huc6272_device::adpcm_end_address_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ m_adpcm.end[N] = data & 0x3ffff;
+}
+
+template <unsigned N> void huc6272_device::adpcm_imm_address_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ m_adpcm.imm[N] = (data * 64) & 0x3ffff;
+}
+
+// TODO: verify me
+// (interrupt_update fns are untested by the BIOS main menu)
uint8_t huc6272_device::adpcm_update(int chan)
{
if (!m_adpcm.playing[chan])
@@ -503,7 +638,11 @@ uint8_t huc6272_device::adpcm_update(int chan)
m_adpcm.pos[chan]++;
if (m_adpcm.pos[chan] >= rate)
{
- if (m_adpcm.input[chan] == -1)
+ m_adpcm.nibble[chan] += 4;
+ if (m_adpcm.nibble[chan] >= 32)
+ m_adpcm.nibble[chan] = 0;
+
+ if (m_adpcm.nibble[chan] == 0)
{
m_adpcm.input[chan] = read_dword(((m_page_setting & 0x1000) << 6) | m_adpcm.addr[chan]);
m_adpcm.addr[chan] = (m_adpcm.addr[chan] & 0x20000) | ((m_adpcm.addr[chan] + 1) & 0x1ffff);
@@ -525,7 +664,7 @@ uint8_t huc6272_device::adpcm_update(int chan)
interrupt_update();
}
- if (BIT(m_adpcm.control[chan],0)) // Ring Buffer
+ if (BIT(m_adpcm.control[chan], 0)) // Ring Buffer
{
m_adpcm.addr[chan] = m_adpcm.start[chan];
}
@@ -535,31 +674,26 @@ uint8_t huc6272_device::adpcm_update(int chan)
return 0;
}
}
- m_adpcm.nibble[chan] = 0;
- }
- else
- {
- m_adpcm.nibble[chan] += 4;
- if (m_adpcm.nibble[chan] >= 28)
- m_adpcm.input[chan] = -1;
+ //m_adpcm.nibble[chan] = 0;
}
+
m_adpcm.pos[chan] = 0;
}
return (m_adpcm.input[chan] >> m_adpcm.nibble[chan]) & 0xf;
}
-READ8_MEMBER(huc6272_device::adpcm_update_0)
+uint8_t huc6272_device::adpcm_update_0()
{
return adpcm_update(0);
}
-READ8_MEMBER(huc6272_device::adpcm_update_1)
+uint8_t huc6272_device::adpcm_update_1()
{
return adpcm_update(1);
}
-WRITE8_MEMBER(huc6272_device::cdda_update)
+void huc6272_device::cdda_update(offs_t offset, uint8_t data)
{
if (offset)
m_cdda_r->set_output_gain(ALL_OUTPUTS, float(data) / 63.0);
@@ -601,12 +735,19 @@ void huc6272_device::device_add_mconfig(machine_config &config)
scsibus.io_handler().set("scsi_ctrl_in", FUNC(input_buffer_device::write_bit2));
scsibus.sel_handler().set("scsi_ctrl_in", FUNC(input_buffer_device::write_bit1));
+ scsibus.rst_handler().append("scsi_cmd_in", FUNC(input_buffer_device::write_bit7));
+ scsibus.ack_handler().set("scsi_cmd_in", FUNC(input_buffer_device::write_bit4));
+ scsibus.sel_handler().append("scsi_cmd_in", FUNC(input_buffer_device::write_bit2));
+ scsibus.atn_handler().set("scsi_cmd_in", FUNC(input_buffer_device::write_bit1));
+ scsibus.bsy_handler().append("scsi_cmd_in", FUNC(input_buffer_device::write_bit0));
+
output_latch_device &scsiout(OUTPUT_LATCH(config, "scsi_data_out"));
scsibus.set_output_latch(scsiout);
+ INPUT_BUFFER(config, "scsi_cmd_in");
INPUT_BUFFER(config, "scsi_ctrl_in");
INPUT_BUFFER(config, "scsi_data_in");
- scsibus.set_slot_device(1, "cdrom", SCSICD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_1));
+ scsibus.set_slot_device(1, "cdrom", SCSICD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_0));
scsibus.slot(1).set_option_machine_config("cdrom", cdrom_config);
}