Merge pull request #5025 from cam900/namcona1_args

namcona1.cpp : Updates
This commit is contained in:
R. Belmont 2019-05-10 11:36:00 -04:00 committed by GitHub
commit 0694e91fa2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 812 additions and 813 deletions

File diff suppressed because it is too large Load Diff

View File

@ -60,32 +60,34 @@ public:
void namcona1_mcu_map(address_map &map); void namcona1_mcu_map(address_map &map);
protected: protected:
DECLARE_READ16_MEMBER(custom_key_r); u16 custom_key_r(offs_t offset);
DECLARE_WRITE16_MEMBER(custom_key_w); void custom_key_w(u16 data);
DECLARE_WRITE16_MEMBER(vreg_w); void vreg_w(offs_t offset, u16 data, u16 mem_mask = ~0);
DECLARE_READ16_MEMBER(mcu_mailbox_r); u16 mcu_mailbox_r(offs_t offset);
DECLARE_WRITE16_MEMBER(mcu_mailbox_w_68k); void mcu_mailbox_w_68k(offs_t offset, u16 data, u16 mem_mask = ~0);
DECLARE_WRITE16_MEMBER(mcu_mailbox_w_mcu); void mcu_mailbox_w_mcu(offs_t offset, u16 data, u16 mem_mask = ~0);
DECLARE_READ16_MEMBER(na1mcu_shared_r); u16 na1mcu_shared_r(offs_t offset);
DECLARE_WRITE16_MEMBER(na1mcu_shared_w); void na1mcu_shared_w(offs_t offset, u16 data, u16 mem_mask = ~0);
DECLARE_READ8_MEMBER(port4_r); u8 port4_r();
DECLARE_WRITE8_MEMBER(port4_w); void port4_w(u8 data);
DECLARE_READ8_MEMBER(port5_r); u8 port5_r();
DECLARE_WRITE8_MEMBER(port5_w); void port5_w(u8 data);
DECLARE_READ8_MEMBER(port6_r); u8 port6_r();
DECLARE_WRITE8_MEMBER(port6_w); void port6_w(u8 data);
DECLARE_READ8_MEMBER(port7_r); u8 port7_r();
DECLARE_WRITE8_MEMBER(port7_w); void port7_w(u8 data);
DECLARE_READ8_MEMBER(port8_r); u8 port8_r();
DECLARE_WRITE8_MEMBER(port8_w); void port8_w(u8 data);
template <int Bit> uint16_t portana_r(); template <int Bit> u16 portana_r();
DECLARE_WRITE16_MEMBER(videoram_w); void videoram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
DECLARE_WRITE16_MEMBER(paletteram_w); void paletteram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
DECLARE_READ16_MEMBER(gfxram_r); u16 gfxram_r(offs_t offset);
DECLARE_WRITE16_MEMBER(gfxram_w); void gfxram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); virtual void device_post_load() override;
u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void scanline_interrupt(int scanline); void scanline_interrupt(int scanline);
@ -129,53 +131,51 @@ protected:
required_ioport_array<4> m_muxed_inputs; required_ioport_array<4> m_muxed_inputs;
required_ioport m_io_p3; required_ioport m_io_p3;
required_shared_ptr<uint16_t> m_workram; required_shared_ptr<u16> m_workram;
required_shared_ptr<uint16_t> m_vreg; required_shared_ptr<u16> m_vreg;
required_shared_ptr<uint16_t> m_paletteram; required_shared_ptr<u16> m_paletteram;
required_shared_ptr<uint16_t> m_cgram; required_shared_ptr<u16> m_cgram;
required_shared_ptr<uint16_t> m_videoram; required_shared_ptr<u16> m_videoram;
required_shared_ptr<uint16_t> m_scroll; required_shared_ptr<u16> m_scroll;
required_shared_ptr<uint16_t> m_spriteram; required_shared_ptr<u16> m_spriteram;
required_region_ptr<uint16_t> m_prgrom; required_region_ptr<u16> m_prgrom;
required_region_ptr<uint16_t> m_maskrom; required_region_ptr<u16> m_maskrom;
emu_timer * m_scan_timer; emu_timer * m_scan_timer;
// this has to be uint8_t to be in the right byte order for the tilemap system // this has to be u8 to be in the right byte order for the tilemap system
std::vector<uint8_t> m_shaperam; std::vector<u8> m_shaperam;
int m_mEnableInterrupts; int m_mEnableInterrupts;
uint16_t m_count; u16 m_count;
uint32_t m_keyval; u32 m_keyval;
uint16_t m_mcu_mailbox[8]; u16 m_mcu_mailbox[8];
uint8_t m_mcu_port4; u8 m_mcu_port4;
uint8_t m_mcu_port5; u8 m_mcu_port5;
uint8_t m_mcu_port6; u8 m_mcu_port6;
uint8_t m_mcu_port8; u8 m_mcu_port8;
tilemap_t *m_bg_tilemap[4+1]; tilemap_t *m_bg_tilemap[4+1];
int m_palette_is_dirty; int m_palette_is_dirty;
void simulate_mcu(); void simulate_mcu();
void write_version_info(); void write_version_info();
int transfer_dword(uint32_t dest, uint32_t source); int transfer_dword(u32 dest, u32 source);
void blit(); void blit();
void UpdatePalette(int offset); void UpdatePalette(int offset);
void pdraw_tile( screen_device &screen, bitmap_ind16 &dest_bmp, const rectangle &clip, uint32_t code, int color, void pdraw_tile(screen_device &screen, bitmap_ind16 &dest_bmp, const rectangle &clip, u32 code, u32 color,
int sx, int sy, int flipx, int flipy, int priority, int bShadow, int bOpaque, int gfx_region ); int sx, int sy, bool flipx, bool flipy, u8 priority, bool bShadow, bool bOpaque, u8 gfx_region);
void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void draw_background(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int which, int primask ); void draw_background(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int which, int primask);
void tilemap_get_info(tile_data &tileinfo, int tile_index, const uint16_t *tilemap_videoram, bool use_4bpp_gfx); void tilemap_get_info(tile_data &tileinfo, int tile_index, const u16 *tilemap_videoram, bool use_4bpp_gfx);
void blit_setup( int format, int *bytes_per_row, int *pitch, int mode ); void blit_setup(int format, int *bytes_per_row, int *pitch, int mode);
void draw_pixel_line( const rectangle &cliprect, uint16_t *pDest, uint8_t *pPri, uint16_t *pSource, const pen_t *paldata ); void draw_pixel_line(const rectangle &cliprect, u16 *pDest, u8 *pPri, u16 *pSource, const pen_t *paldata);
bool screen_enabled( const rectangle &cliprect); bool screen_enabled(const rectangle &cliprect);
TILE_GET_INFO_MEMBER(tilemap_get_info0); TILE_GET_INFO_MEMBER(tilemap_get_info0);
TILE_GET_INFO_MEMBER(tilemap_get_info1); TILE_GET_INFO_MEMBER(tilemap_get_info1);
TILE_GET_INFO_MEMBER(tilemap_get_info2); TILE_GET_INFO_MEMBER(tilemap_get_info2);
TILE_GET_INFO_MEMBER(tilemap_get_info3); TILE_GET_INFO_MEMBER(tilemap_get_info3);
TILE_GET_INFO_MEMBER(roz_get_info); TILE_GET_INFO_MEMBER(roz_get_info);
void postload();
}; };
class namcona2_state : public namcona1_state class namcona2_state : public namcona1_state
@ -211,8 +211,8 @@ public:
private: private:
required_device <msm6242_device> m_rtc; required_device <msm6242_device> m_rtc;
DECLARE_READ8_MEMBER(printer_r); u8 printer_r();
DECLARE_WRITE8_MEMBER(printer_w); void printer_w(u8 data);
void xday2_main_map(address_map &map); void xday2_main_map(address_map &map);
}; };

