mirror of
https://github.com/holub/mame
synced 2025-04-22 00:11:58 +03:00
video/k057714.cpp: Implemented raster timing registers. (#7846)
* Gives precise timings for Firebeat screens.
This commit is contained in:
parent
61a941762c
commit
721fbb5cfe
@ -259,6 +259,7 @@ const double XTAL::known_xtals[] = {
|
||||
16'400'000, /* 16.4_MHz_XTAL MS 6102 */
|
||||
16'572'000, /* 16.572_MHz_XTAL Micro-Term ACT-5A */
|
||||
16'588'800, /* 16.5888_MHz_XTAL SM 7238 */
|
||||
16'666'600, /* 16.6666_MHz_XTAL Firebeat GCU */
|
||||
16'669'800, /* 16.6698_MHz_XTAL Qume QVT-102 */
|
||||
16'670'000, /* 16.67_MHz_XTAL - */
|
||||
16'777'216, /* 16.777216_MHz_XTAL Nintendo Game Boy Advance */
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
GQ972 PWB(A2) 0000070609 Main board
|
||||
-----------------------------------
|
||||
25.175 MHz clock (near GCUs and VGA connectors)
|
||||
16.6666 MHz clock (near GCUs and VGA connectors)
|
||||
OSC 66.0000MHz
|
||||
IBM PowerPC 403GCX at 66MHz
|
||||
(2x) Konami 0000057714 (2D object processor)
|
||||
@ -396,6 +398,7 @@ public:
|
||||
m_work_ram(*this, "work_ram"),
|
||||
m_ata(*this, "ata"),
|
||||
m_gcu(*this, "gcu"),
|
||||
m_gcu_sub(*this, "gcu_sub"),
|
||||
m_duart_com(*this, "duart_com"),
|
||||
m_status_leds(*this, "status_led_%u", 0U),
|
||||
m_io_inputs(*this, "IN%u", 0U)
|
||||
@ -405,6 +408,7 @@ public:
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
virtual void device_resolve_objects() override;
|
||||
|
||||
uint32_t screen_update_firebeat_0(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
@ -433,6 +437,7 @@ protected:
|
||||
required_shared_ptr<uint32_t> m_work_ram;
|
||||
required_device<ata_interface_device> m_ata;
|
||||
required_device<k057714_device> m_gcu;
|
||||
optional_device<k057714_device> m_gcu_sub;
|
||||
|
||||
private:
|
||||
uint32_t cabinet_r(offs_t offset, uint32_t mem_mask = ~0);
|
||||
@ -446,6 +451,8 @@ private:
|
||||
|
||||
uint8_t input_r(offs_t offset);
|
||||
|
||||
void control_w(offs_t offset, uint8_t data);
|
||||
|
||||
uint16_t ata_command_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void ata_command_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
|
||||
@ -465,6 +472,8 @@ private:
|
||||
output_finder<8> m_status_leds;
|
||||
|
||||
required_ioport_array<4> m_io_inputs;
|
||||
|
||||
uint8_t m_control;
|
||||
};
|
||||
|
||||
class firebeat_spu_state : public firebeat_state
|
||||
@ -574,7 +583,6 @@ public:
|
||||
firebeat_state(mconfig, type, tag),
|
||||
m_duart_midi(*this, "duart_midi"),
|
||||
m_kbd(*this, "kbd%u", 0),
|
||||
m_gcu_sub(*this, "gcu_sub"),
|
||||
m_lamps(*this, "lamp_%u", 1U),
|
||||
m_cab_led_door_lamp(*this, "door_lamp"),
|
||||
m_cab_led_start1p(*this, "start1p"),
|
||||
@ -613,7 +621,6 @@ private:
|
||||
|
||||
required_device<pc16552_device> m_duart_midi;
|
||||
required_device_array<midi_keyboard_device, 2> m_kbd;
|
||||
required_device<k057714_device> m_gcu_sub;
|
||||
|
||||
output_finder<3> m_lamps;
|
||||
output_finder<> m_cab_led_door_lamp;
|
||||
@ -691,6 +698,13 @@ void firebeat_state::machine_start()
|
||||
m_maincpu->ppcdrc_add_fastram(0x00000000, 0x01ffffff, false, m_work_ram);
|
||||
}
|
||||
|
||||
void firebeat_state::machine_reset()
|
||||
{
|
||||
m_extend_board_irq_enable = 0x3f;
|
||||
m_extend_board_irq_active = 0x00;
|
||||
m_control = 0;
|
||||
}
|
||||
|
||||
void firebeat_state::device_resolve_objects()
|
||||
{
|
||||
m_status_leds.resolve();
|
||||
@ -699,12 +713,10 @@ void firebeat_state::device_resolve_objects()
|
||||
void firebeat_state::init_firebeat()
|
||||
{
|
||||
uint8_t *rom = memregion("user2")->base();
|
||||
set_ibutton(rom);
|
||||
|
||||
// pc16552d_init(machine(), 0, 19660800, comm_uart_irq_callback, 0); // Network UART
|
||||
|
||||
m_extend_board_irq_enable = 0x3f;
|
||||
m_extend_board_irq_active = 0x00;
|
||||
|
||||
// Set to defaults here, but overridden for most specific games. It represents various bits of
|
||||
// data, such as the firebeat's ability to play certain games at all, whether the firebeat is
|
||||
// meant as a rental unit or normal unit, and whether the unit is meant as a JP firebeat or
|
||||
@ -715,8 +727,6 @@ void firebeat_state::init_firebeat()
|
||||
|
||||
m_maincpu->ppc4xx_spu_set_tx_handler(write8smo_delegate(*this, FUNC(firebeat_state::security_w)));
|
||||
|
||||
set_ibutton(rom);
|
||||
|
||||
init_lights(write32s_delegate(*this), write32s_delegate(*this), write32s_delegate(*this));
|
||||
}
|
||||
|
||||
@ -740,17 +750,14 @@ void firebeat_state::firebeat(machine_config &config)
|
||||
/* video hardware */
|
||||
PALETTE(config, "palette", palette_device::RGB_555);
|
||||
|
||||
K057714(config, m_gcu, 0);
|
||||
m_gcu->irq_callback().set(FUNC(firebeat_state::gcu_interrupt));
|
||||
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
|
||||
screen.set_size(512, 384);
|
||||
screen.set_visarea(0, 511, 0, 383);
|
||||
screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 525, 0, 480);
|
||||
screen.set_screen_update(FUNC(firebeat_state::screen_update_firebeat_0));
|
||||
screen.set_palette("palette");
|
||||
|
||||
K057714(config, m_gcu, 0).set_screen("screen");
|
||||
m_gcu->irq_callback().set(FUNC(firebeat_state::gcu_interrupt));
|
||||
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
@ -774,6 +781,7 @@ void firebeat_state::firebeat_map(address_map &map)
|
||||
map(0x74000000, 0x740003ff).noprw(); // SPU shared RAM
|
||||
map(0x7d000200, 0x7d00021f).r(FUNC(firebeat_state::cabinet_r));
|
||||
map(0x7d000400, 0x7d000401).rw("ymz", FUNC(ymz280b_device::read), FUNC(ymz280b_device::write));
|
||||
map(0x7d000500, 0x7d000501).w(FUNC(firebeat_state::control_w));
|
||||
map(0x7d000800, 0x7d000803).r(FUNC(firebeat_state::input_r));
|
||||
map(0x7d400000, 0x7d5fffff).rw("flash_main", FUNC(fujitsu_29f016a_device::read), FUNC(fujitsu_29f016a_device::write));
|
||||
map(0x7d800000, 0x7d9fffff).rw("flash_snd1", FUNC(fujitsu_29f016a_device::read), FUNC(fujitsu_29f016a_device::write));
|
||||
@ -1018,6 +1026,36 @@ uint8_t firebeat_state::input_r(offs_t offset)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void firebeat_state::control_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
// 0x01 - 31kHz (25.175 MHz)/24kHz (16.6666 MHz) clock switch
|
||||
// 0x02 - Unused?
|
||||
// 0x04 - Set to 1 by all games except beatmania III, usage unknown. Screen related?
|
||||
// 0x08 - Toggles screen mirroring when only one GCU is in use? Default 0
|
||||
// 0x80 - Used by ParaParaParadise and Keyboardmania. Set to 1 when doing YMZ flash initialization?
|
||||
|
||||
if (BIT(data, 0) == 0 && BIT(m_control, 0) == 1)
|
||||
{
|
||||
// Set screen to 31kHz from 24kHz
|
||||
m_gcu->set_pixclock(25.175_MHz_XTAL);
|
||||
|
||||
if (m_gcu_sub)
|
||||
m_gcu_sub->set_pixclock(25.175_MHz_XTAL);
|
||||
}
|
||||
else if (BIT(data, 0) == 1 && BIT(m_control, 0) == 0)
|
||||
{
|
||||
// Set screen to 24kHz from 31kHz
|
||||
m_gcu->set_pixclock(16.6666_MHz_XTAL);
|
||||
|
||||
if (m_gcu_sub)
|
||||
m_gcu_sub->set_pixclock(16.6666_MHz_XTAL);
|
||||
}
|
||||
|
||||
m_control = data;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* ATA Interface */
|
||||
|
||||
@ -1176,11 +1214,13 @@ WRITE_LINE_MEMBER(firebeat_state::sound_irq_callback)
|
||||
|
||||
void firebeat_spu_state::machine_start()
|
||||
{
|
||||
firebeat_state::machine_start();
|
||||
m_dma_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(firebeat_spu_state::spu_dma_callback), this));
|
||||
}
|
||||
|
||||
void firebeat_spu_state::machine_reset()
|
||||
{
|
||||
firebeat_state::machine_reset();
|
||||
m_spu_ata_dma = 0;
|
||||
m_spu_ata_dmarq = 0;
|
||||
m_wave_bank = 0;
|
||||
@ -1430,11 +1470,6 @@ void firebeat_bm3_state::firebeat_bm3(machine_config &config)
|
||||
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &firebeat_bm3_state::firebeat_bm3_map);
|
||||
|
||||
// beatmania III is the only game on the Firebeat platform to use 640x480
|
||||
screen_device *screen = subdevice<screen_device>("screen");
|
||||
screen->set_size(640, 480);
|
||||
screen->set_visarea(0, 639, 0, 479);
|
||||
|
||||
ATA_INTERFACE(config, m_spuata).options(firebeat_ata_devices, "hdd", nullptr, true);
|
||||
m_spuata->irq_handler().set(FUNC(firebeat_bm3_state::spu_ata_interrupt));
|
||||
m_spuata->dmarq_handler().set(FUNC(firebeat_bm3_state::spu_ata_dmarq));
|
||||
@ -1803,28 +1838,22 @@ void firebeat_kbm_state::firebeat_kbm(machine_config &config)
|
||||
/* video hardware */
|
||||
PALETTE(config, "palette", palette_device::RGB_555);
|
||||
|
||||
K057714(config, m_gcu, 0);
|
||||
m_gcu->irq_callback().set(FUNC(firebeat_kbm_state::gcu_interrupt));
|
||||
|
||||
K057714(config, m_gcu_sub, 0);
|
||||
m_gcu_sub->irq_callback().set(FUNC(firebeat_kbm_state::gcu_interrupt));
|
||||
|
||||
screen_device &lscreen(SCREEN(config, "lscreen", SCREEN_TYPE_RASTER));
|
||||
lscreen.set_refresh_hz(60);
|
||||
lscreen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
|
||||
lscreen.set_size(512, 384);
|
||||
lscreen.set_visarea(0, 511, 0, 383);
|
||||
lscreen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 525, 0, 480);
|
||||
lscreen.set_screen_update(FUNC(firebeat_kbm_state::screen_update_firebeat_0));
|
||||
lscreen.set_palette("palette");
|
||||
|
||||
K057714(config, m_gcu, 0).set_screen("lscreen");
|
||||
m_gcu->irq_callback().set(FUNC(firebeat_kbm_state::gcu_interrupt));
|
||||
|
||||
screen_device &rscreen(SCREEN(config, "rscreen", SCREEN_TYPE_RASTER));
|
||||
rscreen.set_refresh_hz(60);
|
||||
rscreen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
|
||||
rscreen.set_size(512, 384);
|
||||
rscreen.set_visarea(0, 511, 0, 383);
|
||||
rscreen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 525, 0, 480);
|
||||
rscreen.set_screen_update(FUNC(firebeat_kbm_state::screen_update_firebeat_1));
|
||||
rscreen.set_palette("palette");
|
||||
|
||||
K057714(config, m_gcu_sub, 0).set_screen("rscreen");
|
||||
m_gcu_sub->irq_callback().set(FUNC(firebeat_kbm_state::gcu_interrupt));
|
||||
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
|
@ -418,14 +418,11 @@ void konendev_state::konendev(machine_config &config)
|
||||
PALETTE(config, "palette", palette_device::RGB_555);
|
||||
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); // Not accurate
|
||||
screen.set_size(640, 480);
|
||||
screen.set_visarea(0, 639, 0, 479);
|
||||
screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 525, 0, 480); // Based on Firebeat settings
|
||||
screen.set_screen_update(FUNC(konendev_state::screen_update));
|
||||
screen.set_palette("palette");
|
||||
|
||||
K057714(config, m_gcu, 0);
|
||||
K057714(config, m_gcu, 0).set_screen("screen");
|
||||
m_gcu->irq_callback().set(FUNC(konendev_state::gcu_interrupt));
|
||||
|
||||
RTC62423(config, m_rtc, XTAL(32'768));
|
||||
|
@ -29,6 +29,7 @@ DEFINE_DEVICE_TYPE(K057714, k057714_device, "k057714", "k057714_device GCU")
|
||||
|
||||
k057714_device::k057714_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, K057714, tag, owner, clock)
|
||||
, device_video_interface(mconfig, *this)
|
||||
, m_irq(*this)
|
||||
{
|
||||
}
|
||||
@ -64,8 +65,15 @@ void k057714_device::device_start()
|
||||
save_item(NAME(m_fb_origin_y));
|
||||
save_item(NAME(m_layer_select));
|
||||
save_item(NAME(m_reg_6c));
|
||||
save_item(NAME(m_display_width));
|
||||
save_item(NAME(m_display_height));
|
||||
save_item(NAME(m_display_h_visarea));
|
||||
save_item(NAME(m_display_h_frontporch));
|
||||
save_item(NAME(m_display_h_backporch));
|
||||
save_item(NAME(m_display_h_syncpulse));
|
||||
save_item(NAME(m_display_v_visarea));
|
||||
save_item(NAME(m_display_v_frontporch));
|
||||
save_item(NAME(m_display_v_backporch));
|
||||
save_item(NAME(m_display_v_syncpulse));
|
||||
save_item(NAME(m_pixclock));
|
||||
}
|
||||
|
||||
void k057714_device::device_reset()
|
||||
@ -75,8 +83,24 @@ void k057714_device::device_reset()
|
||||
// display width/height through registers.
|
||||
// The assumption here is that since beatmania III doesn't set the display width/height
|
||||
// then the game is assuming that it's already at the correct settings upon boot.
|
||||
m_display_width = 639;
|
||||
m_display_height = 479;
|
||||
|
||||
// Timing information taken from table found in all Firebeat games.
|
||||
// table idx (h vis area, front porch, sync pulse, back porch, h total) (v vis area, front porch, sync pulse, back porch, v total)
|
||||
// 0 (640, 16, 96, 48 = 800) (480, 10, 2, 33 = 525)
|
||||
// 1 (512, 5, 96, 72 = 685) (384, 6, 4, 22 = 416)
|
||||
// 2 (800, 40, 128, 88 = 1056) (600, 1, 4, 23 = 628)
|
||||
// 3 (640, 20, 23, 165 = 848) (384, 6, 1, 27 = 418)
|
||||
// 4 (640, 10, 21, 10 = 681) (480, 10, 2, 33 = 525)
|
||||
m_display_h_visarea = 640;
|
||||
m_display_h_frontporch = 16;
|
||||
m_display_h_backporch = 48;
|
||||
m_display_h_syncpulse = 96;
|
||||
m_display_v_visarea = 480;
|
||||
m_display_v_frontporch = 10;
|
||||
m_display_v_backporch = 33;
|
||||
m_display_v_syncpulse = 2;
|
||||
m_pixclock = 25'175'000; // 25.175_MHz_XTAL, default for Firebeat but maybe not other machiness. The value can be changed externally
|
||||
crtc_set_screen_params();
|
||||
|
||||
m_vram_read_addr = 0;
|
||||
m_command_fifo0_ptr = 0;
|
||||
@ -121,6 +145,21 @@ void k057714_device::device_stop()
|
||||
#endif
|
||||
}
|
||||
|
||||
void k057714_device::set_pixclock(const XTAL &xtal)
|
||||
{
|
||||
xtal.validate(std::string("Setting pixel clock for ") + tag());
|
||||
m_pixclock = xtal.value();
|
||||
crtc_set_screen_params();
|
||||
}
|
||||
|
||||
inline void k057714_device::crtc_set_screen_params()
|
||||
{
|
||||
auto htotal = m_display_h_visarea + m_display_h_frontporch + m_display_h_backporch + m_display_h_syncpulse;
|
||||
auto vtotal = m_display_v_visarea + m_display_v_frontporch + m_display_v_backporch + m_display_v_syncpulse;
|
||||
|
||||
rectangle visarea(0, m_display_h_visarea - 1, 0, m_display_v_visarea - 1);
|
||||
screen().configure(htotal, vtotal, visarea, HZ_TO_ATTOSECONDS(m_pixclock) * htotal * vtotal);
|
||||
}
|
||||
|
||||
uint32_t k057714_device::read(offs_t offset)
|
||||
{
|
||||
@ -149,21 +188,40 @@ void k057714_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
int reg = offset * 4;
|
||||
|
||||
|
||||
switch (reg)
|
||||
{
|
||||
case 0x00:
|
||||
if (ACCESSING_BITS_16_31)
|
||||
{
|
||||
// Viewport configurations discovered in game code: 640x480, 512x384, 800x600, 640x384
|
||||
m_display_width = (data >> 16) & 0xffff;
|
||||
m_display_h_visarea = ((data >> 16) & 0xffff) + 1;
|
||||
}
|
||||
if (ACCESSING_BITS_0_15)
|
||||
{
|
||||
m_display_h_frontporch = ((data >> 8) & 0xff) + 1;
|
||||
m_display_h_backporch = (data & 0xff) + 1;
|
||||
}
|
||||
crtc_set_screen_params();
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
if (ACCESSING_BITS_16_31)
|
||||
{
|
||||
m_display_height = (data >> 16) & 0xffff;
|
||||
m_display_v_visarea = ((data >> 16) & 0xffff) + 1;
|
||||
}
|
||||
if (ACCESSING_BITS_0_15)
|
||||
{
|
||||
m_display_v_frontporch = ((data >> 8) & 0xff) + 1;
|
||||
m_display_v_backporch = (data & 0xff) + 1;
|
||||
}
|
||||
crtc_set_screen_params();
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
if (ACCESSING_BITS_16_31)
|
||||
{
|
||||
m_display_h_syncpulse = ((data >> 24) & 0xff) + 1;
|
||||
m_display_v_syncpulse = ((data >> 16) & 0xff) + 1;
|
||||
crtc_set_screen_params();
|
||||
}
|
||||
break;
|
||||
|
||||
@ -462,17 +520,6 @@ void k057714_device::draw_frame(int frame, bitmap_ind16 &bitmap, const rectangle
|
||||
|
||||
int k057714_device::draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
if (m_display_width != 0 && m_display_height != 0)
|
||||
{
|
||||
rectangle visarea = screen.visible_area();
|
||||
if (visarea.max_x != m_display_width || visarea.max_y != m_display_height)
|
||||
{
|
||||
visarea.max_x = m_display_width;
|
||||
visarea.max_y = m_display_height;
|
||||
screen.configure(m_display_width, m_display_height, visarea, screen.frame_period().attoseconds());
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.fill(0, cliprect);
|
||||
|
||||
bool inverse_trans = false;
|
||||
|
@ -6,12 +6,16 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
class k057714_device : public device_t
|
||||
class k057714_device : public device_t, public device_video_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
k057714_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
auto irq_callback() { return m_irq.bind(); }
|
||||
|
||||
void set_pixclock(const XTAL &xtal);
|
||||
|
||||
int draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
uint32_t read(offs_t offset);
|
||||
@ -39,6 +43,8 @@ private:
|
||||
VRAM_SIZE_HALF = 0x2000000 / 2
|
||||
};
|
||||
|
||||
void crtc_set_screen_params();
|
||||
|
||||
void execute_command(uint32_t *cmd);
|
||||
void execute_display_list(uint32_t addr);
|
||||
void draw_object(uint32_t *cmd);
|
||||
@ -70,8 +76,16 @@ private:
|
||||
uint32_t m_layer_select;
|
||||
uint32_t m_reg_6c;
|
||||
|
||||
uint32_t m_display_width;
|
||||
uint32_t m_display_height;
|
||||
uint32_t m_display_h_visarea;
|
||||
uint32_t m_display_h_frontporch;
|
||||
uint32_t m_display_h_backporch;
|
||||
uint32_t m_display_h_syncpulse;
|
||||
uint32_t m_display_v_visarea;
|
||||
uint32_t m_display_v_frontporch;
|
||||
uint32_t m_display_v_backporch;
|
||||
uint32_t m_display_v_syncpulse;
|
||||
|
||||
uint32_t m_pixclock;
|
||||
|
||||
devcb_write_line m_irq;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user