diff --git a/src/emu/xtal.cpp b/src/emu/xtal.cpp index e9c38a3f0ac..40331eb2e03 100644 --- a/src/emu/xtal.cpp +++ b/src/emu/xtal.cpp @@ -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 */ diff --git a/src/mame/drivers/firebeat.cpp b/src/mame/drivers/firebeat.cpp index 26ac10aa36e..13d5b465a71 100644 --- a/src/mame/drivers/firebeat.cpp +++ b/src/mame/drivers/firebeat.cpp @@ -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 m_work_ram; required_device m_ata; required_device m_gcu; + optional_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 m_duart_midi; required_device_array m_kbd; - required_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"); - 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(); diff --git a/src/mame/drivers/konendev.cpp b/src/mame/drivers/konendev.cpp index a0d62195c1b..6736bdbf813 100644 --- a/src/mame/drivers/konendev.cpp +++ b/src/mame/drivers/konendev.cpp @@ -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)); diff --git a/src/mame/video/k057714.cpp b/src/mame/video/k057714.cpp index d26a5d9e636..447f7220510 100644 --- a/src/mame/video/k057714.cpp +++ b/src/mame/video/k057714.cpp @@ -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; diff --git a/src/mame/video/k057714.h b/src/mame/video/k057714.h index 2d584fde4e3..5e6565f5ff8 100644 --- a/src/mame/video/k057714.h +++ b/src/mame/video/k057714.h @@ -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; };