.. stragglers (nw)

This commit is contained in:
Scott Stone 2013-07-11 17:15:55 +00:00
parent 17f7b70131
commit ed4fb24e53
3 changed files with 641 additions and 0 deletions

2
.gitattributes vendored
View File

@ -5536,12 +5536,14 @@ src/mame/video/k051316.c svneol=native#text/plain
src/mame/video/k051316.h svneol=native#text/plain
src/mame/video/k051733.c svneol=native#text/plain
src/mame/video/k051733.h svneol=native#text/plain
src/mame/video/k051960.c svneol=native#text/plain
src/mame/video/k051960.h svneol=native#text/plain
src/mame/video/k052109.c svneol=native#text/plain
src/mame/video/k052109.h svneol=native#text/plain
src/mame/video/k05324x.c svneol=native#text/plain
src/mame/video/k05324x.h svneol=native#text/plain
src/mame/video/k053251.c svneol=native#text/plain
src/mame/video/k053251.h svneol=native#text/plain
src/mame/video/k053936.c svneol=native#text/plain
src/mame/video/k053936.h svneol=native#text/plain
src/mame/video/k054000.c svneol=native#text/plain

581
src/mame/video/k051960.c Normal file
View File

@ -0,0 +1,581 @@
/*
Konami 051960/051937
-------------
Sprite generators. Designed to work in pair. The 051960 manages the sprite
list and produces and address that is fed to the gfx ROMs. The data from the
ROMs is sent to the 051937, along with color code and other stuff from the
051960. The 051937 outputs up to 12 bits of palette index, plus "shadow" and
transparency information.
Both chips are interfaced to the main CPU, through 8-bit data buses and 11
bits of address space. The 051937 sits in the range 000-007, while the 051960
in the range 400-7ff (all RAM). The main CPU can read the gfx ROM data though
the 051937 data bus, while the 051960 provides the address lines.
The 051960 is designed to directly address 1MB of ROM space, since it produces
18 address lines that go to two 16-bit wide ROMs (the 051937 has a 32-bit data
bus to the ROMs). However, the addressing space can be increased by using one
or more of the "color attribute" bits of the sprites as bank selectors.
Moreover a few games store the gfx data in the ROMs in a format different from
the one expected by the 051960, and use external logic to reorder the address
lines.
The 051960 can also genenrate IRQ, FIRQ and NMI signals.
memory map:
000-007 is for the 051937, but also seen by the 051960
400-7ff is 051960 only
000 R bit 0 = unknown, looks like a status flag or something
aliens waits for it to be 0 before starting to copy sprite data
thndrx2 needs it to pulse for the startup checks to succeed
000 W bit 0 = irq enable/acknowledge?
bit 2 = nmi enable?
bit 3 = flip screen (applies to sprites only, not tilemaps)
bit 4 = unknown, used by Devastators, TMNT, Aliens, Chequered Flag, maybe others
aliens sets it just after checking bit 0, and before copying
the sprite data
bit 5 = enable gfx ROM reading
001 W Devastators sets bit 1, function unknown.
Ultraman sets the register to 0x0f.
None of the other games I tested seem to set this register to other than 0.
002-003 W selects the portion of the gfx ROMs to be read.
004 W Aliens uses this to select the ROM bank to be read, but Punk Shot
and TMNT don't, they use another bit of the registers above. Many
other games write to this register before testing.
It is possible that bits 2-7 of 003 go to OC0-OC5, and bits 0-1 of
004 go to OC6-OC7.
004-007 R reads data from the gfx ROMs (32 bits in total). The address of the
data is determined by the register above and by the last address
accessed on the 051960; plus bank switch bits for larger ROMs.
It seems that the data can also be read directly from the 051960
address space: 88 Games does this. First it reads 004 and discards
the result, then it reads from the 051960 the data at the address
it wants. The normal order is the opposite, read from the 051960 at
the address you want, discard the result, and fetch the data from
004-007.
400-7ff RW sprite RAM, 8 bytes per sprite
*/
#include "emu.h"
#include "k051960.h"
#include "konami_helper.h"
#define VERBOSE 0
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
const device_type K051960 = &device_creator<k051960_device>;
k051960_device::k051960_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, K051960, "Konami 051960", tag, owner, clock, "k051960", __FILE__),
m_ram(NULL),
m_gfx(NULL),
//m_spriterombank[3],
m_dx(0),
m_dy(0),
m_romoffset(0),
m_spriteflip(0),
m_readroms(0),
m_irq_enabled(0),
m_nmi_enabled(0),
m_k051937_counter(0)
{
}
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void k051960_device::device_config_complete()
{
// inherit a copy of the static data
const k051960_interface *intf = reinterpret_cast<const k051960_interface *>(static_config());
if (intf != NULL)
*static_cast<k051960_interface *>(this) = *intf;
// or initialize to defaults if none provided
else
{
m_gfx_memory_region = "";
m_gfx_num = 0;
m_plane_order = 0;
m_deinterleave = 0;
m_callback = NULL;
}
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void k051960_device::device_start()
{
UINT32 total;
static const gfx_layout spritelayout =
{
16,16,
0,
4,
{ 0, 8, 16, 24 },
{ 0, 1, 2, 3, 4, 5, 6, 7,
8*32+0, 8*32+1, 8*32+2, 8*32+3, 8*32+4, 8*32+5, 8*32+6, 8*32+7 },
{ 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32,
16*32, 17*32, 18*32, 19*32, 20*32, 21*32, 22*32, 23*32 },
128*8
};
static const gfx_layout spritelayout_reverse =
{
16,16,
0,
4,
{ 24, 16, 8, 0 },
{ 0, 1, 2, 3, 4, 5, 6, 7,
8*32+0, 8*32+1, 8*32+2, 8*32+3, 8*32+4, 8*32+5, 8*32+6, 8*32+7 },
{ 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32,
16*32, 17*32, 18*32, 19*32, 20*32, 21*32, 22*32, 23*32 },
128*8
};
static const gfx_layout spritelayout_gradius3 =
{
16,16,
0,
4,
{ 0, 1, 2, 3 },
{ 2*4, 3*4, 0*4, 1*4, 6*4, 7*4, 4*4, 5*4,
32*8+2*4, 32*8+3*4, 32*8+0*4, 32*8+1*4, 32*8+6*4, 32*8+7*4, 32*8+4*4, 32*8+5*4 },
{ 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32,
64*8+0*32, 64*8+1*32, 64*8+2*32, 64*8+3*32, 64*8+4*32, 64*8+5*32, 64*8+6*32, 64*8+7*32 },
128*8
};
/* decode the graphics */
switch (m_plane_order)
{
case NORMAL_PLANE_ORDER:
total = machine().root_device().memregion(m_gfx_memory_region)->bytes() / 128;
konami_decode_gfx(machine(), m_gfx_num, machine().root_device().memregion(m_gfx_memory_region)->base(), total, &spritelayout, 4);
break;
case REVERSE_PLANE_ORDER:
total = machine().root_device().memregion(m_gfx_memory_region)->bytes() / 128;
konami_decode_gfx(machine(), m_gfx_num, machine().root_device().memregion(m_gfx_memory_region)->base(), total, &spritelayout_reverse, 4);
break;
case GRADIUS3_PLANE_ORDER:
total = 0x4000;
konami_decode_gfx(machine(), m_gfx_num, machine().root_device().memregion(m_gfx_memory_region)->base(), total, &spritelayout_gradius3, 4);
break;
default:
fatalerror("Unknown plane_order\n");
}
if (VERBOSE && !(machine().config().m_video_attributes & VIDEO_HAS_SHADOWS))
popmessage("driver should use VIDEO_HAS_SHADOWS");
/* deinterleave the graphics, if needed */
konami_deinterleave_gfx(machine(), m_gfx_memory_region, m_deinterleave);
m_gfx = machine().gfx[m_gfx_num];
m_ram = auto_alloc_array_clear(machine(), UINT8, 0x400);
save_item(NAME(m_romoffset));
save_item(NAME(m_spriteflip));
save_item(NAME(m_readroms));
save_item(NAME(m_spriterombank));
save_pointer(NAME(m_ram), 0x400);
save_item(NAME(m_irq_enabled));
save_item(NAME(m_nmi_enabled));
save_item(NAME(m_dx));
save_item(NAME(m_dy));
save_item(NAME(m_k051937_counter));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void k051960_device::device_reset()
{
m_dx = m_dy = 0;
m_k051937_counter = 0;
m_romoffset = 0;
m_spriteflip = 0;
m_readroms = 0;
m_irq_enabled = 0;
m_nmi_enabled = 0;
m_spriterombank[0] = 0;
m_spriterombank[1] = 0;
m_spriterombank[2] = 0;
}
/*****************************************************************************
DEVICE HANDLERS
*****************************************************************************/
int k051960_device::k051960_fetchromdata( int byte )
{
int code, color, pri, shadow, off1, addr;
addr = m_romoffset + (m_spriterombank[0] << 8) + ((m_spriterombank[1] & 0x03) << 16);
code = (addr & 0x3ffe0) >> 5;
off1 = addr & 0x1f;
color = ((m_spriterombank[1] & 0xfc) >> 2) + ((m_spriterombank[2] & 0x03) << 6);
pri = 0;
shadow = color & 0x80;
m_callback(machine(), &code, &color, &pri, &shadow);
addr = (code << 7) | (off1 << 2) | byte;
addr &= machine().root_device().memregion(m_gfx_memory_region)->bytes() - 1;
// popmessage("%s: addr %06x", machine().describe_context(), addr);
return machine().root_device().memregion(m_gfx_memory_region)->base()[addr];
}
READ8_MEMBER( k051960_device::k051960_r )
{
if (m_readroms)
{
/* the 051960 remembers the last address read and uses it when reading the sprite ROMs */
m_romoffset = (offset & 0x3fc) >> 2;
return k051960_fetchromdata(offset & 3); /* only 88 Games reads the ROMs from here */
}
else
return m_ram[offset];
}
WRITE8_MEMBER( k051960_device::k051960_w )
{
m_ram[offset] = data;
}
READ16_MEMBER( k051960_device::k051960_word_r )
{
return k051960_r(space, offset * 2 + 1) | (k051960_r(space, offset * 2) << 8);
}
WRITE16_MEMBER( k051960_device::k051960_word_w )
{
if (ACCESSING_BITS_8_15)
k051960_w(space, offset * 2, (data >> 8) & 0xff);
if (ACCESSING_BITS_0_7)
k051960_w(space, offset * 2 + 1, data & 0xff);
}
/* should this be split by k051960? */
READ8_MEMBER( k051960_device::k051937_r )
{
if (m_readroms && offset >= 4 && offset < 8)
return k051960_fetchromdata(offset & 3);
else
{
if (offset == 0)
{
/* some games need bit 0 to pulse */
return (m_k051937_counter++) & 1;
}
//logerror("%04x: read unknown 051937 address %x\n", device->cpu->safe_pc(), offset);
return 0;
}
return 0;
}
WRITE8_MEMBER( k051960_device::k051937_w )
{
if (offset == 0)
{
//if (data & 0xc2) popmessage("051937 reg 00 = %02x",data);
/* bit 0 is IRQ enable */
m_irq_enabled = data & 0x01;
/* bit 1: probably FIRQ enable */
/* bit 2 is NMI enable */
m_nmi_enabled = data & 0x04;
/* bit 3 = flip screen */
m_spriteflip = data & 0x08;
/* bit 4 used by Devastators and TMNT, unknown */
/* bit 5 = enable gfx ROM reading */
m_readroms = data & 0x20;
//logerror("%04x: write %02x to 051937 address %x\n", machine().cpu->safe_pc(), data, offset);
}
else if (offset == 1)
{
// popmessage("%04x: write %02x to 051937 address %x", machine().cpu->safe_pc(), data, offset);
//logerror("%04x: write %02x to unknown 051937 address %x\n", machine().cpu->safe_pc(), data, offset);
}
else if (offset >= 2 && offset < 5)
{
m_spriterombank[offset - 2] = data;
}
else
{
// popmessage("%04x: write %02x to 051937 address %x", machine().cpu->safe_pc(), data, offset);
//logerror("%04x: write %02x to unknown 051937 address %x\n", machine().cpu->safe_pc(), data, offset);
}
}
int k051960_device::k051960_is_irq_enabled( )
{
return m_irq_enabled;
}
int k051960_device::k051960_is_nmi_enabled( )
{
return m_nmi_enabled;
}
void k051960_device::k051960_set_sprite_offsets( int dx, int dy )
{
m_dx = dx;
m_dy = dy;
}
READ16_MEMBER( k051960_device::k051937_word_r )
{
return k051937_r(space, offset * 2 + 1) | (k051937_r(space, offset * 2) << 8);
}
WRITE16_MEMBER( k051960_device::k051937_word_w )
{
if (ACCESSING_BITS_8_15)
k051937_w(space, offset * 2,(data >> 8) & 0xff);
if (ACCESSING_BITS_0_7)
k051937_w(space, offset * 2 + 1,data & 0xff);
}
/*
* Sprite Format
* ------------------
*
* Byte | Bit(s) | Use
* -----+-76543210-+----------------
* 0 | x------- | active (show this sprite)
* 0 | -xxxxxxx | priority order
* 1 | xxx----- | sprite size (see below)
* 1 | ---xxxxx | sprite code (high 5 bits)
* 2 | xxxxxxxx | sprite code (low 8 bits)
* 3 | xxxxxxxx | "color", but depends on external connections (see below)
* 4 | xxxxxx-- | zoom y (0 = normal, >0 = shrink)
* 4 | ------x- | flip y
* 4 | -------x | y position (high bit)
* 5 | xxxxxxxx | y position (low 8 bits)
* 6 | xxxxxx-- | zoom x (0 = normal, >0 = shrink)
* 6 | ------x- | flip x
* 6 | -------x | x position (high bit)
* 7 | xxxxxxxx | x position (low 8 bits)
*
* Example of "color" field for Punk Shot:
* 3 | x------- | shadow
* 3 | -xx----- | priority
* 3 | ---x---- | use second gfx ROM bank
* 3 | ----xxxx | color code
*
* shadow enables transparent shadows. Note that it applies to pen 0x0f ONLY.
* The rest of the sprite remains normal.
* Note that Aliens also uses the shadow bit to select the second sprite bank.
*/
void k051960_device::k051960_sprites_draw( bitmap_ind16 &bitmap, const rectangle &cliprect, int min_priority, int max_priority )
{
#define NUM_SPRITES 128
int offs, pri_code;
int sortedlist[NUM_SPRITES];
UINT8 drawmode_table[256];
memset(drawmode_table, DRAWMODE_SOURCE, sizeof(drawmode_table));
drawmode_table[0] = DRAWMODE_NONE;
for (offs = 0; offs < NUM_SPRITES; offs++)
sortedlist[offs] = -1;
/* prebuild a sorted table */
for (offs = 0; offs < 0x400; offs += 8)
{
if (m_ram[offs] & 0x80)
{
if (max_priority == -1) /* draw front to back when using priority buffer */
sortedlist[(m_ram[offs] & 0x7f) ^ 0x7f] = offs;
else
sortedlist[m_ram[offs] & 0x7f] = offs;
}
}
for (pri_code = 0; pri_code < NUM_SPRITES; pri_code++)
{
int ox, oy, code, color, pri, shadow, size, w, h, x, y, flipx, flipy, zoomx, zoomy;
/* sprites can be grouped up to 8x8. The draw order is
0 1 4 5 16 17 20 21
2 3 6 7 18 19 22 23
8 9 12 13 24 25 28 29
10 11 14 15 26 27 30 31
32 33 36 37 48 49 52 53
34 35 38 39 50 51 54 55
40 41 44 45 56 57 60 61
42 43 46 47 58 59 62 63
*/
static const int xoffset[8] = { 0, 1, 4, 5, 16, 17, 20, 21 };
static const int yoffset[8] = { 0, 2, 8, 10, 32, 34, 40, 42 };
static const int width[8] = { 1, 2, 1, 2, 4, 2, 4, 8 };
static const int height[8] = { 1, 1, 2, 2, 2, 4, 4, 8 };
offs = sortedlist[pri_code];
if (offs == -1)
continue;
code = m_ram[offs + 2] + ((m_ram[offs + 1] & 0x1f) << 8);
color = m_ram[offs + 3] & 0xff;
pri = 0;
shadow = color & 0x80;
m_callback(machine(), &code, &color, &pri, &shadow);
if (max_priority != -1)
if (pri < min_priority || pri > max_priority)
continue;
size = (m_ram[offs + 1] & 0xe0) >> 5;
w = width[size];
h = height[size];
if (w >= 2) code &= ~0x01;
if (h >= 2) code &= ~0x02;
if (w >= 4) code &= ~0x04;
if (h >= 4) code &= ~0x08;
if (w >= 8) code &= ~0x10;
if (h >= 8) code &= ~0x20;
ox = (256 * m_ram[offs + 6] + m_ram[offs + 7]) & 0x01ff;
oy = 256 - ((256 * m_ram[offs + 4] + m_ram[offs + 5]) & 0x01ff);
ox += m_dx;
oy += m_dy;
flipx = m_ram[offs + 6] & 0x02;
flipy = m_ram[offs + 4] & 0x02;
zoomx = (m_ram[offs + 6] & 0xfc) >> 2;
zoomy = (m_ram[offs + 4] & 0xfc) >> 2;
zoomx = 0x10000 / 128 * (128 - zoomx);
zoomy = 0x10000 / 128 * (128 - zoomy);
if (m_spriteflip)
{
ox = 512 - (zoomx * w >> 12) - ox;
oy = 256 - (zoomy * h >> 12) - oy;
flipx = !flipx;
flipy = !flipy;
}
drawmode_table[m_gfx->granularity() - 1] = shadow ? DRAWMODE_SHADOW : DRAWMODE_SOURCE;
if (zoomx == 0x10000 && zoomy == 0x10000)
{
int sx, sy;
for (y = 0; y < h; y++)
{
sy = oy + 16 * y;
for (x = 0; x < w; x++)
{
int c = code;
sx = ox + 16 * x;
if (flipx)
c += xoffset[(w - 1 - x)];
else
c += xoffset[x];
if (flipy)
c += yoffset[(h - 1 - y)];
else
c += yoffset[y];
if (max_priority == -1)
pdrawgfx_transtable(bitmap,cliprect,m_gfx,
c,
color,
flipx,flipy,
sx & 0x1ff,sy,
machine().priority_bitmap,pri,
drawmode_table,machine().shadow_table);
else
drawgfx_transtable(bitmap,cliprect,m_gfx,
c,
color,
flipx,flipy,
sx & 0x1ff,sy,
drawmode_table,machine().shadow_table);
}
}
}
else
{
int sx, sy, zw, zh;
for (y = 0; y < h; y++)
{
sy = oy + ((zoomy * y + (1 << 11)) >> 12);
zh = (oy + ((zoomy * (y + 1) + (1 << 11)) >> 12)) - sy;
for (x = 0; x < w; x++)
{
int c = code;
sx = ox + ((zoomx * x + (1 << 11)) >> 12);
zw = (ox + ((zoomx * (x+1) + (1 << 11)) >> 12)) - sx;
if (flipx)
c += xoffset[(w - 1 - x)];
else
c += xoffset[x];
if (flipy)
c += yoffset[(h - 1 - y)];
else
c += yoffset[y];
if (max_priority == -1)
pdrawgfxzoom_transtable(bitmap,cliprect,m_gfx,
c,
color,
flipx,flipy,
sx & 0x1ff,sy,
(zw << 16) / 16,(zh << 16) / 16,
machine().priority_bitmap,pri,
drawmode_table,machine().shadow_table);
else
drawgfxzoom_transtable(bitmap,cliprect,m_gfx,
c,
color,
flipx,flipy,
sx & 0x1ff,sy,
(zw << 16) / 16,(zh << 16) / 16,
drawmode_table,machine().shadow_table);
}
}
}
}
#if 0
if (machine().input().code_pressed(KEYCODE_D))
{
FILE *fp;
fp=fopen("SPRITE.DMP", "w+b");
if (fp)
{
fwrite(k051960_ram, 0x400, 1, fp);
popmessage("saved");
fclose(fp);
}
}
#endif
#undef NUM_SPRITES
}

58
src/mame/video/k053251.h Normal file
View File

@ -0,0 +1,58 @@
#pragma once
#ifndef __K053251_H__
#define __K053251_H__
enum
{
K053251_CI0 = 0,
K053251_CI1,
K053251_CI2,
K053251_CI3,
K053251_CI4
};
class k053251_device : public device_t
{
public:
k053251_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~k053251_device() {}
/*
Note: k053251_w() automatically does a ALL_TILEMAPS->mark_all_dirty()
when some palette index changes. If ALL_TILEMAPS is too expensive, use
k053251_set_tilemaps() to indicate which tilemap is associated with each index.
*/
DECLARE_WRITE8_MEMBER( write );
DECLARE_WRITE16_MEMBER( lsb_w );
DECLARE_WRITE16_MEMBER( msb_w );
int get_priority(int ci);
int get_palette_index(int ci);
int get_tmap_dirty(int tmap_num);
void set_tmap_dirty(int tmap_num, int data);
DECLARE_READ16_MEMBER( lsb_r ); // PCU1
DECLARE_READ16_MEMBER( msb_r ); // PCU1
protected:
// device-level overrides
virtual void device_config_complete();
virtual void device_start();
virtual void device_reset();
private:
// internal state
int m_dirty_tmap[5];
UINT8 m_ram[16];
int m_tilemaps_set;
int m_palette_index[5];
void reset_indexes();
};
extern const device_type K053251;
#define MCFG_K053251_ADD(_tag) \
MCFG_DEVICE_ADD(_tag, K053251, 0)
#endif