mirror of
https://github.com/holub/mame
synced 2025-04-24 17:30:55 +03:00
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:
parent
9f38859425
commit
eff721ec4c
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 //
|
||||
|
Loading…
Reference in New Issue
Block a user