summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Ville Linde <villedevs@gmail.com>2019-01-20 13:56:09 +0200
committer Ville Linde <villedevs@gmail.com>2019-01-20 14:00:07 +0200
commit44130d5dd9aca78ac2fba84c2cc05f8653be6f35 (patch)
tree3785705b4f23114d4a06180d2a7873405acd43f4
parentd47d3ca4f7f87736de2fdb3a972e9f6be51aedca (diff)
k057714: Various improvements to video emulation in Keyboardmania games. [Ville Linde]
-rw-r--r--src/mame/video/k057714.cpp169
-rw-r--r--src/mame/video/k057714.h6
2 files changed, 122 insertions, 53 deletions
diff --git a/src/mame/video/k057714.cpp b/src/mame/video/k057714.cpp
index 8092e80095c..084ed639473 100644
--- a/src/mame/video/k057714.cpp
+++ b/src/mame/video/k057714.cpp
@@ -10,6 +10,7 @@
#define DUMP_VRAM 0
#define PRINT_GCU 0
+#define PRINT_CMD_EXEC 0
DEFINE_DEVICE_TYPE(K057714, k057714_device, "k057714", "k057714_device GCU")
@@ -36,6 +37,9 @@ void k057714_device::device_reset()
m_vram_fifo0_addr = 0;
m_vram_fifo1_addr = 0;
+ m_fb_origin_x = 0;
+ m_fb_origin_y = 0;
+
for (auto & elem : m_frame)
{
elem.base = 0;
@@ -106,9 +110,12 @@ WRITE32_MEMBER(k057714_device::write)
}
}
if (ACCESSING_BITS_0_15)
+ {
+ m_layer_select = data;
#if PRINT_GCU
printf("%s_w: %02X, %08X, %08X\n", basetag(), reg, data, mem_mask);
#endif
+ }
break;
case 0x14: // ?
@@ -126,15 +133,31 @@ WRITE32_MEMBER(k057714_device::write)
break;
case 0x20: // Framebuffer 0 Origin(?)
+ if (ACCESSING_BITS_16_31)
+ m_frame[0].y = (data >> 16) & 0xffff;
+ if (ACCESSING_BITS_0_15)
+ m_frame[0].x = data & 0xffff;
break;
case 0x24: // Framebuffer 1 Origin(?)
+ if (ACCESSING_BITS_16_31)
+ m_frame[1].y = (data >> 16) & 0xffff;
+ if (ACCESSING_BITS_0_15)
+ m_frame[1].x = data & 0xffff;
break;
case 0x28: // Framebuffer 2 Origin(?)
+ if (ACCESSING_BITS_16_31)
+ m_frame[2].y = (data >> 16) & 0xffff;
+ if (ACCESSING_BITS_0_15)
+ m_frame[2].x = data & 0xffff;
break;
case 0x2c: // Framebuffer 3 Origin(?)
+ if (ACCESSING_BITS_16_31)
+ m_frame[3].y = (data >> 16) & 0xffff;
+ if (ACCESSING_BITS_0_15)
+ m_frame[3].x = data & 0xffff;
break;
case 0x30: // Framebuffer 0 Dimensions
@@ -142,6 +165,9 @@ WRITE32_MEMBER(k057714_device::write)
m_frame[0].height = (data >> 16) & 0xffff;
if (ACCESSING_BITS_0_15)
m_frame[0].width = data & 0xffff;
+#if PRINT_GCU
+ printf("%s FB0 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
+#endif
break;
case 0x34: // Framebuffer 1 Dimensions
@@ -149,6 +175,9 @@ WRITE32_MEMBER(k057714_device::write)
m_frame[1].height = (data >> 16) & 0xffff;
if (ACCESSING_BITS_0_15)
m_frame[1].width = data & 0xffff;
+#if PRINT_GCU
+ printf("%s FB1 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
+#endif
break;
case 0x38: // Framebuffer 2 Dimensions
@@ -156,6 +185,9 @@ WRITE32_MEMBER(k057714_device::write)
m_frame[2].height = (data >> 16) & 0xffff;
if (ACCESSING_BITS_0_15)
m_frame[2].width = data & 0xffff;
+#if PRINT_GCU
+ printf("%s FB2 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
+#endif
break;
case 0x3c: // Framebuffer 3 Dimensions
@@ -163,6 +195,9 @@ WRITE32_MEMBER(k057714_device::write)
m_frame[3].height = (data >> 16) & 0xffff;
if (ACCESSING_BITS_0_15)
m_frame[3].width = data & 0xffff;
+#if PRINT_GCU
+ printf("%s FB3 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
+#endif
break;
case 0x40: // Framebuffer 0 Base
@@ -269,8 +304,15 @@ WRITE32_MEMBER(k057714_device::write)
}
break;
+ case 0x6c:
+ if (ACCESSING_BITS_0_15)
+ {
+ m_reg_6c = data & 0xffff;
+ }
+ break;
+
default:
- //printf("%s_w: %02X, %08X, %08X at %s\n", basetag(), reg, data, mem_mask, m_maincpu->pc());
+ //printf("%s_w: %02X, %08X, %08X\n", basetag(), reg, data, mem_mask);
break;
}
}
@@ -305,12 +347,41 @@ WRITE32_MEMBER(k057714_device::fifo_w)
}
}
-int k057714_device::draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+void k057714_device::draw_frame(int frame, bitmap_ind16 &bitmap, const rectangle &cliprect, bool inverse_trans)
{
+ int height = m_frame[frame].height;
+ int width = m_frame[frame].width;
+
+ if (width == 0 || height == 0)
+ return;
+
uint16_t *vram16 = (uint16_t*)m_vram.get();
- int x = 0;
- int y = 0;
+ int fb_pitch = 1024;
+
+ uint16_t trans_value = inverse_trans ? 0x8000 : 0x0000;
+
+ if (m_frame[frame].y + height > cliprect.max_y)
+ height = cliprect.max_y - m_frame[frame].y;
+ if (m_frame[frame].x + width > cliprect.max_x)
+ width = cliprect.max_x - m_frame[frame].x;
+
+ for (int j = 0; j < height; j++)
+ {
+ uint16_t *d = &bitmap.pix16(j + m_frame[frame].y, m_frame[frame].x);
+ int li = (j * fb_pitch);
+ for (int i = 0; i < width; i++)
+ {
+ uint16_t pix = vram16[(m_frame[frame].base + li + i) ^ NATIVE_ENDIAN_VALUE_LE_BE(1, 0)];
+ if ((pix & 0x8000) != trans_value) {
+ d[i] = pix & 0x7fff;
+ }
+ }
+ }
+}
+
+int k057714_device::draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
int width = m_frame[0].width;
int height = m_frame[0].height;
@@ -325,45 +396,18 @@ int k057714_device::draw(screen_device &screen, bitmap_ind16 &bitmap, const rect
}
}
- int fb_pitch = 1024;
+ bitmap.fill(0, cliprect);
- for (int j=0; j < height; j++)
- {
- uint16_t *d = &bitmap.pix16(j, x);
- int li = ((j+y) * fb_pitch) + x;
- uint32_t fbaddr0 = m_frame[0].base + li;
- uint32_t fbaddr1 = m_frame[1].base + li;
- uint32_t fbaddr2 = m_frame[2].base + li;
-// uint32_t fbaddr3 = m_frame[3].base + li;
+ bool inverse_trans = false;
- for (int i=0; i < width; i++)
- {
- uint16_t pix0 = vram16[fbaddr0 ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
- uint16_t pix1 = vram16[fbaddr1 ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
- uint16_t pix2 = vram16[fbaddr2 ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
-// uint16_t pix3 = vram16[fbaddr3 ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
+ // most likely wrong, inverse transparency is only used by kbm
+ if ((m_reg_6c & 0xf) != 0)
+ inverse_trans = true;
- d[i] = 0;
-
- if (pix2 & 0x8000)
- {
- d[i] = pix2 & 0x7fff;
- }
- if (pix1 & 0x8000)
- {
- d[i] = pix1 & 0x7fff;
- }
- if (pix0 & 0x8000)
- {
- d[i] = pix0 & 0x7fff;
- }
-
- fbaddr0++;
- fbaddr1++;
- fbaddr2++;
-// fbaddr3++;
- }
- }
+ draw_frame((m_layer_select >> 8) & 3, bitmap, cliprect, inverse_trans);
+ draw_frame((m_layer_select >> 10) & 3, bitmap, cliprect, inverse_trans);
+ draw_frame((m_layer_select >> 12) & 3, bitmap, cliprect, inverse_trans);
+ draw_frame((m_layer_select >> 14) & 3, bitmap, cliprect, inverse_trans);
return 0;
}
@@ -382,12 +426,19 @@ void k057714_device::draw_object(uint32_t *cmd)
// 0x01: ----x--- -------- -------- -------- object y flip
// 0x01: --xx---- -------- -------- -------- object alpha enable (different blend modes?)
// 0x01: -x------ -------- -------- -------- object transparency enable (?)
+ // 0x01: x------- -------- -------- -------- inverse transparency? (used by kbm)
// 0x02: -------- -------- ------xx xxxxxxxx object width
// 0x02: -------- -----xxx xxxxxx-- -------- object x scale
+ // 0x02: xxxxx--- -------- -------- -------- ?
+ // 0x02: -----xxx xx------ -------- -------- translucency
+ // 0x02: -------- --xxx--- -------- -------- ?
// 0x03: -------- -------- ------xx xxxxxxxx object height
// 0x03: -------- -----xxx xxxxxx-- -------- object y scale
+ // 0x03: xxxxx--- -------- -------- -------- ?
+ // 0x03: -----xxx xx------ -------- -------- ?
+ // 0x03: -------- --xxx--- -------- -------- ?
int x = cmd[1] & 0x3ff;
int y = (cmd[1] >> 10) & 0x3fff;
@@ -398,11 +449,13 @@ void k057714_device::draw_object(uint32_t *cmd)
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;
+ bool trans_enable = (cmd[1] & 0xc0000000) ? true : false;
uint32_t address = cmd[0] & 0xffffff;
- int alpha_level = (cmd[2] >> 27) & 0x1f;
+ int alpha_level = (cmd[2] >> 22) & 0x1f;
bool relative_coords = (cmd[0] & 0x10000000) ? true : false;
+ uint16_t trans_value = (cmd[1] & 0x80000000) ? 0x0000 : 0x8000;
+
if (relative_coords)
{
x += m_fb_origin_x;
@@ -416,13 +469,21 @@ void k057714_device::draw_object(uint32_t *cmd)
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]);
+#if PRINT_CMD_EXEC
+ printf("%s Draw Object %08X, x %d, y %d, w %d, h %d, sx: %f, sy: %f [%08X %08X %08X %08X]\n", basetag(), address, x, y, width, height, (float)(xscale) / 64.0f, (float)(yscale) / 64.0f, cmd[0], cmd[1], cmd[2], cmd[3]);
#endif
width = (((width * 65536) / xscale) * 64) / 65536;
height = (((height * 65536) / yscale) * 64) / 65536;
+ int fb_width = m_frame[0].width;
+ int fb_height = m_frame[0].height;
+
+ if (width > fb_width)
+ width = fb_width;
+ if (height > fb_height)
+ height = fb_height;
+
int fb_pitch = 1024;
int v = 0;
@@ -455,7 +516,7 @@ void k057714_device::draw_object(uint32_t *cmd)
for (int i=0; i < width; i++)
{
uint16_t pix = vram16[((index + (u >> 6)) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)) & 0xffffff];
- bool draw = !trans_enable || (trans_enable && (pix & 0x8000));
+ bool draw = !trans_enable || (trans_enable && ((pix & 0x8000) == trans_value));
if (alpha_enable)
{
if (draw)
@@ -487,7 +548,7 @@ void k057714_device::draw_object(uint32_t *cmd)
{
if (draw)
{
- vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = pix;
+ vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = (pix & 0xffff);
}
}
@@ -510,6 +571,7 @@ void k057714_device::fill_rect(uint32_t *cmd)
// 0x01: -------- -------- ------xx xxxxxxxx x
// 0x01: -------- xxxxxxxx xxxxxx-- -------- y
+ // 0x01: ---x---- -------- -------- -------- ?
// 0x02: xxxxxxxx xxxxxxxx -------- -------- fill pattern pixel 0
// 0x02: -------- -------- xxxxxxxx xxxxxxxx fill pattern pixel 1
@@ -535,7 +597,7 @@ void k057714_device::fill_rect(uint32_t *cmd)
color[2] = (cmd[3] >> 16);
color[3] = (cmd[3] & 0xffff);
-#if PRINT_GCU
+#if PRINT_CMD_EXEC
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
@@ -568,6 +630,7 @@ void k057714_device::draw_character(uint32_t *cmd)
// 0x01: -------- -------- ------xx xxxxxxxx character x
// 0x01: -------- xxxxxxxx xxxxxx-- -------- character y
// 0x01: -------x -------- -------- -------- double height
+ // 0x01: --x----- -------- -------- -------- ?
// 0x01: -x------ -------- -------- -------- transparency enable
// 0x02: xxxxxxxx xxxxxxxx -------- -------- color 0
@@ -595,8 +658,8 @@ void k057714_device::draw_character(uint32_t *cmd)
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);
+#if PRINT_CMD_EXEC
+ printf("%s Draw Char %08X, x %d, y %d [%08X %08X %08X %08X]\n", basetag(), address, x, y, cmd[0], cmd[1], cmd[2], cmd[3]);
#endif
uint16_t *vram16 = (uint16_t*)m_vram.get();
@@ -615,7 +678,7 @@ void k057714_device::draw_character(uint32_t *cmd)
int p = (line >> ((7-i) * 2)) & 3;
bool draw = !trans_enable || (trans_enable && (color[p] & 0x8000));
if (draw)
- vram16[(fbaddr+x+i) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = color[p] | 0x8000;
+ vram16[(fbaddr+x+i) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = color[p];
}
}
}
@@ -630,7 +693,7 @@ void k057714_device::fb_config(uint32_t *cmd)
// 0x03: -------- -------- --xxxxxx xxxxxxxx Framebuffer Origin Y
-#if PRINT_GCU
+#if PRINT_CMD_EXEC
printf("%s FB Config %08X %08X %08X %08X\n", basetag(), cmd[0], cmd[1], cmd[2], cmd[3]);
#endif
@@ -644,7 +707,7 @@ void k057714_device::execute_display_list(uint32_t addr)
int counter = 0;
-#if PRINT_GCU
+#if PRINT_CMD_EXEC
printf("%s Exec Display List %08X\n", basetag(), addr);
#endif
@@ -698,7 +761,7 @@ void k057714_device::execute_command(uint32_t* cmd)
{
int command = (cmd[0] >> 29) & 0x7;
-#if PRINT_GCU
+#if PRINT_CMD_EXEC
printf("%s Exec Command %08X, %08X, %08X, %08X\n", basetag(), cmd[0], cmd[1], cmd[2], cmd[3]);
#endif
diff --git a/src/mame/video/k057714.h b/src/mame/video/k057714.h
index a52bb898c5a..190a8dd92c7 100644
--- a/src/mame/video/k057714.h
+++ b/src/mame/video/k057714.h
@@ -23,6 +23,8 @@ public:
uint32_t base;
int width;
int height;
+ int x;
+ int y;
};
protected:
@@ -38,6 +40,8 @@ private:
void draw_character(uint32_t *cmd);
void fb_config(uint32_t *cmd);
+ void draw_frame(int frame, bitmap_ind16 &bitmap, const rectangle &cliprect, bool inverse_trans);
+
std::unique_ptr<uint32_t[]> m_vram;
uint32_t m_vram_read_addr;
uint32_t m_vram_fifo0_addr;
@@ -57,6 +61,8 @@ private:
framebuffer m_frame[4];
uint32_t m_fb_origin_x;
uint32_t m_fb_origin_y;
+ uint32_t m_layer_select;
+ uint32_t m_reg_6c;
devcb_write_line m_irq;
};