video/k057714.cpp: Implemented display resolution register and various fixes to drawing. (#7677)

This commit is contained in:
987123879113 2021-01-18 16:56:10 +09:00 committed by GitHub
parent 99e98205ad
commit a39bbeb439
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 215 additions and 140 deletions

View File

@ -9,9 +9,21 @@
#define DUMP_VRAM 0 #define DUMP_VRAM 0
#define PRINT_GCU 0
#define PRINT_CMD_EXEC 0
#define LOG_GENERAL (1 << 0)
#define LOG_REGISTER (1 << 1)
#define LOG_FIFO (1 << 2)
#define LOG_CMDEXEC (1 << 3)
#define LOG_DRAW (1 << 4)
// #define VERBOSE (LOG_GENERAL | LOG_REGISTER | LOG_FIFO | LOG_CMDEXEC | LOG_DRAW)
// #define LOG_OUTPUT_STREAM std::cout
#include "logmacro.h"
#define LOGREGISTER(...) LOGMASKED(LOG_REGISTER, __VA_ARGS__)
#define LOGFIFO(...) LOGMASKED(LOG_FIFO, __VA_ARGS__)
#define LOGCMDEXEC(...) LOGMASKED(LOG_CMDEXEC, __VA_ARGS__)
#define LOGDRAW(...) LOGMASKED(LOG_DRAW, __VA_ARGS__)
DEFINE_DEVICE_TYPE(K057714, k057714_device, "k057714", "k057714_device GCU") DEFINE_DEVICE_TYPE(K057714, k057714_device, "k057714", "k057714_device GCU")
@ -25,12 +37,43 @@ void k057714_device::device_start()
{ {
m_irq.resolve_safe(); m_irq.resolve_safe();
m_vram = std::make_unique<uint32_t[]>(0x2000000/4); m_vram = std::make_unique<uint32_t[]>(VRAM_SIZE/4);
memset(m_vram.get(), 0, 0x2000000); memset(m_vram.get(), 0, VRAM_SIZE);
save_pointer(NAME(m_vram), VRAM_SIZE/4);
save_item(NAME(m_vram_read_addr));
save_item(NAME(m_vram_fifo0_addr));
save_item(NAME(m_vram_fifo1_addr));
save_item(NAME(m_vram_fifo0_mode));
save_item(NAME(m_vram_fifo1_mode));
save_item(NAME(m_command_fifo0));
save_item(NAME(m_command_fifo0_ptr));
save_item(NAME(m_command_fifo1));
save_item(NAME(m_command_fifo1_ptr));
save_item(NAME(m_ext_fifo_addr));
save_item(NAME(m_ext_fifo_count));
save_item(NAME(m_ext_fifo_line));
save_item(NAME(m_ext_fifo_num_lines));
save_item(NAME(m_ext_fifo_width));
save_item(STRUCT_MEMBER(m_frame, base));
save_item(STRUCT_MEMBER(m_frame, width));
save_item(STRUCT_MEMBER(m_frame, height));
save_item(STRUCT_MEMBER(m_frame, x));
save_item(STRUCT_MEMBER(m_frame, y));
save_item(STRUCT_MEMBER(m_frame, alpha));
save_item(NAME(m_fb_origin_x));
save_item(NAME(m_fb_origin_y));
save_item(NAME(m_layer_select));
save_item(NAME(m_reg_6c));
save_item(NAME(m_display_width));
save_item(NAME(m_display_height));
} }
void k057714_device::device_reset() void k057714_device::device_reset()
{ {
m_display_width = 0;
m_display_height = 0;
m_vram_read_addr = 0; m_vram_read_addr = 0;
m_command_fifo0_ptr = 0; m_command_fifo0_ptr = 0;
m_command_fifo1_ptr = 0; m_command_fifo1_ptr = 0;
@ -47,6 +90,7 @@ void k057714_device::device_reset()
elem.base = 0; elem.base = 0;
elem.width = 0; elem.width = 0;
elem.height = 0; elem.height = 0;
elem.alpha = (16 << 7) | (16 << 2); // Set alpha 1 and 2 to 16 (100%) and blend mode to 0
} }
} }
@ -59,7 +103,7 @@ void k057714_device::device_stop()
FILE *file = fopen(filename, "wb"); FILE *file = fopen(filename, "wb");
int i; int i;
for (i=0; i < 0x2000000/4; i++) for (i=0; i < VRAM_SIZE/4; i++)
{ {
fputc((m_vram[i] >> 24) & 0xff, file); fputc((m_vram[i] >> 24) & 0xff, file);
fputc((m_vram[i] >> 16) & 0xff, file); fputc((m_vram[i] >> 16) & 0xff, file);
@ -99,8 +143,22 @@ void k057714_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
{ {
int reg = offset * 4; int reg = offset * 4;
switch (reg) switch (reg)
{ {
case 0x00:
if (ACCESSING_BITS_16_31) {
// Viewport configurations discovered in game code: 640x480, 512x384, 800x600, 640x384
m_display_width = (data >> 16) & 0xffff;
}
break;
case 0x04:
if (ACCESSING_BITS_16_31) {
m_display_height = (data >> 16) & 0xffff;
}
break;
case 0x10: case 0x10:
/* IRQ clear/enable; ppd writes bit off then on in response to interrupt */ /* 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 */ /* it enables bits 0x41, but 0x01 seems to be the one it cares about */
@ -114,16 +172,22 @@ void k057714_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
if (ACCESSING_BITS_0_15) if (ACCESSING_BITS_0_15)
{ {
m_layer_select = data; m_layer_select = data;
#if PRINT_GCU LOGREGISTER("%s_w: %02X, %08X, %08X\n", basetag(), reg, data, mem_mask);
printf("%s_w: %02X, %08X, %08X\n", basetag(), reg, data, mem_mask);
#endif
} }
break; break;
case 0x14: // ? case 0x14: // Framebuffer 0/1 alpha values
if (ACCESSING_BITS_16_31)
m_frame[0].alpha = (data >> 16) & 0xffff;
if (ACCESSING_BITS_0_15)
m_frame[1].alpha = data & 0xffff;
break; break;
case 0x18: // ? case 0x18: // Framebuffer 0/1 alpha values
if (ACCESSING_BITS_16_31)
m_frame[2].alpha = (data >> 16) & 0xffff;
if (ACCESSING_BITS_0_15)
m_frame[3].alpha = data & 0xffff;
break; break;
case 0x1c: // set to 1 on "media bus" access case 0x1c: // set to 1 on "media bus" access
@ -167,9 +231,7 @@ void k057714_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
m_frame[0].height = (data >> 16) & 0xffff; m_frame[0].height = (data >> 16) & 0xffff;
if (ACCESSING_BITS_0_15) if (ACCESSING_BITS_0_15)
m_frame[0].width = data & 0xffff; m_frame[0].width = data & 0xffff;
#if PRINT_GCU LOGREGISTER("%s FB0 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
printf("%s FB0 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
#endif
break; break;
case 0x34: // Framebuffer 1 Dimensions case 0x34: // Framebuffer 1 Dimensions
@ -177,9 +239,7 @@ void k057714_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
m_frame[1].height = (data >> 16) & 0xffff; m_frame[1].height = (data >> 16) & 0xffff;
if (ACCESSING_BITS_0_15) if (ACCESSING_BITS_0_15)
m_frame[1].width = data & 0xffff; m_frame[1].width = data & 0xffff;
#if PRINT_GCU LOGREGISTER("%s FB1 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
printf("%s FB1 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
#endif
break; break;
case 0x38: // Framebuffer 2 Dimensions case 0x38: // Framebuffer 2 Dimensions
@ -187,9 +247,7 @@ void k057714_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
m_frame[2].height = (data >> 16) & 0xffff; m_frame[2].height = (data >> 16) & 0xffff;
if (ACCESSING_BITS_0_15) if (ACCESSING_BITS_0_15)
m_frame[2].width = data & 0xffff; m_frame[2].width = data & 0xffff;
#if PRINT_GCU LOGREGISTER("%s FB2 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
printf("%s FB2 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
#endif
break; break;
case 0x3c: // Framebuffer 3 Dimensions case 0x3c: // Framebuffer 3 Dimensions
@ -197,37 +255,27 @@ void k057714_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
m_frame[3].height = (data >> 16) & 0xffff; m_frame[3].height = (data >> 16) & 0xffff;
if (ACCESSING_BITS_0_15) if (ACCESSING_BITS_0_15)
m_frame[3].width = data & 0xffff; m_frame[3].width = data & 0xffff;
#if PRINT_GCU LOGREGISTER("%s FB3 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
printf("%s FB3 Dimensions: W %04X, H %04X\n", basetag(), data & 0xffff, (data >> 16) & 0xffff);
#endif
break; break;
case 0x40: // Framebuffer 0 Base case 0x40: // Framebuffer 0 Base
m_frame[0].base = data; m_frame[0].base = data;
#if PRINT_GCU LOGREGISTER("%s FB0 Base: %08X\n", basetag(), data);
printf("%s FB0 Base: %08X\n", basetag(), data);
#endif
break; break;
case 0x44: // Framebuffer 1 Base case 0x44: // Framebuffer 1 Base
m_frame[1].base = data; m_frame[1].base = data;
#if PRINT_GCU LOGREGISTER("%s FB1 Base: %08X\n", basetag(), data);
printf("%s FB1 Base: %08X\n", basetag(), data);
#endif
break; break;
case 0x48: // Framebuffer 2 Base case 0x48: // Framebuffer 2 Base
m_frame[2].base = data; m_frame[2].base = data;
#if PRINT_GCU LOGREGISTER("%s FB2 Base: %08X\n", basetag(), data);
printf("%s FB2 Base: %08X\n", basetag(), data);
#endif
break; break;
case 0x4c: // Framebuffer 3 Base case 0x4c: // Framebuffer 3 Base
m_frame[3].base = data; m_frame[3].base = data;
#if PRINT_GCU LOGREGISTER("%s FB3 Base: %08X\n", basetag(), data);
printf("%s FB3 Base: %08X\n", basetag(), data);
#endif
break; break;
case 0x54: case 0x54:
@ -266,7 +314,7 @@ void k057714_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
// execute when filled // execute when filled
if (m_command_fifo0_ptr >= 4) 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]); LOGFIFO("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); execute_command(m_command_fifo0);
m_command_fifo0_ptr = 0; m_command_fifo0_ptr = 0;
} }
@ -293,7 +341,7 @@ void k057714_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
// execute when filled // execute when filled
if (m_command_fifo1_ptr >= 4) 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]); LOGFIFO("GCU FIFO1 exec: %08X %08X %08X %08X\n", m_command_fifo1[0], m_command_fifo1[1], m_command_fifo1[2], m_command_fifo1[3]);
execute_command(m_command_fifo1); execute_command(m_command_fifo1);
m_command_fifo1_ptr = 0; m_command_fifo1_ptr = 0;
} }
@ -314,7 +362,7 @@ void k057714_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
break; break;
default: default:
//printf("%s_w: %02X, %08X, %08X\n", basetag(), reg, data, mem_mask); LOGREGISTER("%s_w: %02X, %08X, %08X\n", basetag(), reg, data, mem_mask);
break; break;
} }
} }
@ -351,12 +399,20 @@ void k057714_device::fifo_w(offs_t offset, uint32_t data, uint32_t mem_mask)
void k057714_device::draw_frame(int frame, bitmap_ind16 &bitmap, const rectangle &cliprect, bool inverse_trans) void k057714_device::draw_frame(int frame, bitmap_ind16 &bitmap, const rectangle &cliprect, bool inverse_trans)
{ {
int height = m_frame[frame].height; if (m_frame[frame].height == 0 || m_frame[frame].width == 0)
int width = m_frame[frame].width;
if (width == 0 || height == 0)
return; return;
int height = m_frame[frame].height + 1;
int width = m_frame[frame].width + 1;
int alpha = m_frame[frame].alpha;
int blend_mode = alpha & 3;
int alpha1 = (alpha >> 2) & 0x1f;
int alpha2 = (alpha >> 7) & 0x1f;
if (blend_mode == 2) {
alpha1 = (alpha1 * 16) / alpha2;
}
uint16_t *vram16 = (uint16_t*)m_vram.get(); uint16_t *vram16 = (uint16_t*)m_vram.get();
int fb_pitch = 1024; int fb_pitch = 1024;
@ -368,15 +424,27 @@ void k057714_device::draw_frame(int frame, bitmap_ind16 &bitmap, const rectangle
if (m_frame[frame].x + width > cliprect.max_x) if (m_frame[frame].x + width > cliprect.max_x)
width = cliprect.max_x - m_frame[frame].x; width = cliprect.max_x - m_frame[frame].x;
for (int j = 0; j < height; j++) for (int j = 0; j <= height; j++)
{ {
uint16_t *const d = &bitmap.pix(j + m_frame[frame].y, m_frame[frame].x); uint16_t *const d = &bitmap.pix(j + m_frame[frame].y, m_frame[frame].x);
int li = (j * fb_pitch); int li = (j * fb_pitch);
for (int i = 0; i < width; i++) for (int i = 0; i <= width; i++)
{ {
uint16_t pix = vram16[(m_frame[frame].base + li + i) ^ NATIVE_ENDIAN_VALUE_LE_BE(1, 0)]; uint16_t pix = vram16[(m_frame[frame].base + li + i) ^ NATIVE_ENDIAN_VALUE_LE_BE(1, 0)];
if ((pix & 0x8000) != trans_value) { if ((pix & 0x8000) != trans_value) {
d[i] = pix & 0x7fff; uint32_t r = (pix >> 10) & 0x1f;
uint32_t g = (pix >> 5) & 0x1f;
uint32_t b = (pix >> 0) & 0x1f;
r = (r * alpha1) >> 4;
g = (g * alpha1) >> 4;
b = (b * alpha1) >> 4;
if (r > 0x1f) r = 0x1f;
if (g > 0x1f) g = 0x1f;
if (b > 0x1f) b = 0x1f;
d[i] = (r << 10) | (g << 5) | b;
} }
} }
} }
@ -384,17 +452,14 @@ void k057714_device::draw_frame(int frame, bitmap_ind16 &bitmap, const rectangle
int k057714_device::draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) int k057714_device::draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{ {
int width = m_frame[0].width; if (m_display_width != 0 && m_display_height != 0)
int height = m_frame[0].height;
if (width != 0 && height != 0)
{ {
rectangle visarea = screen.visible_area(); rectangle visarea = screen.visible_area();
if ((visarea.max_x+1) != width || (visarea.max_y+1) != height) if (visarea.max_x != m_display_width || visarea.max_y != m_display_height)
{ {
visarea.max_x = width-1; visarea.max_x = m_display_width;
visarea.max_y = height-1; visarea.max_y = m_display_height;
screen.configure(width, height, visarea, screen.frame_period().attoseconds()); screen.configure(m_display_width, m_display_height, visarea, screen.frame_period().attoseconds());
} }
} }
@ -416,70 +481,84 @@ int k057714_device::draw(screen_device &screen, bitmap_ind16 &bitmap, const rect
void k057714_device::draw_object(uint32_t *cmd) void k057714_device::draw_object(uint32_t *cmd)
{ {
// 0x00: xxx----- -------- -------- -------- command (5) // 0x00: -------- -------- ------xx xxxxxxxx ram x
// 0x00: -------- xxxxxxxx xxxxxx-- -------- ram y
// 0x00: ---x---- -------- -------- -------- 0: absolute coordinates // 0x00: ---x---- -------- -------- -------- 0: absolute coordinates
// 1: relative coordinates from framebuffer origin // 1: relative coordinates from framebuffer origin
// 0x00: ----xx-- -------- -------- -------- ? // 0x00: xxx----- -------- -------- -------- command (always 5)
// 0x00: -------- xxxxxxxx xxxxxxxx xxxxxxxx object data address in vram
// 0x01: -------- -------- ------xx xxxxxxxx object x // 0x01: -------- -------- ------xx xxxxxxxx object x
// 0x01: -------- xxxxxxxx xxxxxx-- -------- object y // 0x01: -------- xxxxxxxx xxxxxx-- -------- object y
// 0x01: -----x-- -------- -------- -------- object x flip // 0x01: -----x-- -------- -------- -------- object x flip
// 0x01: ----x--- -------- -------- -------- object y flip // 0x01: ----x--- -------- -------- -------- object y flip
// 0x01: --xx---- -------- -------- -------- object alpha enable (different blend modes?) // 0x01: --xx---- -------- -------- -------- blend mode
// 0x01: -x------ -------- -------- -------- object transparency enable (?) // 0x01: -x------ -------- -------- -------- object transparency enable
// 0x01: x------- -------- -------- -------- inverse transparency? (used by kbm) // 0x01: x------- -------- -------- -------- inverse transparency? (used by kbm)
// 0x02: -------- -------- ------xx xxxxxxxx object width // 0x02: -------- -------- -------x xxxxxxxx object width
// 0x02: -------- -----xxx xxxxxx-- -------- object x scale // 0x02: -------- --xxxxxx xxxxxx-- -------- object x scale
// 0x02: xxxxx--- -------- -------- -------- ? // 0x02: -----xxx xx------ -------- -------- alpha1_1 (blend mode 2)
// 0x02: -----xxx xx------ -------- -------- translucency // 0x02: xxxxx--- -------- -------- -------- alpha1_2 (blend mode 1)
// 0x02: -------- --xxx--- -------- -------- ?
// 0x03: -------- -------- ------xx xxxxxxxx object height // 0x03: -------- -------- ------xx xxxxxxxx object height
// 0x03: -------- -----xxx xxxxxx-- -------- object y scale // 0x03: -------- --xxxxxx xxxxxx-- -------- object y scale
// 0x03: xxxxx--- -------- -------- -------- ? // 0x03: -----xxx xx------ -------- -------- alpha2_1 (blend mode 2)
// 0x03: -----xxx xx------ -------- -------- ? // 0x03: xxxxx--- -------- -------- -------- alpha2_2 (blend mode 1)
// 0x03: -------- --xxx--- -------- -------- ?
uint32_t address_x = cmd[0] & 0x3ff;
uint32_t address_y = (cmd[0] >> 10) & 0x3fff;
bool relative_coords = (cmd[0] & 0x10000000) ? true : false;
int x = cmd[1] & 0x3ff; int x = cmd[1] & 0x3ff;
int y = (cmd[1] >> 10) & 0x3fff; 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 xflip = (cmd[1] & 0x04000000) ? true : false;
bool yflip = (cmd[1] & 0x08000000) ? true : false; bool yflip = (cmd[1] & 0x08000000) ? true : false;
bool alpha_enable = (cmd[1] & 0x30000000) ? true : false; int blend_mode = (cmd[1] >> 28) & 3;
bool trans_enable = (cmd[1] & 0xc0000000) ? true : false; bool trans_enable = (cmd[1] & 0xc0000000) ? true : false;
uint32_t address = cmd[0] & 0xffffff;
int alpha_level = (cmd[2] >> 22) & 0x1f;
bool relative_coords = (cmd[0] & 0x10000000) ? true : false;
uint16_t trans_value = (cmd[1] & 0x80000000) ? 0x0000 : 0x8000; uint16_t trans_value = (cmd[1] & 0x80000000) ? 0x0000 : 0x8000;
int width = (cmd[2] & 0x1ff) + 1;
int xscale = ((cmd[2] >> 10) & 0x7ff) * (((cmd[2] >> 10) & 0x800) ? -1 : 1);
int alpha1_1 = (cmd[2] >> 22) & 0x1f;
int alpha1_2 = (cmd[2] >> 27) & 0x1f;
int height = (cmd[3] & 0x3ff) + 1;
int yscale = ((cmd[3] >> 10) & 0x7ff) * (((cmd[3] >> 10) & 0x800) ? -1 : 1);
int alpha2_1 = (cmd[3] >> 22) & 0x1f;
int alpha2_2 = (cmd[3] >> 27) & 0x1f;
if (xflip && ((4 - ((width - 1) % 4)) <= (address_x % 4))) {
// Based on logic from pop'n music 8 @ 0x800b30d0
address_x -= 4;
}
if (yflip) {
// Based on logic from pop'n music 8 @ 0x800b3140
y -= (((height * 64) - 1) / yscale) - (((height - 1) * 64) / yscale);
}
if (relative_coords) if (relative_coords)
{ {
x += m_fb_origin_x; x += m_fb_origin_x;
y += m_fb_origin_y; y += m_fb_origin_y;
} }
uint16_t *vram16 = (uint16_t*)m_vram.get(); uint32_t address = (address_y << 10) | address_x;
if (xscale == 0 || yscale == 0) LOGDRAW("%s Draw Object %08X (%d, %d), x %d, y %d, w %d, h %d, sx: %f, sy: %f [%08X %08X %08X %08X]\n", basetag(), address, address_x, address_y, x, y, width, height, 64.0f / (float)xscale, 64.0f / (float)yscale, cmd[0], cmd[1], cmd[2], cmd[3]);
{
return;
}
#if PRINT_CMD_EXEC int orig_height = height;
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; width = (((width * 65536) / xscale) * 64) / 65536;
height = (((height * 65536) / yscale) * 64) / 65536; height = (((height * 65536) / yscale) * 64) / 65536;
int fb_width = m_frame[0].width; if (height <= 0 || width <= 0)
int fb_height = m_frame[0].height; {
return;
}
int fb_width = m_frame[0].width + 1;
int fb_height = m_frame[0].height + 1;
if (width > fb_width) if (width > fb_width)
width = fb_width; width = fb_width;
@ -489,29 +568,25 @@ void k057714_device::draw_object(uint32_t *cmd)
int fb_pitch = 1024; int fb_pitch = 1024;
int v = 0; int v = 0;
int xinc = xflip ? -1 : 1;
uint16_t *vram16 = (uint16_t*)m_vram.get();
for (int j=0; j < height; j++) for (int j=0; j < height; j++)
{ {
int index; int index;
int xinc;
uint32_t fbaddr = ((j+y) * fb_pitch) + x; uint32_t fbaddr = ((j+y) * fb_pitch) + x;
if (yflip) if (yflip)
{ {
index = address + ((height - 1 - (v >> 6)) * 1024); index = address + ((orig_height - 1 - (v >> 6)) * fb_pitch);
} }
else else
{ {
index = address + ((v >> 6) * 1024); index = address + ((v >> 6) * fb_pitch);
} }
if (xflip) if (xflip)
{ {
fbaddr += width; fbaddr += width - 1;
xinc = -1;
}
else
{
xinc = 1;
} }
int u = 0; int u = 0;
@ -519,39 +594,43 @@ void k057714_device::draw_object(uint32_t *cmd)
{ {
uint16_t pix = vram16[((index + (u >> 6)) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)) & 0xffffff]; uint16_t pix = vram16[((index + (u >> 6)) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)) & 0xffffff];
bool draw = !trans_enable || (trans_enable && ((pix & 0x8000) == trans_value)); bool draw = !trans_enable || (trans_enable && ((pix & 0x8000) == trans_value));
if (alpha_enable)
{
if (draw) if (draw)
{ {
if ((pix & 0x7fff) != 0) if (blend_mode)
{ {
uint16_t srcpix = vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)]; uint16_t srcpix = vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)];
uint32_t sr = (srcpix >> 10) & 0x1f; uint32_t sr = (srcpix >> 10) & 0x1f;
uint32_t sg = (srcpix >> 5) & 0x1f; uint32_t sg = (srcpix >> 5) & 0x1f;
uint32_t sb = (srcpix >> 0) & 0x1f; uint32_t sb = (srcpix >> 0) & 0x1f;
uint32_t r = (pix >> 10) & 0x1f; uint32_t r = (pix >> 10) & 0x1f;
uint32_t g = (pix >> 5) & 0x1f; uint32_t g = (pix >> 5) & 0x1f;
uint32_t b = (pix >> 0) & 0x1f; uint32_t b = (pix >> 0) & 0x1f;
sr += (r * alpha_level) >> 4; if (blend_mode == 1)
sg += (g * alpha_level) >> 4; {
sb += (b * alpha_level) >> 4; sr = ((sr * alpha2_2) + (r * alpha1_2)) >> 4;
sg = ((sg * alpha2_2) + (g * alpha1_2)) >> 4;
sb = ((sb * alpha2_2) + (b * alpha1_2)) >> 4;
}
else if (blend_mode == 2)
{
// Used by Keyboardmania for pulsating glow effects
sr = ((sr * alpha2_1) + (r * alpha1_1)) >> 4;
sg = ((sg * alpha2_1) + (g * alpha1_1)) >> 4;
sb = ((sb * alpha2_1) + (b * alpha1_1)) >> 4;
}
if (sr > 0x1f) sr = 0x1f; if (sr > 0x1f) sr = 0x1f;
if (sg > 0x1f) sg = 0x1f; if (sg > 0x1f) sg = 0x1f;
if (sb > 0x1f) sb = 0x1f; if (sb > 0x1f) sb = 0x1f;
vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = (sr << 10) | (sg << 5) | sb | (pix & 0x8000); pix = (sr << 10) | (sg << 5) | sb | (pix & 0x8000);
}
}
}
else
{
if (draw)
{
vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = (pix & 0xffff);
} }
vram16[fbaddr ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = pix;
} }
fbaddr += xinc; fbaddr += xinc;
@ -599,9 +678,7 @@ void k057714_device::fill_rect(uint32_t *cmd)
color[2] = (cmd[3] >> 16); color[2] = (cmd[3] >> 16);
color[3] = (cmd[3] & 0xffff); color[3] = (cmd[3] & 0xffff);
#if PRINT_CMD_EXEC LOGCMDEXEC("%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]);
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 x1 = x;
int x2 = x + width; int x2 = x + width;
@ -660,9 +737,7 @@ void k057714_device::draw_character(uint32_t *cmd)
color[2] = cmd[3] >> 16; color[2] = cmd[3] >> 16;
color[3] = cmd[3] & 0xffff; color[3] = cmd[3] & 0xffff;
#if PRINT_CMD_EXEC LOGCMDEXEC("%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]);
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(); uint16_t *vram16 = (uint16_t*)m_vram.get();
int fb_pitch = 1024; int fb_pitch = 1024;
@ -695,9 +770,7 @@ void k057714_device::fb_config(uint32_t *cmd)
// 0x03: -------- -------- --xxxxxx xxxxxxxx Framebuffer Origin Y // 0x03: -------- -------- --xxxxxx xxxxxxxx Framebuffer Origin Y
#if PRINT_CMD_EXEC LOGCMDEXEC("%s FB Config %08X %08X %08X %08X\n", basetag(), cmd[0], cmd[1], cmd[2], cmd[3]);
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_x = cmd[2] & 0x3ff;
m_fb_origin_y = cmd[3] & 0x3fff; m_fb_origin_y = cmd[3] & 0x3fff;
@ -709,12 +782,10 @@ void k057714_device::execute_display_list(uint32_t addr)
int counter = 0; int counter = 0;
#if PRINT_CMD_EXEC LOGCMDEXEC("%s Exec Display List %08X\n", basetag(), addr);
printf("%s Exec Display List %08X\n", basetag(), addr);
#endif
addr /= 2; addr /= 2;
while (!end && counter < 0x1000 && addr < (0x2000000/4)) while (!end && counter < 0x1000 && addr < (VRAM_SIZE/4))
{ {
uint32_t *cmd = &m_vram[addr]; uint32_t *cmd = &m_vram[addr];
addr += 4; addr += 4;
@ -752,7 +823,7 @@ void k057714_device::execute_display_list(uint32_t addr)
break; break;
default: default:
printf("GCU Unknown command %08X %08X %08X %08X\n", cmd[0], cmd[1], cmd[2], cmd[3]); LOGCMDEXEC("GCU Unknown command %08X %08X %08X %08X\n", cmd[0], cmd[1], cmd[2], cmd[3]);
break; break;
} }
counter++; counter++;
@ -763,9 +834,7 @@ void k057714_device::execute_command(uint32_t* cmd)
{ {
int command = (cmd[0] >> 29) & 0x7; int command = (cmd[0] >> 29) & 0x7;
#if PRINT_CMD_EXEC LOGCMDEXEC("%s Exec Command %08X, %08X, %08X, %08X\n", basetag(), cmd[0], cmd[1], cmd[2], cmd[3]);
printf("%s Exec Command %08X, %08X, %08X, %08X\n", basetag(), cmd[0], cmd[1], cmd[2], cmd[3]);
#endif
switch (command) switch (command)
{ {
@ -797,7 +866,7 @@ void k057714_device::execute_command(uint32_t* cmd)
break; break;
default: default:
printf("GCU Unknown command %08X %08X %08X %08X\n", cmd[0], cmd[1], cmd[2], cmd[3]); LOGCMDEXEC("GCU Unknown command %08X %08X %08X %08X\n", cmd[0], cmd[1], cmd[2], cmd[3]);
break; break;
} }
} }

View File

@ -25,6 +25,7 @@ public:
int height; int height;
int x; int x;
int y; int y;
int alpha;
}; };
protected: protected:
@ -33,6 +34,8 @@ protected:
virtual void device_reset() override; virtual void device_reset() override;
private: private:
enum { VRAM_SIZE = 0x2000000 };
void execute_command(uint32_t *cmd); void execute_command(uint32_t *cmd);
void execute_display_list(uint32_t addr); void execute_display_list(uint32_t addr);
void draw_object(uint32_t *cmd); void draw_object(uint32_t *cmd);
@ -64,6 +67,9 @@ private:
uint32_t m_layer_select; uint32_t m_layer_select;
uint32_t m_reg_6c; uint32_t m_reg_6c;
uint32_t m_display_width;
uint32_t m_display_height;
devcb_write_line m_irq; devcb_write_line m_irq;
}; };