diff options
Diffstat (limited to 'src/mame/video/namcos22.cpp')
-rw-r--r-- | src/mame/video/namcos22.cpp | 792 |
1 files changed, 436 insertions, 356 deletions
diff --git a/src/mame/video/namcos22.cpp b/src/mame/video/namcos22.cpp index da5ceb60a56..78060588b4a 100644 --- a/src/mame/video/namcos22.cpp +++ b/src/mame/video/namcos22.cpp @@ -14,9 +14,11 @@ namcos22_renderer::namcos22_renderer(namcos22_state &state) : poly_manager<float, namcos22_object_data, 4, 8000>(state.machine()), m_state(state) - { } + { + init(); + } -void namcos22_renderer::reset() +void namcos22_renderer::init() { memset(&m_scenenode_root, 0, sizeof(m_scenenode_root)); m_scenenode_cur = nullptr; @@ -75,7 +77,7 @@ void namcos22_renderer::renderscanline_uvi_full(int32_t scanline, const extent_t } // slight differences between super and non-super, do the branch here for optimization - // normal: 1 fader, no alpha, shading after fog + // normal: no alpha, shading after fog, global fader // super: 2 faders, alpha, shading before fog if (m_state.m_is_ss22) { @@ -172,11 +174,6 @@ void namcos22_renderer::renderscanline_uvi_full(int32_t scanline, const extent_t int shade = i*ooz; rgb.scale_imm_and_clamp(shade << 2); - if (polyfade_enabled) - { - rgb.scale_and_clamp(polycolor); - } - dest[x] = rgb.to_rgba(); primap[x] |= prioverchar; @@ -272,10 +269,11 @@ void namcos22_renderer::poly3d_drawquad(screen_device &screen, bitmap_rgb32 &bit m_clipx = cx; m_clipy = cy; m_cliprect.set( - std::max<s32>(cx + node->data.quad.vw, 0), - std::min<s32>(cx - node->data.quad.vw, 639), - std::max<s32>(cy + node->data.quad.vh, 0), - std::min<s32>(cy - node->data.quad.vh, 479)); + std::max<s32>(cx + node->data.quad.vw, 0), + std::min<s32>(cx - node->data.quad.vw, 639), + std::max<s32>(cy + node->data.quad.vh, 0), + std::min<s32>(cy - node->data.quad.vh, 479) + ); // non-direct case: project and z-clip if (!direct) @@ -336,83 +334,29 @@ void namcos22_renderer::poly3d_drawquad(screen_device &screen, bitmap_rgb32 &bit extra.pfade_enabled = m_state.m_poly_fade_enabled; extra.polycolor.set(0, m_state.m_poly_fade_r, m_state.m_poly_fade_g, m_state.m_poly_fade_b); - /* poly fog (not completely accurate yet) - - czram contents, it's basically a big cz compare table - - testmode: - o_16 0 1 2 3 4 5 6 7 < > f8 f9 fa fb fc fd fe ff - czram[0] = 1fff 1fdf 1fbf 1f9f 1f7f 1f5f 1f3f 1f1f .... 00ff 00df 00bf 009f 007f 005f 003f 001f - czram[1] = 0000 0000 0000 0001 0002 0003 0005 0007 .... 1e45 1e83 1ec2 1f01 1f40 1f7f 1fbf 1fff - czram[2] = 003f 007f 00be 00fd 013c 017b 01b9 01f7 .... 1ff9 1ffb 1ffc 1ffd 1ffe 1fff 1fff 1fff - czram[3] = 0000 001f 003f 005f 007f 009f 00bf 00df .... 1eff 1f1f 1f3f 1f5f 1f7f 1f9f 1fbf 1fdf - - airco22b demo mode, fog color: 76 9a c3 - o_16 0 1 2 3 4 5 6 7 < > f8 f9 fa fb fc fd fe ff - czram[0] = 0000 00e4 0141 0189 01c6 01fb 022c 0258 .... 13bb 13c4 13cd 13d6 13df 13e7 13f0 13f9 - - alpinerd (1st course), fog color: c8 c8 c8 - o_16 0 1 2 3 4 5 6 7 < > ec ed ee ef f0 f1 f2 - ff - czram[0] = 00c8 00ca 00cc 00ce 00d0 00d2 00d4 00d6 .... 02a0 02a2 02a4 02a6 02a8 1fff 1fff .... - - alpinr2b (1st course), fog color: ff ff ff - alpinr2b start of race: - gets gradually filled from left to right, initial contents filled with 1fff? - game should be foggy here - o_16 0 1 2 3 4 5 6 7 < > 67 68 69 6a 6b 6c 6d - ff - czram[0] = 01cd 01d7 01e1 01eb 01f5 01ff 0209 0213 .... 05d3 05dd 05e7 05f1 05fb 1fff 1fff .... - other banks unused, zerofilled - alpinr2b mid race: - gets gradually filled from right to left, initial contents above - game should not be foggy here - o_16 0 1 2 3 4 5 6 7 < > ec ed ee ef f0 f1 f2 - ff - czram[0] = 1ffe 1fff 1fff 1fff 1fff 1fff 1fff 1fff .... 1fff 1fff 1fff 1fff 1fff 1fff 1fff 1fff - - cybrcycc (1st course), fog color: 80 80 c0 - 2nd course has same cz table, but fog color 00 00 00 - o_16 0 1 2 3 4 5 6 7 < > d4 d5 d6 d7 d8 d9 da - ff - czram[0] = 0000 0011 0021 0031 0041 0051 0060 0061 .... 04e0 04e4 04e7 04eb 04ee 1fff 1fff .... - - tokyowar, fog color: 80 c0 ff - it uses cztype 1 too by accident? (becomes fogfactor 0) - o_16 0 1 2 3 4 5 6 7 < > f8 f9 fa fb fc fd fe ff - czram[0] = 0000 01c5 0244 029f 02e7 0325 035b 038b .... 0eaf 0ec7 0ee0 0efc 0f1b 0f3f 0f6a 0faa - czram[1] = 0000 0000 0000 0000 0000 0000 0000 0000 .... 0000 0000 0000 0000 0000 0000 0000 0000 - czram[2] = 0000 0000 0000 0000 0000 0000 0000 0000 .... 0000 0000 0000 0000 0000 0000 0000 0000 - czram[3] = 0000 00e8 0191 0206 0265 02b7 0301 0345 .... 1c7e 1cbc 1d00 1d4a 1d9c 1dfb 1e70 1f19 - - */ - - /* czattr: - assumed that it's write-only - 0 2 4 6 8 a c e - ^^^^ ^^^^ ^^^^ ^^^^ cz offset, signed16 per cztype 0,1,2,3 - ^^^^ flags, nybble per cztype 3,2,1,0 - 4 probably means enable - ^^^^ maincpu ram access bank - ^^^^ flags, nybble per cztype 3,2,1,0 - ? - ^^^^ ? (only set sometimes in timecris) - 0000 0000 0000 0000 7555 0000 00e4 0000 // testmode normal - 0=white to black(mid), 1=white to black(weak), 2=white to black(strong), 3=black to white(mid, reverse of 0) - 7fff 8000 7fff 8000 7555 0000 00e4 0000 // testmode offset - 0=black, 1=white, 2=black, 3=white - 0000 0000 0000 0000 3111 0000 00e4 0000 // testmode off - 0=white, 1=white, 2=white, 3=white - 0000 0000 0000 0000 4444 0000 0000 0000 // propcycl solitar - 0004 0004 0004 0004 4444 0000 0000 0000 // propcycl out pool - 00a4 00a4 00a4 00a4 4444 0000 0000 0000 // propcycl in pool - ff80 ff80 ff80 ff80 4444 0000 0000 0000 // propcycl ending - ff80 ff80 ff80 ff80 0000 0000 0000 0000 // propcycl hs entry - 0000 0000 0000 0000 0b6c 0000 00e4 0000 // cybrcycc - 0000 0000 0000 0000 5554 0000 00e4 0000 // airco22b - ff01 ff01 0000 0000 4444 0000 0000 0000 // alpinerd - 0000 0000 0000 0000 4455 0000 000a 0000 // alpinr2b - 8001 8001 0000 0000 1111 0000 5555 0000 // aquajet (reg 8 is either 1111 or 5555, reg c is usually interlaced) - 0000 0000 0000 0000 5554 0000 0000 0000 // tokyowar - */ + // poly fog if (~color & 0x80) { int cztype = flags & 3; - if (nthword(m_state.m_czattr, 4) & (4 << (cztype * 4))) + int bank = m_state.m_czattr[6] >> (cztype * 2) & 3; + int bank_enabled = m_state.m_czattr[4] >> (bank * 4) & 4; + + if (bank_enabled) { - int delta = (s16)nthword(m_state.m_czattr, cztype); + s16 delta = m_state.m_czattr[bank]; + // sign-extend + if (delta < 0) delta |= 0xff00; + else delta &= 0x00ff; + extra.fogcolor.set(0, m_state.m_fog_r, m_state.m_fog_g, m_state.m_fog_b); + if (direct) { int cz = ((flags & 0x1fff00) + cz_adjust) >> 8; if (cz < 0) cz = 0; else if (cz > 0x1fff) cz = 0x1fff; - int fogfactor = m_state.m_recalc_czram[cztype][cz] + delta; + int fogfactor = m_state.m_recalc_czram[bank][cz] + delta; if (fogfactor > 0) { if (fogfactor > 0xff) fogfactor = 0xff; @@ -423,7 +367,7 @@ void namcos22_renderer::poly3d_drawquad(screen_device &screen, bitmap_rgb32 &bit { extra.zfog_enabled = 1; extra.cz_sdelta = delta; - extra.czram = m_state.m_recalc_czram[cztype].get(); + extra.czram = m_state.m_recalc_czram[bank].get(); } } } @@ -431,13 +375,6 @@ void namcos22_renderer::poly3d_drawquad(screen_device &screen, bitmap_rgb32 &bit else { - // global fade - if (m_state.m_mixer_flags & 1) - { - extra.pfade_enabled = m_state.m_poly_fade_enabled; - extra.polycolor.set(0, m_state.m_poly_fade_r, m_state.m_poly_fade_g, m_state.m_poly_fade_b); - } - // poly fog if (~color & 0x80) { @@ -475,6 +412,7 @@ void namcos22_renderer::poly3d_drawsprite( int scalex, int scaley, int cz_factor, int prioverchar, + int fade_enabled, int alpha ) { @@ -525,16 +463,15 @@ void namcos22_renderer::poly3d_drawsprite( vert[3].p[1] = fheight; // global fade - if (m_state.m_mixer_flags & 2) + if (m_state.m_mixer_flags & 2 || fade_enabled) { extra.fadefactor = m_state.m_screen_fade_factor; extra.fadecolor.set(0, m_state.m_screen_fade_r, m_state.m_screen_fade_g, m_state.m_screen_fade_b); } - // fog, 0xfe is a special case for sprite priority over textlayer - if (~color & 0x80 && cz_factor > 0 && cz_factor != 0xfe) + // sprite fog + if (~color & 0x80 && cz_factor > 0) { - // or does it fetch from poly-cz ram? that will break timecris though extra.fogfactor = cz_factor; extra.fogcolor.set(0, m_state.m_fog_r, m_state.m_fog_g, m_state.m_fog_b); } @@ -543,15 +480,15 @@ void namcos22_renderer::poly3d_drawsprite( } } - void namcos22_renderer::render_sprite(screen_device &screen, bitmap_rgb32 &bitmap, struct namcos22_scenenode *node) { // scene clip m_cliprect.set( - std::max<s32>(node->data.sprite.cx_min, 0), - std::min<s32>(node->data.sprite.cx_max, 639), - std::max<s32>(node->data.sprite.cy_min, 0), - std::min<s32>(node->data.sprite.cy_max, 479)); + std::max<s32>(node->data.sprite.cx_min, 0), + std::min<s32>(node->data.sprite.cx_max, 639), + std::max<s32>(node->data.sprite.cy_min, 0), + std::min<s32>(node->data.sprite.cy_max, 479) + ); int offset = 0; @@ -566,19 +503,21 @@ void namcos22_renderer::render_sprite(screen_device &screen, bitmap_rgb32 &bitma code += nthword(&m_state.m_spriteram[0x800/4], offset + node->data.sprite.linktype*4); poly3d_drawsprite( - screen, - bitmap, - code, - node->data.sprite.color, - node->data.sprite.flipx, - node->data.sprite.flipy, - node->data.sprite.xpos + col * node->data.sprite.sizex, - node->data.sprite.ypos + row * node->data.sprite.sizey, - (node->data.sprite.sizex << 16) / 32, - (node->data.sprite.sizey << 16) / 32, - node->data.sprite.cz, - node->data.sprite.pri, - 0xff - node->data.sprite.translucency); + screen, + bitmap, + code, + node->data.sprite.color, + node->data.sprite.flipx, + node->data.sprite.flipy, + node->data.sprite.xpos + col * node->data.sprite.sizex, + node->data.sprite.ypos + row * node->data.sprite.sizey, + (node->data.sprite.sizex << 16) / 32, + (node->data.sprite.sizey << 16) / 32, + node->data.sprite.cz, + node->data.sprite.prioverchar, + node->data.sprite.fade_enabled, + 0xff - node->data.sprite.translucency + ); offset++; } } @@ -720,7 +659,7 @@ float namcos22_state::dspfloat_to_nativefloat(u32 val) return result; } -/* model rendering properties */ +// model rendering properties void namcos22_state::matrix3d_multiply(float a[4][4], float b[4][4]) { float result[4][4]; @@ -847,7 +786,6 @@ void namcos22_state::draw_direct_poly(const u16 *src) if (m_is_ss22) { - cztype ^= 3; // ? not sure, but this makes testmode look like on a pcb (only 1 pcb checked) node->data.quad.cmode = (src[2] & 0x00f0) >> 4; node->data.quad.texturebank = (src[2] & 0x000f); } @@ -997,13 +935,16 @@ void namcos22_state::blit_single_quad(u32 color, u32 addr, float m[4][4], int po { // lighting (prelim) bri = m_LitSurfaceInfo[m_LitSurfaceIndex % m_LitSurfaceCount]; + if (m_SurfaceNormalFormat == 0x6666) { if (i == 3) m_LitSurfaceIndex++; } else if (m_SurfaceNormalFormat == 0x4000) + { m_LitSurfaceIndex++; + } else logerror("blit_single_quad:unknown normal format: 0x%x\n", m_SurfaceNormalFormat); } @@ -1092,14 +1033,10 @@ void namcos22_state::blit_single_quad(u32 color, u32 addr, float m[4][4], int po } -void namcos22_state::blit_quads(int addr, float m[4][4], int base) +void namcos22_state::blit_quads(int addr, int len, float m[4][4]) { -// int additionalnormals = 0; - int chunklength = point_read(addr++); - int finish = addr + chunklength; - - if (chunklength > 0x100) - fatalerror("bad packet length\n"); + //int additionalnormals = 0; + int finish = addr + len; while (addr < finish) { @@ -1156,7 +1093,7 @@ void namcos22_state::blit_quads(int addr, float m[4][4], int base) 000000 000000 007fff // normal vector 000000 000000 007fff // normal vector */ -// additionalnormals = point_read(addr+2); + //additionalnormals = point_read(addr+2); m_SurfaceNormalFormat = point_read(addr + 3); m_LitSurfaceCount = 0; m_LitSurfaceIndex = 0; @@ -1175,7 +1112,8 @@ void namcos22_state::blit_quads(int addr, float m[4][4], int base) break; default: - break; + logerror("blit_quads unknown packet length: addr=0x%06x len=0x%x format=0x%x\n", addr-1, packetlength, packetformat); + return; } addr += packetlength; } @@ -1183,16 +1121,44 @@ void namcos22_state::blit_quads(int addr, float m[4][4], int base) void namcos22_state::blit_polyobject(int code, float m[4][4]) { - int addr1 = point_read(code); + // list start address, code 5 is special case for pointram + int list_addr; + bool pointram = (code == 0x5); + if (pointram) + list_addr = (m_is_ss22) ? 0xf80000 : 0xf00000; + else + list_addr = point_read(code); + m_LitSurfaceCount = 0; m_LitSurfaceIndex = 0; for (;;) { - int addr2 = point_read(addr1++); - if (addr2 < 0) + int object_addr = point_read(list_addr++); + + if (object_addr < 0) + { + if (object_addr == -1) + { + // 0xffffff is end-of-list marker + break; + } + else if (!pointram) + { + logerror("blit_polyobject unexpected end: addr=0x%06x\n", list_addr-1); + break; + } + object_addr &= 0x00ffffff; + } + + u32 chunklength = point_read(object_addr++); + if (chunklength > 0x100) + { + logerror("blit_polyobject bad chunk length: addr=0x%06x len=0x%x\n", object_addr-1, chunklength); break; - blit_quads(addr2, m, code); + } + + blit_quads(object_addr, chunklength, m); } } @@ -1258,11 +1224,11 @@ void namcos22_state::slavesim_handle_bb0003(const s32 *src) m_reflection = src[0x2] >> 16 & 0x30; // z too? m_cullflip = (m_reflection == 0x10 || m_reflection == 0x20); m_absolute_priority = src[0x3] >> 16; - m_camera_vx = (s16)(src[5] >> 16); - m_camera_vy = (s16)(src[5] & 0xffff); - m_camera_zoom = dspfloat_to_nativefloat(src[6]); - m_camera_vw = dspfloat_to_nativefloat(src[7]) * m_camera_zoom; - m_camera_vh = dspfloat_to_nativefloat(src[9]) * m_camera_zoom; + m_camera_vx = (s16)(src[0x5] >> 16); + m_camera_vy = (s16)(src[0x5] & 0xffff); + m_camera_zoom = dspfloat_to_nativefloat(src[0x6]); + m_camera_vw = dspfloat_to_nativefloat(src[0x7]) * m_camera_zoom; + m_camera_vh = dspfloat_to_nativefloat(src[0x9]) * m_camera_zoom; m_viewmatrix[0][0] = dspfixed_to_nativefloat(src[0x0c]); m_viewmatrix[1][0] = dspfixed_to_nativefloat(src[0x0d]); @@ -1280,17 +1246,18 @@ void namcos22_state::slavesim_handle_bb0003(const s32 *src) transform_normal(&m_camera_lx, &m_camera_ly, &m_camera_lz, m_viewmatrix); } -void namcos22_state::slavesim_handle_200002(const s32 *src) +void namcos22_state::slavesim_handle_200002(const s32 *src, int code) { /** * 0xfffd * 0x0: transform * 0x1 * 0x2 - * 0x5: transform - * >=0x45: draw primitive + * 0x5: draw primitive(RAM) + * >=0x45: draw primitive(ROM) */ - if (m_PrimitiveID >= 0x45) + + if (code == 0x5 || code >= 0x45) { float m[4][4]; /* row major */ @@ -1313,12 +1280,11 @@ void namcos22_state::slavesim_handle_200002(const s32 *src) m[3][2] = src[0xc]; /* zpos */ matrix3d_multiply(m, m_viewmatrix); - blit_polyobject(m_PrimitiveID, m); + blit_polyobject(code, m); } - else if (m_PrimitiveID != 0 && m_PrimitiveID != 2) + else if (code != 0 && code != 2) { - logerror("slavesim_handle_200002:unknown code=0x%x\n", m_PrimitiveID); - // ridgerac title screen waving flag: 0x5 + logerror("slavesim_handle_200002:unknown code=0x%x\n", code); } } @@ -1371,12 +1337,12 @@ void namcos22_state::simulate_slavedsp() for (;;) { // hackery! commands should be streamed, not parsed here - m_PrimitiveID = *src++; + u16 code = *src++; u16 len = *src++; s32 index = src - (s32 *)m_polygonram.target(); if ((index + len) >= 0x7fff) { - logerror("simulate_slavedsp buffer overflow: len=0x%x code=0x%x addr=0x%x\n", len, m_PrimitiveID, index); + logerror("simulate_slavedsp buffer overflow: len=0x%x code=0x%x addr=0x%x\n", len, code, index); return; } @@ -1395,7 +1361,7 @@ void namcos22_state::simulate_slavedsp() break; case 0x0d: - slavesim_handle_200002(src); // render primitive + slavesim_handle_200002(src, code); // render primitive break; default: @@ -1410,7 +1376,7 @@ void namcos22_state::simulate_slavedsp() } if (i < len) polydata += " (...)"; - logerror("simulate_slavedsp unknown 3d data: len=0x%x code=0x%x addr=0x%x!%s\n", len, m_PrimitiveID, index, polydata); + logerror("simulate_slavedsp unknown 3d data: len=0x%x code=0x%x addr=0x%x!%s\n", len, code, index, polydata); return; } } @@ -1434,15 +1400,42 @@ void namcos22_state::simulate_slavedsp() } } + void namcos22_state::draw_polygons() { - if (m_slave_simulation_active) + if (m_pdp_render_done && m_slave_simulation_active) { simulate_slavedsp(); m_poly->wait("draw_polygons"); } } +void namcos22_state::render_frame_active() +{ + /** + * Since pdp_begin and simulate_slavedsp are basically the same thing, when PDP is inactive, + * the parser here needs to be inactive too. However, propcycl attract mode(during the pauses) + * doesn't trigger the PDP and still expects polygons to be shown. It doesn't overwrite the PDP + * loop address, so it must be drawing the previous framebuffer, it's not known exactly where/how + * this is controlled. + */ + if (m_screen->frame_number() > m_pdp_frame && m_render_refresh) + m_pdp_render_done = false; + + m_render_refresh = false; +} + +WRITE_LINE_MEMBER(namcos22_state::screen_vblank) +{ + if (state) + { + // still need to determine active state if frame was skipped + if (m_skipped_this_frame) + render_frame_active(); + m_skipped_this_frame = machine().video().skip_this_frame(); + } +} + /*********************************************************************************************/ @@ -1461,10 +1454,10 @@ void namcos22_state::draw_sprite_group(const u32 *src, const u32 *attr, int num_ ----.----.----.---- | xxxx.xxxx.xxxx.xxxx y size src[2] - xxxx.x---.----.---- | ----.----.----.---- no function + xxxx.x---.----.---- | ----.----.----.---- unused ----.-xxx.----.---- | ----.----.----.---- clip target ----.----.xxxx.xxxx | ----.----.----.---- linktype - ----.----.----.---- | xxxx.xx--.----.---- no function(?) - set in airco22b + ----.----.----.---- | xxxx.xx--.----.---- no function(?) - 0x400 set in airco22b(invisible sprite) ----.----.----.---- | ----.--x-.----.---- right justify ----.----.----.---- | ----.---x.----.---- bottom justify ----.----.----.---- | ----.----.x---.---- flipx @@ -1475,17 +1468,17 @@ void namcos22_state::draw_sprite_group(const u32 *src, const u32 *attr, int num_ src[3] xxxx.xxxx.xxxx.xxxx | ----.----.----.---- tile number ----.----.----.---- | xxxx.xxxx.----.---- translucency - ----.----.----.---- | ----.----.xxxx.xxxx no function(?) - set in timecris + ----.----.----.---- | ----.----.xxxx.xxxx no function(?) - set in timecris when increasing translucency, it's probably not 16bit attr[0] - xxxx.xxxx.----.---- | ----.----.----.---- no function + xxxx.xxxx.----.---- | ----.----.----.---- unused ----.----.xxxx.xxxx | xxxx.xxxx.xxxx.xxxx z pos attr[1] - xxxx.xxxx.----.---- | ----.----.----.---- no function + xxxx.xxxx.----.---- | ----.----.----.---- unused ----.----.x---.---- | ----.----.----.---- cz enable ----.----.-xxx.xxxx | ----.----.----.---- color - ----.----.----.---- | xxxx.xxxx.----.---- no function(?) - set in airco22b, propcycl + ----.----.----.---- | xxxx.xxxx.----.---- unknown flags? - set in airco22b(0x7/0x1, invisible sprite), propcycl score hinge(0xff), cybrcycc at boot(0x2b) ----.----.----.---- | ----.----.xxxx.xxxx cz factor (fog aka depth cueing) */ int xpos = (src[0] >> 16) - deltax; @@ -1502,11 +1495,15 @@ void namcos22_state::draw_sprite_group(const u32 *src, const u32 *attr, int num_ int translucency = (code & 0xff00) >> 8; u32 zcoord = attr[0] & 0x00ffffff; - int color = attr[1] >> 16; + int color = attr[1] >> 16 & 0xff; int cz = attr[1] & 0xff; + // one of these is to override global fade setting? + // eg. propcycl time over, where global fade affects score hinge, but not "TIME" + int fade_enabled = (attr[1] & 0x8000) ? 1 : 0; + // priority over textlayer, trusted by testmode and timecris - int pri = ((attr[1] & 0xffff) == 0x00fe); + int prioverchar = (cz == 0xfe) ? 1 : 0; // set window clipping int clip = src[2] >> 23 & 0xe; @@ -1518,11 +1515,11 @@ void namcos22_state::draw_sprite_group(const u32 *src, const u32 *attr, int num_ if (rows == 0) rows = 8; if (cols == 0) cols = 8; - /* right justify */ + // right justify if (src[2] & 0x0200) xpos -= sizex * cols - 1; - /* bottom justify */ + // bottom justify if (src[2] & 0x0100) ypos -= sizey * rows - 1; @@ -1565,8 +1562,10 @@ void namcos22_state::draw_sprite_group(const u32 *src, const u32 *attr, int num_ node->data.sprite.translucency = translucency; node->data.sprite.color = color; node->data.sprite.cz = cz; - node->data.sprite.pri = pri; + node->data.sprite.prioverchar = prioverchar; + node->data.sprite.fade_enabled = fade_enabled; } + src += 4; attr += 2; } @@ -1743,9 +1742,9 @@ TILE_GET_INFO_MEMBER(namcos22_state::get_text_tile_info) WRITE32_MEMBER(namcos22_state::namcos22_textram_w) { - u32 prevdata = m_textram[offset]; + u32 prev = m_textram[offset]; COMBINE_DATA(&m_textram[offset]); - if (prevdata != m_textram[offset]) + if (prev != m_textram[offset]) { m_bgtilemap->mark_tile_dirty(offset * 2); m_bgtilemap->mark_tile_dirty(offset * 2 + 1); @@ -1754,29 +1753,82 @@ WRITE32_MEMBER(namcos22_state::namcos22_textram_w) WRITE32_MEMBER(namcos22_state::namcos22_cgram_w) { - u32 prevdata = m_cgram[offset]; + u32 prev = m_cgram[offset]; COMBINE_DATA(&m_cgram[offset]); - if (prevdata != m_cgram[offset]) + if (prev != m_cgram[offset]) m_gfxdecode->gfx(0)->mark_dirty(offset/32); } -READ32_MEMBER(namcos22_state::namcos22_tilemapattr_r) +void namcos22_state::posirq_update() +{ + int scanline = 2 * m_tilemapattr[4]; + + // schedule next timeout + if (scanline < m_screen->height()) + { + scanline = (scanline + 480) % m_screen->height(); // 0 = vblank start + m_posirq_timer->adjust(m_screen->time_until_pos(scanline)); + } + else + m_posirq_timer->adjust(attotime::never); +} + +TIMER_CALLBACK_MEMBER(namcos22_state::posirq_callback) +{ + // hblank irq line differs between s22/ss22 (see syscon) + int line = (m_is_ss22) ? 1 : 0; + + if (m_irq_enabled & (1 << line)) + { + // driver doesn't support partial updates yet + // partial updates here should apply to the text layer only, not the 3D framebuffer + //m_screen->update_partial(m_screen->vpos()); + + m_irq_state |= (1 << line); + m_maincpu->set_input_line(m_syscontrol[line] & 7, ASSERT_LINE); + } + + posirq_update(); +} + +WRITE16_MEMBER(namcos22_state::namcos22_tilemapattr_w) { + /* + 0: R/W - x offset + 1: R/W - y offset + 2: R/W - ??? always 0x006e? + 3: ? - unused? + 4: R/W - posirq scanline + 5: R - current scanline? + 6: ? - unused? + 7: R - ??? + */ + COMBINE_DATA(&m_tilemapattr[offset]); + switch (offset) { - case 2: + case 4: + posirq_update(); + break; + + default: + break; + } +} + +READ16_MEMBER(namcos22_state::namcos22_tilemapattr_r) +{ + switch (offset) + { + case 5: { - u16 lo, hi = (m_tilemapattr[offset] & 0xffff0000) >> 16; - // assume current scanline, 0x1ff if in vblank (used in alpinesa) - // or maybe relative to posirq? - if (m_screen->vblank()) lo = 0x1ff; - else lo = m_screen->vpos() >> 1; + // unknown, maybe posirq related // dirtdash has slowdowns if high bit is clear, why?? - return hi << 16 | lo | 0x8000; + return 0x8000; } - case 3: - // don't know, maybe also scanline related + case 7: + // unknown // timecris reads it everytime the gun triggers and will decline if it's 0xffff return 0; @@ -1787,25 +1839,10 @@ READ32_MEMBER(namcos22_state::namcos22_tilemapattr_r) return m_tilemapattr[offset]; } -WRITE32_MEMBER(namcos22_state::namcos22_tilemapattr_w) -{ - /* - 0.hiword R/W x offset - 0.loword R/W y offset - 1.hiword R/W ??? always 0x006e? - 1.loword ? unused? - 2.hiword R/W posirq scanline? - not hooked up yet - 2.loword R assume current scanline - 3.hiword ? unused? - 3.loword R ??? - */ - COMBINE_DATA(&m_tilemapattr[offset]); - //popmessage("%08x\n%08x\n%08x\n%08x\n",m_tilemapattr[0],m_tilemapattr[1],m_tilemapattr[2],m_tilemapattr[3]); -} /** - * Spot RAM affects how the text layer is blended with the scene, it is not yet known exactly how. + * Spot RAM affects how the text layer is blended with the scene. * It isn't directly memory mapped, but rather ports are used to populate and poll it. * * See Time Crisis "SPOT RAM" self test for sample use, maybe also used in-game, but where? @@ -1817,73 +1854,61 @@ WRITE32_MEMBER(namcos22_state::namcos22_tilemapattr_w) * 0x860006: enable */ -// tokyowar and timecris test ram 000-4ff, but the only practically usable part seems to be 000-3ff -#define SPOTRAM_SIZE (0x800) - /* RAM looks like it is a 256 * 4 words table testmode: offs: 0000 0001 0002 0003 - 03f4 03f5 03f6 03f7 03f8 03f9 03fa 03fb 03fc 03fd 03fe 03ff data: 00fe 00fe 00fe 00fe - 0001 0001 0001 0001 0000 0000 0000 0000 ffff ffff ffff ffff -is the high byte of each word used? it's usually 00, and in dirtdash always 02 - -low byte of each word: - byte 0 looks like a blend factor - bytes 1,2,3 a secondary brightness factor per rgb channel(?) +tokyowar and timecris test ram 000-4ff, but the only practically usable part seems to be 000-3ff +low byte is indirect pen, high byte is shift amount when spot is in alpha blend mode(pens 0x80-0xff) */ -READ32_MEMBER(namcos22_state::namcos22s_spotram_r) +READ16_MEMBER(namcos22_state::spotram_r) { - if (offset == 1) + if (offset == 2) { // read - if (m_spot_read_address >= SPOTRAM_SIZE) - { - m_spot_read_address = 0; - } - return m_spotram[m_spot_read_address++] << 16; + u16 ret = m_spotram[m_spotram_address >> 1 & 0x7ff]; + m_spotram_address += 2; + return ret; } + return 0; } -WRITE32_MEMBER(namcos22_state::namcos22s_spotram_w) +WRITE16_MEMBER(namcos22_state::spotram_w) { - if (offset == 0) + switch (offset) { - if (ACCESSING_BITS_16_31) - { + case 0: // set address - m_spot_read_address = data >> (16 + 1); - m_spot_write_address = data >> (16 + 1); - } - else - { + COMBINE_DATA(&m_spotram_address); + break; + + case 1: // write - if (m_spot_write_address >= SPOTRAM_SIZE) - { - m_spot_write_address = 0; - } - m_spotram[m_spot_write_address++] = data; - } - } - else - { - if (ACCESSING_BITS_0_15) - { + COMBINE_DATA(&m_spotram[m_spotram_address >> 1 & 0x7ff]); + m_spotram_address += 2; + break; + + case 3: // enable - m_spot_enable = data & 1; - } + COMBINE_DATA(&m_spotram_enable); + break; + + default: + // 2=read-only + break; } } void namcos22_state::namcos22s_mix_text_layer(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int prival) { const pen_t *pens = m_palette->pens(); - u16 *src; - u32 *dest; - u8 *pri; + u8 pen = 0; + rgbaint_t rgb; // prepare alpha u8 alpha_check12 = nthbyte(m_mixer, 0x12); @@ -1892,9 +1917,11 @@ void namcos22_state::namcos22s_mix_text_layer(screen_device &screen, bitmap_rgb3 u8 alpha_factor = nthbyte(m_mixer, 0x15); // prepare spot - int spot_flags = m_mixer_flags >> 16; - bool spot_enabled = (spot_flags & 1) && (spot_flags & 0xc); - int spot_limit = (spot_flags & 2) ? m_spot_limit : 0xff; + bool spot_enabled = (m_spotram_enable & 1) && (m_chipselect & 0xc000); + int spot_factor = (m_spot_factor < 0x100) ? 0 : m_spot_factor & 0xff; + rgbaint_t spot_color(0, spot_factor, spot_factor, spot_factor); + int spot_palbase = m_text_palbase >> 8 & 3; // src[x] >> 8 & 3 + int spot_shift = 0; // prepare fader bool fade_enabled = (m_mixer_flags & 2) && m_screen_fade_factor; @@ -1904,49 +1931,45 @@ void namcos22_state::namcos22s_mix_text_layer(screen_device &screen, bitmap_rgb3 // mix textlayer with poly/sprites for (int y = cliprect.top(); y <= cliprect.bottom(); y++) { - src = &m_mix_bitmap->pix16(y); - dest = &bitmap.pix32(y); - pri = &screen.priority().pix8(y); + u16 *src = &m_mix_bitmap->pix16(y); + u32 *dest = &bitmap.pix32(y); + u8 *pri = &screen.priority().pix8(y); for (int x = cliprect.left(); x <= cliprect.right(); x++) { // skip if transparent or under poly/sprite if (pri[x] == prival) { - rgbaint_t rgb(pens[src[x]]); - - // apply alpha - if (alpha_factor) - { - u8 pen = src[x] & 0xff; - if ((pen & 0xf) == alpha_mask || (pen >= alpha_check12 && pen <= alpha_check13)) - { - rgb.blend(rgbaint_t(dest[x]), 0xff - alpha_factor); - } - } - - // apply spot if (spot_enabled) { - u8 pen = src[x] & 0xff; - rgbaint_t mix(dest[x]); - if (spot_flags & 8) - { - // mix with per-channel brightness - rgbaint_t shade(0, (0xff - (m_spotram[pen << 2 | 1] & 0xff)) << 2, (0xff - (m_spotram[pen << 2 | 2] & 0xff)) << 2, (0xff - (m_spotram[pen << 2 | 3] & 0xff)) << 2); - mix.scale_and_clamp(shade); - } + // remap pen + int spot_data = m_spotram[(src[x] << 2 | spot_palbase) & 0x3ff]; + pen = spot_data; - int spot_factor = 0xff - (m_spotram[pen << 2] & 0xff); - if (spot_factor < spot_limit) + if (pen >= 0x80) { - rgb.blend(mix, spot_factor); + spot_shift = spot_data >> 8 & 7; + rgb.set(spot_color); } + else + rgb.set(pens[pen | m_text_palbase]); + } + else + { + rgb.set(pens[src[x]]); + pen = src[x]; } + // apply fade if (fade_enabled) - { rgb.blend(fade_color, fade_factor); - } + + // spot pen becomes brightness factor + if (spot_enabled && pen >= 0x80) + rgb.blend(rgbaint_t(dest[x]), (~pen & 0x7f) >> spot_shift); + + // otherwise apply alpha + else if (alpha_factor && ((pen & 0xf) == alpha_mask || (pen >= alpha_check12 && pen <= alpha_check13))) + rgb.blend(rgbaint_t(dest[x]), 0xff - alpha_factor); dest[x] = rgb.to_rgba(); } @@ -1957,31 +1980,32 @@ void namcos22_state::namcos22s_mix_text_layer(screen_device &screen, bitmap_rgb3 void namcos22_state::namcos22_mix_text_layer(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { const pen_t *pens = m_palette->pens(); - u16 *src; - u32 *dest; - u8 *pri; - const u8 *rlut = &m_gamma_proms[0x000]; const u8 *glut = &m_gamma_proms[0x100]; const u8 *blut = &m_gamma_proms[0x200]; // prepare fader and shadow factor - bool fade_enabled = m_mixer_flags & 2 && m_poly_fade_enabled; + bool fade_enabled = (m_screen_fade_r != 0x100 || m_screen_fade_g != 0x100 || m_screen_fade_b != 0x100); + u32 fade_r_add = (m_screen_fade_r > 0x100) ? (1 << 16) : 0; + u32 fade_g_add = (m_screen_fade_g > 0x100) ? (1 << 8) : 0; + u32 fade_b_add = (m_screen_fade_b > 0x100) ? 1 : 0; + bool fade_white = fade_r_add || fade_g_add || fade_b_add; + bool shadow_enabled = (m_mixer_flags & 0x100) != 0; // ? (ridgerac is the only game not using shadow) - rgbaint_t fade_color(0, m_poly_fade_r, m_poly_fade_g, m_poly_fade_b); + rgbaint_t fade_color(0, m_screen_fade_r, m_screen_fade_g, m_screen_fade_b); rgbaint_t rgb_mix[3] = { rgbaint_t(0, nthbyte(m_mixer, 0x08), nthbyte(m_mixer, 0x09), nthbyte(m_mixer, 0x0a)), // pen c rgbaint_t(0, nthbyte(m_mixer, 0x0b), nthbyte(m_mixer, 0x0c), nthbyte(m_mixer, 0x0d)), // pen d rgbaint_t(0, nthbyte(m_mixer, 0x0e), nthbyte(m_mixer, 0x0f), nthbyte(m_mixer, 0x10)) // pen e }; - // mix textlayer with poly/sprites + // mix textlayer with polys + do final mix for (int y = cliprect.top(); y <= cliprect.bottom(); y++) { - src = &m_mix_bitmap->pix16(y); - dest = &bitmap.pix32(y); - pri = &screen.priority().pix8(y); + u16 *src = &m_mix_bitmap->pix16(y); + u32 *dest = &bitmap.pix32(y); + u8 *pri = &screen.priority().pix8(y); for (int x = cliprect.left(); x <= cliprect.right(); x++) { u32 pixel = dest[x]; @@ -1990,37 +2014,33 @@ void namcos22_state::namcos22_mix_text_layer(screen_device &screen, bitmap_rgb32 if (pri[x] == 2) { // apply shadow - rgbaint_t rgb; - switch (src[x] & 0xff) + u8 pen = src[x]; + if (shadow_enabled && pen >= 0xfc && pen <= 0xfe) { - case 0xfc: - case 0xfd: - case 0xfe: - if (shadow_enabled) - { - rgb.set(pixel); - rgb.scale_and_clamp(rgb_mix[(src[x] & 0xf) - 0xc]); - break; - } - // (fall through) - default: - rgb.set(pens[src[x]]); - break; + rgbaint_t rgb(pixel); + rgb.scale_and_clamp(rgb_mix[pen - 0xfc]); + pixel = rgb.to_rgba(); } + else + pixel = pens[src[x]]; + } - if (fade_enabled) + // apply global fade + if (fade_enabled) + { + if (fade_white) { - rgb.scale_and_clamp(fade_color); + // need to make sure that blacks can scale up + if (!(pixel & 0xff0000)) pixel += fade_r_add; + if (!(pixel & 0x00ff00)) pixel += fade_g_add; + if (!(pixel & 0x0000ff)) pixel += fade_b_add; } - - // BTANB note: fading to white does not affect color channels set to 00, - // eg. a rr-gg-bb of 3f-7f-00 will fade to ff-ff-00 and not ff-ff-ff - // seen in victlapw attract mode - + rgbaint_t rgb(pixel); + rgb.scale_and_clamp(fade_color); pixel = rgb.to_rgba(); } - // final mix gamma here + // apply gamma dest[x] = (rlut[(pixel >> 16) & 0xff] << 16) | (glut[(pixel >> 8) & 0xff] << 8) | blut[pixel & 0xff]; } } @@ -2028,12 +2048,12 @@ void namcos22_state::namcos22_mix_text_layer(screen_device &screen, bitmap_rgb32 void namcos22_state::draw_text_layer(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { - int scroll_x = (m_tilemapattr[0] >> 16) - 0x35c; - int scroll_y = m_tilemapattr[0] & 0xffff; + int scroll_x = m_tilemapattr[0] - 0x35c; + int scroll_y = m_tilemapattr[1]; m_bgtilemap->set_scrollx(0, scroll_x & 0x3ff); m_bgtilemap->set_scrolly(0, scroll_y & 0x3ff); - m_bgtilemap->set_palette_offset(m_text_palbase * 256); + m_bgtilemap->set_palette_offset(m_text_palbase); if (m_is_ss22) { @@ -2053,8 +2073,10 @@ void namcos22_state::draw_text_layer(screen_device &screen, bitmap_rgb32 &bitmap WRITE32_MEMBER(namcos22_state::namcos22_paletteram_w) { + u32 prev = m_paletteram[offset]; COMBINE_DATA(&m_paletteram[offset]); - m_dirtypal[offset & (0x7fff/4)] = 1; + if (prev != m_paletteram[offset]) + m_dirtypal[offset & (0x7fff/4)] = 1; } void namcos22_state::update_palette() @@ -2077,83 +2099,128 @@ void namcos22_state::update_palette() } +WRITE16_MEMBER(namcos22_state::namcos22s_czattr_w) +{ + /* + 0 1 2 3 4 5 6 7 + ^^^^ ^^^^ ^^^^ ^^^^ cz offset, 8-bit(+high bit for sign) per czbank 0,1,2,3 + ^^^^ flags, nybble per czbank 3,2,1,0 - 8=?, 4=enable in-game, 2=reverse compare, 1=ram write enable if 0 + ^^^^ maincpu ram bank on read + ^^^^ bank select for in-game, 2 bits per cztype 3,2,1,0 (0xe4 = 3,2,1,0) + ^^^^ ? (only set sometimes in timecris) + 0000 0000 0000 0000 7555 0000 00e4 0000 // testmode normal - 0=white to black(mid), 1=white to black(weak), 2=white to black(strong), 3=black to white(mid, reverse of 0) + 7fff 8000 7fff 8000 7555 0000 00e4 0000 // testmode offset - 0=black, 1=white, 2=black, 3=white + 0000 0000 0000 0000 3111 0000 00e4 0000 // testmode off - 0=white, 1=white, 2=white, 3=white + 8001 8001 0000 0000 5555 0000 5555 0000 // aquajet (reg 6 is usually interlaced for double buffering) + 0000 0000 0000 0000 0b6c 0000 00e4 0000 // cybrcycc + 00a4 00a4 00a4 00a4 4444 0000 0000 0000 // propcycl in pool + ff80 ff80 ff80 ff80 4444 0000 0000 0000 // propcycl ending + */ + u16 prev = m_czattr[offset]; + COMBINE_DATA(&m_czattr[offset]); + + if (offset == 4) + { + // invalidate if compare function changed + u16 changed = prev ^ m_czattr[offset]; + for (int bank = 0; bank < 4; bank++) + m_cz_was_written[bank] |= changed >> (bank * 4) & 2; + } +} + +READ16_MEMBER(namcos22_state::namcos22s_czattr_r) +{ + return m_czattr[offset]; +} + WRITE32_MEMBER(namcos22_state::namcos22s_czram_w) { - int bank = nthword(m_czattr, 0xa/2) & 3; - u32 prev = (m_banked_czram[bank][offset * 2] << 16) | m_banked_czram[bank][offset * 2 + 1]; - u32 temp = prev; - COMBINE_DATA(&temp); - data = temp; - m_banked_czram[bank][offset * 2] = data >> 16; - m_banked_czram[bank][offset * 2 + 1] = data & 0xffff; - m_cz_was_written[bank] |= (prev ^ data); + /* + czram contents, it's basically a big cz compare table + + testmode: + o_16 0 1 2 3 4 5 6 7 < > f8 f9 fa fb fc fd fe ff + czram[0] = 0000 001f 003f 005f 007f 009f 00bf 00df .... 1eff 1f1f 1f3f 1f5f 1f7f 1f9f 1fbf 1fdf + czram[1] = 003f 007f 00be 00fd 013c 017b 01b9 01f7 .... 1ff9 1ffb 1ffc 1ffd 1ffe 1fff 1fff 1fff + czram[2] = 0000 0000 0000 0001 0002 0003 0005 0007 .... 1e45 1e83 1ec2 1f01 1f40 1f7f 1fbf 1fff + czram[3] = 1fff 1fdf 1fbf 1f9f 1f7f 1f5f 1f3f 1f1f .... 00ff 00df 00bf 009f 007f 005f 003f 001f + */ + for (int bank = 0; bank < 4; bank++) + { + // write enable bit + if (~m_czattr[4] >> (bank * 4) & 1) + { + u32 prev = (m_banked_czram[bank][offset * 2] << 16) | m_banked_czram[bank][offset * 2 + 1]; + u32 temp = prev; + COMBINE_DATA(&temp); + m_banked_czram[bank][offset * 2] = temp >> 16; + m_banked_czram[bank][offset * 2 + 1] = temp & 0xffff; + m_cz_was_written[bank] |= (prev ^ temp); + } + } } READ32_MEMBER(namcos22_state::namcos22s_czram_r) { - int bank = nthword(m_czattr, 0xa/2) & 3; + int bank = m_czattr[5] & 3; return (m_banked_czram[bank][offset * 2] << 16) | m_banked_czram[bank][offset * 2 + 1]; } void namcos22_state::recalc_czram() { - for (int table = 0; table < 4; table++) + for (int bank = 0; bank < 4; bank++) { // as documented above, ss22 czram is 'just' a big compare table // this is very slow when emulating, so let's recalculate it to a simpler lookup table - if (m_cz_was_written[table]) + if (m_cz_was_written[bank]) { + int reverse = (m_czattr[4] >> (bank * 4) & 2) ? 0xff : 0; int small_val = 0x2000; - int small_offset = 0; + int small_offset = reverse; int large_val = 0; - int large_offset = 0; - int prev = 0x2000; + int large_offset = reverse ^ 0xff; + int prev = 0; for (int i = 0; i < 0x100; i++) { - int val = m_banked_czram[table][i]; - - // discard if larger than 1fff - if (val > 0x1fff) val = prev; - if (prev > 0x1fff) - { - prev = val; - continue; - } - + int factor = i ^ reverse; + int val = std::min<u16>(m_banked_czram[bank][factor], 0x2000); int start = prev; int end = val; - if (start > end) + + if (i > 0) { - start = val; - end = prev; - } - prev = val; + // discard if compare function doesn't match + if (start >= end) + continue; - // fill range - for (int j = start; j < end; j++) - m_recalc_czram[table][j] = i; + // fill range + for (int j = start; j < end; j++) + m_recalc_czram[bank][j] = factor; + } // remember largest/smallest for later if (val < small_val) { small_val = val; - small_offset = i; + small_offset = factor; } if (val > large_val) { large_val = val; - large_offset = i; + large_offset = factor; } + + prev = val; } // fill possible leftover ranges for (int j = 0; j < small_val; j++) - m_recalc_czram[table][j] = small_offset; + m_recalc_czram[bank][j] = small_offset; for (int j = large_val; j < 0x2000; j++) - m_recalc_czram[table][j] = large_offset; + m_recalc_czram[bank][j] = large_offset; - m_cz_was_written[table] = 0; + m_cz_was_written[bank] = 0; } } } @@ -2201,8 +2268,7 @@ void namcos22_state::update_mixer() 08,09,0a background color 0b 0c - 0d spot factor limit value - 0e enable spot factor limit + 0d,0e spot factor 0f 10 11 global polygon alpha factor @@ -2224,19 +2290,14 @@ void namcos22_state::update_mixer() m_fog_r = nthbyte(m_mixer, 0x05); m_fog_g = nthbyte(m_mixer, 0x06); m_fog_b = nthbyte(m_mixer, 0x07); - m_spot_limit = nthbyte(m_mixer, 0x0d); + m_spot_factor = nthbyte(m_mixer, 0x0e) << 8 | nthbyte(m_mixer, 0x0d); m_poly_translucency = nthbyte(m_mixer, 0x11); m_screen_fade_r = nthbyte(m_mixer, 0x16); m_screen_fade_g = nthbyte(m_mixer, 0x17); m_screen_fade_b = nthbyte(m_mixer, 0x18); m_screen_fade_factor = nthbyte(m_mixer, 0x19); m_mixer_flags = nthbyte(m_mixer, 0x1a); - m_text_palbase = nthbyte(m_mixer, 0x1b) & 0x7f; - - // put spot-specific flags into high word - m_mixer_flags |= m_spot_enable << 16; - m_mixer_flags |= (nthbyte(m_mixer, 0x0e) & 1) << 17; - m_mixer_flags |= (m_chipselect & 0xc000) << 4; + m_text_palbase = nthbyte(m_mixer, 0x1b) << 8 & 0x7f00; } else { @@ -2252,7 +2313,7 @@ void namcos22_state::update_mixer() 00,01 display flags 02 03 - 04 + 04 bgcolor palette base? 05 06 07 textlayer palette base? @@ -2268,14 +2329,15 @@ void namcos22_state::update_mixer() 102,182,202 fog rgb 2 103,183,203 fog rgb 3 */ - m_mixer_flags = nthbyte(m_mixer, 0x00) << 8 | nthbyte(m_mixer, 0x01); - m_poly_fade_r = nthbyte(m_mixer, 0x11) << 8 | nthbyte(m_mixer, 0x12); // 0x0100 = 1.0 - m_poly_fade_g = nthbyte(m_mixer, 0x13) << 8 | nthbyte(m_mixer, 0x14); - m_poly_fade_b = nthbyte(m_mixer, 0x15) << 8 | nthbyte(m_mixer, 0x16); - m_poly_fade_enabled = (m_poly_fade_r == 0x100 && m_poly_fade_g == 0x100 && m_poly_fade_b == 0x100) ? 0 : 1; + m_mixer_flags = nthbyte(m_mixer, 0x00) << 8 | nthbyte(m_mixer, 0x01); + m_bg_palbase = nthbyte(m_mixer, 0x04) << 8 & 0x7f00; + m_text_palbase = nthbyte(m_mixer, 0x07) << 8 & 0x7f00; + m_screen_fade_r = nthbyte(m_mixer, 0x11) << 8 | nthbyte(m_mixer, 0x12); // 0x0100 = 1.0 + m_screen_fade_g = nthbyte(m_mixer, 0x13) << 8 | nthbyte(m_mixer, 0x14); + m_screen_fade_b = nthbyte(m_mixer, 0x15) << 8 | nthbyte(m_mixer, 0x16); // raveracw is the only game using multiple fog colors (city smog, cars under tunnels, brake disc in attract mode) - m_fog_colormask = m_mixer[0x84/4]; + m_fog_colormask = m_mixer[0x84/4]; // fog color per cz type for (i = 0; i < 4; i++) @@ -2284,8 +2346,6 @@ void namcos22_state::update_mixer() m_fog_g_per_cztype[i] = nthbyte(m_mixer, 0x0180+i); m_fog_b_per_cztype[i] = nthbyte(m_mixer, 0x0200+i); } - - m_text_palbase = 0x7f; } } @@ -2295,6 +2355,7 @@ void namcos22_state::update_mixer() u32 namcos22_state::screen_update_namcos22s(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { + render_frame_active(); update_mixer(); update_palette(); recalc_czram(); @@ -2339,17 +2400,19 @@ u32 namcos22_state::screen_update_namcos22s(screen_device &screen, bitmap_rgb32 u32 namcos22_state::screen_update_namcos22(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { + render_frame_active(); update_mixer(); update_palette(); screen.priority().fill(0, cliprect); // background color - bitmap.fill(m_palette->pen(0x7fff), cliprect); + int bg_color = m_bg_palbase | 0xff; + bitmap.fill(m_palette->pen(bg_color), cliprect); // layers draw_polygons(); m_poly->render_scene(screen, bitmap); - draw_text_layer(screen, bitmap, cliprect); // text layer + final mix(gamma) + draw_text_layer(screen, bitmap, cliprect); // text layer + final mix return 0; } @@ -2360,27 +2423,42 @@ u32 namcos22_state::screen_update_namcos22(screen_device &screen, bitmap_rgb32 & void namcos22_state::init_tables() { - matrix3d_identity(m_viewmatrix); - m_dirtypal = std::make_unique<u8[]>(0x8000/4); + save_pointer(NAME(m_dirtypal), 0x8000/4); memset(m_dirtypal.get(), 1, 0x8000/4); memset(m_paletteram, 0, 0x8000); + matrix3d_identity(m_viewmatrix); memset(m_polygonram, 0xcc, m_polygonram.bytes()); // init spotram (super22 only) if (m_is_ss22) - m_spotram = make_unique_clear<u16[]>(SPOTRAM_SIZE); + { + m_spotram = make_unique_clear<u16[]>(0x800); + save_pointer(NAME(m_spotram), 0x800); + } // init czram tables (super22 only) if (m_is_ss22) { - for (int table = 0; table < 4; table++) + for (int bank = 0; bank < 4; bank++) { - m_banked_czram[table] = make_unique_clear<u16[]>(0x100); - m_recalc_czram[table] = make_unique_clear<u8[]>(0x2000); - m_cz_was_written[table] = 1; + m_banked_czram[bank] = make_unique_clear<u16[]>(0x100); + m_recalc_czram[bank] = make_unique_clear<u8[]>(0x2000); + m_cz_was_written[bank] = 1; + + save_pointer(NAME(m_banked_czram[bank]), 0x100, bank); + save_pointer(NAME(m_recalc_czram[bank]), 0x2000, bank); } + + save_item(NAME(m_czattr)); + save_item(NAME(m_cz_was_written)); + } + else + { + save_item(NAME(m_fog_r_per_cztype)); + save_item(NAME(m_fog_g_per_cztype)); + save_item(NAME(m_fog_b_per_cztype)); } // init pointrom @@ -2395,6 +2473,7 @@ void namcos22_state::init_tables() } m_pointram = make_unique_clear<u32[]>(0x20000); + save_pointer(NAME(m_pointram), 0x20000); // force all texture tiles to be decoded now for (int i = 0; i < m_gfxdecode->gfx(1)->elements(); i++) @@ -2468,12 +2547,13 @@ void namcos22_state::init_tables() } } - void namcos22_state::video_start() { m_is_ss22 = (m_iomcu == nullptr); init_tables(); + m_posirq_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(namcos22_state::posirq_callback),this)); + m_mix_bitmap = std::make_unique<bitmap_ind16>(640, 480); m_bgtilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(namcos22_state::get_text_tile_info), this), TILEMAP_SCAN_ROWS, 16, 16, 64, 64); m_bgtilemap->set_transparent_pen(0xf); |