mirror of
https://github.com/holub/mame
synced 2025-04-16 21:44:32 +03:00
gameboy: fix SGB VRAM transfers (#2504)
* gameboy.xml: remove misleading comment Sachen 4B-003 was recently added Signed-off-by: Tauwasser <tauwasser@tauwasser.eu> * gameboy: fix Super Game Boy VRAM transfer A basic implementation of VRAM transfer. It fixes a number of games and removes the SGB border hack. However, it's very likely that the bahvior is much more complex. The old implementation was good enough for the majority of games, so this should suffice until such time when SGB is implemented on top of SNES. The attribute data was resized to 4096 bytes, so a whole VRAM transfer can take place even though only 4050 bytes are used. The idea is that the whole 4096 bytes are _probably_ transferred to WRAM and a game might theoretically upload a small executable and use that data. However, running native SNES code is currently unsupported anyway. Signed-off-by: Tauwasser <tauwasser@tauwasser.eu> * gameboy: various code style/comment fixes - return GB_MBC_NONE instead of magic 0 value - add MLT_REQ case in sgb code and mention where it's actually handled - add PAL_PRI to list of known SGB commands (not implemented) - fix two comments Signed-off-by: Tauwasser <tauwasser@tauwasser.eu> * gameboy: coding style fixes for gb_lcd Signed-off-by: Tauwasser <tauwasser@tauwasser.eu>
This commit is contained in:
parent
42a9427f18
commit
c33f141c53
@ -24963,8 +24963,6 @@
|
||||
</part>
|
||||
</software>
|
||||
|
||||
<!-- 4in1_003 missing -->
|
||||
|
||||
<software name="4in1_004">
|
||||
<description>4 in 1 (Euro, 4B-004)</description>
|
||||
<year>19??</year>
|
||||
|
@ -141,7 +141,6 @@ gb_cart_slot_device_base::gb_cart_slot_device_base(const machine_config &mconfig
|
||||
device_t(mconfig, type, tag, owner, clock),
|
||||
device_image_interface(mconfig, *this),
|
||||
device_slot_interface(mconfig, *this),
|
||||
m_sgb_hack(0),
|
||||
m_type(GB_MBC_UNKNOWN),
|
||||
m_cart(nullptr)
|
||||
{
|
||||
@ -227,7 +226,7 @@ static int gb_get_pcb_id(const char *slot)
|
||||
return elem.pcb_id;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return GB_MBC_NONE;
|
||||
}
|
||||
|
||||
static const char *gb_get_slot(int type)
|
||||
@ -386,12 +385,6 @@ image_init_result gb_cart_slot_device_base::call_load()
|
||||
|
||||
internal_header_logging(ROM + offset, len);
|
||||
|
||||
// Hack to support Donkey Kong Land 2 + 3 in SGB
|
||||
// For some reason, these store the tile data differently. Hacks will go once it's been figured out
|
||||
if (strncmp((const char*)(ROM + 0x134), "DONKEYKONGLAND 2", 16) == 0 ||
|
||||
strncmp((const char*)(ROM + 0x134), "DONKEYKONGLAND 3", 16) == 0)
|
||||
m_sgb_hack = 1;
|
||||
|
||||
return image_init_result::PASS;
|
||||
}
|
||||
|
||||
|
@ -127,8 +127,6 @@ public:
|
||||
static int get_cart_type(const uint8_t *ROM, uint32_t len);
|
||||
static bool get_mmm01_candidate(const uint8_t *ROM, uint32_t len);
|
||||
static bool is_mbc1col_game(const uint8_t *ROM, uint32_t len);
|
||||
// remove me when SGB is properly emulated
|
||||
int get_sgb_hack() { return m_sgb_hack; }
|
||||
|
||||
void setup_ram(uint8_t banks);
|
||||
void internal_header_logging(uint8_t *ROM, uint32_t len);
|
||||
@ -156,9 +154,6 @@ public:
|
||||
protected:
|
||||
gb_cart_slot_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
// Donkey Kong Land 2 + 3 store SGB border tiles differently... this will be hopefully be removed when SGB is properly emulated!
|
||||
int m_sgb_hack;
|
||||
|
||||
int m_type;
|
||||
device_gb_cart_interface* m_cart;
|
||||
};
|
||||
|
@ -12,7 +12,7 @@
|
||||
Improvements to match real hardware Wilbert Pol 2006-2008
|
||||
|
||||
Timing is not accurate enough:
|
||||
- Mode 3 takes 172 cycles (measuered with logic analyzer by costis)
|
||||
- Mode 3 takes 172 cycles (measured with logic analyzer by costis)
|
||||
|
||||
The following timing of the first frame when the LCD is turned on, is with
|
||||
no sprites being displayed. If sprites are displayed then the timing of mode
|
||||
@ -322,7 +322,6 @@ dmg_ppu_device::dmg_ppu_device(const machine_config &mconfig, device_type type,
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
, device_video_interface(mconfig, *this)
|
||||
, m_lr35902(*this, finder_base::DUMMY_TAG)
|
||||
, m_sgb_border_hack(0)
|
||||
, m_enable_experimental_engine(false)
|
||||
, m_oam_size(0x100)
|
||||
, m_vram_size(vram_size)
|
||||
@ -1395,19 +1394,8 @@ void sgb_ppu_device::refresh_border()
|
||||
pal = 1;
|
||||
pal <<= 4;
|
||||
|
||||
if (m_sgb_border_hack)
|
||||
{ /* A few games do weird stuff */
|
||||
uint8_t tileno = map[xidx];
|
||||
if (tileno >= 128) tileno = ((64 + tileno) % 128) + 128;
|
||||
else tileno = (64 + tileno) % 128;
|
||||
data = tiles[tileno * 32] | (tiles[(tileno * 32) + 1] << 8);
|
||||
data2 = tiles2[tileno * 32] | (tiles2[(tileno * 32) + 1] << 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = tiles[map[xidx] * 32] | (tiles[(map[xidx] * 32) + 1] << 8);
|
||||
data2 = tiles2[map[xidx] * 32] | (tiles2[(map[xidx] * 32) + 1] << 8);
|
||||
}
|
||||
data = tiles[map[xidx] * 32] | (tiles[(map[xidx] * 32) + 1] << 8);
|
||||
data2 = tiles2[map[xidx] * 32] | (tiles2[(map[xidx] * 32) + 1] << 8);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
@ -3508,6 +3496,44 @@ WRITE8_MEMBER(cgb_ppu_device::video_w)
|
||||
|
||||
// Super Game Boy
|
||||
|
||||
/* Super Game Boys transfer VRAM data using the display signals.
|
||||
* That means not DMG VRAM is copied from 0x8800 to SNES VRAM
|
||||
* but displayed BG contents.
|
||||
* Things to consider: LCDC (0xFF40) and SCY/SCX (0xFF42/3)
|
||||
* - LCD must be on
|
||||
* - TODO: Window might or might not influence result
|
||||
* - CHR and BG likely influence result
|
||||
* - BG must be on
|
||||
* - BG should not be scrolled, but likely does influence transfer
|
||||
* - TODO: are BG attributes (hflip, vflip) ignored?
|
||||
*/
|
||||
/**
|
||||
* Copy DMG VRAM data to SGM VRAM
|
||||
* @param dst Destination Pointer
|
||||
* @param start Logical Start Tile index inside display area.
|
||||
* @param num_tiles Number of DMG tiles (0x10u bytes) to copy.
|
||||
*/
|
||||
void sgb_ppu_device::sgb_vram_memcpy(uint8_t *dst, uint8_t start, size_t num_tiles) {
|
||||
|
||||
uint16_t bg_ix = (start / 0x14u) * 0x20u + (start % 0x14u);
|
||||
const uint8_t* const map = m_layer[0].bg_map;
|
||||
const uint8_t* const tiles = m_layer[0].bg_tiles;
|
||||
const uint8_t mod = m_gb_tile_no_mod;
|
||||
|
||||
for (size_t i = 0x00u; i < num_tiles && i < 0x100u; ++i) {
|
||||
|
||||
const uint8_t tile_ix = map[bg_ix] ^ mod;
|
||||
memcpy(dst, &tiles[tile_ix << 4], 0x10u);
|
||||
dst += 0x10u;
|
||||
|
||||
++bg_ix;
|
||||
if ((bg_ix & 0x1Fu) == 0x14u) {
|
||||
bg_ix += 0x20u - 0x14u; /* advance to next start of line */
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void sgb_ppu_device::sgb_io_write_pal(int offs, uint8_t *data)
|
||||
{
|
||||
switch (offs)
|
||||
@ -3819,40 +3845,34 @@ void sgb_ppu_device::sgb_io_write_pal(int offs, uint8_t *data)
|
||||
case 0x10: /* DATA_TRN */
|
||||
/* Not Implemented */
|
||||
break;
|
||||
case 0x11: /* MLT_REQ */
|
||||
/* MLT_REQ currently handled inside gb.cpp logic */
|
||||
break;
|
||||
case 0x12: /* JUMP */
|
||||
/* Not Implemented */
|
||||
break;
|
||||
case 0x13: /* CHR_TRN */
|
||||
if (data[1] & 0x1)
|
||||
memcpy(m_sgb_tile_data.get() + 4096, m_vram.get() + 0x0800, 4096);
|
||||
if (data[1] & 0x01u)
|
||||
sgb_vram_memcpy(m_sgb_tile_data.get() + 0x1000u, 0x00u, 0x100u);
|
||||
else
|
||||
memcpy(m_sgb_tile_data.get(), m_vram.get() + 0x0800, 4096);
|
||||
sgb_vram_memcpy(m_sgb_tile_data.get(), 0x00u, 0x100u);
|
||||
break;
|
||||
case 0x14: /* PCT_TRN */
|
||||
{
|
||||
uint16_t col;
|
||||
if (m_sgb_border_hack)
|
||||
uint8_t sgb_pal[0x80u];
|
||||
|
||||
sgb_vram_memcpy(m_sgb_tile_map, 0x00u, 0x80u);
|
||||
sgb_vram_memcpy(sgb_pal, 0x80u, 0x08u);
|
||||
for (int i = 0; i < 4 * 16 /* 4 pals at 16 colors each */; i++)
|
||||
{
|
||||
memcpy(m_sgb_tile_map, m_vram.get() + 0x1000, 2048);
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
col = (m_vram[0x0800 + (i * 2) + 1 ] << 8) | m_vram[0x0800 + (i * 2)];
|
||||
m_sgb_pal[SGB_BORDER_PAL_OFFSET + i] = col;
|
||||
}
|
||||
}
|
||||
else /* Do things normally */
|
||||
{
|
||||
memcpy(m_sgb_tile_map, m_vram.get() + 0x0800, 2048);
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
col = (m_vram[0x1000 + (i * 2) + 1] << 8) | m_vram[0x1000 + (i * 2)];
|
||||
m_sgb_pal[SGB_BORDER_PAL_OFFSET + i] = col;
|
||||
}
|
||||
col = (sgb_pal[(i * 2) + 1] << 8) | sgb_pal[i * 2];
|
||||
m_sgb_pal[SGB_BORDER_PAL_OFFSET + i] = col;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x15: /* ATTR_TRN */
|
||||
memcpy(m_sgb_atf_data, m_vram.get() + 0x0800, 4050);
|
||||
sgb_vram_memcpy(m_sgb_atf_data, 0x00u, 0x100u);
|
||||
break;
|
||||
case 0x16: /* ATTR_SET */
|
||||
{
|
||||
@ -3876,11 +3896,10 @@ void sgb_ppu_device::sgb_io_write_pal(int offs, uint8_t *data)
|
||||
m_sgb_window_mask = data[1];
|
||||
break;
|
||||
case 0x18: /* OBJ_TRN */
|
||||
/* Not Implemnted */
|
||||
/* Not Implemented */
|
||||
break;
|
||||
case 0x19: /* ? */
|
||||
/* Called by: dkl,dkl2,dkl3,zeldadx
|
||||
But I don't know what it is for. */
|
||||
case 0x19: /* PAL_PRI */
|
||||
/* Called by: dkl,dkl2,dkl3,zeldadx */
|
||||
/* Not Implemented */
|
||||
break;
|
||||
case 0x1E: /* Used by bootrom to transfer the gb cart header */
|
||||
|
@ -32,9 +32,6 @@ public:
|
||||
virtual DECLARE_READ8_MEMBER(video_r);
|
||||
virtual DECLARE_WRITE8_MEMBER(video_w);
|
||||
|
||||
// FIXME: remove it when proper sgb support is added
|
||||
void set_sgb_hack(bool val) { m_sgb_border_hack = val ? 1 : 0; }
|
||||
|
||||
virtual void update_state();
|
||||
|
||||
protected:
|
||||
@ -90,7 +87,7 @@ protected:
|
||||
// state variables
|
||||
bitmap_ind16 m_bitmap;
|
||||
|
||||
uint8_t m_sgb_atf_data[4050]; /* (SGB) Attributes files */
|
||||
uint8_t m_sgb_atf_data[4096]; /* (SGB) Attributes files 4050 bytes, but it's in WRAM, because 4k is transferred */
|
||||
uint32_t m_sgb_atf;
|
||||
uint16_t m_sgb_pal_data[4096];
|
||||
uint8_t m_sgb_pal_map[20][18];
|
||||
@ -99,9 +96,6 @@ protected:
|
||||
uint8_t m_sgb_tile_map[2048];
|
||||
uint8_t m_sgb_window_mask;
|
||||
|
||||
// this is temporarily needed for a bunch of games which draw the border differently...
|
||||
int m_sgb_border_hack;
|
||||
|
||||
int m_window_lines_drawn;
|
||||
|
||||
static constexpr unsigned NR_GB_VID_REGS = 0x40;
|
||||
@ -262,6 +256,8 @@ protected:
|
||||
virtual void update_sprites() override;
|
||||
virtual void update_scanline(uint32_t cycles_to_go) override;
|
||||
void refresh_border();
|
||||
|
||||
void sgb_vram_memcpy(uint8_t *dst, uint8_t start, size_t num_tiles);
|
||||
};
|
||||
|
||||
|
||||
|
@ -190,10 +190,6 @@ MACHINE_START_MEMBER(gb_state,sgb)
|
||||
|
||||
save_gb_base();
|
||||
save_sgb_only();
|
||||
|
||||
if (m_cartslot && m_cartslot->get_sgb_hack()) {
|
||||
dynamic_cast<sgb_ppu_device*>(m_ppu.target())->set_sgb_hack(true);
|
||||
}
|
||||
}
|
||||
|
||||
void gb_state::machine_reset()
|
||||
@ -323,38 +319,38 @@ WRITE8_MEMBER(gb_state::gb_io2_w)
|
||||
#ifdef MAME_DEBUG
|
||||
static const char *const sgbcmds[32] =
|
||||
{
|
||||
"PAL01 ",
|
||||
"PAL23 ",
|
||||
"PAL03 ",
|
||||
"PAL12 ",
|
||||
"ATTR_BLK",
|
||||
"ATTR_LIN",
|
||||
"ATTR_DIV",
|
||||
"ATTR_CHR",
|
||||
"SOUND ",
|
||||
"SOU_TRN ",
|
||||
"PAL_SET ",
|
||||
"PAL_TRN ",
|
||||
"ATRC_EN ",
|
||||
"TEST_EN ",
|
||||
"ICON_EN ",
|
||||
"DATA_SND",
|
||||
"DATA_TRN",
|
||||
"MLT_REG ",
|
||||
"JUMP ",
|
||||
"CHR_TRN ",
|
||||
"PCT_TRN ",
|
||||
"ATTR_TRN",
|
||||
"ATTR_SET",
|
||||
"MASK_EN ",
|
||||
"OBJ_TRN ",
|
||||
"????????",
|
||||
"????????",
|
||||
"????????",
|
||||
"????????",
|
||||
"????????",
|
||||
"????????",
|
||||
"????????"
|
||||
/* 0x00 */ "PAL01 ",
|
||||
/* 0x01 */ "PAL23 ",
|
||||
/* 0x02 */ "PAL03 ",
|
||||
/* 0x03 */ "PAL12 ",
|
||||
/* 0x04 */ "ATTR_BLK",
|
||||
/* 0x05 */ "ATTR_LIN",
|
||||
/* 0x06 */ "ATTR_DIV",
|
||||
/* 0x07 */ "ATTR_CHR",
|
||||
/* 0x08 */ "SOUND ",
|
||||
/* 0x09 */ "SOU_TRN ",
|
||||
/* 0x0A */ "PAL_SET ",
|
||||
/* 0x0B */ "PAL_TRN ",
|
||||
/* 0x0C */ "ATRC_EN ",
|
||||
/* 0x0D */ "TEST_EN ",
|
||||
/* 0x0E */ "ICON_EN ",
|
||||
/* 0x0F */ "DATA_SND",
|
||||
/* 0x10 */ "DATA_TRN",
|
||||
/* 0x11 */ "MLT_REG ",
|
||||
/* 0x12 */ "JUMP ",
|
||||
/* 0x13 */ "CHR_TRN ",
|
||||
/* 0x14 */ "PCT_TRN ",
|
||||
/* 0x15 */ "ATTR_TRN",
|
||||
/* 0x16 */ "ATTR_SET",
|
||||
/* 0x17 */ "MASK_EN ",
|
||||
/* 0x18 */ "OBJ_TRN ",
|
||||
/* 0x19 */ "PAL_PRI ",
|
||||
/* 0x1A */ "????????",
|
||||
/* 0x1B */ "????????",
|
||||
/* 0x1C */ "????????",
|
||||
/* 0x1D */ "????????",
|
||||
/* 0x1E */ "????????",
|
||||
/* 0x1F */ "????????"
|
||||
};
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user