View File

@ -1,6 +1,6 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Phil Stroffolino // copyright-holders:Phil Stroffolino
/* Namco System NA1/2 Video Hardware */ /* Namco System NA1 / 2 Video Hardware */
/* /*
Notes: Notes:
@ -24,107 +24,116 @@ TODO:
void namcona1_state::tilemap_get_info( void namcona1_state::tilemap_get_info(
tile_data &tileinfo, tile_data &tileinfo,
int tile_index, int tile_index,
const uint16_t *tilemap_videoram, const u16 *tilemap_videoram,
bool use_4bpp_gfx ) bool use_4bpp_gfx)
{ {
int data = tilemap_videoram[tile_index]; const u16 data = tilemap_videoram[tile_index];
int tile = data&0xfff; const u32 tile = data & 0xfff;
int gfx = use_4bpp_gfx ? 1 : 0; const u8 gfx = use_4bpp_gfx ? 1 : 0;
int color = use_4bpp_gfx ? (data & 0x7000)>>12 : 0; const u32 color = use_4bpp_gfx ? (data & 0x7000) >> 12 : 0;
if( data & 0x8000 ) if (data & 0x8000)
{ {
SET_TILE_INFO_MEMBER(gfx,tile,color,TILE_FORCE_LAYER0 ); SET_TILE_INFO_MEMBER(gfx, tile, color, TILE_FORCE_LAYER0);
} }
else else
{ {
SET_TILE_INFO_MEMBER(gfx,tile,color,0 ); SET_TILE_INFO_MEMBER(gfx, tile, color, 0);
tileinfo.mask_data = &m_shaperam[tile*8]; tileinfo.mask_data = &m_shaperam[tile << 3];
} }
} /* tilemap_get_info */ } /* tilemap_get_info */
TILE_GET_INFO_MEMBER(namcona1_state::tilemap_get_info0) TILE_GET_INFO_MEMBER(namcona1_state::tilemap_get_info0)
{ {
tilemap_get_info(tileinfo,tile_index,0*0x1000+m_videoram,m_vreg[0xbc/2]&1); tilemap_get_info(tileinfo, tile_index, 0 * 0x1000 + m_videoram, m_vreg[0xbc / 2] & 0x1);
} }
TILE_GET_INFO_MEMBER(namcona1_state::tilemap_get_info1) TILE_GET_INFO_MEMBER(namcona1_state::tilemap_get_info1)
{ {
tilemap_get_info(tileinfo,tile_index,1*0x1000+m_videoram,m_vreg[0xbc/2]&2); tilemap_get_info(tileinfo, tile_index, 1 * 0x1000 + m_videoram, m_vreg[0xbc / 2] & 0x2);
} }
TILE_GET_INFO_MEMBER(namcona1_state::tilemap_get_info2) TILE_GET_INFO_MEMBER(namcona1_state::tilemap_get_info2)
{ {
tilemap_get_info(tileinfo,tile_index,2*0x1000+m_videoram,m_vreg[0xbc/2]&4); tilemap_get_info(tileinfo, tile_index, 2 * 0x1000 + m_videoram, m_vreg[0xbc / 2] & 0x4);
} }
TILE_GET_INFO_MEMBER(namcona1_state::tilemap_get_info3) TILE_GET_INFO_MEMBER(namcona1_state::tilemap_get_info3)
{ {
tilemap_get_info(tileinfo,tile_index,3*0x1000+m_videoram,m_vreg[0xbc/2]&8); tilemap_get_info(tileinfo, tile_index, 3 * 0x1000 + m_videoram, m_vreg[0xbc / 2] & 0x8);
} }
TILE_GET_INFO_MEMBER(namcona1_state::roz_get_info) TILE_GET_INFO_MEMBER(namcona1_state::roz_get_info)
{ {
/* each logical tile is constructed from 4*4 normal tiles */ /* each logical tile is constructed from 4*4 normal tiles */
int use_4bpp_gfx = m_vreg[0xbc/2]&16; /* ? */ const bool use_4bpp_gfx = m_vreg[0xbc / 2] & 0x10; /* ? */
int c = tile_index%0x40; const u16 c = tile_index & 0x3f;
int r = tile_index/0x40; const u16 r = tile_index >> 6;
int data = m_videoram[0x8000/2+(r/4)*0x40+c/4]&0xfbf; /* mask out bit 0x40 - patch for Emeraldia Japan */ const u16 data = m_videoram[0x8000 / 2 + ((r >> 2) << 6) + (c >> 2)];
int tile = (data+(c%4)+(r%4)*0x40)&0xfff; const u32 tile = ((data & 0xfbf) + (c & 3) + ((r & 3) << 6)) & 0xfff; /* mask out bit 0x40 - patch for Emeraldia Japan */
int gfx = use_4bpp_gfx ? 1 : 0; const u8 gfx = use_4bpp_gfx ? 1 : 0;
int color = use_4bpp_gfx ? (data & 0x7000)>>12 : 0; const u32 color = use_4bpp_gfx ? (data & 0x7000) >> 12 : 0;
if( data & 0x8000 ) if (data & 0x8000)
{ {
SET_TILE_INFO_MEMBER(gfx,tile,color,TILE_FORCE_LAYER0 ); SET_TILE_INFO_MEMBER(gfx, tile, color, TILE_FORCE_LAYER0);
} }
else else
{ {
SET_TILE_INFO_MEMBER(gfx,tile,color,0 ); SET_TILE_INFO_MEMBER(gfx, tile, color, 0);
tileinfo.mask_data = &m_shaperam[tile*8]; tileinfo.mask_data = &m_shaperam[tile << 3];
} }
} /* roz_get_info */ } /* roz_get_info */
/*************************************************************************/ /*************************************************************************/
WRITE16_MEMBER(namcona1_state::videoram_w) void namcona1_state::videoram_w(offs_t offset, u16 data, u16 mem_mask)
{ {
COMBINE_DATA( &m_videoram[offset] ); COMBINE_DATA(&m_videoram[offset]);
if( offset<0x8000/2 ) if (offset < 0x8000 / 2)
{ {
m_bg_tilemap[offset/0x1000]->mark_tile_dirty(offset&0xfff); m_bg_tilemap[offset >> 12]->mark_tile_dirty(offset & 0xfff);
} }
else if( offset<0xa000/2 ) else if (offset < 0x8800 / 2)
{ {
m_bg_tilemap[4]->mark_all_dirty(); if (offset & ~0x30)
{
for (int i = 0; i < 4; i++)
{
m_bg_tilemap[4]->mark_tile_dirty(((offset & 0x3cf) << 2) + i);
m_bg_tilemap[4]->mark_tile_dirty(((offset & 0x3cf) << 2) + 0x40 + i);
m_bg_tilemap[4]->mark_tile_dirty(((offset & 0x3cf) << 2) + 0x80 + i);
m_bg_tilemap[4]->mark_tile_dirty(((offset & 0x3cf) << 2) + 0xc0 + i);
}
}
} }
} /* videoram_w */ } /* videoram_w */
/*************************************************************************/ /*************************************************************************/
void namcona1_state::UpdatePalette( int offset ) void namcona1_state::UpdatePalette(int offset)
{ {
uint16_t data = m_paletteram[offset]; /* -RRRRRGG GGGBBBBB */ const u16 data = m_paletteram[offset]; /* -RRRRRGG GGGBBBBB */
/** /**
* sprites can be configured to use an alternate interpretation of palette ram * sprites can be configured to use an alternate interpretation of palette ram
* (used in-game in Emeraldia) * (used in-game in Emeraldia)
* *
* RRRGGGBB RRRGGGBB * RRRGGGBB RRRGGGBB
*/ */
int r = (((data&0x00e0)>>5)+((data&0xe000)>>13)*2)*0xff/(0x7*3); int r = (((data & 0x00e0) >> 5) + ((data & 0xe000) >> 13) * 2) * 0xff / (0x7 * 3);
int g = (((data&0x001c)>>2)+((data&0x1c00)>>10)*2)*0xff/(0x7*3); int g = (((data & 0x001c) >> 2) + ((data & 0x1c00) >> 10) * 2) * 0xff / (0x7 * 3);
int b = (((data&0x0003)>>0)+((data&0x0300)>>8)*2)*0xff/(0x3*3); int b = (((data & 0x0003) >> 0) + ((data & 0x0300) >> 8) * 2) * 0xff / (0x3 * 3);
m_palette->set_pen_color(offset+0x1000, r, g, b); m_palette->set_pen_color(offset + 0x1000, r, g, b);
m_palette->set_pen_color(offset, pal5bit(data >> 10), pal5bit(data >> 5), pal5bit(data >> 0)); m_palette->set_pen_color(offset, pal5bit(data >> 10), pal5bit(data >> 5), pal5bit(data >> 0));
} }
WRITE16_MEMBER(namcona1_state::paletteram_w) void namcona1_state::paletteram_w(offs_t offset, u16 data, u16 mem_mask)
{ {
COMBINE_DATA( &m_paletteram[offset] ); COMBINE_DATA(&m_paletteram[offset]);
if( m_vreg[0x8e/2] ) if (m_vreg[0x8e / 2])
{ /* graphics enabled; update palette immediately */ { /* graphics enabled; update palette immediately */
UpdatePalette( offset ); UpdatePalette(offset);
} }
else else
{ {
@ -133,49 +142,48 @@ WRITE16_MEMBER(namcona1_state::paletteram_w)
} }
READ16_MEMBER(namcona1_state::gfxram_r) u16 namcona1_state::gfxram_r(offs_t offset)
{ {
uint16_t type = m_vreg[0x0c/2]; const u16 type = m_vreg[0x0c / 2];
if( type == 0x03 ) if (type == 0x03)
{ {
if( offset<0x4000 ) if (offset < 0x4000)
{ {
offset *= 2; offset *= 2;
return (m_shaperam[offset] << 8) | m_shaperam[offset+1]; return (m_shaperam[offset] << 8) | m_shaperam[offset+1];
} }
} }
else if( type == 0x02 ) else if (type == 0x02)
{ {
return m_cgram[offset]; return m_cgram[offset];
} }
return 0x0000; return 0x0000;
} /* gfxram_r */ } /* gfxram_r */
WRITE16_MEMBER(namcona1_state::gfxram_w) void namcona1_state::gfxram_w(offs_t offset, u16 data, u16 mem_mask)
{ {
uint16_t type = m_vreg[0x0c/2]; const u16 type = m_vreg[0x0c / 2];
uint16_t old_word;
if( type == 0x03 ) if (type == 0x03)
{ {
if( offset<0x4000 ) if (offset < 0x4000)
{ {
offset *= 2; offset *= 2;
if (ACCESSING_BITS_8_15) if (ACCESSING_BITS_8_15)
m_shaperam[offset] = data >> 8; m_shaperam[offset] = data >> 8;
if (ACCESSING_BITS_0_7) if (ACCESSING_BITS_0_7)
m_shaperam[offset+1] = data; m_shaperam[offset + 1] = data;
m_gfxdecode->gfx(2)->mark_dirty(offset/8); m_gfxdecode->gfx(2)->mark_dirty(offset >> 3);
} }
} }
else if( type == 0x02 ) else if (type == 0x02)
{ {
old_word = m_cgram[offset]; const u16 old_word = m_cgram[offset];
COMBINE_DATA( &m_cgram[offset] ); COMBINE_DATA(&m_cgram[offset]);
if( m_cgram[offset]!=old_word ) if (m_cgram[offset] != old_word)
{ {
m_gfxdecode->gfx(0)->mark_dirty(offset/0x20); m_gfxdecode->gfx(0)->mark_dirty(offset >> 5);
m_gfxdecode->gfx(1)->mark_dirty(offset/0x20); m_gfxdecode->gfx(1)->mark_dirty(offset >> 5);
} }
} }
} /* gfxram_w */ } /* gfxram_w */
@ -183,13 +191,13 @@ WRITE16_MEMBER(namcona1_state::gfxram_w)
void namcona1_state::video_start() void namcona1_state::video_start()
{ {
// normal tilemaps // normal tilemaps
m_bg_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(namcona1_state::tilemap_get_info0),this), TILEMAP_SCAN_ROWS, 8,8,64,64 ); m_bg_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(namcona1_state::tilemap_get_info0),this), TILEMAP_SCAN_ROWS, 8,8,64,64);
m_bg_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(namcona1_state::tilemap_get_info1),this), TILEMAP_SCAN_ROWS, 8,8,64,64 ); m_bg_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(namcona1_state::tilemap_get_info1),this), TILEMAP_SCAN_ROWS, 8,8,64,64);
m_bg_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(namcona1_state::tilemap_get_info2),this), TILEMAP_SCAN_ROWS, 8,8,64,64 ); m_bg_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(namcona1_state::tilemap_get_info2),this), TILEMAP_SCAN_ROWS, 8,8,64,64);
m_bg_tilemap[3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(namcona1_state::tilemap_get_info3),this), TILEMAP_SCAN_ROWS, 8,8,64,64 ); m_bg_tilemap[3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(namcona1_state::tilemap_get_info3),this), TILEMAP_SCAN_ROWS, 8,8,64,64);
// roz tilemap // roz tilemap
m_bg_tilemap[4] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(namcona1_state::roz_get_info),this), TILEMAP_SCAN_ROWS, 8,8,64,64 ); m_bg_tilemap[4] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(namcona1_state::roz_get_info),this), TILEMAP_SCAN_ROWS, 8,8,64,64);
m_shaperam.resize(0x8000); m_shaperam.resize(0x8000);
@ -197,11 +205,9 @@ void namcona1_state::video_start()
save_item(NAME(m_shaperam)); save_item(NAME(m_shaperam));
save_item(NAME(m_palette_is_dirty)); save_item(NAME(m_palette_is_dirty));
machine().save().register_postload(save_prepost_delegate(FUNC(namcona1_state::postload), this));
} /* video_start */ } /* video_start */
void namcona1_state::postload() void namcona1_state::device_post_load()
{ {
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
m_gfxdecode->gfx(i)->mark_all_dirty(); m_gfxdecode->gfx(i)->mark_all_dirty();
@ -214,222 +220,204 @@ void namcona1_state::pdraw_tile(
screen_device &screen, screen_device &screen,
bitmap_ind16 &dest_bmp, bitmap_ind16 &dest_bmp,
const rectangle &clip, const rectangle &clip,
uint32_t code, u32 code,
int color, u32 color,
int sx, int sy, int sx, int sy,
int flipx, int flipy, bool flipx, bool flipy,
int priority, u8 priority,
int bShadow, bool bShadow,
int bOpaque, bool bOpaque,
int gfx_region ) u8 gfx_region)
{ {
gfx_element *gfx = m_gfxdecode->gfx(gfx_region); gfx_element *gfx = m_gfxdecode->gfx(gfx_region);
gfx_element *mask = m_gfxdecode->gfx(2); gfx_element *mask = m_gfxdecode->gfx(2);
int pal_base = gfx->colorbase() + gfx->granularity() * (color % gfx->colors()); const u16 pal_base = gfx->colorbase() + gfx->granularity() * (color % gfx->colors());
const uint8_t *source_base = gfx->get_data((code % gfx->elements())); const u8 *source_base = gfx->get_data((code % gfx->elements()));
const uint8_t *mask_base = mask->get_data((code % mask->elements())); const u8 *mask_base = mask->get_data((code % mask->elements()));
int sprite_screen_height = ((1<<16)*gfx->height()+0x8000)>>16; /* compute sprite increment per screen pixel */
int sprite_screen_width = ((1<<16)*gfx->width()+0x8000)>>16; int dx, dy;
if (sprite_screen_width && sprite_screen_height) int ex = sx + gfx->width();
int ey = sy + gfx->height();
int x_index_base;
int y_index;
if (flipx)
{ {
/* compute sprite increment per screen pixel */ x_index_base = gfx->width() - 1;
int dx = (gfx->width()<<16)/sprite_screen_width; dx = -1;
int dy = (gfx->height()<<16)/sprite_screen_height; }
else
{
x_index_base = 0;
dx = 1;
}
int ex = sx+sprite_screen_width; if (flipy)
int ey = sy+sprite_screen_height; {
y_index = gfx->height() - 1;
dy = -1;
}
else
{
y_index = 0;
dy = 1;
}
int x_index_base; if (sx < clip.min_x)
int y_index; { /* clip left */
int pixels = clip.min_x - sx;
sx += pixels;
x_index_base += pixels * dx;
}
if (sy < clip.min_y)
{ /* clip top */
int pixels = clip.min_y - sy;
sy += pixels;
y_index += pixels * dy;
}
/* NS 980211 - fixed incorrect clipping */
if (ex > clip.max_x + 1)
{ /* clip right */
int pixels = ex - clip.max_x - 1;
ex -= pixels;
}
if (ey > clip.max_y + 1)
{ /* clip bottom */
int pixels = ey - clip.max_y - 1;
ey -= pixels;
}
if( flipx ) if (ex > sx)
{ /* skip if inner loop doesn't draw anything */
for (int y = sy; y < ey; y++)
{ {
x_index_base = (sprite_screen_width-1)*dx; const u8 *source = source_base + y_index * gfx->rowbytes();
dx = -dx; const u8 *mask_addr = mask_base + y_index * mask->rowbytes();
} u16 *dest = &dest_bmp.pix16(y);
else u8 *pri = &screen.priority().pix8(y);
{
x_index_base = 0;
}
if( flipy ) int x_index = x_index_base;
{ for (int x = sx; x < ex; x++)
y_index = (sprite_screen_height-1)*dy;
dy = -dy;
}
else
{
y_index = 0;
}
if( sx < clip.min_x)
{ /* clip left */
int pixels = clip.min_x-sx;
sx += pixels;
x_index_base += pixels*dx;
}
if( sy < clip.min_y )
{ /* clip top */
int pixels = clip.min_y-sy;
sy += pixels;
y_index += pixels*dy;
}
/* NS 980211 - fixed incorrect clipping */
if( ex > clip.max_x+1 )
{ /* clip right */
int pixels = ex-clip.max_x-1;
ex -= pixels;
}
if( ey > clip.max_y+1 )
{ /* clip bottom */
int pixels = ey-clip.max_y-1;
ey -= pixels;
}
if( ex>sx )
{ /* skip if inner loop doesn't draw anything */
int y;
for( y=sy; y<ey; y++ )
{ {
const uint8_t *source = source_base + (y_index>>16) * gfx->rowbytes(); if (bOpaque)
const uint8_t *mask_addr = mask_base + (y_index>>16) * mask->rowbytes();
uint16_t *dest = &dest_bmp.pix16(y);
uint8_t *pri = &screen.priority().pix8(y);
int x, x_index = x_index_base;
for( x=sx; x<ex; x++ )
{ {
if( bOpaque ) if (pri[x] <= priority)
{
const u8 c = source[x_index];
dest[x] = pal_base + c;
}
pri[x] = 0xff;
}
else
{
/* sprite pixel is opaque */
if (mask_addr[x_index] != 0)
{ {
if (pri[x] <= priority) if (pri[x] <= priority)
{ {
int c = source[x_index>>16]; const u8 c = source[x_index];
dest[x] = pal_base + c;
}
pri[x] = 0xff; /* render a shadow only if the sprites color is $F (8bpp) or $FF (4bpp) */
} if (bShadow)
else
{
/* sprite pixel is opaque */
if( mask_addr[x_index>>16] != 0 )
{
if (pri[x] <= priority)
{ {
int c = source[x_index>>16]; if ((gfx_region == 0 && color == 0x0f) ||
(gfx_region == 1 && color == 0xff))
/* render a shadow only if the sprites color is $F (8bpp) or $FF (4bpp) */
if( bShadow )
{ {
if( (gfx_region == 0 && color == 0x0f) || pen_t *palette_shadow_table = m_palette->shadow_table();
(gfx_region == 1 && color == 0xff) ) dest[x] = palette_shadow_table[dest[x]];
{
pen_t *palette_shadow_table = m_palette->shadow_table();
dest[x] = palette_shadow_table[dest[x]];
}
else
{
dest[x] = pal_base + c + 0x1000;
}
} }
else else
{ {
dest[x] = pal_base + c; dest[x] = pal_base + c + 0x1000;
} }
} }
pri[x] = 0xff; else
{
dest[x] = pal_base + c;
}
} }
pri[x] = 0xff;
} }
x_index += dx;
} }
x_index += dx;
y_index += dy;
} }
y_index += dy;
} }
} }
} /* pdraw_tile */ } /* pdraw_tile */
void namcona1_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) void namcona1_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{ {
int which; const u16 *source = m_spriteram;
const uint16_t *source = m_spriteram;
uint16_t sprite_control;
uint16_t ypos,tile,color,xpos;
int priority;
int width,height;
int flipy,flipx;
int row,col;
int sx,sy;
sprite_control = m_vreg[0x22/2]; const u16 sprite_control = m_vreg[0x22 / 2];
if( sprite_control&1 ) source += 0x400; /* alternate spriteram bank */ if (sprite_control & 1) source += 0x400; /* alternate spriteram bank */
for( which=0; which<0x100; which++ ) for (int which = 0; which < 0x100; which++)
{ /* max 256 sprites */ { /* max 256 sprites */
int bpp4,palbase; int bpp4,palbase;
ypos = source[0]; /* FHHH---Y YYYYYYYY flipy, height, ypos */ const u16 ypos = source[0]; /* FHHH---Y YYYYYYYY flipy, height, ypos */
tile = source[1]; /* O???TTTT TTTTTTTT opaque tile */ const u16 tile = source[1]; /* O???TTTT TTTTTTTT opaque tile */
color = source[2]; /* FSWWOOOO CCCCBPPP flipx, shadow, width, color offset for 4bpp, color, 4bbp - 8bpp mode, pri*/ const u16 color = source[2]; /* FSWWOOOO CCCCBPPP flipx, shadow, width, color offset for 4bpp, color, 4bbp - 8bpp mode, pri*/
xpos = source[3]; /* -------X XXXXXXXX xpos */ const u16 xpos = source[3]; /* -------X XXXXXXXX xpos */
priority = color&0x7; const u8 priority = color & 0x7;
width = ((color>>12)&0x3)+1; const u16 width = ((color >> 12) & 0x3) + 1;
height = ((ypos>>12)&0x7)+1; const u16 height = ((ypos >> 12) & 0x7) + 1;
flipy = ypos&0x8000; bool flipy = ypos & 0x8000;
flipx = color&0x8000; bool flipx = color & 0x8000;
if( color&8 ) if (color & 8)
{ {
palbase = (color&0xf0) | ((color & 0xf00) >> 8); palbase = (color & 0xf0) | ((color & 0xf00) >> 8);
bpp4 = 1; bpp4 = 1;
} }
else else
{ {
palbase = (color&0xf0)>>4; palbase = (color & 0xf0) >> 4;
bpp4 = 0; bpp4 = 0;
} }
for( row=0; row<height; row++ ) for (int row = 0; row < height; row++)
{ {
sy = (ypos&0x1ff)-30+32; int sy = (ypos & 0x1ff) - 30 + 32;
if( flipy ) if (flipy)
{ {
sy += (height-1-row)*8; sy += (height - 1 - row) << 3;
} }
else else
{ {
sy += row*8; sy += row << 3;
} }
sy = ((sy+8)&0x1ff)-8; sy = ((sy + 8) & 0x1ff) - 8;
for( col=0; col<width; col++ ) for (int col = 0; col < width; col++)
{ {
sx = (xpos&0x1ff)-10; int sx = (xpos & 0x1ff) - 10;
if( flipx ) if (flipx)
{ {
sx += (width-1-col)*8; sx += (width - 1 - col) << 3;
} }
else else
{ {
sx+=col*8; sx += col << 3;
} }
sx = ((sx+16)&0x1ff)-8; sx = ((sx + 16) & 0x1ff) - 8;
pdraw_tile(screen, pdraw_tile(screen,
bitmap, bitmap,
cliprect, cliprect,
(tile & 0xfff) + row*64+col, (tile & 0xfff) + (row << 6) + col,
palbase, palbase,
sx,sy,flipx,flipy, sx,sy,flipx,flipy,
priority, priority,
color & 0x4000, /* shadow */ color & 0x4000, /* shadow */
tile & 0x8000, /* opaque */ tile & 0x8000, /* opaque */
bpp4 ); bpp4);
} /* next col */ } /* next col */
} /* next row */ } /* next row */
@ -437,36 +425,35 @@ void namcona1_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, c
} }
} /* draw_sprites */ } /* draw_sprites */
void namcona1_state::draw_pixel_line( const rectangle &cliprect, uint16_t *pDest, uint8_t *pPri, uint16_t *pSource, const pen_t *paldata ) void namcona1_state::draw_pixel_line(const rectangle &cliprect, u16 *pDest, u8 *pPri, u16 *pSource, const pen_t *paldata)
{ {
int x; for (int x = 0; x < 38 << 3; x += 2)
for( x=0; x<38*8; x+=2 )
{ {
uint16_t data = *pSource++; u16 data = *pSource++;
pPri[x+0] = 0xff; pPri[x + 0] = 0xff;
pPri[x+1] = 0xff; pPri[x + 1] = 0xff;
if(x >= cliprect.min_x && x <= cliprect.max_x) if (x >= cliprect.min_x && x <= cliprect.max_x)
pDest[x+0] = paldata[data>>8]; pDest[x+0] = paldata[data>>8];
if(x+1 >= cliprect.min_x && x+1 <= cliprect.max_x) if (x+1 >= cliprect.min_x && x+1 <= cliprect.max_x)
pDest[x+1] = paldata[data&0xff]; pDest[x+1] = paldata[data&0xff];
} /* next x */ } /* next x */
} /* draw_pixel_line */ } /* draw_pixel_line */
void namcona1_state::draw_background(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int which, int primask ) void namcona1_state::draw_background(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int which, int primask)
{ {
if(which == 4) if (which == 4)
{ {
/* draw the roz tilemap all at once */ /* draw the roz tilemap all at once */
int incxx = ((int16_t)m_vreg[0xc0/2])<<8; int incxx = ((s16)m_vreg[0xc0 / 2])<<8;
int incxy = ((int16_t)m_vreg[0xc2/2])<<8; int incxy = ((s16)m_vreg[0xc2 / 2])<<8;
int incyx = ((int16_t)m_vreg[0xc4/2])<<8; int incyx = ((s16)m_vreg[0xc4 / 2])<<8;
int incyy = ((int16_t)m_vreg[0xc6/2])<<8; int incyy = ((s16)m_vreg[0xc6 / 2])<<8;
int16_t xoffset = m_vreg[0xc8/2]; s16 xoffset = m_vreg[0xc8 / 2];
int16_t yoffset = m_vreg[0xca/2]; s16 yoffset = m_vreg[0xca / 2];
int dx = 46; /* horizontal adjust */ int dx = 46; /* horizontal adjust */
int dy = -8; /* vertical adjust */ int dy = -8; /* vertical adjust */
uint32_t startx = (xoffset<<12)+incxx*dx+incyx*dy; u32 startx = (xoffset<<12) + incxx * dx + incyx * dy;
uint32_t starty = (yoffset<<12)+incxy*dx+incyy*dy; u32 starty = (yoffset<<12) + incxy * dx + incyy * dy;
m_bg_tilemap[4]->draw_roz(screen, bitmap, cliprect, m_bg_tilemap[4]->draw_roz(screen, bitmap, cliprect,
startx, starty, incxx, incxy, incyx, incyy, 0, 0, primask, 0); startx, starty, incxx, incxy, incyx, incyy, 0, 0, primask, 0);
} }
@ -479,38 +466,38 @@ void namcona1_state::draw_background(screen_device &screen, bitmap_ind16 &bitmap
* tmap2 ffe800 ffea00 * tmap2 ffe800 ffea00
* tmap3 ffec00 ffee00 * tmap3 ffec00 ffee00
*/ */
const uint16_t *scroll = &m_scroll[which * 0x400/2]; const u16 *scroll = &m_scroll[which * 0x400 / 2];
rectangle clip = cliprect; rectangle clip = cliprect;
int xadjust = 0x3a - which*2; int xadjust = 0x3a - which*2;
int scrollx = xadjust; int scrollx = xadjust;
int scrolly = 0; int scrolly = 0;
for( int line = 0; line < 256; line++ ) for (int line = 0; line < 256; line++)
{ {
clip.min_y = line; clip.min_y = line;
clip.max_y = line; clip.max_y = line;
int xdata = scroll[line]; int xdata = scroll[line];
int ydata = scroll[line + 0x200/2]; int ydata = scroll[line + 0x200 / 2];
if( xdata ) if (xdata)
{ {
/* screenwise linescroll */ /* screenwise linescroll */
if(xdata & 0x4000) // resets current xscroll value (knuckle head) if (xdata & 0x4000) // resets current xscroll value (knuckle head)
scrollx = xadjust+xdata; scrollx = xadjust + xdata;
else else
scrollx += xdata & 0x1ff; scrollx += xdata & 0x1ff;
} }
if( ydata&0x4000 ) if (ydata & 0x4000)
{ {
/* line select: dword offset from 0xff000 or tilemap source line */ /* line select: dword offset from 0xff000 or tilemap source line */
scrolly = (ydata - line)&0x1ff; scrolly = (ydata - line) & 0x1ff;
} }
if (line >= cliprect.min_y && line <= cliprect.max_y) if (line >= cliprect.min_y && line <= cliprect.max_y)
{ {
// TODO: not convinced about this trigger // TODO: not convinced about this trigger
if( xdata == 0xc001 ) if (xdata == 0xc001)
{ {
/* This is a simplification, but produces the correct behavior for the only game that uses this /* This is a simplification, but produces the correct behavior for the only game that uses this
* feature, Numan Athletics. * feature, Numan Athletics.
@ -522,13 +509,13 @@ void namcona1_state::draw_background(screen_device &screen, bitmap_ind16 &bitmap
draw_pixel_line(cliprect, &bitmap.pix16(line), draw_pixel_line(cliprect, &bitmap.pix16(line),
&screen.priority().pix8(line), &screen.priority().pix8(line),
m_videoram + ydata + 25, m_videoram + ydata + 25,
paldata ); paldata);
} }
else else
{ {
m_bg_tilemap[which]->set_scrollx(0, scrollx ); m_bg_tilemap[which]->set_scrollx(0, scrollx);
m_bg_tilemap[which]->set_scrolly(0, scrolly ); m_bg_tilemap[which]->set_scrolly(0, scrolly);
m_bg_tilemap[which]->draw(screen, bitmap, clip, 0, primask, 0 ); m_bg_tilemap[which]->draw(screen, bitmap, clip, 0, primask, 0);
} }
} }
} }
@ -538,80 +525,73 @@ void namcona1_state::draw_background(screen_device &screen, bitmap_ind16 &bitmap
// CRTC safety checks // CRTC safety checks
bool namcona1_state::screen_enabled(const rectangle &cliprect) bool namcona1_state::screen_enabled(const rectangle &cliprect)
{ {
if(cliprect.min_x < 0) if (cliprect.min_x < 0)
return false; return false;
if(cliprect.max_x < 0) if (cliprect.max_x < 0)
return false; return false;
if(cliprect.min_x > cliprect.max_x) if (cliprect.min_x > cliprect.max_x)
return false; return false;
if(cliprect.min_y > cliprect.max_y) if (cliprect.min_y > cliprect.max_y)
return false; return false;
return true; return true;
} }
uint32_t namcona1_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) u32 namcona1_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{ {
int which;
int priority;
// CRTC visible area parameters // CRTC visible area parameters
// (used mostly by Numan Athletics for global screen window effects, cfr. start of events/title screen to demo mode transitions) // (used mostly by Numan Athletics for global screen window effects, cfr. start of events/title screen to demo mode transitions)
rectangle display_rect; rectangle display_rect;
display_rect.min_x = m_vreg[0x80/2]-0x48; display_rect.min_x = m_vreg[0x80 / 2]-0x48;
display_rect.max_x = m_vreg[0x82/2]-0x48-1; display_rect.max_x = m_vreg[0x82 / 2]-0x48-1;
display_rect.min_y = std::max((int)m_vreg[0x84/2], cliprect.min_y); display_rect.min_y = std::max((int)m_vreg[0x84 / 2], cliprect.min_y);
display_rect.max_y = std::min((int)m_vreg[0x86/2]-1, cliprect.max_y); display_rect.max_y = std::min((int)m_vreg[0x86 / 2] - 1, cliprect.max_y);
/* int flipscreen = m_vreg[0x98/2]; (TBA) */ /* int flipscreen = m_vreg[0x98 / 2]; (TBA) */
screen.priority().fill(0, cliprect ); screen.priority().fill(0, cliprect);
// guess for X-Day 2 (flames in attract), seems wrong for Emeraldia but unsure // guess for X-Day 2 (flames in attract), seems wrong for Emeraldia but unsure
// bitmap.fill(0xff, cliprect ); /* background color? */ // bitmap.fill(0xff, cliprect); /* background color? */
bitmap.fill((m_vreg[0xba/2] & 0xf) * 256, cliprect ); bitmap.fill((m_vreg[0xba / 2] & 0xf) << 8, cliprect);
if( m_vreg[0x8e/2] && screen_enabled(display_rect) == true ) if (m_vreg[0x8e / 2] && screen_enabled(display_rect) == true)
{ {
/* gfx enabled */ /* gfx enabled */
if( m_palette_is_dirty ) if (m_palette_is_dirty)
{ {
/* palette updates are delayed when graphics are disabled */ /* palette updates are delayed when graphics are disabled */
for( which=0; which<0x1000; which++ ) for (int which = 0; which < 0x1000; which++)
{ {
UpdatePalette( which ); UpdatePalette(which);
} }
m_palette_is_dirty = 0; m_palette_is_dirty = 0;
} }
for( which=0; which < 4; which++ ) for (int priority = 0; priority < 8; priority++)
m_bg_tilemap[which]->set_palette_offset((m_vreg[0xb0/2 + which] & 0xf) * 256);
m_bg_tilemap[4]->set_palette_offset((m_vreg[0xba/2] & 0xf) * 256);
for( priority = 0; priority<8; priority++ )
{ {
for( which=4; which>=0; which-- ) for (int which = 4; which >= 0; which--)
{ {
int pri; int pri;
if( which==4 ) if (which == 4)
{ {
pri = m_vreg[0xa0/2+5]&0x7; pri = m_vreg[0xa0 / 2 + 5] & 0x7;
} }
else else
{ {
pri = m_vreg[0xa0/2+which]&0x7; pri = m_vreg[0xa0 / 2 + which] & 0x7;
} }
if( pri == priority ) if (pri == priority)
{ {
draw_background(screen,bitmap,display_rect,which,priority); draw_background(screen, bitmap, display_rect, which, priority);
} }
} /* next tilemap */ } /* next tilemap */
} /* next priority level */ } /* next priority level */
draw_sprites(screen,bitmap,display_rect); draw_sprites(screen, bitmap, display_rect);
} /* gfx enabled */ } /* gfx enabled */
return 0; return 0;
} }