mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
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
This commit is contained in:
parent
d4e3fc102c
commit
3be65c90a5
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
|
||||
if((offset & 1) == 0)
|
||||
{
|
||||
/*
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
u16 res = m_register & 0x7f;
|
||||
res |= (m_adpcm.interrupt << 10);
|
||||
// TODO: other IRQs
|
||||
return res;
|
||||
}
|
||||
|
||||
void huc6272_device::write(offs_t offset, uint32_t data)
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
if((offset & 1) == 0)
|
||||
m_register = data & 0x7f;
|
||||
else
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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));
|
||||
// TODO: bits 7-0: SCSI DMA trigger?
|
||||
LOG("SCSI DMA trigger %04x & %08x\n", data, mem_mask);
|
||||
}
|
||||
|
||||
break;
|
||||
if (ACCESSING_BITS_16_23)
|
||||
m_scsi_data_out->write((data >> 16) & 0xff);
|
||||
}
|
||||
|
||||
case 0x02: // SCSI mode
|
||||
break;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
case 0x05: // SCSI bus status
|
||||
// bits 7-0: SCSI DMA trigger?
|
||||
m_scsi_data_out->write((data >> 8) & 0xff);
|
||||
break;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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
|
||||
*/
|
||||
case 0x0f:
|
||||
m_page_setting = data;
|
||||
break;
|
||||
/*
|
||||
* ---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;
|
||||
}
|
||||
|
||||
//
|
||||
// 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;
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
void huc6272_device::bg_mode_w(offs_t offset, u32 data, u32 mem_mask)
|
||||
{
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
for(int i = 0; i < 2; i++)
|
||||
m_bg[i].mode = (data >> i*4) & 0x0f;
|
||||
}
|
||||
|
||||
/*
|
||||
---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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
if(m_register & 1)
|
||||
m_bg[reg_offs].yscroll = data & 0xffff;
|
||||
else
|
||||
m_bg[reg_offs].xscroll = data & 0xffff;
|
||||
break;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
m_adpcm.rate = (data & 0xc) >> 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
if (BIT(m_adpcm.control[reg_offs], 2) == 0)
|
||||
m_adpcm.status &= ~(1 << (2*reg_offs+1));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
if (ACCESSING_BITS_8_15)
|
||||
{
|
||||
for(int i = 2; i < 4; i++)
|
||||
m_bg[i].mode = (data >> i*4) & 0x0f;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: clearly written in blind faith
|
||||
/*
|
||||
* ---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)
|
||||
{
|
||||
// TODO: fix access
|
||||
// TODO: rotation enable
|
||||
|
||||
if (ACCESSING_BITS_0_15)
|
||||
{
|
||||
for(int i = 0; i < 4; i++)
|
||||
m_bg[i].priority = (data >> i*3) & 0x07;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
template <unsigned N> void huc6272_device::bg_cg_w(offs_t offset, u32 data, u32 mem_mask)
|
||||
{
|
||||
m_bg[N].cg_address = data * 1024;
|
||||
}
|
||||
|
||||
void huc6272_device::bg0sub_bat_w(offs_t offset, u32 data, u32 mem_mask)
|
||||
{
|
||||
m_bg0sub.bat_address = data * 1024;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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 <typename T> void set_rainbow_tag(T &&tag) { m_huc6271.set_tag(std::forward<T>(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<uint16_t> m_microprg_ram;
|
||||
required_shared_ptr<uint32_t> m_kram_page0;
|
||||
required_shared_ptr<uint32_t> 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 <unsigned N> void bg_bat_w(offs_t offset, u32 data, u32 mem_mask = ~0);
|
||||
template <unsigned N> 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 <unsigned N> void adpcm_start_address_w(offs_t offset, u32 data, u32 mem_mask = ~0);
|
||||
template <unsigned N> void adpcm_end_address_w(offs_t offset, u32 data, u32 mem_mask = ~0);
|
||||
template <unsigned N> void adpcm_imm_address_w(offs_t offset, u32 data, u32 mem_mask = ~0);
|
||||
|
||||
u32 adpcm_status_r(offs_t offset);
|
||||
};
|
||||
|
||||
// device type definition
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user