mirror of
https://github.com/holub/mame
synced 2025-04-16 13:34:55 +03:00
firebeat: Split GCU into its own file (nw)
This commit is contained in:
parent
a765979c61
commit
01b95b1973
@ -1921,6 +1921,7 @@ files {
|
||||
MAME_DIR .. "src/mame/video/k001006.c",
|
||||
MAME_DIR .. "src/mame/video/k001005.c",
|
||||
MAME_DIR .. "src/mame/video/k001604.c",
|
||||
MAME_DIR .. "src/mame/video/k057714.c",
|
||||
}
|
||||
|
||||
createMAMEProjects(_target, _subtarget, "matic")
|
||||
|
@ -136,13 +136,10 @@
|
||||
#include "sound/ymz280b.h"
|
||||
#include "sound/cdda.h"
|
||||
#include "sound/rf5c400.h"
|
||||
#include "video/k057714.h"
|
||||
#include "firebeat.lh"
|
||||
|
||||
|
||||
#define DUMP_VRAM 0
|
||||
#define PRINT_GCU 0
|
||||
|
||||
|
||||
struct IBUTTON_SUBKEY
|
||||
{
|
||||
UINT8 identifier[8];
|
||||
@ -155,717 +152,6 @@ struct IBUTTON
|
||||
IBUTTON_SUBKEY subkey[3];
|
||||
};
|
||||
|
||||
#define MCFG_FIREBEAT_GCU_CPU_TAG(_tag) \
|
||||
firebeat_gcu_device::static_set_cpu_tag(*device, _tag);
|
||||
|
||||
class firebeat_gcu_device : public device_t
|
||||
{
|
||||
public:
|
||||
firebeat_gcu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
static void static_set_cpu_tag(device_t &device, const char *tag) { downcast<firebeat_gcu_device &>(device).m_cputag = tag; }
|
||||
|
||||
int draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
DECLARE_READ32_MEMBER(read);
|
||||
DECLARE_WRITE32_MEMBER(write);
|
||||
|
||||
struct framebuffer
|
||||
{
|
||||
UINT32 base;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual void device_start();
|
||||
virtual void device_stop();
|
||||
virtual void device_reset();
|
||||
|
||||
private:
|
||||
void execute_command(UINT32 *cmd);
|
||||
void execute_display_list(UINT32 addr);
|
||||
void draw_object(UINT32 *cmd);
|
||||
void fill_rect(UINT32 *cmd);
|
||||
void draw_character(UINT32 *cmd);
|
||||
void fb_config(UINT32 *cmd);
|
||||
|
||||
UINT32 *m_vram;
|
||||
UINT32 m_vram_read_addr;
|
||||
UINT32 m_vram_fifo0_addr;
|
||||
UINT32 m_vram_fifo1_addr;
|
||||
UINT32 m_vram_fifo0_mode;
|
||||
UINT32 m_vram_fifo1_mode;
|
||||
UINT32 m_command_fifo0[4];
|
||||
UINT32 m_command_fifo0_ptr;
|
||||
UINT32 m_command_fifo1[4];
|
||||
UINT32 m_command_fifo1_ptr;
|
||||
|
||||
const char* m_cputag;
|
||||
device_t* m_cpu;
|
||||
|
||||
framebuffer m_frame[4];
|
||||
UINT32 m_fb_origin_x;
|
||||
UINT32 m_fb_origin_y;
|
||||
};
|
||||
|
||||
const device_type FIREBEAT_GCU = &device_creator<firebeat_gcu_device>;
|
||||
|
||||
firebeat_gcu_device::firebeat_gcu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, FIREBEAT_GCU, "FireBeat GCU", tag, owner, clock, "firebeat_gcu", __FILE__)
|
||||
{
|
||||
}
|
||||
|
||||
READ32_MEMBER(firebeat_gcu_device::read)
|
||||
{
|
||||
int reg = offset * 4;
|
||||
|
||||
// VRAM Read
|
||||
if (reg >= 0x80 && reg < 0x100)
|
||||
{
|
||||
return m_vram[m_vram_read_addr + offset - 0x20];
|
||||
}
|
||||
|
||||
switch (reg)
|
||||
{
|
||||
case 0x78: // GCU Status
|
||||
/* ppd checks bits 0x0041 of the upper halfword on interrupt */
|
||||
return 0xffff0005;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(firebeat_gcu_device::write)
|
||||
{
|
||||
int reg = offset * 4;
|
||||
|
||||
switch (reg)
|
||||
{
|
||||
case 0x10:
|
||||
/* IRQ clear/enable; ppd writes bit off then on in response to interrupt */
|
||||
/* it enables bits 0x41, but 0x01 seems to be the one it cares about */
|
||||
if (ACCESSING_BITS_16_31 && (data & 0x00010000) == 0)
|
||||
m_cpu->execute().set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE);
|
||||
if (ACCESSING_BITS_0_15)
|
||||
#if PRINT_GCU
|
||||
printf("%s_w: %02X, %08X, %08X\n", basetag(), reg, data, mem_mask);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x14: // ?
|
||||
break;
|
||||
|
||||
case 0x18: // ?
|
||||
break;
|
||||
|
||||
case 0x20: // Framebuffer 0 Origin(?)
|
||||
break;
|
||||
|
||||
case 0x24: // Framebuffer 1 Origin(?)
|
||||
break;
|
||||
|
||||
case 0x28: // Framebuffer 2 Origin(?)
|
||||
break;
|
||||
|
||||
case 0x2c: // Framebuffer 3 Origin(?)
|
||||
break;
|
||||
|
||||
case 0x30: // Framebuffer 0 Dimensions
|
||||
if (ACCESSING_BITS_16_31)
|
||||
m_frame[0].height = (data >> 16) & 0xffff;
|
||||
if (ACCESSING_BITS_0_15)
|
||||
m_frame[0].width = data & 0xffff;
|
||||
break;
|
||||
|
||||
case 0x34: // Framebuffer 1 Dimensions
|
||||
if (ACCESSING_BITS_16_31)
|
||||
m_frame[1].height = (data >> 16) & 0xffff;
|
||||
if (ACCESSING_BITS_0_15)
|
||||
m_frame[1].width = data & 0xffff;
|
||||
break;
|
||||
|
||||
case 0x38: // Framebuffer 2 Dimensions
|
||||
if (ACCESSING_BITS_16_31)
|
||||
m_frame[2].height = (data >> 16) & 0xffff;
|
||||
if (ACCESSING_BITS_0_15)
|
||||
m_frame[2].width = data & 0xffff;
|
||||
break;
|
||||
|
||||
case 0x3c: // Framebuffer 3 Dimensions
|
||||
if (ACCESSING_BITS_16_31)
|
||||
m_frame[3].height = (data >> 16) & 0xffff;
|
||||
if (ACCESSING_BITS_0_15)
|
||||
m_frame[3].width = data & 0xffff;
|
||||
break;
|
||||
|
||||
case 0x40: // Framebuffer 0 Base
|
||||
m_frame[0].base = data;
|
||||
#if PRINT_GCU
|
||||
printf("%s FB0 Base: %08X\n", basetag(), data);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x44: // Framebuffer 1 Base
|
||||
m_frame[1].base = data;
|
||||
#if PRINT_GCU
|
||||
printf("%s FB1 Base: %08X\n", basetag(), data);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x48: // Framebuffer 2 Base
|
||||
m_frame[2].base = data;
|
||||
#if PRINT_GCU
|
||||
printf("%s FB2 Base: %08X\n", basetag(), data);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x4c: // Framebuffer 3 Base
|
||||
m_frame[3].base = data;
|
||||
#if PRINT_GCU
|
||||
printf("%s FB3 Base: %08X\n", basetag(), data);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x5c: // VRAM Read Address
|
||||
m_vram_read_addr = (data & 0xffffff) / 2;
|
||||
break;
|
||||
|
||||
case 0x60: // VRAM Port 0 Write Address
|
||||
m_vram_fifo0_addr = (data & 0xffffff) / 2;
|
||||
break;
|
||||
|
||||
case 0x68: // VRAM Port 0/1 Mode
|
||||
if (ACCESSING_BITS_16_31)
|
||||
m_vram_fifo0_mode = data >> 16;
|
||||
if (ACCESSING_BITS_0_15)
|
||||
m_vram_fifo1_mode = data & 0xffff;
|
||||
break;
|
||||
|
||||
case 0x70: // VRAM Port 0 Write FIFO
|
||||
if (m_vram_fifo0_mode & 0x100)
|
||||
{
|
||||
// write to command fifo
|
||||
m_command_fifo0[m_command_fifo0_ptr] = data;
|
||||
m_command_fifo0_ptr++;
|
||||
|
||||
// execute when filled
|
||||
if (m_command_fifo0_ptr >= 4)
|
||||
{
|
||||
//printf("GCU FIFO0 exec: %08X %08X %08X %08X\n", m_command_fifo0[0], m_command_fifo0[1], m_command_fifo0[2], m_command_fifo0[3]);
|
||||
execute_command(m_command_fifo0);
|
||||
m_command_fifo0_ptr = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// write to VRAM fifo
|
||||
m_vram[m_vram_fifo0_addr] = data;
|
||||
m_vram_fifo0_addr++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x64: // VRAM Port 1 Write Address
|
||||
m_vram_fifo1_addr = (data & 0xffffff) / 2;
|
||||
printf("GCU FIFO1 addr = %08X\n", data);
|
||||
break;
|
||||
|
||||
case 0x74: // VRAM Port 1 Write FIFO
|
||||
printf("GCU FIFO1 write = %08X\n", data);
|
||||
|
||||
if (m_vram_fifo1_mode & 0x100)
|
||||
{
|
||||
// write to command fifo
|
||||
m_command_fifo1[m_command_fifo1_ptr] = data;
|
||||
m_command_fifo1_ptr++;
|
||||
|
||||
// execute when filled
|
||||
if (m_command_fifo1_ptr >= 4)
|
||||
{
|
||||
printf("GCU FIFO1 exec: %08X %08X %08X %08X\n", m_command_fifo1[0], m_command_fifo1[1], m_command_fifo1[2], m_command_fifo1[3]);
|
||||
m_command_fifo1_ptr = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// write to VRAM fifo
|
||||
m_vram[m_vram_fifo1_addr] = data;
|
||||
m_vram_fifo1_addr++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
//printf("%s_w: %02X, %08X, %08X\n", basetag(), reg, data, mem_mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int firebeat_gcu_device::draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
UINT16 *vram16 = (UINT16*)m_vram;
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int width = m_frame[0].width;
|
||||
int height = m_frame[0].height;
|
||||
|
||||
if (width != 0 && height != 0)
|
||||
{
|
||||
rectangle visarea = screen.visible_area();
|
||||
if ((visarea.max_x+1) != width || (visarea.max_y+1) != height)
|
||||
{
|
||||
visarea.max_x = width-1;
|
||||
visarea.max_y = height-1;
|
||||
screen.configure(width, height, visarea, screen.frame_period().attoseconds);
|
||||
}
|
||||
}
|
||||
|
||||
int fb_pitch = 1024;
|
||||
|
||||
for (int j=0; j < height; j++)
|
||||
{
|
||||
UINT16 *d = &bitmap.pix16(j, x);
|
||||
int li = ((j+y) * fb_pitch) + x;
|
||||
UINT32 fbaddr0 = m_frame[0].base + li;
|
||||
UINT32 fbaddr1 = m_frame[1].base + li;
|
||||
// UINT32 fbaddr2 = m_frame[2].base + li;
|
||||
// UINT32 fbaddr3 = m_frame[3].base + li;
|
||||
|
||||
for (int i=0; i < width; i++)
|
||||
{
|
||||
UINT16 pix0 = vram16[fbaddr0 ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
|
||||
UINT16 pix1 = vram16[fbaddr1 ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
|
||||
// UINT16 pix2 = vram16[fbaddr2 ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
|
||||
// UINT16 pix3 = vram16[fbaddr3 ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
|
||||
|
||||
if (pix0 & 0x8000)
|
||||
{
|
||||
d[i] = pix0 & 0x7fff;
|
||||
}
|
||||
else
|
||||
{
|
||||
d[i] = pix1 & 0x7fff;
|
||||
}
|
||||
|
||||
fbaddr0++;
|
||||
fbaddr1++;
|
||||
// fbaddr2++;
|
||||
// fbaddr3++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void firebeat_gcu_device::draw_object(UINT32 *cmd)
|
||||
{
|
||||
// 0x00: xxx----- -------- -------- -------- command (5)
|
||||
// 0x00: ---x---- -------- -------- -------- 0: absolute coordinates
|
||||
// 1: relative coordinates from framebuffer origin
|
||||
// 0x00: ----xx-- -------- -------- -------- ?
|
||||
// 0x00: -------- xxxxxxxx xxxxxxxx xxxxxxxx object data address in vram
|
||||
|
||||
// 0x01: -------- -------- ------xx xxxxxxxx object x
|
||||
// 0x01: -------- xxxxxxxx xxxxxx-- -------- object y
|
||||
// 0x01: -----x-- -------- -------- -------- object x flip
|
||||
// 0x01: ----x--- -------- -------- -------- object y flip
|
||||
// 0x01: --xx---- -------- -------- -------- object alpha enable (different blend modes?)
|
||||
// 0x01: -x------ -------- -------- -------- object transparency enable (?)
|
||||
|
||||
// 0x02: -------- -------- ------xx xxxxxxxx object width
|
||||
// 0x02: -------- -----xxx xxxxxx-- -------- object x scale
|
||||
|
||||
// 0x03: -------- -------- ------xx xxxxxxxx object height
|
||||
// 0x03: -------- -----xxx xxxxxx-- -------- object y scale
|
||||
|
||||
int x = cmd[1] & 0x3ff;
|
||||
int y = (cmd[1] >> 10) & 0x3fff;
|
||||
int width = (cmd[2] & 0x3ff) + 1;
|
||||
int height = (cmd[3] & 0x3ff) + 1;
|
||||
int xscale = (cmd[2] >> 10) & 0x1ff;
|
||||
int yscale = (cmd[3] >> 10) & 0x1ff;
|
||||
bool xflip = (cmd[1] & 0x04000000) ? true : false;
|
||||
bool yflip = (cmd[1] & 0x08000000) ? true : false;
|
||||
bool alpha_enable = (cmd[1] & 0x30000000) ? true : false;
|
||||
bool trans_enable = (cmd[1] & 0x40000000) ? true : false;
|
||||
UINT32 address = cmd[0] & 0xffffff;
|
||||
int alpha_level = (cmd[2] >> 27) & 0x1f;
|
||||
bool relative_coords = (cmd[0] & 0x10000000) ? true : false;
|
||||
|
||||
if (relative_coords)
|
||||
{
|
||||
x += m_fb_origin_x;
|
||||
y += m_fb_origin_y;
|
||||
}
|
||||
|
||||
UINT16 *vram16 = (UINT16*)m_vram;
|
||||
|
||||
if (xscale == 0 || yscale == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if PRINT_GCU
|
||||
printf("%s Draw Object %08X, x %d, y %d, w %d, h %d [%08X %08X %08X %08X]\n", basetag(), address, x, y, width, height, cmd[0], cmd[1], cmd[2], cmd[3]);
|
||||
#endif
|
||||
|
||||
width = (((width * 65536) / xscale) * 64) / 65536;
|
||||
height = (((height * 65536) / yscale) * 64) / 65536;
|
||||
|
||||
int fb_pitch = 1024;
|
||||
|
||||
int v = 0;
|
||||
for (int j=0; j < height; j++)
|
||||
{
|
||||
int index;
|
||||
int xinc;
|
||||
UINT32 fbaddr = ((j+y) * fb_pitch) + x;
|
||||
|
||||
if (yflip)
|
||||
{
|
||||
index = address + ((height - 1 - (v >> 6)) * 1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
index = address + ((v >> 6) * 1024);
|
||||
}
|
||||
|
||||
if (xflip)
|
||||
{
|
||||
fbaddr += width;
|
||||
xinc = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
xinc = 1;
|
||||
}
|
||||
|
||||
int u = 0;
|
||||
for (int i=0; i < width; i++)
|
||||
{
|
||||
UINT16 pix = vram16[((index + (u >> 6)) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)) & 0xffffff];
|
||||
bool draw = !trans_enable || (trans_enable && (pix & 0x8000));
|
||||
if (alpha_enable)
|
||||
{
|
||||
if (draw)
|
||||
{
|
||||
if ((pix & 0x7fff) != 0)
|
||||
{
|
||||
UINT16 srcpix = vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
|
||||
|
||||
UINT32 sr = (srcpix >> 10) & 0x1f;
|
||||
UINT32 sg = (srcpix >> 5) & 0x1f;
|
||||
UINT32 sb = (srcpix >> 0) & 0x1f;
|
||||
UINT32 r = (pix >> 10) & 0x1f;
|
||||
UINT32 g = (pix >> 5) & 0x1f;
|
||||
UINT32 b = (pix >> 0) & 0x1f;
|
||||
|
||||
sr += (r * alpha_level) >> 4;
|
||||
sg += (g * alpha_level) >> 4;
|
||||
sb += (b * alpha_level) >> 4;
|
||||
|
||||
if (sr > 0x1f) sr = 0x1f;
|
||||
if (sg > 0x1f) sg = 0x1f;
|
||||
if (sb > 0x1f) sb = 0x1f;
|
||||
|
||||
vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = (sr << 10) | (sg << 5) | sb | 0x8000;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (draw)
|
||||
{
|
||||
vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = pix | 0x8000;
|
||||
}
|
||||
}
|
||||
|
||||
fbaddr += xinc;
|
||||
u += xscale;
|
||||
}
|
||||
|
||||
v += yscale;
|
||||
}
|
||||
}
|
||||
|
||||
void firebeat_gcu_device::fill_rect(UINT32 *cmd)
|
||||
{
|
||||
// 0x00: xxx----- -------- -------- -------- command (4)
|
||||
// 0x00: ---x---- -------- -------- -------- 0: absolute coordinates
|
||||
// 1: relative coordinates from framebuffer origin
|
||||
// 0x00: ----xx-- -------- -------- -------- ?
|
||||
// 0x00: -------- -------- ------xx xxxxxxxx width
|
||||
// 0x00: -------- ----xxxx xxxxxx-- -------- height
|
||||
|
||||
// 0x01: -------- -------- ------xx xxxxxxxx x
|
||||
// 0x01: -------- xxxxxxxx xxxxxx-- -------- y
|
||||
|
||||
// 0x02: xxxxxxxx xxxxxxxx -------- -------- fill pattern pixel 0
|
||||
// 0x02: -------- -------- xxxxxxxx xxxxxxxx fill pattern pixel 1
|
||||
|
||||
// 0x03: xxxxxxxx xxxxxxxx -------- -------- fill pattern pixel 2
|
||||
// 0x03: -------- -------- xxxxxxxx xxxxxxxx fill pattern pixel 3
|
||||
|
||||
int x = cmd[1] & 0x3ff;
|
||||
int y = (cmd[1] >> 10) & 0x3fff;
|
||||
int width = (cmd[0] & 0x3ff) + 1;
|
||||
int height = ((cmd[0] >> 10) & 0x3ff) + 1;
|
||||
bool relative_coords = (cmd[0] & 0x10000000) ? true : false;
|
||||
|
||||
if (relative_coords)
|
||||
{
|
||||
x += m_fb_origin_x;
|
||||
y += m_fb_origin_y;
|
||||
}
|
||||
|
||||
UINT16 color[4];
|
||||
color[0] = (cmd[2] >> 16);
|
||||
color[1] = (cmd[2] & 0xffff);
|
||||
color[2] = (cmd[3] >> 16);
|
||||
color[3] = (cmd[3] & 0xffff);
|
||||
|
||||
#if PRINT_GCU
|
||||
printf("%s Fill Rect x %d, y %d, w %d, h %d, %08X %08X [%08X %08X %08X %08X]\n", basetag(), x, y, width, height, cmd[2], cmd[3], cmd[0], cmd[1], cmd[2], cmd[3]);
|
||||
#endif
|
||||
|
||||
int x1 = x;
|
||||
int x2 = x + width;
|
||||
int y1 = y;
|
||||
int y2 = y + height;
|
||||
|
||||
UINT16 *vram16 = (UINT16*)m_vram;
|
||||
|
||||
int fb_pitch = 1024;
|
||||
|
||||
for (int j=y1; j < y2; j++)
|
||||
{
|
||||
UINT32 fbaddr = j * fb_pitch;
|
||||
for (int i=x1; i < x2; i++)
|
||||
{
|
||||
vram16[(fbaddr+i) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = color[i&3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void firebeat_gcu_device::draw_character(UINT32 *cmd)
|
||||
{
|
||||
// 0x00: xxx----- -------- -------- -------- command (7)
|
||||
// 0x00: ---x---- -------- -------- -------- 0: absolute coordinates
|
||||
// 1: relative coordinates from framebuffer base (unverified, should be same as other operations)
|
||||
// 0x00: -------- xxxxxxxx xxxxxxxx xxxxxxxx character data address in vram
|
||||
|
||||
// 0x01: -------- -------- ------xx xxxxxxxx character x
|
||||
// 0x01: -------- ----xxxx xxxxxx-- -------- character y
|
||||
|
||||
// 0x02: xxxxxxxx xxxxxxxx -------- -------- color 0
|
||||
// 0x02: -------- -------- xxxxxxxx xxxxxxxx color 1
|
||||
|
||||
// 0x03: xxxxxxxx xxxxxxxx -------- -------- color 2
|
||||
// 0x03: -------- -------- xxxxxxxx xxxxxxxx color 3
|
||||
|
||||
int x = cmd[1] & 0x3ff;
|
||||
int y = (cmd[1] >> 10) & 0x3ff;
|
||||
UINT32 address = cmd[0] & 0xffffff;
|
||||
UINT16 color[4];
|
||||
bool relative_coords = (cmd[0] & 0x10000000) ? true : false;
|
||||
|
||||
if (relative_coords)
|
||||
{
|
||||
x += m_fb_origin_x;
|
||||
y += m_fb_origin_y;
|
||||
}
|
||||
|
||||
color[0] = cmd[2] >> 16;
|
||||
color[1] = cmd[2] & 0xffff;
|
||||
color[2] = cmd[3] >> 16;
|
||||
color[3] = cmd[3] & 0xffff;
|
||||
|
||||
#if PRINT_GCU
|
||||
printf("%s Draw Char %08X, x %d, y %d\n", basetag(), address, x, y);
|
||||
#endif
|
||||
|
||||
UINT16 *vram16 = (UINT16*)m_vram;
|
||||
int fb_pitch = 1024;
|
||||
|
||||
for (int j=0; j < 8; j++)
|
||||
{
|
||||
UINT32 fbaddr = (y+j) * fb_pitch;
|
||||
UINT16 line = vram16[address ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
|
||||
|
||||
address += 4;
|
||||
|
||||
for (int i=0; i < 8; i++)
|
||||
{
|
||||
int p = (line >> ((7-i) * 2)) & 3;
|
||||
vram16[(fbaddr+x+i) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = color[p] | 0x8000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void firebeat_gcu_device::fb_config(UINT32 *cmd)
|
||||
{
|
||||
// 0x00: xxx----- -------- -------- -------- command (3)
|
||||
|
||||
// 0x01: -------- -------- -------- -------- unused?
|
||||
|
||||
// 0x02: -------- -------- ------xx xxxxxxxx Framebuffer Origin X
|
||||
|
||||
// 0x03: -------- -------- --xxxxxx xxxxxxxx Framebuffer Origin Y
|
||||
|
||||
#if PRINT_GCU
|
||||
printf("%s FB Config %08X %08X %08X %08X\n", basetag(), cmd[0], cmd[1], cmd[2], cmd[3]);
|
||||
#endif
|
||||
|
||||
m_fb_origin_x = cmd[2] & 0x3ff;
|
||||
m_fb_origin_y = cmd[3] & 0x3fff;
|
||||
}
|
||||
|
||||
void firebeat_gcu_device::execute_display_list(UINT32 addr)
|
||||
{
|
||||
bool end = false;
|
||||
|
||||
int counter = 0;
|
||||
|
||||
#if PRINT_GCU
|
||||
printf("%s Exec Display List %08X\n", basetag(), addr);
|
||||
#endif
|
||||
|
||||
addr /= 2;
|
||||
while (!end && counter < 0x1000 && addr < (0x2000000/4))
|
||||
{
|
||||
UINT32 *cmd = &m_vram[addr];
|
||||
addr += 4;
|
||||
|
||||
int command = (cmd[0] >> 29) & 0x7;
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case 0: // NOP?
|
||||
break;
|
||||
|
||||
case 1: // Execute display list
|
||||
execute_display_list(cmd[0] & 0xffffff);
|
||||
break;
|
||||
|
||||
case 2: // End of display list
|
||||
end = true;
|
||||
break;
|
||||
|
||||
case 3: // Framebuffer config
|
||||
fb_config(cmd);
|
||||
break;
|
||||
|
||||
case 4: // Fill rectangle
|
||||
fill_rect(cmd);
|
||||
break;
|
||||
|
||||
case 5: // Draw object
|
||||
draw_object(cmd);
|
||||
break;
|
||||
|
||||
case 7: // Draw 8x8 character (2 bits per pixel)
|
||||
draw_character(cmd);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("GCU Unknown command %08X %08X %08X %08X\n", cmd[0], cmd[1], cmd[2], cmd[3]);
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
};
|
||||
}
|
||||
|
||||
void firebeat_gcu_device::execute_command(UINT32* cmd)
|
||||
{
|
||||
int command = (cmd[0] >> 29) & 0x7;
|
||||
|
||||
#if PRINT_GCU
|
||||
printf("%s Exec Command %08X, %08X, %08X, %08X\n", basetag(), cmd[0], cmd[1], cmd[2], cmd[3]);
|
||||
#endif
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case 0: // NOP?
|
||||
break;
|
||||
|
||||
case 1: // Execute display list
|
||||
execute_display_list(cmd[0] & 0xffffff);
|
||||
break;
|
||||
|
||||
case 2: // End of display list
|
||||
break;
|
||||
|
||||
case 3: // Framebuffer config
|
||||
fb_config(cmd);
|
||||
break;
|
||||
|
||||
case 4: // Fill rectangle
|
||||
fill_rect(cmd);
|
||||
break;
|
||||
|
||||
case 5: // Draw object
|
||||
draw_object(cmd);
|
||||
break;
|
||||
|
||||
case 7: // Draw 8x8 character (2 bits per pixel)
|
||||
draw_character(cmd);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("GCU Unknown command %08X %08X %08X %08X\n", cmd[0], cmd[1], cmd[2], cmd[3]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void firebeat_gcu_device::device_start()
|
||||
{
|
||||
m_cpu = machine().device(m_cputag);
|
||||
|
||||
m_vram = auto_alloc_array(machine(), UINT32, 0x2000000/4);
|
||||
memset(m_vram, 0, 0x2000000);
|
||||
}
|
||||
|
||||
void firebeat_gcu_device::device_reset()
|
||||
{
|
||||
m_vram_read_addr = 0;
|
||||
m_command_fifo0_ptr = 0;
|
||||
m_command_fifo1_ptr = 0;
|
||||
m_vram_fifo0_addr = 0;
|
||||
m_vram_fifo1_addr = 0;
|
||||
|
||||
for (int i=0; i < 4; i++)
|
||||
{
|
||||
m_frame[i].base = 0;
|
||||
m_frame[i].width = 0;
|
||||
m_frame[i].height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void firebeat_gcu_device::device_stop()
|
||||
{
|
||||
#if DUMP_VRAM
|
||||
char filename[200];
|
||||
sprintf(filename, "%s_vram.bin", basetag());
|
||||
printf("dumping %s\n", filename);
|
||||
FILE *file = fopen(filename, "wb");
|
||||
int i;
|
||||
|
||||
for (i=0; i < 0x2000000/4; i++)
|
||||
{
|
||||
fputc((m_vram[i] >> 24) & 0xff, file);
|
||||
fputc((m_vram[i] >> 16) & 0xff, file);
|
||||
fputc((m_vram[i] >> 8) & 0xff, file);
|
||||
fputc((m_vram[i] >> 0) & 0xff, file);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define PRINT_SPU_MEM 0
|
||||
|
||||
@ -901,8 +187,8 @@ public:
|
||||
optional_device<midi_keyboard_device> m_kbd0;
|
||||
optional_device<midi_keyboard_device> m_kbd1;
|
||||
required_device<ata_interface_device> m_ata;
|
||||
required_device<firebeat_gcu_device> m_gcu0;
|
||||
required_device<firebeat_gcu_device> m_gcu1;
|
||||
required_device<k057714_device> m_gcu0;
|
||||
required_device<k057714_device> m_gcu1;
|
||||
optional_device<ata_interface_device> m_spuata;
|
||||
|
||||
UINT8 m_extend_board_irq_enable;
|
||||
@ -1758,8 +1044,8 @@ static ADDRESS_MAP_START( firebeat_map, AS_PROGRAM, 32, firebeat_state )
|
||||
AM_RANGE(0x7dc00000, 0x7dc0000f) AM_DEVREADWRITE8("duart_com", pc16552_device, read, write, 0xffffffff)
|
||||
AM_RANGE(0x7e000000, 0x7e00003f) AM_DEVREADWRITE8("rtc", rtc65271_device, rtc_r, rtc_w, 0xffffffff)
|
||||
AM_RANGE(0x7e000100, 0x7e00013f) AM_DEVREADWRITE8("rtc", rtc65271_device, xram_r, xram_w, 0xffffffff)
|
||||
AM_RANGE(0x7e800000, 0x7e8000ff) AM_DEVREADWRITE("gcu0", firebeat_gcu_device, read, write)
|
||||
AM_RANGE(0x7e800100, 0x7e8001ff) AM_DEVREADWRITE("gcu1", firebeat_gcu_device, read, write)
|
||||
AM_RANGE(0x7e800000, 0x7e8000ff) AM_DEVREADWRITE("gcu0", k057714_device, read, write)
|
||||
AM_RANGE(0x7e800100, 0x7e8001ff) AM_DEVREADWRITE("gcu1", k057714_device, read, write)
|
||||
AM_RANGE(0x7fe00000, 0x7fe0000f) AM_READWRITE(ata_command_r, ata_command_w)
|
||||
AM_RANGE(0x7fe80000, 0x7fe8000f) AM_READWRITE(ata_control_r, ata_control_w)
|
||||
AM_RANGE(0x7ff80000, 0x7fffffff) AM_ROM AM_REGION("user1", 0) /* System BIOS */
|
||||
@ -1984,11 +1270,11 @@ static MACHINE_CONFIG_START( firebeat, firebeat_state )
|
||||
/* video hardware */
|
||||
MCFG_PALETTE_ADD_RRRRRGGGGGBBBBB("palette")
|
||||
|
||||
MCFG_DEVICE_ADD("gcu0", FIREBEAT_GCU, 0)
|
||||
MCFG_FIREBEAT_GCU_CPU_TAG("maincpu")
|
||||
MCFG_DEVICE_ADD("gcu0", K057714, 0)
|
||||
MCFG_K057714_CPU_TAG("maincpu")
|
||||
|
||||
MCFG_DEVICE_ADD("gcu1", FIREBEAT_GCU, 0)
|
||||
MCFG_FIREBEAT_GCU_CPU_TAG("maincpu")
|
||||
MCFG_DEVICE_ADD("gcu1", K057714, 0)
|
||||
MCFG_K057714_CPU_TAG("maincpu")
|
||||
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
MCFG_SCREEN_REFRESH_RATE(60)
|
||||
@ -2044,11 +1330,11 @@ static MACHINE_CONFIG_START( firebeat2, firebeat_state )
|
||||
/* video hardware */
|
||||
MCFG_PALETTE_ADD_RRRRRGGGGGBBBBB("palette")
|
||||
|
||||
MCFG_DEVICE_ADD("gcu0", FIREBEAT_GCU, 0)
|
||||
MCFG_FIREBEAT_GCU_CPU_TAG("maincpu")
|
||||
MCFG_DEVICE_ADD("gcu0", K057714, 0)
|
||||
MCFG_K057714_CPU_TAG("maincpu")
|
||||
|
||||
MCFG_DEVICE_ADD("gcu1", FIREBEAT_GCU, 0)
|
||||
MCFG_FIREBEAT_GCU_CPU_TAG("maincpu")
|
||||
MCFG_DEVICE_ADD("gcu1", K057714, 0)
|
||||
MCFG_K057714_CPU_TAG("maincpu")
|
||||
|
||||
MCFG_SCREEN_ADD("lscreen", RASTER)
|
||||
MCFG_SCREEN_REFRESH_RATE(60)
|
||||
|
669
src/mame/video/k057714.c
Normal file
669
src/mame/video/k057714.c
Normal file
@ -0,0 +1,669 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ville Linde
|
||||
|
||||
// Konami 0000057714 "GCU" 2D Graphics Chip
|
||||
|
||||
#include "emu.h"
|
||||
#include "k057714.h"
|
||||
|
||||
|
||||
#define DUMP_VRAM 0
|
||||
#define PRINT_GCU 0
|
||||
|
||||
|
||||
const device_type K057714 = &device_creator<k057714_device>;
|
||||
|
||||
k057714_device::k057714_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, K057714, "K057714 GCU", tag, owner, clock, "k057714", __FILE__)
|
||||
{
|
||||
}
|
||||
|
||||
void k057714_device::device_start()
|
||||
{
|
||||
m_cpu = machine().device(m_cputag);
|
||||
|
||||
m_vram = auto_alloc_array(machine(), UINT32, 0x2000000/4);
|
||||
memset(m_vram, 0, 0x2000000);
|
||||
}
|
||||
|
||||
void k057714_device::device_reset()
|
||||
{
|
||||
m_vram_read_addr = 0;
|
||||
m_command_fifo0_ptr = 0;
|
||||
m_command_fifo1_ptr = 0;
|
||||
m_vram_fifo0_addr = 0;
|
||||
m_vram_fifo1_addr = 0;
|
||||
|
||||
for (int i=0; i < 4; i++)
|
||||
{
|
||||
m_frame[i].base = 0;
|
||||
m_frame[i].width = 0;
|
||||
m_frame[i].height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void k057714_device::device_stop()
|
||||
{
|
||||
#if DUMP_VRAM
|
||||
char filename[200];
|
||||
sprintf(filename, "%s_vram.bin", basetag());
|
||||
printf("dumping %s\n", filename);
|
||||
FILE *file = fopen(filename, "wb");
|
||||
int i;
|
||||
|
||||
for (i=0; i < 0x2000000/4; i++)
|
||||
{
|
||||
fputc((m_vram[i] >> 24) & 0xff, file);
|
||||
fputc((m_vram[i] >> 16) & 0xff, file);
|
||||
fputc((m_vram[i] >> 8) & 0xff, file);
|
||||
fputc((m_vram[i] >> 0) & 0xff, file);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
READ32_MEMBER(k057714_device::read)
|
||||
{
|
||||
int reg = offset * 4;
|
||||
|
||||
// VRAM Read
|
||||
if (reg >= 0x80 && reg < 0x100)
|
||||
{
|
||||
return m_vram[m_vram_read_addr + offset - 0x20];
|
||||
}
|
||||
|
||||
switch (reg)
|
||||
{
|
||||
case 0x78: // GCU Status
|
||||
/* ppd checks bits 0x0041 of the upper halfword on interrupt */
|
||||
return 0xffff0005;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(k057714_device::write)
|
||||
{
|
||||
int reg = offset * 4;
|
||||
|
||||
switch (reg)
|
||||
{
|
||||
case 0x10:
|
||||
/* IRQ clear/enable; ppd writes bit off then on in response to interrupt */
|
||||
/* it enables bits 0x41, but 0x01 seems to be the one it cares about */
|
||||
if (ACCESSING_BITS_16_31 && (data & 0x00010000) == 0)
|
||||
m_cpu->execute().set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE);
|
||||
if (ACCESSING_BITS_0_15)
|
||||
#if PRINT_GCU
|
||||
printf("%s_w: %02X, %08X, %08X\n", basetag(), reg, data, mem_mask);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x14: // ?
|
||||
break;
|
||||
|
||||
case 0x18: // ?
|
||||
break;
|
||||
|
||||
case 0x20: // Framebuffer 0 Origin(?)
|
||||
break;
|
||||
|
||||
case 0x24: // Framebuffer 1 Origin(?)
|
||||
break;
|
||||
|
||||
case 0x28: // Framebuffer 2 Origin(?)
|
||||
break;
|
||||
|
||||
case 0x2c: // Framebuffer 3 Origin(?)
|
||||
break;
|
||||
|
||||
case 0x30: // Framebuffer 0 Dimensions
|
||||
if (ACCESSING_BITS_16_31)
|
||||
m_frame[0].height = (data >> 16) & 0xffff;
|
||||
if (ACCESSING_BITS_0_15)
|
||||
m_frame[0].width = data & 0xffff;
|
||||
break;
|
||||
|
||||
case 0x34: // Framebuffer 1 Dimensions
|
||||
if (ACCESSING_BITS_16_31)
|
||||
m_frame[1].height = (data >> 16) & 0xffff;
|
||||
if (ACCESSING_BITS_0_15)
|
||||
m_frame[1].width = data & 0xffff;
|
||||
break;
|
||||
|
||||
case 0x38: // Framebuffer 2 Dimensions
|
||||
if (ACCESSING_BITS_16_31)
|
||||
m_frame[2].height = (data >> 16) & 0xffff;
|
||||
if (ACCESSING_BITS_0_15)
|
||||
m_frame[2].width = data & 0xffff;
|
||||
break;
|
||||
|
||||
case 0x3c: // Framebuffer 3 Dimensions
|
||||
if (ACCESSING_BITS_16_31)
|
||||
m_frame[3].height = (data >> 16) & 0xffff;
|
||||
if (ACCESSING_BITS_0_15)
|
||||
m_frame[3].width = data & 0xffff;
|
||||
break;
|
||||
|
||||
case 0x40: // Framebuffer 0 Base
|
||||
m_frame[0].base = data;
|
||||
#if PRINT_GCU
|
||||
printf("%s FB0 Base: %08X\n", basetag(), data);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x44: // Framebuffer 1 Base
|
||||
m_frame[1].base = data;
|
||||
#if PRINT_GCU
|
||||
printf("%s FB1 Base: %08X\n", basetag(), data);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x48: // Framebuffer 2 Base
|
||||
m_frame[2].base = data;
|
||||
#if PRINT_GCU
|
||||
printf("%s FB2 Base: %08X\n", basetag(), data);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x4c: // Framebuffer 3 Base
|
||||
m_frame[3].base = data;
|
||||
#if PRINT_GCU
|
||||
printf("%s FB3 Base: %08X\n", basetag(), data);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x5c: // VRAM Read Address
|
||||
m_vram_read_addr = (data & 0xffffff) / 2;
|
||||
break;
|
||||
|
||||
case 0x60: // VRAM Port 0 Write Address
|
||||
m_vram_fifo0_addr = (data & 0xffffff) / 2;
|
||||
break;
|
||||
|
||||
case 0x68: // VRAM Port 0/1 Mode
|
||||
if (ACCESSING_BITS_16_31)
|
||||
m_vram_fifo0_mode = data >> 16;
|
||||
if (ACCESSING_BITS_0_15)
|
||||
m_vram_fifo1_mode = data & 0xffff;
|
||||
break;
|
||||
|
||||
case 0x70: // VRAM Port 0 Write FIFO
|
||||
if (m_vram_fifo0_mode & 0x100)
|
||||
{
|
||||
// write to command fifo
|
||||
m_command_fifo0[m_command_fifo0_ptr] = data;
|
||||
m_command_fifo0_ptr++;
|
||||
|
||||
// execute when filled
|
||||
if (m_command_fifo0_ptr >= 4)
|
||||
{
|
||||
//printf("GCU FIFO0 exec: %08X %08X %08X %08X\n", m_command_fifo0[0], m_command_fifo0[1], m_command_fifo0[2], m_command_fifo0[3]);
|
||||
execute_command(m_command_fifo0);
|
||||
m_command_fifo0_ptr = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// write to VRAM fifo
|
||||
m_vram[m_vram_fifo0_addr] = data;
|
||||
m_vram_fifo0_addr++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x64: // VRAM Port 1 Write Address
|
||||
m_vram_fifo1_addr = (data & 0xffffff) / 2;
|
||||
printf("GCU FIFO1 addr = %08X\n", data);
|
||||
break;
|
||||
|
||||
case 0x74: // VRAM Port 1 Write FIFO
|
||||
printf("GCU FIFO1 write = %08X\n", data);
|
||||
|
||||
if (m_vram_fifo1_mode & 0x100)
|
||||
{
|
||||
// write to command fifo
|
||||
m_command_fifo1[m_command_fifo1_ptr] = data;
|
||||
m_command_fifo1_ptr++;
|
||||
|
||||
// execute when filled
|
||||
if (m_command_fifo1_ptr >= 4)
|
||||
{
|
||||
printf("GCU FIFO1 exec: %08X %08X %08X %08X\n", m_command_fifo1[0], m_command_fifo1[1], m_command_fifo1[2], m_command_fifo1[3]);
|
||||
m_command_fifo1_ptr = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// write to VRAM fifo
|
||||
m_vram[m_vram_fifo1_addr] = data;
|
||||
m_vram_fifo1_addr++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
//printf("%s_w: %02X, %08X, %08X\n", basetag(), reg, data, mem_mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int k057714_device::draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
UINT16 *vram16 = (UINT16*)m_vram;
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int width = m_frame[0].width;
|
||||
int height = m_frame[0].height;
|
||||
|
||||
if (width != 0 && height != 0)
|
||||
{
|
||||
rectangle visarea = screen.visible_area();
|
||||
if ((visarea.max_x+1) != width || (visarea.max_y+1) != height)
|
||||
{
|
||||
visarea.max_x = width-1;
|
||||
visarea.max_y = height-1;
|
||||
screen.configure(width, height, visarea, screen.frame_period().attoseconds);
|
||||
}
|
||||
}
|
||||
|
||||
int fb_pitch = 1024;
|
||||
|
||||
for (int j=0; j < height; j++)
|
||||
{
|
||||
UINT16 *d = &bitmap.pix16(j, x);
|
||||
int li = ((j+y) * fb_pitch) + x;
|
||||
UINT32 fbaddr0 = m_frame[0].base + li;
|
||||
UINT32 fbaddr1 = m_frame[1].base + li;
|
||||
// UINT32 fbaddr2 = m_frame[2].base + li;
|
||||
// UINT32 fbaddr3 = m_frame[3].base + li;
|
||||
|
||||
for (int i=0; i < width; i++)
|
||||
{
|
||||
UINT16 pix0 = vram16[fbaddr0 ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
|
||||
UINT16 pix1 = vram16[fbaddr1 ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
|
||||
// UINT16 pix2 = vram16[fbaddr2 ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
|
||||
// UINT16 pix3 = vram16[fbaddr3 ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
|
||||
|
||||
if (pix0 & 0x8000)
|
||||
{
|
||||
d[i] = pix0 & 0x7fff;
|
||||
}
|
||||
else
|
||||
{
|
||||
d[i] = pix1 & 0x7fff;
|
||||
}
|
||||
|
||||
fbaddr0++;
|
||||
fbaddr1++;
|
||||
// fbaddr2++;
|
||||
// fbaddr3++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void k057714_device::draw_object(UINT32 *cmd)
|
||||
{
|
||||
// 0x00: xxx----- -------- -------- -------- command (5)
|
||||
// 0x00: ---x---- -------- -------- -------- 0: absolute coordinates
|
||||
// 1: relative coordinates from framebuffer origin
|
||||
// 0x00: ----xx-- -------- -------- -------- ?
|
||||
// 0x00: -------- xxxxxxxx xxxxxxxx xxxxxxxx object data address in vram
|
||||
|
||||
// 0x01: -------- -------- ------xx xxxxxxxx object x
|
||||
// 0x01: -------- xxxxxxxx xxxxxx-- -------- object y
|
||||
// 0x01: -----x-- -------- -------- -------- object x flip
|
||||
// 0x01: ----x--- -------- -------- -------- object y flip
|
||||
// 0x01: --xx---- -------- -------- -------- object alpha enable (different blend modes?)
|
||||
// 0x01: -x------ -------- -------- -------- object transparency enable (?)
|
||||
|
||||
// 0x02: -------- -------- ------xx xxxxxxxx object width
|
||||
// 0x02: -------- -----xxx xxxxxx-- -------- object x scale
|
||||
|
||||
// 0x03: -------- -------- ------xx xxxxxxxx object height
|
||||
// 0x03: -------- -----xxx xxxxxx-- -------- object y scale
|
||||
|
||||
int x = cmd[1] & 0x3ff;
|
||||
int y = (cmd[1] >> 10) & 0x3fff;
|
||||
int width = (cmd[2] & 0x3ff) + 1;
|
||||
int height = (cmd[3] & 0x3ff) + 1;
|
||||
int xscale = (cmd[2] >> 10) & 0x1ff;
|
||||
int yscale = (cmd[3] >> 10) & 0x1ff;
|
||||
bool xflip = (cmd[1] & 0x04000000) ? true : false;
|
||||
bool yflip = (cmd[1] & 0x08000000) ? true : false;
|
||||
bool alpha_enable = (cmd[1] & 0x30000000) ? true : false;
|
||||
bool trans_enable = (cmd[1] & 0x40000000) ? true : false;
|
||||
UINT32 address = cmd[0] & 0xffffff;
|
||||
int alpha_level = (cmd[2] >> 27) & 0x1f;
|
||||
bool relative_coords = (cmd[0] & 0x10000000) ? true : false;
|
||||
|
||||
if (relative_coords)
|
||||
{
|
||||
x += m_fb_origin_x;
|
||||
y += m_fb_origin_y;
|
||||
}
|
||||
|
||||
UINT16 *vram16 = (UINT16*)m_vram;
|
||||
|
||||
if (xscale == 0 || yscale == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if PRINT_GCU
|
||||
printf("%s Draw Object %08X, x %d, y %d, w %d, h %d [%08X %08X %08X %08X]\n", basetag(), address, x, y, width, height, cmd[0], cmd[1], cmd[2], cmd[3]);
|
||||
#endif
|
||||
|
||||
width = (((width * 65536) / xscale) * 64) / 65536;
|
||||
height = (((height * 65536) / yscale) * 64) / 65536;
|
||||
|
||||
int fb_pitch = 1024;
|
||||
|
||||
int v = 0;
|
||||
for (int j=0; j < height; j++)
|
||||
{
|
||||
int index;
|
||||
int xinc;
|
||||
UINT32 fbaddr = ((j+y) * fb_pitch) + x;
|
||||
|
||||
if (yflip)
|
||||
{
|
||||
index = address + ((height - 1 - (v >> 6)) * 1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
index = address + ((v >> 6) * 1024);
|
||||
}
|
||||
|
||||
if (xflip)
|
||||
{
|
||||
fbaddr += width;
|
||||
xinc = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
xinc = 1;
|
||||
}
|
||||
|
||||
int u = 0;
|
||||
for (int i=0; i < width; i++)
|
||||
{
|
||||
UINT16 pix = vram16[((index + (u >> 6)) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)) & 0xffffff];
|
||||
bool draw = !trans_enable || (trans_enable && (pix & 0x8000));
|
||||
if (alpha_enable)
|
||||
{
|
||||
if (draw)
|
||||
{
|
||||
if ((pix & 0x7fff) != 0)
|
||||
{
|
||||
UINT16 srcpix = vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
|
||||
|
||||
UINT32 sr = (srcpix >> 10) & 0x1f;
|
||||
UINT32 sg = (srcpix >> 5) & 0x1f;
|
||||
UINT32 sb = (srcpix >> 0) & 0x1f;
|
||||
UINT32 r = (pix >> 10) & 0x1f;
|
||||
UINT32 g = (pix >> 5) & 0x1f;
|
||||
UINT32 b = (pix >> 0) & 0x1f;
|
||||
|
||||
sr += (r * alpha_level) >> 4;
|
||||
sg += (g * alpha_level) >> 4;
|
||||
sb += (b * alpha_level) >> 4;
|
||||
|
||||
if (sr > 0x1f) sr = 0x1f;
|
||||
if (sg > 0x1f) sg = 0x1f;
|
||||
if (sb > 0x1f) sb = 0x1f;
|
||||
|
||||
vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = (sr << 10) | (sg << 5) | sb | 0x8000;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (draw)
|
||||
{
|
||||
vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = pix | 0x8000;
|
||||
}
|
||||
}
|
||||
|
||||
fbaddr += xinc;
|
||||
u += xscale;
|
||||
}
|
||||
|
||||
v += yscale;
|
||||
}
|
||||
}
|
||||
|
||||
void k057714_device::fill_rect(UINT32 *cmd)
|
||||
{
|
||||
// 0x00: xxx----- -------- -------- -------- command (4)
|
||||
// 0x00: ---x---- -------- -------- -------- 0: absolute coordinates
|
||||
// 1: relative coordinates from framebuffer origin
|
||||
// 0x00: ----xx-- -------- -------- -------- ?
|
||||
// 0x00: -------- -------- ------xx xxxxxxxx width
|
||||
// 0x00: -------- ----xxxx xxxxxx-- -------- height
|
||||
|
||||
// 0x01: -------- -------- ------xx xxxxxxxx x
|
||||
// 0x01: -------- xxxxxxxx xxxxxx-- -------- y
|
||||
|
||||
// 0x02: xxxxxxxx xxxxxxxx -------- -------- fill pattern pixel 0
|
||||
// 0x02: -------- -------- xxxxxxxx xxxxxxxx fill pattern pixel 1
|
||||
|
||||
// 0x03: xxxxxxxx xxxxxxxx -------- -------- fill pattern pixel 2
|
||||
// 0x03: -------- -------- xxxxxxxx xxxxxxxx fill pattern pixel 3
|
||||
|
||||
int x = cmd[1] & 0x3ff;
|
||||
int y = (cmd[1] >> 10) & 0x3fff;
|
||||
int width = (cmd[0] & 0x3ff) + 1;
|
||||
int height = ((cmd[0] >> 10) & 0x3ff) + 1;
|
||||
bool relative_coords = (cmd[0] & 0x10000000) ? true : false;
|
||||
|
||||
if (relative_coords)
|
||||
{
|
||||
x += m_fb_origin_x;
|
||||
y += m_fb_origin_y;
|
||||
}
|
||||
|
||||
UINT16 color[4];
|
||||
color[0] = (cmd[2] >> 16);
|
||||
color[1] = (cmd[2] & 0xffff);
|
||||
color[2] = (cmd[3] >> 16);
|
||||
color[3] = (cmd[3] & 0xffff);
|
||||
|
||||
#if PRINT_GCU
|
||||
printf("%s Fill Rect x %d, y %d, w %d, h %d, %08X %08X [%08X %08X %08X %08X]\n", basetag(), x, y, width, height, cmd[2], cmd[3], cmd[0], cmd[1], cmd[2], cmd[3]);
|
||||
#endif
|
||||
|
||||
int x1 = x;
|
||||
int x2 = x + width;
|
||||
int y1 = y;
|
||||
int y2 = y + height;
|
||||
|
||||
UINT16 *vram16 = (UINT16*)m_vram;
|
||||
|
||||
int fb_pitch = 1024;
|
||||
|
||||
for (int j=y1; j < y2; j++)
|
||||
{
|
||||
UINT32 fbaddr = j * fb_pitch;
|
||||
for (int i=x1; i < x2; i++)
|
||||
{
|
||||
vram16[(fbaddr+i) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = color[i&3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void k057714_device::draw_character(UINT32 *cmd)
|
||||
{
|
||||
// 0x00: xxx----- -------- -------- -------- command (7)
|
||||
// 0x00: ---x---- -------- -------- -------- 0: absolute coordinates
|
||||
// 1: relative coordinates from framebuffer base (unverified, should be same as other operations)
|
||||
// 0x00: -------- xxxxxxxx xxxxxxxx xxxxxxxx character data address in vram
|
||||
|
||||
// 0x01: -------- -------- ------xx xxxxxxxx character x
|
||||
// 0x01: -------- ----xxxx xxxxxx-- -------- character y
|
||||
|
||||
// 0x02: xxxxxxxx xxxxxxxx -------- -------- color 0
|
||||
// 0x02: -------- -------- xxxxxxxx xxxxxxxx color 1
|
||||
|
||||
// 0x03: xxxxxxxx xxxxxxxx -------- -------- color 2
|
||||
// 0x03: -------- -------- xxxxxxxx xxxxxxxx color 3
|
||||
|
||||
int x = cmd[1] & 0x3ff;
|
||||
int y = (cmd[1] >> 10) & 0x3ff;
|
||||
UINT32 address = cmd[0] & 0xffffff;
|
||||
UINT16 color[4];
|
||||
bool relative_coords = (cmd[0] & 0x10000000) ? true : false;
|
||||
|
||||
if (relative_coords)
|
||||
{
|
||||
x += m_fb_origin_x;
|
||||
y += m_fb_origin_y;
|
||||
}
|
||||
|
||||
color[0] = cmd[2] >> 16;
|
||||
color[1] = cmd[2] & 0xffff;
|
||||
color[2] = cmd[3] >> 16;
|
||||
color[3] = cmd[3] & 0xffff;
|
||||
|
||||
#if PRINT_GCU
|
||||
printf("%s Draw Char %08X, x %d, y %d\n", basetag(), address, x, y);
|
||||
#endif
|
||||
|
||||
UINT16 *vram16 = (UINT16*)m_vram;
|
||||
int fb_pitch = 1024;
|
||||
|
||||
for (int j=0; j < 8; j++)
|
||||
{
|
||||
UINT32 fbaddr = (y+j) * fb_pitch;
|
||||
UINT16 line = vram16[address ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
|
||||
|
||||
address += 4;
|
||||
|
||||
for (int i=0; i < 8; i++)
|
||||
{
|
||||
int p = (line >> ((7-i) * 2)) & 3;
|
||||
vram16[(fbaddr+x+i) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = color[p] | 0x8000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void k057714_device::fb_config(UINT32 *cmd)
|
||||
{
|
||||
// 0x00: xxx----- -------- -------- -------- command (3)
|
||||
|
||||
// 0x01: -------- -------- -------- -------- unused?
|
||||
|
||||
// 0x02: -------- -------- ------xx xxxxxxxx Framebuffer Origin X
|
||||
|
||||
// 0x03: -------- -------- --xxxxxx xxxxxxxx Framebuffer Origin Y
|
||||
|
||||
#if PRINT_GCU
|
||||
printf("%s FB Config %08X %08X %08X %08X\n", basetag(), cmd[0], cmd[1], cmd[2], cmd[3]);
|
||||
#endif
|
||||
|
||||
m_fb_origin_x = cmd[2] & 0x3ff;
|
||||
m_fb_origin_y = cmd[3] & 0x3fff;
|
||||
}
|
||||
|
||||
void k057714_device::execute_display_list(UINT32 addr)
|
||||
{
|
||||
bool end = false;
|
||||
|
||||
int counter = 0;
|
||||
|
||||
#if PRINT_GCU
|
||||
printf("%s Exec Display List %08X\n", basetag(), addr);
|
||||
#endif
|
||||
|
||||
addr /= 2;
|
||||
while (!end && counter < 0x1000 && addr < (0x2000000/4))
|
||||
{
|
||||
UINT32 *cmd = &m_vram[addr];
|
||||
addr += 4;
|
||||
|
||||
int command = (cmd[0] >> 29) & 0x7;
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case 0: // NOP?
|
||||
break;
|
||||
|
||||
case 1: // Execute display list
|
||||
execute_display_list(cmd[0] & 0xffffff);
|
||||
break;
|
||||
|
||||
case 2: // End of display list
|
||||
end = true;
|
||||
break;
|
||||
|
||||
case 3: // Framebuffer config
|
||||
fb_config(cmd);
|
||||
break;
|
||||
|
||||
case 4: // Fill rectangle
|
||||
fill_rect(cmd);
|
||||
break;
|
||||
|
||||
case 5: // Draw object
|
||||
draw_object(cmd);
|
||||
break;
|
||||
|
||||
case 7: // Draw 8x8 character (2 bits per pixel)
|
||||
draw_character(cmd);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("GCU Unknown command %08X %08X %08X %08X\n", cmd[0], cmd[1], cmd[2], cmd[3]);
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
};
|
||||
}
|
||||
|
||||
void k057714_device::execute_command(UINT32* cmd)
|
||||
{
|
||||
int command = (cmd[0] >> 29) & 0x7;
|
||||
|
||||
#if PRINT_GCU
|
||||
printf("%s Exec Command %08X, %08X, %08X, %08X\n", basetag(), cmd[0], cmd[1], cmd[2], cmd[3]);
|
||||
#endif
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case 0: // NOP?
|
||||
break;
|
||||
|
||||
case 1: // Execute display list
|
||||
execute_display_list(cmd[0] & 0xffffff);
|
||||
break;
|
||||
|
||||
case 2: // End of display list
|
||||
break;
|
||||
|
||||
case 3: // Framebuffer config
|
||||
fb_config(cmd);
|
||||
break;
|
||||
|
||||
case 4: // Fill rectangle
|
||||
fill_rect(cmd);
|
||||
break;
|
||||
|
||||
case 5: // Draw object
|
||||
draw_object(cmd);
|
||||
break;
|
||||
|
||||
case 7: // Draw 8x8 character (2 bits per pixel)
|
||||
draw_character(cmd);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("GCU Unknown command %08X %08X %08X %08X\n", cmd[0], cmd[1], cmd[2], cmd[3]);
|
||||
break;
|
||||
}
|
||||
}
|
63
src/mame/video/k057714.h
Normal file
63
src/mame/video/k057714.h
Normal file
@ -0,0 +1,63 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ville Linde
|
||||
|
||||
#pragma once
|
||||
#ifndef __K057714_H__
|
||||
#define __K057714_H__
|
||||
|
||||
class k057714_device : public device_t
|
||||
{
|
||||
public:
|
||||
k057714_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
static void static_set_cpu_tag(device_t &device, const char *tag) { downcast<k057714_device &>(device).m_cputag = tag; }
|
||||
|
||||
int draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
DECLARE_READ32_MEMBER(read);
|
||||
DECLARE_WRITE32_MEMBER(write);
|
||||
|
||||
struct framebuffer
|
||||
{
|
||||
UINT32 base;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual void device_start();
|
||||
virtual void device_stop();
|
||||
virtual void device_reset();
|
||||
|
||||
private:
|
||||
void execute_command(UINT32 *cmd);
|
||||
void execute_display_list(UINT32 addr);
|
||||
void draw_object(UINT32 *cmd);
|
||||
void fill_rect(UINT32 *cmd);
|
||||
void draw_character(UINT32 *cmd);
|
||||
void fb_config(UINT32 *cmd);
|
||||
|
||||
UINT32 *m_vram;
|
||||
UINT32 m_vram_read_addr;
|
||||
UINT32 m_vram_fifo0_addr;
|
||||
UINT32 m_vram_fifo1_addr;
|
||||
UINT32 m_vram_fifo0_mode;
|
||||
UINT32 m_vram_fifo1_mode;
|
||||
UINT32 m_command_fifo0[4];
|
||||
UINT32 m_command_fifo0_ptr;
|
||||
UINT32 m_command_fifo1[4];
|
||||
UINT32 m_command_fifo1_ptr;
|
||||
|
||||
const char* m_cputag;
|
||||
device_t* m_cpu;
|
||||
|
||||
framebuffer m_frame[4];
|
||||
UINT32 m_fb_origin_x;
|
||||
UINT32 m_fb_origin_y;
|
||||
};
|
||||
|
||||
extern const device_type K057714;
|
||||
|
||||
#define MCFG_K057714_CPU_TAG(_tag) \
|
||||
k057714_device::static_set_cpu_tag(*device, _tag);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user