diff --git a/src/mame/drivers/hng64.cpp b/src/mame/drivers/hng64.cpp index da62725d74b..37c9c952508 100644 --- a/src/mame/drivers/hng64.cpp +++ b/src/mame/drivers/hng64.cpp @@ -450,19 +450,6 @@ or Fatal Fury for example). #define VERBOSE 1 #include "logmacro.h" -/* TODO: NOT measured! */ -#define PIXEL_CLOCK ((HNG64_MASTER_CLOCK*2)/4) // x 2 is due of the interlaced screen ... - -#define HTOTAL (0x200+0x100) -#define HBEND (0) -#define HBSTART (0x200) - -#define VTOTAL (264*2) -#define VBEND (0) -#define VBSTART (224*2) - - - READ32_MEMBER(hng64_state::hng64_com_r) { //LOG("com read (PC=%08x): %08x %08x = %08x\n", m_maincpu->pc(), (offset*4)+0xc0000000, mem_mask, m_idt7133_dpram[offset]); @@ -676,63 +663,6 @@ WRITE8_MEMBER(hng64_state::hng64_dualport_w) LOG("%s: dualport WRITE %04x %02x\n", machine().describe_context(), offset, data); } - -// Transition Control memory. -WRITE32_MEMBER(hng64_state::tcram_w) -{ - uint32_t *hng64_tcram = m_tcram; - - COMBINE_DATA (&hng64_tcram[offset]); - - if(offset == 0x02) - { - uint16_t min_x, min_y, max_x, max_y; - rectangle visarea = m_screen->visible_area(); - - min_x = (hng64_tcram[1] & 0xffff0000) >> 16; - min_y = (hng64_tcram[1] & 0x0000ffff) >> 0; - max_x = (hng64_tcram[2] & 0xffff0000) >> 16; - max_y = (hng64_tcram[2] & 0x0000ffff) >> 0; - - if(max_x == 0 || max_y == 0) // bail out if values are invalid, Fatal Fury WA sets this to disable the screen. - { - m_screen_dis = 1; - return; - } - - m_screen_dis = 0; - - visarea.set(min_x, min_x + max_x - 1, min_y, min_y + max_y - 1); - m_screen->configure(HTOTAL, VTOTAL, visarea, m_screen->frame_period().attoseconds() ); - } -} - -READ32_MEMBER(hng64_state::tcram_r) -{ - //printf("Q1 R : %.8x %.8x\n", offset, hng64_tcram[offset]); - if(offset == 0x12) - return ioport("VBLANK")->read(); - - return m_tcram[offset]; -} - -/* Some games (namely sams64 after the title screen) tests bit 15 of this to be high, - unknown purpose (vblank? related to the display list?). - - bit 1 needs to be off, otherwise Fatal Fury WA locks up (FIFO full?) - bit 0 is likely to be fifo empty (active low) - */ -READ32_MEMBER(hng64_state::unk_vreg_r) -{ -// m_unk_vreg_toggle^=0x8000; - - return 0; - -// return ++m_unk_vreg_toggle; -} - - - /************************************************************************************************************/ /* The following is guesswork, needs confirmation with a test on the real board. */ @@ -782,18 +712,6 @@ WRITE32_MEMBER(hng64_state::hng64_sprite_clear_odd_w) } } -/* - 0xE0000000 sound - 0xD0100000 3D bank A - 0xD0200000 3D bank B - 0xC0000000-0xC000C000 Sprite - 0xC0200000-0xC0204000 palette - 0xC0100000-0xC0180000 Tilemap - 0xBF808000-0xBF808800 Dualport ram - 0xBF800000-0xBF808000 S-RAM - 0x60000000-0x60001000 Comm dualport ram -*/ - WRITE32_MEMBER(hng64_state::hng64_vregs_w) { // printf("hng64_vregs_w %02x, %08x %08x\n", offset * 4, data, mem_mask); @@ -839,7 +757,7 @@ WRITE16_MEMBER(hng64_state::main_sound_comms_w) void hng64_state::hng_map(address_map &map) { - + // main RAM / ROM map(0x00000000, 0x00ffffff).ram().share("mainram"); map(0x04000000, 0x05ffffff).nopw().rom().region("gameprg", 0).share("cart"); @@ -849,30 +767,43 @@ void hng64_state::hng_map(address_map &map) // SRAM. Coin data, Player Statistics, etc. map(0x1F800000, 0x1F803fff).ram().share("nvram"); - // Dualport RAM + // Dualport RAM (shared with IO MCU) map(0x1F808000, 0x1F8087ff).rw(FUNC(hng64_state::hng64_dualport_r), FUNC(hng64_state::hng64_dualport_w)).umask32(0xffffffff); - // BIOS + // BIOS ROM map(0x1fc00000, 0x1fc7ffff).nopw().rom().region("user1", 0).share("rombase"); - // Video + // Sprites map(0x20000000, 0x2000bfff).ram().share("spriteram"); map(0x2000d800, 0x2000e3ff).w(FUNC(hng64_state::hng64_sprite_clear_even_w)); map(0x2000e400, 0x2000efff).w(FUNC(hng64_state::hng64_sprite_clear_odd_w)); map(0x20010000, 0x20010013).ram().share("spriteregs"); + + // Backgrounds map(0x20100000, 0x2017ffff).ram().w(FUNC(hng64_state::hng64_videoram_w)).share("videoram"); // Tilemap map(0x20190000, 0x20190037).ram().w(FUNC(hng64_state::hng64_vregs_w)).share("videoregs"); + + // Mixing map(0x20200000, 0x20203fff).ram().w(m_palette, FUNC(palette_device::write32)).share("palette"); - map(0x20208000, 0x2020805f).rw(FUNC(hng64_state::tcram_r), FUNC(hng64_state::tcram_w)).share("tcram"); // Transition Control + map(0x20208000, 0x2020805f).w(FUNC(hng64_state::tcram_w)).share("tcram"); // Transition Control + map(0x20208000, 0x2020805f).r(FUNC(hng64_state::tcram_r)); + + // 3D display list control map(0x20300000, 0x203001ff).w(FUNC(hng64_state::dl_w)); // 3d Display List map(0x20300200, 0x20300203).w(FUNC(hng64_state::dl_upload_w)); // 3d Display List Upload + map(0x20300210, 0x20300213).w(FUNC(hng64_state::dl_unk_w)); // once, on startup map(0x20300214, 0x20300217).w(FUNC(hng64_state::dl_control_w)); - map(0x20300218, 0x2030021b).r(FUNC(hng64_state::unk_vreg_r)); + map(0x20300218, 0x2030021b).r(FUNC(hng64_state::dl_vreg_r)); - // 3d? - map(0x30000000, 0x3000002f).ram().share("3dregs"); - map(0x30100000, 0x3015ffff).rw(FUNC(hng64_state::hng64_3d_1_r), FUNC(hng64_state::hng64_3d_1_w)).share("3d_1"); // 3D Display Buffer A - map(0x30200000, 0x3025ffff).rw(FUNC(hng64_state::hng64_3d_2_r), FUNC(hng64_state::hng64_3d_2_w)).share("3d_2"); // 3D Display Buffer B + // 3D framebuffer + map(0x30000000, 0x30000003).rw(FUNC(hng64_state::hng64_fbcontrol_r), FUNC(hng64_state::hng64_fbcontrol_w)).umask32(0xffffffff); + map(0x30000004, 0x30000007).w(FUNC(hng64_state::hng64_fbunkpair_w)).umask32(0xffff); + map(0x30000008, 0x3000000b).w(FUNC(hng64_state::hng64_fbscroll_w)).umask32(0xffff); + map(0x3000000c, 0x3000000f).w(FUNC(hng64_state::hng64_fbunkbyte_w)).umask32(0xffffffff); + map(0x30000010, 0x3000002f).rw(FUNC(hng64_state::hng64_fbtable_r), FUNC(hng64_state::hng64_fbtable_w)).share("fbtable"); + + map(0x30100000, 0x3015ffff).rw(FUNC(hng64_state::hng64_fbram1_r), FUNC(hng64_state::hng64_fbram1_w)).share("fbram1"); // 3D Display Buffer A + map(0x30200000, 0x3025ffff).rw(FUNC(hng64_state::hng64_fbram2_r), FUNC(hng64_state::hng64_fbram2_w)).share("fbram2"); // 3D Display Buffer B // Sound map(0x60000000, 0x601fffff).rw(FUNC(hng64_state::hng64_soundram2_r), FUNC(hng64_state::hng64_soundram2_w)); // actually seems unmapped, see note in audio/hng64.c @@ -882,16 +813,9 @@ void hng64_state::hng_map(address_map &map) map(0x68000000, 0x6800000f).rw(FUNC(hng64_state::main_sound_comms_r), FUNC(hng64_state::main_sound_comms_w)); map(0x6f000000, 0x6f000003).w(FUNC(hng64_state::hng64_soundcpu_enable_w)); - // Communications + // Dualport RAM (shared with Communications CPU) map(0xc0000000, 0xc0000fff).rw(FUNC(hng64_state::hng64_com_r), FUNC(hng64_state::hng64_com_w)).share("com_ram"); map(0xc0001000, 0xc0001007).ram().share("comhack");//.rw(FUNC(hng64_state::hng64_com_share_mips_r), FUNC(hng64_state::hng64_com_share_mips_w)); - - /* 6e000000-6fffffff */ - /* 80000000-81ffffff */ - /* 88000000-89ffffff */ - /* 90000000-97ffffff */ - /* 98000000-9bffffff */ - /* a0000000-a3ffffff */ } @@ -1475,6 +1399,12 @@ void hng64_state::init_hng64_race() init_hng64(); } +void hng64_state::init_roadedge() +{ + init_hng64_race(); + m_roadedge_3d_hack = 1; +} + void hng64_state::init_hng64_shoot() { m_no_machine_error_code = 0x03; @@ -1778,7 +1708,7 @@ void hng64_state::machine_start() TIMER_CALLBACK_MEMBER(hng64_state::comhack_callback) { - printf("comhack_callback %04x\n\n", m_comhack[0]); + LOG("comhack_callback %04x\n\n", m_comhack[0]); m_comhack[0] = m_comhack[0] | 0x0002; } @@ -1794,6 +1724,13 @@ void hng64_state::machine_reset() // on real hardware, even with no network, it takes until the counter reaches about 37 (Xtreme Rally) to boot, this kicks in at around 7 m_comhack_timer->adjust(m_maincpu->cycles_to_attotime(400000000)); + + // does the HW init these to anything? + m_fbcontrol[0] = 0x00; + m_fbcontrol[1] = 0x00; + m_fbcontrol[2] = 0x00; + m_fbcontrol[3] = 0x00; + } /*********************************************** @@ -2497,7 +2434,7 @@ ROM_END GAME( 1997, hng64, 0, hng64, hng64, hng64_state, init_hng64, ROT0, "SNK", "Hyper NeoGeo 64 Bios", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND|MACHINE_IS_BIOS_ROOT ) /* Games */ -GAME( 1997, roadedge, hng64, hng64, hng64_drive, hng64_state, init_hng64_race, ROT0, "SNK", "Roads Edge / Round Trip (rev.B)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 001 */ +GAME( 1997, roadedge, hng64, hng64, hng64_drive, hng64_state, init_roadedge, ROT0, "SNK", "Roads Edge / Round Trip (rev.B)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 001 */ GAME( 1998, sams64, hng64, hng64, hng64_fight, hng64_state, init_ss64, ROT0, "SNK", "Samurai Shodown 64 / Samurai Spirits 64", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 002 */ GAME( 1998, xrally, hng64, hng64, hng64_drive, hng64_state, init_hng64_race, ROT0, "SNK", "Xtreme Rally / Off Beat Racer!", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 003 */ GAME( 1998, bbust2, hng64, hng64, hng64_shoot, hng64_state, init_hng64_shoot, ROT0, "SNK", "Beast Busters 2nd Nightmare", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND ) /* 004 */ diff --git a/src/mame/includes/hng64.h b/src/mame/includes/hng64.h index 1c3792ec014..47b71ec7995 100644 --- a/src/mame/includes/hng64.h +++ b/src/mame/includes/hng64.h @@ -149,18 +149,20 @@ public: m_videoram(*this, "videoram"), m_videoregs(*this, "videoregs"), m_tcram(*this, "tcram"), - m_3dregs(*this, "3dregs"), + m_fbtable(*this, "fbtable"), m_comhack(*this, "comhack"), - m_3d_1(*this, "3d_1"), - m_3d_2(*this, "3d_2"), + m_fbram1(*this, "fbram1"), + m_fbram2(*this, "fbram2"), m_idt7133_dpram(*this, "com_ram"), m_gfxdecode(*this, "gfxdecode"), m_intest(*this, "IN%u", 0U), - m_samsho64_3d_hack(0) + m_samsho64_3d_hack(0), + m_roadedge_3d_hack(0) {} void hng64(machine_config &config); + void init_roadedge(); void init_hng64_race(); void init_hng64(); void init_hng64_shoot(); @@ -172,6 +174,18 @@ public: required_device m_palette; private: + /* TODO: NOT measured! */ + const int PIXEL_CLOCK = (HNG64_MASTER_CLOCK*2)/4; // x 2 is due to the interlaced screen ... + + const int HTOTAL = 0x200+0x100; + const int HBEND = 0; + const int HBSTART = 0x200; + + const int VTOTAL = 264*2; + const int VBEND = 0; + const int VBSTART = 224*2; + + required_device m_maincpu; required_device m_audiocpu; required_device m_iomcu; @@ -191,10 +205,10 @@ private: required_shared_ptr m_tcram; std::unique_ptr m_dl; - required_shared_ptr m_3dregs; + required_shared_ptr m_fbtable; required_shared_ptr m_comhack; - required_shared_ptr m_3d_1; - required_shared_ptr m_3d_2; + required_shared_ptr m_fbram1; + required_shared_ptr m_fbram2; required_shared_ptr m_idt7133_dpram; //required_shared_ptr m_com_mmu_mem; @@ -204,6 +218,9 @@ private: optional_ioport_array<8> m_intest; int m_samsho64_3d_hack; + int m_roadedge_3d_hack; + + uint8_t m_fbcontrol[4]; std::unique_ptr m_soundram; std::unique_ptr m_soundram2; @@ -265,17 +282,33 @@ private: DECLARE_READ8_MEMBER(hng64_dualport_r); DECLARE_WRITE8_MEMBER(hng64_dualport_w); - DECLARE_READ32_MEMBER(hng64_3d_1_r); - DECLARE_READ32_MEMBER(hng64_3d_2_r); - DECLARE_WRITE32_MEMBER(hng64_3d_1_w); - DECLARE_WRITE32_MEMBER(hng64_3d_2_w); + DECLARE_READ8_MEMBER(hng64_fbcontrol_r); + DECLARE_WRITE8_MEMBER(hng64_fbcontrol_w); + + DECLARE_WRITE16_MEMBER(hng64_fbunkpair_w); + DECLARE_WRITE16_MEMBER(hng64_fbscroll_w); + + DECLARE_WRITE8_MEMBER(hng64_fbunkbyte_w); + + DECLARE_READ32_MEMBER(hng64_fbtable_r); + DECLARE_WRITE32_MEMBER(hng64_fbtable_w); + + DECLARE_READ32_MEMBER(hng64_fbram1_r); + DECLARE_WRITE32_MEMBER(hng64_fbram1_w); + + DECLARE_READ32_MEMBER(hng64_fbram2_r); + DECLARE_WRITE32_MEMBER(hng64_fbram2_w); + DECLARE_WRITE16_MEMBER(dl_w); //DECLARE_READ32_MEMBER(dl_r); DECLARE_WRITE32_MEMBER(dl_control_w); DECLARE_WRITE32_MEMBER(dl_upload_w); + DECLARE_WRITE32_MEMBER(dl_unk_w); + DECLARE_READ32_MEMBER(dl_vreg_r); + DECLARE_WRITE32_MEMBER(tcram_w); DECLARE_READ32_MEMBER(tcram_r); - DECLARE_READ32_MEMBER(unk_vreg_r); + DECLARE_WRITE32_MEMBER(hng64_soundram_w); DECLARE_READ32_MEMBER(hng64_soundram_r); DECLARE_WRITE32_MEMBER(hng64_vregs_w); diff --git a/src/mame/video/hng64.cpp b/src/mame/video/hng64.cpp index 10580f27c50..7628fafe227 100644 --- a/src/mame/video/hng64.cpp +++ b/src/mame/video/hng64.cpp @@ -722,8 +722,9 @@ void hng64_state::hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap, see 1:32 in http://www.youtube.com/watch?v=PoYaHOILuGs Xtreme Rally seems to have an issue with this mode on the communication check - screen at startup, but according to videos that should scroll, and no scroll - values are updated, so it might be an unrelated bug. + screen at startup, however during the period in which the values are invalid + it looks like the display shouldn't even be enabled (only gets enabled when + the value starts counting up) */ @@ -915,7 +916,7 @@ void hng64_state::hng64_drawtilemap(screen_device &screen, bitmap_rgb32 &bitmap, uint32_t hng64_state::screen_update_hng64(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { -#if 1 +#if 0 // press in sams64_2 attract mode for a nice debug screen from the game // not sure how functional it is, and it doesn't appear to test everything (rowscroll modes etc.) // but it could be useful @@ -927,15 +928,6 @@ uint32_t hng64_state::screen_update_hng64(screen_device &screen, bitmap_rgb32 &b { space.write_byte(0x2f27c8, 0x2); } - else if (!strcmp(machine().system().name, "roadedge")) // hack to get test mode (useful for sound test) - { - space.write_byte(0xcfb53, 0x1); - } - else if (!strcmp(machine().system().name, "xrally")) // hack to get test mode (useful for sound test) - { - space.write_byte(0xa2363, 0x1); - } - } #endif @@ -1001,7 +993,7 @@ uint32_t hng64_state::screen_update_hng64(screen_device &screen, bitmap_rgb32 &b hng64_drawtilemap(screen,bitmap,cliprect, 0); // 3d gets drawn next - if(!(m_3dregs[0] & 0x1000000)) + if(!(m_fbcontrol[0] & 0x01)) { int x, y; @@ -1054,12 +1046,6 @@ uint32_t hng64_state::screen_update_hng64(screen_device &screen, bitmap_rgb32 &b m_videoregs[0x0c], m_videoregs[0x0d]); - if (0) - popmessage("3D: %08x %08x %08x %08x : %08x %08x %08x %08x : %08x %08x %08x %08x", - m_3dregs[0x00/4], m_3dregs[0x04/4], m_3dregs[0x08/4], m_3dregs[0x0c/4], - m_3dregs[0x10/4], m_3dregs[0x14/4], m_3dregs[0x18/4], m_3dregs[0x1c/4], - m_3dregs[0x20/4], m_3dregs[0x24/4], m_3dregs[0x28/4], m_3dregs[0x2c/4]); - if (0) popmessage("TC: %08x %08x %08x %08x : %08x %08x %08x %08x : %08x %08x %08x %08x : %08x %08x %08x %08x : %08x %08x %08x %08x : %08x %08x %08x %08x", m_tcram[0x00/4], @@ -1159,6 +1145,46 @@ WRITE_LINE_MEMBER(hng64_state::screen_vblank_hng64) * Or maybe they set transition type (there seems to be a cute scaling-squares transition in there somewhere)... */ +// Transition Control memory. +WRITE32_MEMBER(hng64_state::tcram_w) +{ + uint32_t *hng64_tcram = m_tcram; + + COMBINE_DATA (&hng64_tcram[offset]); + + if(offset == 0x02) + { + uint16_t min_x, min_y, max_x, max_y; + rectangle visarea = m_screen->visible_area(); + + min_x = (hng64_tcram[1] & 0xffff0000) >> 16; + min_y = (hng64_tcram[1] & 0x0000ffff) >> 0; + max_x = (hng64_tcram[2] & 0xffff0000) >> 16; + max_y = (hng64_tcram[2] & 0x0000ffff) >> 0; + + if(max_x == 0 || max_y == 0) // bail out if values are invalid, Fatal Fury WA sets this to disable the screen. + { + m_screen_dis = 1; + return; + } + + m_screen_dis = 0; + + visarea.set(min_x, min_x + max_x - 1, min_y, min_y + max_y - 1); + m_screen->configure(HTOTAL, VTOTAL, visarea, m_screen->frame_period().attoseconds() ); + } +} + +READ32_MEMBER(hng64_state::tcram_r) +{ + /* is this really a port? this seems treated like RAM otherwise, check if there's code anywhere + to write the desired value here instead */ + if ((offset*4) == 0x48) + return ioport("VBLANK")->read(); + + return m_tcram[offset]; +} + // Very much a work in progress - no hard testing has been done void hng64_state::transition_control( bitmap_rgb32 &bitmap, const rectangle &cliprect) { diff --git a/src/mame/video/hng64_3d.hxx b/src/mame/video/hng64_3d.hxx index 45ed1c0f685..218c54b5abc 100644 --- a/src/mame/video/hng64_3d.hxx +++ b/src/mame/video/hng64_3d.hxx @@ -17,31 +17,37 @@ hng64_poly_renderer::hng64_poly_renderer(hng64_state& state) -// Hardware calls these '3d buffers' -// They're only read during the startup check of fatfurwa. Z-buffer memory? Front buffer, back buffer? -// They're definitely mirrored in the startup test, according to ElSemi -// 30100000-3011ffff is framebuffer A0 -// 30120000-3013ffff is framebuffer A1 -// 30140000-3015ffff is ZBuffer A +/* Hardware calls these '3d buffers' -READ32_MEMBER(hng64_state::hng64_3d_1_r) + They're only read during the startup check, never written + + They're definitely mirrored in the startup test, according to ElSemi + + The games run in interlace mode, so buffer resolution can be half the effective screen height + + 30100000-3011ffff is framebuffer A0 (512x256 8-bit?) (pal data?) + 30120000-3013ffff is framebuffer A1 (512x256 8-bit?) (pal data?) + 30140000-3015ffff is ZBuffer A (512x256 8-bit?) +*/ + +READ32_MEMBER(hng64_state::hng64_fbram1_r) { - return m_3d_1[offset]; + return m_fbram1[offset]; } -WRITE32_MEMBER(hng64_state::hng64_3d_1_w) +WRITE32_MEMBER(hng64_state::hng64_fbram1_w) { - COMBINE_DATA (&m_3d_1[offset]); + COMBINE_DATA (&m_fbram1[offset]); } -READ32_MEMBER(hng64_state::hng64_3d_2_r) +READ32_MEMBER(hng64_state::hng64_fbram2_r) { - return m_3d_2[offset]; + return m_fbram2[offset]; } -WRITE32_MEMBER(hng64_state::hng64_3d_2_w) +WRITE32_MEMBER(hng64_state::hng64_fbram2_w) { - COMBINE_DATA (&m_3d_2[offset]); + COMBINE_DATA (&m_fbram2[offset]); } // The 3d 'display list' @@ -50,8 +56,10 @@ WRITE16_MEMBER(hng64_state::dl_w) COMBINE_DATA(&m_dl[offset]); } - - +WRITE32_MEMBER(hng64_state::dl_unk_w) +{ + logerror("%s: dl_unk_w %08x (%08x)\n", machine().describe_context(), data, mem_mask); +} WRITE32_MEMBER(hng64_state::dl_upload_w) { @@ -82,29 +90,43 @@ TIMER_CALLBACK_MEMBER(hng64_state::hng64_3dfifo_processed) WRITE32_MEMBER(hng64_state::dl_control_w) { - // This could be a multiple display list thing, but the palette seems to be lost between lists? - // Many games briefly set this to 0x4 on startup. Maybe there are 3 display lists? - // The sams64 games briefly set this value to 0x0c00 on boot. Maybe there are 4 lists and they can be combined? + /* m_activeDisplayList is not currently connected to anything, it seems unlikely there are different banks. + games typically write up to 8 lots of 0x200 data, writing bit 0 between them + + bit 0 (0x01) process DMA from 3d FIFO to framebuffer? + bit 1 (0x02) written before first set of dl data each frame on some games, but not on SS? + bit 2 (0x04) reset buffer count (startup only) + */ + + /* if (data & 0x01) m_activeDisplayList = 0; else if (data & 0x02) m_activeDisplayList = 1; + */ -// printf("dl_control_w %08x %08x\n", data, mem_mask); -// -// if(data & 2) // swap buffers -// { -// clear3d(); -// } -// -// printf("%02x\n",data); -// -// if(data & 1) // process DMA from 3d FIFO to framebuffer -// if(data & 4) // reset buffer count + /* + printf("dl_control_w %08x %08x\n", data, mem_mask); + + if(data & 2) // swap buffers + { + clear3d(); + } + */ } +READ32_MEMBER(hng64_state::dl_vreg_r) +{ + /* tested with possible masked bits 0xf003 (often masking 0xf000 or 0x0003) + + various wait loops on bit 0x02 (bit 1) after sending 3d commands + tests failing on other bits can cause display list writes to be skipped + Sams64 after the title screen) tests bit 15 of this to be high, unknown reason + */ + return 0; +} //////////////////// // 3d 'Functions' // @@ -520,9 +542,9 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys) // FIXME: This isn't correct. // Buriki & Xrally need this line. Roads Edge needs it removed. // So instead we're looking for a bit that is on for XRally & Buriki, but noone else. - if (m_3dregs[0x00/4] & 0x2000) + if (m_fbcontrol[2] & 0x20) { - if (strcmp(machine().basename(), "roadedge")) + if (!m_roadedge_3d_hack) currentPoly.palOffset += 0x800; } @@ -785,30 +807,25 @@ void hng64_state::recoverPolygonBlock(const uint16_t* packet, int& numPolys) } } - - // BACKFACE CULL // - // (empirical evidence seems to show the hng64 hardware does not backface cull) // -#if 0 + // BACKFACE CULL + // roadedge has various one-way barriers that you can drive through, but need to be invisible from behind, so needs this culling float cullRay[4]; float cullNorm[4]; // Cast a ray out of the camera towards the polygon's point in eyespace. - vecmatmul4(cullRay, modelViewMatrix, currentPoly.vert[0].worldCoords); + vecmatmul4(cullRay, m_modelViewMatrix, currentPoly.vert[0].worldCoords); normalize(cullRay); // Dot product that with the normal to see if you're negative... - vecmatmul4(cullNorm, modelViewMatrix, currentPoly.faceNormal); + vecmatmul4(cullNorm, m_modelViewMatrix, currentPoly.faceNormal); const float backfaceCullResult = vecDotProduct(cullRay, cullNorm); if (backfaceCullResult < 0.0f) currentPoly.visible = 1; else currentPoly.visible = 0; -#endif - // BEHIND-THE-CAMERA CULL // - float cullRay[4]; vecmatmul4(cullRay, m_modelViewMatrix, currentPoly.vert[0].worldCoords); if (cullRay[2] > 0.0f) // Camera is pointing down -Z { @@ -910,7 +927,9 @@ void hng64_state::hng64_command3d(const uint16_t* packet) switch (packet[0]) { - case 0x0000: // Appears to be a NOP. + case 0x0000: // NOP? + /* Appears to be a NOP (or 'end of list for this frame, ignore everything after' doesn't stop stray 3d objects in game for xrally/roadedge + although does stop a partial hng64 logo being displayed assuming that's meant to be kept onscreen by some other means without valid data) */ break; case 0x0001: // Camera transformation. @@ -935,15 +954,6 @@ void hng64_state::hng64_command3d(const uint16_t* packet) break; case 0x0102: // Geometry with only translation - // HACK. Give up on strange calls to 0102. - if (packet[8] != 0x0102) - { - // It appears as though packet[7] might hold the magic # - // Almost looks like there is a chain mode for these guys. Same for 0101? - // printf("WARNING: "); printPacket(packet, 1); - break; - } - // Split the packet and call recoverPolygonBlock on each half. uint16_t miniPacket[16]; memset(miniPacket, 0, sizeof(uint16_t)*16); @@ -953,12 +963,23 @@ void hng64_state::hng64_command3d(const uint16_t* packet) miniPacket[15] = 0x7fff; recoverPolygonBlock(miniPacket, numPolys); - memset(miniPacket, 0, sizeof(uint16_t)*16); - for (int i = 0; i < 7; i++) miniPacket[i] = packet[i+8]; - miniPacket[7] = 0x7fff; - miniPacket[11] = 0x7fff; - miniPacket[15] = 0x7fff; - recoverPolygonBlock(miniPacket, numPolys); + + if (packet[8] == 0x0102) + { + memset(miniPacket, 0, sizeof(uint16_t) * 16); + for (int i = 0; i < 7; i++) miniPacket[i] = packet[i + 8]; + miniPacket[7] = 0x7fff; + miniPacket[11] = 0x7fff; + miniPacket[15] = 0x7fff; + recoverPolygonBlock(miniPacket, numPolys); + } + else + { + /* if the 2nd value isn't 0x0102 don't render it + it could just be that the display list is corrupt at this point tho, see note above + */ + } + break; case 0x1000: // Unknown: Some sort of global flags? @@ -1006,19 +1027,85 @@ void hng64_state::clear3d() /* 3D/framebuffer video registers * ------------------------------ * - * uint32_t | Bits | Use - * | 3322 2222 2222 1111 1111 11 | - * -------+-1098-7654-3210-9876-5432-1098-7654-3210-+---------------- - * 0 | ---- --x- ---- ---- ---- ---- ---- ---- | Reads in Fatal Fury WA, if on then there isn't a 3d refresh (busy flag?). - * 0 | ---- ---x ---- ---- ---- ---- ---- ---- | set at POST/service modes, almost likely fb disable - * 0 | ???? ???? ???? ???? ccc? ???? ???? ???? | framebuffer color base, 0x311800 in Fatal Fury WA, 0x313800 in Buriki One - * 1 | | - * 2 | ???? ???? ???? ???? ???? ???? ???? ???? | camera / framebuffer global x/y? Actively used by Samurai Shodown 64 2 - * 3 | ---- --?x ---- ---- ---- ---- ---- ---- | unknown, unsetted by Buriki One and set by Fatal Fury WA, buffering mode? - * 4-11 | ---- ???? ---- ???? ---- ???? ---- ???? | Table filled with 0x0? data - * - */ + * | Bits | Use + * | | + * -------+ 7654-3210-+---------------- + * 0 | ---- --xy | x = Reads in Fatal Fury WA, if on then there isn't a 3d refresh (busy flag?). y = set at POST/service modes, almost likely fb disable + * 1 | ---- ---- | + * 2 | ccc- b--- | c = framebuffer color base, 0x311800 in Fatal Fury WA, 0x313800 in Buriki One (or not?) b = don't clear buffer + * 3 | ---- ---- | +*/ +READ8_MEMBER(hng64_state::hng64_fbcontrol_r) +{ + logerror("%s: hng64_fbcontrol_r (%03x)\n", machine().describe_context(), offset); + return m_fbcontrol[offset]; +} + +WRITE8_MEMBER(hng64_state::hng64_fbcontrol_w) +{ + + /* roadedge does the following to turn off the framebuffer clear (leave trails) and then turn it back on when selecting a car + ':maincpu' (8001EDE0): hng64_fbcontrol_w (002) 10 (disable frame buffer clear) + ':maincpu' (8001FE4C): hng64_fbcontrol_w (002) 38 (normal) + + during the Hyper Neogeo 64 logo it has a value of + ':maincpu' (8005AA44): hng64_fbcontrol_w (002) 18 + + sams64 does + ':maincpu' (800C13C4): hng64_fbcontrol_r (002) (ANDs with 0x07, ORs with 0x18) + ':maincpu' (800C13D0): hng64_fbcontrol_w (002) 18 + + other games use either mix of 0x18 and 0x38. bit 0x08 must prevent the framebuffer clear tho + according to above table bit 0x20 is color base, but implementation for it is a hack + + (3d car currently not visible on roadedge select screen due to priority issue, disable sprites to see it) + + */ + + logerror("%s: hng64_fbcontrol_w (%03x) %02x\n", machine().describe_context(), offset, data); + m_fbcontrol[offset] = data; +} + +WRITE16_MEMBER(hng64_state::hng64_fbunkpair_w) +{ + // set to fixed values? + + logerror("%s: hng64_fbunkpair_w (%03x) %04x\n", machine().describe_context(), offset, data); +} + +WRITE16_MEMBER(hng64_state::hng64_fbscroll_w) +{ + // this is used ingame on the samsho games, and on the car select screen in xrally (youtube video confirms position of car needs to change) + + logerror("%s: hng64_fbscroll_w (%03x) %04x\n", machine().describe_context(), offset, data); +} + +WRITE8_MEMBER(hng64_state::hng64_fbunkbyte_w) +{ + if (offset == 0) + { + // | ---- --?x | unknown, unsetted by Buriki One and set by Fatal Fury WA, buffering mode? + logerror("%s: hng64_unkbyte_w (%03x) %02x\n", machine().describe_context(), offset, data); + } + else + { + logerror("%s: hng64_unkbyte_w (%03x - unexpected) %02x \n", machine().describe_context(), offset, data); + } +} + +// this is a table filled with 0x0? data, seems to be 16-bit values +READ32_MEMBER(hng64_state::hng64_fbtable_r) +{ + logerror("%s: hng64_fbtable_r (%03x) (%08x)\n", machine().describe_context(), offset * 4, mem_mask); + return m_fbtable[offset]; +} + +WRITE32_MEMBER(hng64_state::hng64_fbtable_w) +{ + logerror("%s: hng64_fbtable_w (%03x) %08x (%08x)\n", machine().describe_context(), offset * 4, data, mem_mask); + COMBINE_DATA(&m_fbtable[offset]); +} ///////////////////// // 3D UTILITY CODE //