diff options
Diffstat (limited to 'src/mame/nec/pc88va_v.cpp')
-rw-r--r-- | src/mame/nec/pc88va_v.cpp | 438 |
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; + } +} + |