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

View File

@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Phil Stroffolino
/* Namco System NA1/2 Video Hardware */
/* Namco System NA1 / 2 Video Hardware */
/*
Notes:
@ -24,107 +24,116 @@ TODO:
void namcona1_state::tilemap_get_info(
tile_data &tileinfo,
int tile_index,
const uint16_t *tilemap_videoram,
bool use_4bpp_gfx )
const u16 *tilemap_videoram,
bool use_4bpp_gfx)
{
int data = tilemap_videoram[tile_index];
int tile = data&0xfff;
int gfx = use_4bpp_gfx ? 1 : 0;
int color = use_4bpp_gfx ? (data & 0x7000)>>12 : 0;
const u16 data = tilemap_videoram[tile_index];
const u32 tile = data & 0xfff;
const u8 gfx = use_4bpp_gfx ? 1 : 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
{
SET_TILE_INFO_MEMBER(gfx,tile,color,0 );
tileinfo.mask_data = &m_shaperam[tile*8];
SET_TILE_INFO_MEMBER(gfx, tile, color, 0);
tileinfo.mask_data = &m_shaperam[tile << 3];
}
} /* tilemap_get_info */
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)
{
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)
{
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)
{
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)
{
/* each logical tile is constructed from 4*4 normal tiles */
int use_4bpp_gfx = m_vreg[0xbc/2]&16; /* ? */
int c = tile_index%0x40;
int r = tile_index/0x40;
int data = m_videoram[0x8000/2+(r/4)*0x40+c/4]&0xfbf; /* mask out bit 0x40 - patch for Emeraldia Japan */
int tile = (data+(c%4)+(r%4)*0x40)&0xfff;
int gfx = use_4bpp_gfx ? 1 : 0;
int color = use_4bpp_gfx ? (data & 0x7000)>>12 : 0;
const bool use_4bpp_gfx = m_vreg[0xbc / 2] & 0x10; /* ? */
const u16 c = tile_index & 0x3f;
const u16 r = tile_index >> 6;
const u16 data = m_videoram[0x8000 / 2 + ((r >> 2) << 6) + (c >> 2)];
const u32 tile = ((data & 0xfbf) + (c & 3) + ((r & 3) << 6)) & 0xfff; /* mask out bit 0x40 - patch for Emeraldia Japan */
const u8 gfx = use_4bpp_gfx ? 1 : 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
{
SET_TILE_INFO_MEMBER(gfx,tile,color,0 );
tileinfo.mask_data = &m_shaperam[tile*8];
SET_TILE_INFO_MEMBER(gfx, tile, color, 0);
tileinfo.mask_data = &m_shaperam[tile << 3];
}
} /* 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] );
if( offset<0x8000/2 )
COMBINE_DATA(&m_videoram[offset]);
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 */
/*************************************************************************/
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
* (used in-game in Emeraldia)
*
* RRRGGGBB RRRGGGBB
*/
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 b = (((data&0x0003)>>0)+((data&0x0300)>>8)*2)*0xff/(0x3*3);
m_palette->set_pen_color(offset+0x1000, r, g, b);
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 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, 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] );
if( m_vreg[0x8e/2] )
COMBINE_DATA(&m_paletteram[offset]);
if (m_vreg[0x8e / 2])
{ /* graphics enabled; update palette immediately */
UpdatePalette( offset );
UpdatePalette(offset);
}
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];
if( type == 0x03 )
const u16 type = m_vreg[0x0c / 2];
if (type == 0x03)
{
if( offset<0x4000 )
if (offset < 0x4000)
{
offset *= 2;
return (m_shaperam[offset] << 8) | m_shaperam[offset+1];
}
}
else if( type == 0x02 )
else if (type == 0x02)
{
return m_cgram[offset];
}
return 0x0000;
} /* 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];
uint16_t old_word;
const u16 type = m_vreg[0x0c / 2];
if( type == 0x03 )
if (type == 0x03)
{
if( offset<0x4000 )
if (offset < 0x4000)
{
offset *= 2;
if (ACCESSING_BITS_8_15)
m_shaperam[offset] = data >> 8;
if (ACCESSING_BITS_0_7)
m_shaperam[offset+1] = data;
m_gfxdecode->gfx(2)->mark_dirty(offset/8);
m_shaperam[offset + 1] = data;
m_gfxdecode->gfx(2)->mark_dirty(offset >> 3);
}
}
else if( type == 0x02 )
else if (type == 0x02)
{
old_word = m_cgram[offset];
COMBINE_DATA( &m_cgram[offset] );
if( m_cgram[offset]!=old_word )
const u16 old_word = m_cgram[offset];
COMBINE_DATA(&m_cgram[offset]);
if (m_cgram[offset] != old_word)
{
m_gfxdecode->gfx(0)->mark_dirty(offset/0x20);
m_gfxdecode->gfx(1)->mark_dirty(offset/0x20);
m_gfxdecode->gfx(0)->mark_dirty(offset >> 5);
m_gfxdecode->gfx(1)->mark_dirty(offset >> 5);
}
}
} /* gfxram_w */
@ -183,13 +191,13 @@ WRITE16_MEMBER(namcona1_state::gfxram_w)
void namcona1_state::video_start()
{
// 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[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[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[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[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);
// 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);
@ -197,11 +205,9 @@ void namcona1_state::video_start()
save_item(NAME(m_shaperam));
save_item(NAME(m_palette_is_dirty));
machine().save().register_postload(save_prepost_delegate(FUNC(namcona1_state::postload), this));
} /* video_start */
void namcona1_state::postload()
void namcona1_state::device_post_load()
{
for (int i = 0; i < 3; i++)
m_gfxdecode->gfx(i)->mark_all_dirty();
@ -214,222 +220,204 @@ void namcona1_state::pdraw_tile(
screen_device &screen,
bitmap_ind16 &dest_bmp,
const rectangle &clip,
uint32_t code,
int color,
u32 code,
u32 color,
int sx, int sy,
int flipx, int flipy,
int priority,
int bShadow,
int bOpaque,
int gfx_region )
bool flipx, bool flipy,
u8 priority,
bool bShadow,
bool bOpaque,
u8 gfx_region)
{
gfx_element *gfx = m_gfxdecode->gfx(gfx_region);
gfx_element *mask = m_gfxdecode->gfx(2);
int pal_base = gfx->colorbase() + gfx->granularity() * (color % gfx->colors());
const uint8_t *source_base = gfx->get_data((code % gfx->elements()));
const uint8_t *mask_base = mask->get_data((code % mask->elements()));
const u16 pal_base = gfx->colorbase() + gfx->granularity() * (color % gfx->colors());
const u8 *source_base = gfx->get_data((code % gfx->elements()));
const u8 *mask_base = mask->get_data((code % mask->elements()));
int sprite_screen_height = ((1<<16)*gfx->height()+0x8000)>>16;
int sprite_screen_width = ((1<<16)*gfx->width()+0x8000)>>16;
/* compute sprite increment per screen pixel */
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 */
int dx = (gfx->width()<<16)/sprite_screen_width;
int dy = (gfx->height()<<16)/sprite_screen_height;
x_index_base = gfx->width() - 1;
dx = -1;
}
else
{
x_index_base = 0;
dx = 1;
}
int ex = sx+sprite_screen_width;
int ey = sy+sprite_screen_height;
if (flipy)
{
y_index = gfx->height() - 1;
dy = -1;
}
else
{
y_index = 0;
dy = 1;
}
int x_index_base;
int y_index;
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( 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;
dx = -dx;
}
else
{
x_index_base = 0;
}
const u8 *source = source_base + y_index * gfx->rowbytes();
const u8 *mask_addr = mask_base + y_index * mask->rowbytes();
u16 *dest = &dest_bmp.pix16(y);
u8 *pri = &screen.priority().pix8(y);
if( flipy )
{
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++ )
int x_index = x_index_base;
for (int x = sx; x < ex; x++)
{
const uint8_t *source = source_base + (y_index>>16) * gfx->rowbytes();
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( 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)
{
int c = source[x_index>>16];
dest[x] = pal_base + c;
}
const u8 c = source[x_index];
pri[x] = 0xff;
}
else
{
/* sprite pixel is opaque */
if( mask_addr[x_index>>16] != 0 )
{
if (pri[x] <= priority)
/* render a shadow only if the sprites color is $F (8bpp) or $FF (4bpp) */
if (bShadow)
{
int c = source[x_index>>16];
/* render a shadow only if the sprites color is $F (8bpp) or $FF (4bpp) */
if( bShadow )
if ((gfx_region == 0 && color == 0x0f) ||
(gfx_region == 1 && color == 0xff))
{
if( (gfx_region == 0 && color == 0x0f) ||
(gfx_region == 1 && color == 0xff) )
{
pen_t *palette_shadow_table = m_palette->shadow_table();
dest[x] = palette_shadow_table[dest[x]];
}
else
{
dest[x] = pal_base + c + 0x1000;
}
pen_t *palette_shadow_table = m_palette->shadow_table();
dest[x] = palette_shadow_table[dest[x]];
}
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;
}
y_index += dy;
x_index += dx;
}
y_index += dy;
}
}
} /* pdraw_tile */
void namcona1_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
int which;
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;
const u16 *source = m_spriteram;
sprite_control = m_vreg[0x22/2];
if( sprite_control&1 ) source += 0x400; /* alternate spriteram bank */
const u16 sprite_control = m_vreg[0x22 / 2];
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 */
int bpp4,palbase;
ypos = source[0]; /* FHHH---Y YYYYYYYY flipy, height, ypos */
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*/
xpos = source[3]; /* -------X XXXXXXXX xpos */
const u16 ypos = source[0]; /* FHHH---Y YYYYYYYY flipy, height, ypos */
const u16 tile = source[1]; /* O???TTTT TTTTTTTT opaque tile */
const u16 color = source[2]; /* FSWWOOOO CCCCBPPP flipx, shadow, width, color offset for 4bpp, color, 4bbp - 8bpp mode, pri*/
const u16 xpos = source[3]; /* -------X XXXXXXXX xpos */
priority = color&0x7;
width = ((color>>12)&0x3)+1;
height = ((ypos>>12)&0x7)+1;
flipy = ypos&0x8000;
flipx = color&0x8000;
const u8 priority = color & 0x7;
const u16 width = ((color >> 12) & 0x3) + 1;
const u16 height = ((ypos >> 12) & 0x7) + 1;
bool flipy = ypos & 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;
}
else
{
palbase = (color&0xf0)>>4;
palbase = (color & 0xf0) >> 4;
bpp4 = 0;
}
for( row=0; row<height; row++ )
for (int row = 0; row < height; row++)
{
sy = (ypos&0x1ff)-30+32;
if( flipy )
int sy = (ypos & 0x1ff) - 30 + 32;
if (flipy)
{
sy += (height-1-row)*8;
sy += (height - 1 - row) << 3;
}
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;
if( flipx )
int sx = (xpos & 0x1ff) - 10;
if (flipx)
{
sx += (width-1-col)*8;
sx += (width - 1 - col) << 3;
}
else
{
sx+=col*8;
sx += col << 3;
}
sx = ((sx+16)&0x1ff)-8;
sx = ((sx + 16) & 0x1ff) - 8;
pdraw_tile(screen,
bitmap,
cliprect,
(tile & 0xfff) + row*64+col,
(tile & 0xfff) + (row << 6) + col,
palbase,
sx,sy,flipx,flipy,
priority,
color & 0x4000, /* shadow */
tile & 0x8000, /* opaque */
bpp4 );
bpp4);
} /* next col */
} /* next row */
@ -437,36 +425,35 @@ void namcona1_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, c
}
} /* 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( x=0; x<38*8; x+=2 )
for (int x = 0; x < 38 << 3; x += 2)
{
uint16_t data = *pSource++;
pPri[x+0] = 0xff;
pPri[x+1] = 0xff;
if(x >= cliprect.min_x && x <= cliprect.max_x)
u16 data = *pSource++;
pPri[x + 0] = 0xff;
pPri[x + 1] = 0xff;
if (x >= cliprect.min_x && x <= cliprect.max_x)
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];
} /* next x */
} /* 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 */
int incxx = ((int16_t)m_vreg[0xc0/2])<<8;
int incxy = ((int16_t)m_vreg[0xc2/2])<<8;
int incyx = ((int16_t)m_vreg[0xc4/2])<<8;
int incyy = ((int16_t)m_vreg[0xc6/2])<<8;
int16_t xoffset = m_vreg[0xc8/2];
int16_t yoffset = m_vreg[0xca/2];
int incxx = ((s16)m_vreg[0xc0 / 2])<<8;
int incxy = ((s16)m_vreg[0xc2 / 2])<<8;
int incyx = ((s16)m_vreg[0xc4 / 2])<<8;
int incyy = ((s16)m_vreg[0xc6 / 2])<<8;
s16 xoffset = m_vreg[0xc8 / 2];
s16 yoffset = m_vreg[0xca / 2];
int dx = 46; /* horizontal adjust */
int dy = -8; /* vertical adjust */
uint32_t startx = (xoffset<<12)+incxx*dx+incyx*dy;
uint32_t starty = (yoffset<<12)+incxy*dx+incyy*dy;
u32 startx = (xoffset<<12) + incxx * dx + incyx * dy;
u32 starty = (yoffset<<12) + incxy * dx + incyy * dy;
m_bg_tilemap[4]->draw_roz(screen, bitmap, cliprect,
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
* tmap3 ffec00 ffee00
*/
const uint16_t *scroll = &m_scroll[which * 0x400/2];
const u16 *scroll = &m_scroll[which * 0x400 / 2];
rectangle clip = cliprect;
int xadjust = 0x3a - which*2;
int scrollx = xadjust;
int scrolly = 0;
for( int line = 0; line < 256; line++ )
for (int line = 0; line < 256; line++)
{
clip.min_y = line;
clip.max_y = line;
int xdata = scroll[line];
int ydata = scroll[line + 0x200/2];
int ydata = scroll[line + 0x200 / 2];
if( xdata )
if (xdata)
{
/* screenwise linescroll */
if(xdata & 0x4000) // resets current xscroll value (knuckle head)
scrollx = xadjust+xdata;
if (xdata & 0x4000) // resets current xscroll value (knuckle head)
scrollx = xadjust + xdata;
else
scrollx += xdata & 0x1ff;
}
if( ydata&0x4000 )
if (ydata & 0x4000)
{
/* 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)
{
// 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
* 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),
&screen.priority().pix8(line),
m_videoram + ydata + 25,
paldata );
paldata);
}
else
{
m_bg_tilemap[which]->set_scrollx(0, scrollx );
m_bg_tilemap[which]->set_scrolly(0, scrolly );
m_bg_tilemap[which]->draw(screen, bitmap, clip, 0, primask, 0 );
m_bg_tilemap[which]->set_scrollx(0, scrollx);
m_bg_tilemap[which]->set_scrolly(0, scrolly);
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
bool namcona1_state::screen_enabled(const rectangle &cliprect)
{
if(cliprect.min_x < 0)
if (cliprect.min_x < 0)
return false;
if(cliprect.max_x < 0)
if (cliprect.max_x < 0)
return false;
if(cliprect.min_x > cliprect.max_x)
if (cliprect.min_x > cliprect.max_x)
return false;
if(cliprect.min_y > cliprect.max_y)
if (cliprect.min_y > cliprect.max_y)
return false;
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
// (used mostly by Numan Athletics for global screen window effects, cfr. start of events/title screen to demo mode transitions)
rectangle display_rect;
display_rect.min_x = m_vreg[0x80/2]-0x48;
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.max_y = std::min((int)m_vreg[0x86/2]-1, cliprect.max_y);
display_rect.min_x = m_vreg[0x80 / 2]-0x48;
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.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
// bitmap.fill(0xff, cliprect ); /* background color? */
bitmap.fill((m_vreg[0xba/2] & 0xf) * 256, cliprect );
// bitmap.fill(0xff, cliprect); /* background color? */
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 */
if( m_palette_is_dirty )
if (m_palette_is_dirty)
{
/* 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;
}
for( which=0; which < 4; which++ )
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 (int priority = 0; priority < 8; priority++)
{
for( which=4; which>=0; which-- )
for (int which = 4; which >= 0; which--)
{
int pri;
if( which==4 )
if (which == 4)
{
pri = m_vreg[0xa0/2+5]&0x7;
pri = m_vreg[0xa0 / 2 + 5] & 0x7;
}
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 priority level */
draw_sprites(screen,bitmap,display_rect);
draw_sprites(screen, bitmap, display_rect);
} /* gfx enabled */
return 0;
}