hng64 : misc progress (nw) (#3858)

* hng64 : misc progress (nw)

* note (nw)

* move some bits closer to relevant comments etc. (nw)

* refactor (nw)

* document fb registers more correctly (nw)

* some renaming (nw)
This commit is contained in:
David Haywood 2018-08-17 15:55:49 +01:00 committed by R. Belmont
parent 9f38859425
commit eff721ec4c
4 changed files with 285 additions and 202 deletions

View File

@ -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)
}
}
/*
<ElSemi> 0xE0000000 sound
<ElSemi> 0xD0100000 3D bank A
<ElSemi> 0xD0200000 3D bank B
<ElSemi> 0xC0000000-0xC000C000 Sprite
<ElSemi> 0xC0200000-0xC0204000 palette
<ElSemi> 0xC0100000-0xC0180000 Tilemap
<ElSemi> 0xBF808000-0xBF808800 Dualport ram
<ElSemi> 0xBF800000-0xBF808000 S-RAM
<ElSemi> 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 */

View File

@ -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<palette_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<mips3_device> m_maincpu;
required_device<v53a_device> m_audiocpu;
required_device<tmp87ph40an_device> m_iomcu;
@ -191,10 +205,10 @@ private:
required_shared_ptr<uint32_t> m_tcram;
std::unique_ptr<uint16_t[]> m_dl;
required_shared_ptr<uint32_t> m_3dregs;
required_shared_ptr<uint32_t> m_fbtable;
required_shared_ptr<uint32_t> m_comhack;
required_shared_ptr<uint32_t> m_3d_1;
required_shared_ptr<uint32_t> m_3d_2;
required_shared_ptr<uint32_t> m_fbram1;
required_shared_ptr<uint32_t> m_fbram2;
required_shared_ptr<uint32_t> m_idt7133_dpram;
//required_shared_ptr<uint8_t> 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<uint16_t[]> m_soundram;
std::unique_ptr<uint16_t[]> 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);

View File

@ -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)
{

View File

@ -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 //