summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/nec/pc88va_v.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/nec/pc88va_v.cpp')
-rw-r--r--src/mame/nec/pc88va_v.cpp438
1 files changed, 342 insertions, 96 deletions
diff --git a/src/mame/nec/pc88va_v.cpp b/src/mame/nec/pc88va_v.cpp
index 30f4ce5fea4..54b12bf28cf 100644
--- a/src/mame/nec/pc88va_v.cpp
+++ b/src/mame/nec/pc88va_v.cpp
@@ -4,8 +4,6 @@
#include "emu.h"
#include "pc88va.h"
-#include <iostream>
-
#define LOG_IDP (1U << 1) // TSP data
#define LOG_FB (1U << 2) // framebuffer strips (verbose)
@@ -14,6 +12,8 @@
#define LOG_COLOR (1U << 5) // current color mode
#define LOG_TEXT (1U << 6) // text strips (verbose)
+//#include <iostream>
+
#define VERBOSE (LOG_GENERAL | LOG_IDP)
//#define LOG_OUTPUT_STREAM std::cout
@@ -28,10 +28,14 @@
void pc88va_state::video_start()
{
+ const u32 gvram_size = 0x40000;
+ m_gvram = make_unique_clear<uint8_t[]>(gvram_size);
+ std::fill_n(m_gvram.get(), gvram_size, 0);
+
const u32 kanjiram_size = 0x4000;
- m_kanjiram = std::make_unique<uint8_t[]>(kanjiram_size);
- m_gfxdecode->gfx(2)->set_source(m_kanjiram.get());
- m_gfxdecode->gfx(3)->set_source(m_kanjiram.get());
+ m_kanji_ram = make_unique_clear<uint8_t[]>(kanjiram_size);
+ m_gfxdecode->gfx(2)->set_source(m_kanji_ram.get());
+ m_gfxdecode->gfx(3)->set_source(m_kanji_ram.get());
m_vrtc_irq_line = 432;
for (int i = 0; i < 2; i++)
@@ -45,14 +49,26 @@ void pc88va_state::video_start()
save_item(NAME(m_text_transpen));
save_pointer(NAME(m_video_pri_reg), 2);
- save_pointer(NAME(m_kanjiram), kanjiram_size);
+ save_pointer(NAME(m_gvram), gvram_size);
+ save_pointer(NAME(m_kanji_ram), kanjiram_size);
save_item(NAME(m_vrtc_irq_line));
}
+// TODO: all needs to be verified
+void pc88va_state::video_reset()
+{
+ m_gden0 = false;
+ m_text_transpen = 0;
+ m_screen_ctrl_reg = 0;
+ m_color_mode = 0;
+ m_pltm = 0;
+ m_pltp = 0;
+ m_video_pri_reg[0] = m_video_pri_reg[1] = 0;
+}
+
void pc88va_state::palette_init(palette_device &palette) const
{
- // default palette
const u16 default_palette[16] = {
0x0000, 0x001f, 0x03e0, 0x03ff, 0xfc00, 0xfc1f, 0xffe0, 0xffff,
0x7def, 0x0015, 0x02a0, 0x02b5, 0xac00, 0xac15, 0xaea0, 0xaeb5
@@ -69,7 +85,6 @@ void pc88va_state::palette_init(palette_device &palette) const
}
}
-
uint32_t pc88va_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
uint8_t pri, cur_pri_lv;
@@ -233,6 +248,7 @@ void pc88va_state::draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect)
}
}
+ // TODO: std::function
if(md) // 1bpp mode
{
int fg_col = (tvram[(offs + i + 6) / 2] & 0xf0) >> 4;
@@ -255,19 +271,22 @@ void pc88va_state::draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect)
for(int x_s = 0; x_s < 16; x_s++)
{
int res_x = xp + x_i + x_s;
- // TODO: MG actually doubles Y size
int res_y = (yp + y_i) << m_tsp.spr_mg;
- if (!cliprect.contains(res_x, res_y))
- continue;
-
const u32 data_offset = ((spda + spr_count) & 0xffff) / 2;
u8 pen = (bitswap<16>(tvram[data_offset],7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8) >> (15 - x_s)) & 1;
pen = pen & 1 ? fg_col : (bc) ? 8 : 0;
if(pen != 0)
- bitmap.pix(res_y, res_x) = m_palette->pen(pen + layer_pal_bank);
+ {
+ for (int mg = 0; mg < m_tsp.spr_mg + 1; mg ++)
+ {
+ if (!cliprect.contains(res_x, res_y + mg))
+ continue;
+ bitmap.pix(res_y + mg, res_x) = m_palette->pen(pen + layer_pal_bank);
+ }
+ }
}
spr_count += 2;
@@ -291,16 +310,20 @@ void pc88va_state::draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect)
int res_x = xp + x_i + x_s;
int res_y = (yp + y_i) << m_tsp.spr_mg;
- if (!cliprect.contains(res_x, res_y))
- continue;
-
const u32 data_offset = ((spda + spr_count) & 0xffff) / 2;
int pen = (bitswap<16>(tvram[data_offset],7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8)) >> (12 - (x_s * 4)) & 0xf;
//if (pen != 0 && pen != m_text_transpen)
if (pen != 0)
- bitmap.pix(res_y, res_x) = m_palette->pen(pen + layer_pal_bank);
+ {
+ for (int mg = 0; mg < m_tsp.spr_mg + 1; mg ++)
+ {
+ if (!cliprect.contains(res_x, res_y + mg))
+ continue;
+ bitmap.pix(res_y + mg, res_x) = m_palette->pen(pen + layer_pal_bank);
+ }
+ }
}
spr_count += 2;
@@ -419,20 +442,24 @@ void pc88va_state::draw_text(bitmap_rgb32 &bitmap, const rectangle &cliprect)
rectangle split_cliprect(rxp, rxp + rw - 1, ryp, ryp + rh - 1);
split_cliprect &= cliprect;
+ const int line_height = m_tsp.line_height;
+
+ if (line_height < 8)
+ continue;
+
for(int y = 0; y < vh; y++)
{
- int y_base = y * 16 + ryp - raster_offset;
+ int y_base = y * line_height + ryp - raster_offset;
- // TODO: consult with OG
if (!split_cliprect.contains(rxp, y_base) &&
- !split_cliprect.contains(rxp, y_base + 16))
+ !split_cliprect.contains(rxp, y_base + line_height))
continue;
for(int x = 0; x < vw; x++)
{
int x_base = x * 8;
if (!split_cliprect.contains(x_base, y_base) &&
- !split_cliprect.contains(x_base, y_base + 16))
+ !split_cliprect.contains(x_base, y_base + line_height))
continue;
// TODO: understand where VSA comes into equation
@@ -607,7 +634,7 @@ void pc88va_state::draw_text(bitmap_rgb32 &bitmap, const rectangle &cliprect)
if(!split_cliprect.contains(res_x, res_y))
continue;
- int pen = m_kanjiram[(( yi * 2 ) + lr_half_gfx) + tile_num] >> (7 - xi) & 1;
+ int pen = m_kanji_ram[(( yi * 2 ) + lr_half_gfx) + tile_num] >> (7 - xi) & 1;
if(reverse)
pen = pen & 1 ? bg_col : fg_col;
@@ -679,8 +706,12 @@ void pc88va_state::draw_text(bitmap_rgb32 &bitmap, const rectangle &cliprect)
void pc88va_state::draw_graphic_layer(bitmap_rgb32 &bitmap, const rectangle &cliprect, u8 which)
{
+ // Master graphic enable
+ if (!m_gden0)
+ return;
+
// disable graphic B if screen 0 only setting is enabled
- if (which > m_ymmd)
+ if (which && !m_ymmd)
return;
// ditto for 5bpp color mode
@@ -692,9 +723,13 @@ void pc88va_state::draw_graphic_layer(bitmap_rgb32 &bitmap, const rectangle &cli
const u8 gfx_ctrl = (m_gfx_ctrl_reg >> (which * 8)) & 0x13;
- // TODO: xak2 wants independent doubled Y axis on setup menu & Micro Cabin logo
- // i.e. 200 lines draw on a 400 lines canvas
+ // H320 setting
const u32 pixel_size = 0x10000 >> BIT(gfx_ctrl, 4);
+ // xak2/fray/boomer all sets independent doubled Y axis
+ // i.e. 200 lines draw on a 400 lines canvas
+ const int v_sizes[4] = { 400, 408, 200, 204 };
+ const u32 line_size = (0x10000 * v_sizes[m_vw]) / m_screen->visible_area().height();
+ //popmessage("%08x %d %d %d", line_size, m_screen->visible_area().height(), m_vw, BIT(m_screen_ctrl_reg, 7));
const u8 layer_pal_bank = get_layer_pal_bank(2 + which);
@@ -704,6 +739,7 @@ void pc88va_state::draw_graphic_layer(bitmap_rgb32 &bitmap, const rectangle &cli
, layer_pal_bank
);
+// m_graphic_bitmap[which].fill(m_palette->pen(layer_pal_bank), cliprect);
m_graphic_bitmap[which].fill(0, cliprect);
const int layer_inc = (!is_5bpp) + 1;
@@ -725,9 +761,13 @@ void pc88va_state::draw_graphic_layer(bitmap_rgb32 &bitmap, const rectangle &cli
// (almost likely an HW quirk, described in the docs)
// also animefrm swaps this with layer 2 (main canvas)
const u32 fsa = (layer_n == layer_fixed) ? 0x20000
- : (fb_strip_regs[0x00 / 2] & 0xfffc) | ((fb_strip_regs[0x02 / 2] & 0x3) << 16) >> 1;
+ : (fb_strip_regs[0x00 / 2] & 0xfffc) | ((fb_strip_regs[0x02 / 2] & 0x3) << 16);
+
+ u16 fbl = (fb_strip_regs[0x06 / 2] & 0x3ff) + 1;
+ // shinraba relies on this for Graphic B, assume same behaviour of upd7220 pc98:madoum*
+ if (fbl == 1)
+ fbl = 0x400;
- const u16 fbl = (fb_strip_regs[0x06 / 2] & 0x3ff) + 1;
const u8 x_dot_offs = fb_strip_regs[0x08 / 2];
const u16 ofx = fb_strip_regs[0x0a / 2] & 0x7fc;
const u16 ofy = fb_strip_regs[0x0c / 2] & 0x3ff;
@@ -737,7 +777,7 @@ void pc88va_state::draw_graphic_layer(bitmap_rgb32 &bitmap, const rectangle &cli
LOGFB("%d %08x FSA|\n\t%d FBW | %d FBL |\n\t %d OFX (%d dot)| %d OFY|\n\t %08x DSA|\n\t %04x (%d) DSH | %04x (%d) DSP\n"
, layer_n
- , fsa << 1
+ , fsa
, fbw
, fbl
, ofx
@@ -758,11 +798,19 @@ void pc88va_state::draw_graphic_layer(bitmap_rgb32 &bitmap, const rectangle &cli
rectangle fb_cliprect(cliprect.min_x, cliprect.max_x, dsp, dsp + fbl - 1);
split_cliprect &= fb_cliprect;
+ if (split_cliprect.empty())
+ continue;
+
+ // TODO: picture mask
+
if (!m_dm)
{
switch(gfx_ctrl & 3)
{
- case 1: draw_packed_gfx_4bpp(m_graphic_bitmap[which], split_cliprect, fsa, dsa, layer_pal_bank, fbw, fbl); break;
+ case 1: draw_packed_gfx_4bpp(m_graphic_bitmap[which], split_cliprect, fsa, dsa, ofx, layer_pal_bank, fbw, fbl); break;
+ default:
+ popmessage("pc88va_v.cpp: unhandled %d GFX mode DM = 0 (Multiplane)", which);
+ break;
}
}
else
@@ -770,33 +818,35 @@ void pc88va_state::draw_graphic_layer(bitmap_rgb32 &bitmap, const rectangle &cli
switch(gfx_ctrl & 3)
{
//case 0: draw_indexed_gfx_1bpp(bitmap, cliprect, dsa, layer_pal_bank); break;
- case 1: draw_indexed_gfx_4bpp(m_graphic_bitmap[which], split_cliprect, fsa, dsa, layer_pal_bank, fbw, fbl); break;
+ case 1: draw_indexed_gfx_4bpp(m_graphic_bitmap[which], split_cliprect, fsa, dsa, dsp, ofx, layer_pal_bank, fbw, fbl); break;
case 2:
- if (m_pltm == 7)
+ if (is_5bpp)
{
- draw_packed_gfx_5bpp(m_graphic_bitmap[which], split_cliprect, fsa, dsa, layer_pal_bank, fbw, fbl);
+ draw_packed_gfx_5bpp(m_graphic_bitmap[which], split_cliprect, fsa, dsa, dsp, ofx, layer_pal_bank, fbw, fbl);
}
else
- draw_direct_gfx_8bpp(m_graphic_bitmap[which], split_cliprect, fsa, fbw, fbl);
+ draw_direct_gfx_8bpp(m_graphic_bitmap[which], split_cliprect, fsa, dsa, dsp, ofx, fbw, fbl);
+ break;
+ case 3: draw_direct_gfx_rgb565(m_graphic_bitmap[which], split_cliprect, fsa, dsa, ofx, fbw, fbl); break;
+ default:
+ popmessage("pc88va_v.cpp: unhandled %d GFX mode DM = 1 (Singleplane)", which);
break;
- case 3: draw_direct_gfx_rgb565(m_graphic_bitmap[which], split_cliprect, fsa, fbw, fbl); break;
}
}
}
- // TODO: we eventually need primask_copyrozbitmap_trans here, or a custom copy, depending on what the "transpen" registers really do.
+ // TODO: primask_copyrozbitmap_trans
copyrozbitmap_trans(
bitmap, cliprect, m_graphic_bitmap[which],
0, 0,
- pixel_size, 0, 0, pixel_size,
+ pixel_size, 0, 0, line_size,
false, 0
);
}
+// TODO: incomplete
void pc88va_state::draw_indexed_gfx_1bpp(bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 fb_start_offset, u8 pal_base)
{
- uint8_t *gvram = (uint8_t *)m_gvram.target();
-
for(int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
const u32 line_offset = (((y * 640) / 8) + fb_start_offset) & 0x3ffff;
@@ -804,11 +854,11 @@ void pc88va_state::draw_indexed_gfx_1bpp(bitmap_rgb32 &bitmap, const rectangle &
for(int x = cliprect.min_x; x <= cliprect.max_x; x += 8)
{
u16 x_char = (x >> 3);
- u32 bitmap_offset = line_offset + x_char;
+ u32 bitmap_offset = (line_offset + x_char) & 0x3ffff;
for (int xi = 0; xi < 8; xi ++)
{
- uint32_t color = (gvram[bitmap_offset] >> (7 - xi)) & 1;
+ uint32_t color = (m_gvram[bitmap_offset] >> (7 - xi)) & 1;
int res_x = x + xi;
if(color && cliprect.contains(res_x, y))
@@ -818,27 +868,27 @@ void pc88va_state::draw_indexed_gfx_1bpp(bitmap_rgb32 &bitmap, const rectangle &
}
}
-void pc88va_state::draw_indexed_gfx_4bpp(bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 fb_start_offset, u32 display_start_offset, u8 pal_base, u16 fb_width, u16 fb_height)
+void pc88va_state::draw_indexed_gfx_4bpp(bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 fb_start_offset, u32 display_start_offset, u16 dsp_start_base, u16 scrollx, u8 pal_base, u16 fb_width, u16 fb_height)
{
- uint8_t *gvram = (uint8_t *)m_gvram.target();
-
// const u16 y_min = std::max(cliprect.min_y, y_start);
// const u16 y_max = std::min(cliprect.max_y, y_min + fb_height);
//printf("%d %d %d %08x %d\n", y_min, y_max, fb_width, start_offset, fb_height);
+ const u32 base_address = (fb_start_offset & 0x20000) | (display_start_offset & 0x1ffff);
+
for(int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
- const u32 line_offset = ((y * fb_width) + fb_start_offset) & 0x3ffff;
+ const u32 line_offset = (((y - dsp_start_base) * fb_width) + base_address) & 0x3ffff;
for(int x = cliprect.min_x; x <= cliprect.max_x; x += 2)
{
u16 x_char = (x >> 1);
- u32 bitmap_offset = line_offset + x_char;
+ u32 bitmap_offset = (line_offset + x_char - (scrollx >> 6)) & 0x3ffff;
for (int xi = 0; xi < 2; xi ++)
{
- u8 color = (gvram[bitmap_offset] >> (xi ? 0 : 4)) & 0xf;
+ u8 color = (m_gvram[bitmap_offset] >> (xi ? 0 : 4)) & 0xf;
if(color && cliprect.contains(x + xi, y))
bitmap.pix(y, x + xi) = m_palette->pen(color + pal_base);
@@ -847,24 +897,23 @@ void pc88va_state::draw_indexed_gfx_4bpp(bitmap_rgb32 &bitmap, const rectangle &
}
}
-void pc88va_state::draw_packed_gfx_5bpp(bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 fb_start_offset, u32 display_start_offset, u8 pal_base, u16 fb_width, u16 fb_height)
+void pc88va_state::draw_packed_gfx_5bpp(bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 fb_start_offset, u32 display_start_offset, u16 dsp_start_base, u16 scrollx, u8 pal_base, u16 fb_width, u16 fb_height)
{
- uint8_t *gvram = (uint8_t *)m_gvram.target();
-
// const u16 y_min = std::max(cliprect.min_y, y_start);
// const u16 y_max = std::min(cliprect.max_y, y_min + fb_height);
//printf("%d %d %d %08x %d\n", y_min, y_max, fb_width, start_offset, fb_height);
+ const u32 base_address = (fb_start_offset & 0x20000) | (display_start_offset & 0x1ffff);
for(int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
- const u32 line_offset = ((y * fb_width) + fb_start_offset) & 0x3ffff;
+ const u32 line_offset = (((y - dsp_start_base) * fb_width) + base_address) & 0x3ffff;
for(int x = cliprect.min_x; x <= cliprect.max_x; x++)
{
- u32 bitmap_offset = line_offset + x;
+ u32 bitmap_offset = (line_offset + x - (scrollx >> 6)) & 0x3ffff;
- u8 color = gvram[bitmap_offset] & 0x1f;
+ u8 color = m_gvram[bitmap_offset] & 0x1f;
if(color && cliprect.contains(x, y))
bitmap.pix(y, x) = m_palette->pen(color);
@@ -872,22 +921,21 @@ void pc88va_state::draw_packed_gfx_5bpp(bitmap_rgb32 &bitmap, const rectangle &c
}
}
-void pc88va_state::draw_direct_gfx_8bpp(bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 fb_start_offset, u16 fb_width, u16 fb_height)
+void pc88va_state::draw_direct_gfx_8bpp(bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 fb_start_offset, u32 display_start_offset, u16 dsp_start_base, u16 scrollx, u16 fb_width, u16 fb_height)
{
- uint8_t *gvram = (uint8_t *)m_gvram.target();
-
// const u16 y_min = std::max(cliprect.min_y, y_start);
// const u16 y_max = std::min(cliprect.max_y, y_min + fb_height);
+ const u32 base_address = (fb_start_offset & 0x20000) | (display_start_offset & 0x1ffff);
for(int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
- const u32 line_offset = ((y * fb_width) + fb_start_offset) & 0x3ffff;
+ const u32 line_offset = (((y - dsp_start_base) * fb_width) + base_address) & 0x3ffff;
for(int x = cliprect.min_x; x <= cliprect.max_x; x++)
{
- u32 bitmap_offset = line_offset + x;
+ u32 bitmap_offset = (line_offset + x - (scrollx >> 6)) & 0x3ffff;
- uint32_t color = (gvram[bitmap_offset] & 0xff);
+ uint32_t color = (m_gvram[bitmap_offset] & 0xff);
// boomer suggests that transparency is calculated over just color = 0, may be settable?
// TODO: may not be clamped to palNbit
@@ -902,22 +950,22 @@ void pc88va_state::draw_direct_gfx_8bpp(bitmap_rgb32 &bitmap, const rectangle &c
}
}
-void pc88va_state::draw_direct_gfx_rgb565(bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 fb_start_offset, u16 fb_width, u16 fb_height)
+void pc88va_state::draw_direct_gfx_rgb565(bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 fb_start_offset, u32 display_start_offset, u16 scrollx, u16 fb_width, u16 fb_height)
{
- uint8_t *gvram = (uint8_t *)m_gvram.target();
-
// const u16 y_min = std::max(cliprect.min_y, y_start);
// const u16 y_max = std::min(cliprect.max_y, y_min + fb_height);
+ const u32 base_address = (display_start_offset & 0x3ffff);
for(int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
- const u32 line_offset = ((y * fb_width) + fb_start_offset) & 0x3ffff;
+ // pc88vad requires halved pitch for first screen
+ const u32 line_offset = ((y * fb_width >> 1) + base_address) & 0x3ffff;
for(int x = cliprect.min_x; x <= cliprect.max_x; x++)
{
- u32 bitmap_offset = (line_offset + x) << 1;
+ u32 bitmap_offset = ((line_offset + x - (scrollx >> 1)) << 1) & 0x3ffff;
- uint16_t color = (gvram[bitmap_offset] & 0xff) | (gvram[bitmap_offset + 1] << 8);
+ uint16_t color = (m_gvram[bitmap_offset] & 0xff) | (m_gvram[bitmap_offset + 1] << 8);
if(cliprect.contains(x, y))
{
@@ -930,27 +978,28 @@ void pc88va_state::draw_direct_gfx_rgb565(bitmap_rgb32 &bitmap, const rectangle
}
}
-void pc88va_state::draw_packed_gfx_4bpp(bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 fb_start_offset, u32 display_start_offset, u8 pal_base, u16 fb_width, u16 fb_height)
+// famista, all inufuto games
+void pc88va_state::draw_packed_gfx_4bpp(bitmap_rgb32 &bitmap, const rectangle &cliprect, u32 fb_start_offset, u32 display_start_offset, u16 scrollx, u8 pal_base, u16 fb_width, u16 fb_height)
{
- uint8_t *gvram = (uint8_t *)m_gvram.target();
-
// const u16 y_min = std::max(cliprect.min_y, y_start);
// const u16 y_max = std::min(cliprect.max_y, y_min + fb_height);
+ const u32 base_offset = display_start_offset >> 2;
+
for(int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
- const u32 line_offset = ((y * (fb_width >> 2)) + fb_start_offset) & 0x0ffff;
+ const u32 line_offset = ((y * (fb_width >> 2)) + base_offset) & 0x0ffff;
for(int x = cliprect.min_x; x <= cliprect.max_x; x += 8)
{
u16 x_char = (x >> 3);
- u32 bitmap_offset = line_offset + x_char;
+ u32 bitmap_offset = (line_offset + x_char - (scrollx >> 2)) & 0x0ffff;
for (int xi = 0; xi < 8; xi ++)
{
u8 color = 0;
for (int bank_num = 0; bank_num < 4; bank_num ++)
- color |= ((gvram[bitmap_offset + bank_num * 0x10000] >> (7 - xi)) & 1) << bank_num;
+ color |= ((m_gvram[bitmap_offset + bank_num * 0x10000] >> (7 - xi)) & 1) << bank_num;
if(color && cliprect.contains(x + xi, y))
bitmap.pix(y, x + xi) = m_palette->pen(color + pal_base);
@@ -1141,21 +1190,29 @@ void pc88va_state::execute_sync_cmd()
// olteus will punt loading on PC Engine OS if the vblank bit is completely off
// illcity expects the actual IDP vblank bit to work, from setup menu to opening transition PC=0x418f6
// upo wants precise vblank bit readouts plus something else (SGP irq?)
-
- rectangle visarea;
- attoseconds_t refresh;
-
+ // TODO: verify fray
LOGCRTC("IDP SYNC: ");
for (int i = 0; i < 15; i++)
+ {
LOGCRTC("%02x ", m_buf_ram[i]);
+ m_crtc_regs[i] = m_buf_ram[i];
+ }
+
+ recompute_parameters();
+}
+
+void pc88va_state::recompute_parameters()
+{
+ rectangle visarea;
+ attoseconds_t refresh;
- const u8 h_blank_start = (m_buf_ram[0x02] & 0x3f) + 1;
- const u8 h_border_start = (m_buf_ram[0x03] & 0x3f) + 1;
- const u16 h_vis_area = (m_buf_ram[0x04] + 1) * 4;
- const u8 h_border_end = (m_buf_ram[0x05] & 0x3f) + 1;
- const u8 h_blank_end = (m_buf_ram[0x06] & 0x3f) + 1;
- const u8 h_sync = (m_buf_ram[0x07] & 0x3f) + 1;
+ const u8 h_blank_start = (m_crtc_regs[0x02] & 0x3f) + 1;
+ const u8 h_border_start = (m_crtc_regs[0x03] & 0x3f) + 1;
+ const u16 h_vis_area = (m_crtc_regs[0x04] + 1) * 4;
+ const u8 h_border_end = (m_crtc_regs[0x05] & 0x3f) + 1;
+ const u8 h_blank_end = (m_crtc_regs[0x06] & 0x3f) + 1;
+ const u8 h_sync = (m_crtc_regs[0x07] & 0x3f) + 1;
LOGCRTC("\n\t");
LOGCRTC("H blank start %d - end %d|", h_blank_start, h_blank_end);
@@ -1170,23 +1227,32 @@ void pc88va_state::execute_sync_cmd()
LOGCRTC("H Total calc = %d", h_total);
LOGCRTC("\n\t");
- const u8 v_blank_start = m_buf_ram[0x08] & 0x3f;
- const u8 v_border_start = m_buf_ram[0x09] & 0x3f;
- const u16 v_vis_area = (m_buf_ram[0x0a]) | ((m_buf_ram[0x0b] & 0x40) << 2);
- const u8 v_border_end = m_buf_ram[0x0b] & 0x3f;
- const u8 v_blank_end = m_buf_ram[0x0c] & 0x3f;
- const u8 v_sync = (m_buf_ram[0x0d] & 0x3f);
+ const u8 v_blank_start = m_crtc_regs[0x08] & 0x3f;
+ const u8 v_border_start = m_crtc_regs[0x09] & 0x3f;
+ u16 v_vis_area = (m_crtc_regs[0x0a]) | ((m_crtc_regs[0x0b] & 0x40) << 2);
+ const u8 v_border_end = m_crtc_regs[0x0b] & 0x3f;
+ const u8 v_blank_end = m_crtc_regs[0x0c] & 0x3f;
+ const u8 v_sync = (m_crtc_regs[0x0d] & 0x3f);
LOGCRTC("V blank start %d - end %d|", v_blank_start, v_blank_end);
LOGCRTC("V visible area: %d|", v_vis_area);
- LOGCRTC("V border start: %d - end %d|", v_border_start, v_border_end);
+ LOGCRTC("V border start %d - end %d|", v_border_start, v_border_end);
LOGCRTC("V sync: %d", v_sync);
LOGCRTC("\n\t");
m_vrtc_irq_line = v_blank_start + v_blank_end + v_vis_area + v_border_start + v_border_end;
- const u16 v_total = m_vrtc_irq_line + v_sync;
+ u16 v_total = m_vrtc_irq_line + v_sync;
+
+ LOGCRTC("V Total calc = %d (VRTC %d)", v_total, m_vrtc_irq_line);
- LOGCRTC("V Total calc = %d (VRTC %d)\n", v_total, m_vrtc_irq_line);
+ if (BIT(m_screen_ctrl_reg, 7))
+ {
+ m_vrtc_irq_line <<= 1;
+ v_total <<= 1;
+ v_vis_area <<= 1;
+ LOGCRTC(" (Interlace)");
+ }
+ LOGCRTC("\n");
// punt with message if values are off (shouldn't happen)
// TODO: more validation:
@@ -1205,9 +1271,11 @@ void pc88va_state::execute_sync_cmd()
visarea.set(0, h_vis_area - 1, 0, v_vis_area - 1);
- // TODO: interlace / vertical magnify, bit 7
- // TODO: actual clock source must be external, assume known PC-88 XTALs, a bit off compared to PC-88 with the values above
- const int clock_speed = BIT(m_buf_ram[0x00], 6) ? (31'948'800 / 4) : (28'636'363 / 2);
+ // TODO: vertical global magnify at bit 7
+ // TODO: actual clock source must be external, assume known PC-88 XTALs
+ // TODO: a bit off compared to PC-88 equivalent with the configured values
+ // TODO: famista pukes a 31.2 Hz vertical in 24kHz mode
+ const int clock_speed = !!BIT(m_crtc_regs[0x00], 6) ? (31'948'800 / 4) : (28'636'363 / 2);
refresh = HZ_TO_ATTOSECONDS(clock_speed) * h_vis_area * v_vis_area;
@@ -1263,7 +1331,7 @@ void pc88va_state::execute_dspdef_cmd()
m_tsp.blink = (m_buf_ram[5] & 0xf8);
if (m_tsp.blink == 0)
m_tsp.blink = 0x100;
- LOGIDP("DSPDEF (%02x %02x %02x %02x %02x %02x) %05x ATTR | %02x pitch | %02x line height| %02x hline | %d blink rate\n"
+ LOGIDP("DSPDEF (%02x %02x %02x %02x %02x %02x) %05x ATTR | %d pitch | %d line height| %d hline | %d blink rate\n"
, m_buf_ram[0], m_buf_ram[1], m_buf_ram[2], m_buf_ram[3], m_buf_ram[4], m_buf_ram[5]
, m_tsp.attr_offset | 0x40000
, m_tsp.pitch
@@ -1462,12 +1530,23 @@ void pc88va_state::idp_param_w(uint8_t data)
*/
void pc88va_state::screen_ctrl_w(offs_t offset, u16 data, u16 mem_mask)
{
+ // Interlace mode (inufuto games), cheat for now.
+ if (BIT(data, 7) != BIT(m_screen_ctrl_reg, 7))
+ {
+ recompute_parameters();
+ }
+
COMBINE_DATA(&m_screen_ctrl_reg);
- m_ymmd = bool(BIT(m_screen_ctrl_reg, 11));
- m_dm = bool(BIT(m_screen_ctrl_reg, 10));
// YMMD DM
// mightmag 0xb060 (0) screen 0 (0) multiplane
+ m_gden0 = !!(BIT(m_screen_ctrl_reg, 15));
+ m_ymmd = !!(BIT(m_screen_ctrl_reg, 11));
+ m_dm = !!(BIT(m_screen_ctrl_reg, 10));
+
+ m_vw = m_screen_ctrl_reg & 3;
+ if (m_vw & 1)
+ popmessage("pc88va_v.cpp: VW = %d (408/204 lines mode)", m_vw);
}
u16 pc88va_state::screen_ctrl_r()
@@ -1597,6 +1676,19 @@ void pc88va_state::text_transpen_w(offs_t offset, u16 data, u16 mem_mask)
popmessage("text transpen > 15 (%04x)", m_text_transpen);
}
+void pc88va_state::picture_mask_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ switch(offset)
+ {
+ case 0: COMBINE_DATA(&m_picture_mask.left); m_picture_mask.left &= 0x3ff; break;
+ case 1: COMBINE_DATA(&m_picture_mask.right); m_picture_mask.right &= 0x3ff; break;
+ case 2: COMBINE_DATA(&m_picture_mask.top); m_picture_mask.top &= 0xff; break;
+ case 3: COMBINE_DATA(&m_picture_mask.bottom); m_picture_mask.bottom &= 0xff; break;
+ }
+
+// popmessage("x0 %d y0 %d - x1 %d y1 %d", m_picture_mask.left, m_picture_mask.top, m_picture_mask.right, m_picture_mask.bottom);
+}
+
/*
* $14c-$14f Kanji CG ports
* Alt method for access kanji ROM for drawing to graphic layers
@@ -1615,7 +1707,7 @@ u8 pc88va_state::kanji_cg_r()
// jis2 = 0x21 / 0x22 "PC" on hovered top status bar for animefrm
// NB: software reverts the two chars once it gets upped to bitmap layer.
const u32 pcg_addr = ((m_kanji_cg_jis[1] & 0x1f) + ((m_kanji_cg_jis[1] & 0x60) << 1)) * 0x20;
- return m_kanjiram[pcg_addr + (m_kanji_cg_line << 1) + (m_kanji_cg_lr ^ 1)];
+ return m_kanji_ram[pcg_addr + (m_kanji_cg_line << 1) + (m_kanji_cg_lr ^ 1)];
}
const u32 kanji_address = calc_kanji_rom_addr(m_kanji_cg_jis[0] + 0x20, m_kanji_cg_jis[1], 0, 0);
@@ -1652,3 +1744,157 @@ void pc88va_state::text_control_1_w(u8 data)
if ((data & 0x7d) != 1)
LOG("I/O $148 write %02x\n", data);
}
+
+
+/****************************************
+ * GVRAM
+ ***************************************/
+
+u8 pc88va_state::rop_execute(u8 plane_rop, u8 src, u8 dst, u8 pat)
+{
+ u8 res = 0;
+
+ for (int i = 0; i < 8; i++)
+ {
+ if (BIT(plane_rop, i))
+ {
+ u8 src_data = BIT(i, 0) ? src : ~src;
+ u8 dst_data = BIT(i, 1) ? dst : ~dst;
+ u8 pat_data = BIT(i, 2) ? pat : ~pat;
+ res |= src_data & dst_data & pat_data;
+ }
+ }
+ return res;
+}
+
+u8 pc88va_state::gvram_multiplane_r(offs_t offset)
+{
+ if (m_multiplane.aacc)
+ {
+ u32 address = (offset & 0x7fff) | (m_multiplane.gmap << 15);
+ u8 res = 0xff;
+ for (int plane = 0; plane < 4; plane++)
+ {
+ if (!BIT(m_multiplane.xrpm, plane))
+ {
+ const u8 src = m_gvram[address | plane * 0x10000];
+ // Comparison enable
+ if (m_multiplane.cmpen)
+ res &= ~(src ^ m_multiplane.cmpr[plane]);
+ else
+ res &= src;
+
+ // update on reads
+ if (BIT(m_multiplane.pmod, 0) && !machine().side_effects_disabled())
+ {
+ m_multiplane.patr[plane][BIT(m_multiplane.prwp, plane)] = src;
+ }
+ }
+ }
+
+ // flip register write index on 16-bit mode
+ if ((m_multiplane.pmod & 5) == 5 && !machine().side_effects_disabled())
+ {
+ m_multiplane.prwp ^= 0xf;
+ }
+
+ return res;
+ }
+
+ return m_gvram[offset];
+}
+
+void pc88va_state::gvram_multiplane_w(offs_t offset, u8 data)
+{
+ if (m_multiplane.aacc)
+ {
+ u32 address = (offset & 0x7fff) | (m_multiplane.gmap << 15);
+ for (int plane = 0; plane < 4; plane++)
+ {
+ if (!BIT(m_multiplane.xwpm, plane))
+ {
+ switch(m_multiplane.wss & 3)
+ {
+ // ROP
+ case 0:
+ {
+ const u8 src = m_gvram[address | plane * 0x10000];
+ m_gvram[address | plane * 0x10000] = rop_execute(
+ m_multiplane.rop[plane],
+ src,
+ data,
+ m_multiplane.patr[plane][BIT(m_multiplane.prrp, plane)]
+ );
+
+ // update pattern on writes
+ if (BIT(m_multiplane.pmod, 1))
+ {
+ m_multiplane.patr[plane][BIT(m_multiplane.prwp, plane)] = src;
+ }
+ break;
+ }
+ // Pattern
+ case 1:
+ m_gvram[address | plane * 0x10000] = m_multiplane.patr[plane][BIT(m_multiplane.prrp, plane)];
+ break;
+ // Normal writes
+ case 2:
+ m_gvram[address | plane * 0x10000] = data;
+ break;
+ // NOP
+ case 3:
+ break;
+ }
+ }
+ }
+
+ // flip register indices on 16-bit mode
+ if (BIT(m_multiplane.pmod, 2))
+ {
+ m_multiplane.prrp ^= 0xf;
+ if (BIT(m_multiplane.pmod, 1))
+ m_multiplane.prwp ^= 0xf;
+ }
+ return;
+ }
+
+ m_gvram[offset] = data;
+}
+
+u8 pc88va_state::gvram_singleplane_r(offs_t offset)
+{
+ // apparently no side effects on reads
+ return m_gvram[offset];
+}
+
+void pc88va_state::gvram_singleplane_w(offs_t offset, u8 data)
+{
+ const u8 page_bank = BIT(offset, 17);
+ switch(m_singleplane.wss & 3)
+ {
+ // ROP
+ case 0:
+ {
+ const u8 src = m_gvram[offset];
+ m_gvram[offset] = rop_execute(
+ m_singleplane.rop[page_bank],
+ src,
+ data,
+ m_singleplane.patr[page_bank]
+ );
+ break;
+ }
+ // Pattern
+ case 1:
+ m_gvram[offset] = m_singleplane.patr[page_bank];
+ break;
+ // Normal writes
+ case 2:
+ m_gvram[offset] = data;
+ break;
+ // NOP
+ case 3:
+ break;
+ }
+}
+