From 5cd86c77812cbee7d909bc4847aad1ea68428611 Mon Sep 17 00:00:00 2001 From: mamehaze <140764005+mamehaze@users.noreply.github.com> Date: Mon, 3 Jun 2024 01:06:49 +0100 Subject: the actual TCH PR (#12434) Co-authored-by: DavidHaywood --- src/mame/tch/wheelfir.cpp | 675 +++++++++++++++++++++++----------------------- 1 file changed, 341 insertions(+), 334 deletions(-) diff --git a/src/mame/tch/wheelfir.cpp b/src/mame/tch/wheelfir.cpp index a1b38bba425..c337e9714c9 100644 --- a/src/mame/tch/wheelfir.cpp +++ b/src/mame/tch/wheelfir.cpp @@ -61,79 +61,6 @@ level 3 interrupt = vblank interrupt level 1 interrupt = blitter interrupt -Blitter data foramt ( offset in words, offset in bytes, offset inside ram data table ) - - - fedcba9876543210 - -0 0 0 - --------76543210 dest_x0 bits 0-7 - 76543210-------- src_x0 bits 0-7 - -1 2 2 - --------76543210 dest_x1 bits 0-7 - - - -2 4 4 - --------76543210 dest_y0 bits 0-7 - 76543210-------- src_y0 bits 0-7 -3 6 6 - --------76543210 dest_y1 bits 0-7 - -4 8 -5 a -6 c 8 - ??------???????? image flags (directly copied from image info table, page and ?) - --3210---------- image page - -------8-------- src_x0 bit 8 - ------8--------- src_y0 bit 8 -7 e a - ????????--?----- flags - ---------------X X direction (src?) - --------------Y- Y direction (src?) - ---------8------ dest_x0 bit 8 - --------8------- dest_y0 bit 8 - -----------L---- dest layer - ------------??-- unknown bits, set usually when rendering target = bitmap layer - - -8 10 c - -------5-------- x scale data1 bit 5 - ------5--------- y scale data1 bit 5 - -----5---------- x scale data2 bit 5 - ----5----------- y scala data2 bit 5 - ---D------------ x scale >200% - --D------------- y scale >200% - -x-------------- X direction (dest?) - Y--------------- Y direction (dest?) - ---------8------ scroll x bit 8 - --------8------- scroll y bit 8 - ----------?----- set for road ? buffer num (is there double buffering ? or two bitmap layers?) - -9 12 e - ---------------H x scale < 50% - --------------H- y scale < 50% - -------------8-- dest_x1 bit 8 - ------------8--- dest_y1 bit 8 - - -a 14 10 - ---43210-------- x scale data1 bits 0-4 - -4-------------- y scale data1 bit 4 - --------76543210 scroll x of bitmap layer - -b 16 12 - ---43210-------- x scale data2 bits 0-4 - 10-------------- y scale data1 bits 0-1 - --------76543210 scroll y of bitmap layer -c 18 14 - ---43210-------- y scale data2 bits 0-4 - 32-------------- y scale data1 bits 2-3 -d 1a -e 1c -f 1e - @@ -178,33 +105,31 @@ BIT N - ( scale < 50% ) ? 1 : 0 #include "screen.h" #include "speaker.h" -namespace { - -static const int ZOOM_TABLE_SIZE=1<<14; -static const int NUM_SCANLINES=256-8; -static const int NUM_VBLANK_LINES=8; -static const int LAYER_BG=0; -static const int LAYER_FG=1; -static const int NUM_COLORS=256; -struct scroll_info -{ - int32_t x = 0, y = 0, unkbits = 0; -}; +namespace { +static const int ZOOM_TABLE_SIZE = 1 << 14; +static const int NUM_SCANLINES = 256 - 8; +static const int NUM_VBLANK_LINES = 64; // unknown, too low and sprites at top of screen on power ball flicker +static const int LAYER_BG = 0; +static const int LAYER_FG = 1; +static const int NUM_COLORS = 256; class wheelfir_state : public driver_device { public: - wheelfir_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag), + wheelfir_state(const machine_config &mconfig, device_type type, const char* tag) : + driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), m_subcpu(*this, "subcpu"), m_eeprom(*this, "eeprom"), m_screen(*this, "screen"), m_palette(*this, "palette"), + m_blitter_data(*this, "blitram"), + m_tilepages(*this, "gfx1"), + m_maincpurom(*this, "maincpu"), m_adc_eoc(0), - m_is_pwball(false), + m_force_extra_irq1(false), m_disable_raster_irq(false) { } @@ -228,9 +153,9 @@ private: required_device m_palette; std::unique_ptr m_zoom_table; - std::unique_ptr m_blitter_data; - - std::unique_ptr m_scanlines; + required_shared_ptr m_blitter_data; + required_region_ptr m_tilepages; + required_region_ptr m_maincpurom; int32_t m_direct_write_x0 = 0; int32_t m_direct_write_x1 = 0; @@ -240,14 +165,13 @@ private: int16_t m_scanline_cnt = 0; - std::unique_ptr m_tmp_bitmap[2]{}; int32_t get_scale(int32_t index) { - while(index=0) + if (m_zoom_table[index] >= 0) { return m_zoom_table[index]; } @@ -256,12 +180,14 @@ private: return 0; } void wheelfir_scanline_cnt_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + void do_direct_write(uint8_t sixdat); + void do_blit(); void wheelfir_blit_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); void wheelfir_7c0000_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); uint16_t wheelfir_7c0000_r(offs_t offset, uint16_t mem_mask = ~0); void coin_cnt_w(uint16_t data); void adc_eoc_w(int state); - uint32_t screen_update_wheelfir(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + uint32_t screen_update_wheelfir(screen_device &screen, bitmap_ind16& bitmap, const rectangle &cliprect); void screen_vblank_wheelfir(int state); TIMER_DEVICE_CALLBACK_MEMBER(scanline_timer_callback); void ramdac_map(address_map &map); @@ -269,237 +195,247 @@ private: void wheelfir_sub(address_map &map); int m_adc_eoc; - bool m_is_pwball; + bool m_force_extra_irq1; bool m_disable_raster_irq; -}; + int m_current_yscroll; +}; void wheelfir_state::wheelfir_scanline_cnt_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_scanline_cnt); + //logerror("%d: set scanline counter to %d\n", machine().describe_context(), m_scanline_cnt); } - -void wheelfir_state::wheelfir_blit_w(offs_t offset, uint16_t data, uint16_t mem_mask) +void wheelfir_state::do_blit() { - COMBINE_DATA(&m_blitter_data[offset]); - - if(!ACCESSING_BITS_8_15 && offset==0x6) //LSB only! - { - int direct_width=m_direct_write_x1-m_direct_write_x0+1; - int direct_height=m_direct_write_y1-m_direct_write_y0+1; + // blitter irq? should be timed? + m_maincpu->set_input_line(1, HOLD_LINE); - int sixdat = data&0xff; + uint8_t const* const rom = m_tilepages; - if(direct_width>0 && direct_height>0) - { - int x = m_direct_write_idx % direct_width; - int y = (m_direct_write_idx / direct_width) % direct_height; + const int src_u0 = (m_blitter_data[0] >> 8) + ((m_blitter_data[6] & 0x100) ? 256 : 0); + const int src_v0 = (m_blitter_data[2] >> 8) + ((m_blitter_data[6] & 0x200) ? 256 : 0); - x += m_direct_write_x0; - y += m_direct_write_y0; + int dst_x0 = (m_blitter_data[0] & 0xff) + ((m_blitter_data[7] & 0x40) ? 256 : 0); + int dst_y0 = (m_blitter_data[2] & 0xff) + ((m_blitter_data[7] & 0x80) ? 256 : 0); - if (x<512 && y <512) - { - m_tmp_bitmap[LAYER_BG]->pix(y, x) = sixdat; - } - } + int dst_x1 = (m_blitter_data[1] & 0xff) + ((m_blitter_data[9] & 4) ? 256 : 0); + int dst_y1 = (m_blitter_data[3] & 0xff) + ((m_blitter_data[9] & 8) ? 256 : 0); - ++m_direct_write_idx; + const bool flipx = (m_blitter_data[7] & 0x1); + const bool flipy = (m_blitter_data[7] & 0x2); - return; - } + const int x_dst_step = flipx ? 1 : -1; + const int y_dst_step = flipy ? 1 : -1; - if(offset==0xf && data==0xffff) - { - m_maincpu->set_input_line(1, HOLD_LINE); + const int u_src_step = (m_blitter_data[8] & 0x4000) ? 1 : -1; + const int v_src_step = (m_blitter_data[8] & 0x8000) ? 1 : -1; - uint8_t const *const rom = memregion("gfx1")->base(); + const int page = ((m_blitter_data[6]) >> 10) * 0x40000; - const int width = m_screen->width(); - const int height = m_screen->height(); + if (page >= 0x700000) /* src set to unav. page before direct write to the framebuffer */ + { + logerror("%s: page set to above ROM %08x - direct write enable?\n", machine().describe_context(), page); + // wheelfir sets 0xfc0000 and 0xf00000, both of which are out of range of any GFX ROM + // kongball sets 0xfc0000 but only on startup + m_direct_write_x0 = dst_x0; + m_direct_write_x1 = dst_x1; + m_direct_write_y0 = dst_y0; + m_direct_write_y1 = dst_y1; + m_direct_write_idx = 0; + } - const int src_x0=(m_blitter_data[0]>>8)+((m_blitter_data[6]&0x100)?256:0); - const int src_y0=(m_blitter_data[2]>>8)+((m_blitter_data[6]&0x200)?256:0); + if (flipy) + dst_y0 -= 1; + else + dst_y0 += 1; - const int dst_x0=(m_blitter_data[0]&0xff)+((m_blitter_data[7]&0x40)?256:0); - const int dst_y0=(m_blitter_data[2]&0xff)+((m_blitter_data[7]&0x80)?256:0); + if (flipy) + dst_y1 += 1; + else + dst_y1 -= 1; - const int dst_x1=(m_blitter_data[1]&0xff)+((m_blitter_data[9]&4)?256:0); - const int dst_y1=(m_blitter_data[3]&0xff)+((m_blitter_data[9]&8)?256:0); + dst_x0 &= 0x1ff; + dst_x1 &= 0x1ff; + dst_y0 &= 0x1ff; + dst_y1 &= 0x1ff; - const int x_dst_step=(m_blitter_data[7]&0x1)?1:-1; - const int y_dst_step=(m_blitter_data[7]&0x2)?1:-1; + int vpage = (m_blitter_data[0x7] & 0x10) ? LAYER_BG : LAYER_FG; - const int x_src_step=(m_blitter_data[8]&0x4000)?1:-1; - const int y_src_step=(m_blitter_data[8]&0x8000)?1:-1; - const int page=((m_blitter_data[6])>>10)*0x40000; + // ?? prevents some sprite flickering in pwball and wheelfir + if (vpage == LAYER_FG) + { + dst_y0 &= 0xff; + dst_y1 &= 0xff; + } + float scale_u_step; + float scale_v_step; + + // calculate u zoom (horizontal source scale) + const int d1u = ((m_blitter_data[0x0a] & 0x1f00) >> 8) | + ((m_blitter_data[0x08] & 0x0100) >> 3); + const int d2u = ((m_blitter_data[0x0b] & 0x1f00) >> 8) | + ((m_blitter_data[0x08] & 0x0400) >> 5); + const int hflagu = (m_blitter_data[0x09] & 0x0001) ? 1 : 0; + const int dflagu = (m_blitter_data[0x08] & 0x1000) ? 1 : 0; + const int indexu = d1u | (d2u << 6) | (hflagu << 12) | (dflagu << 13); + const float scale_u = get_scale(indexu); + + // calculate v zoom (vertical source scale) + const int d1v = ((m_blitter_data[0x0b] & 0xc000) >> 14) | + ((m_blitter_data[0x0c] & 0xc000) >> 12) | + ((m_blitter_data[0x0a] & 0x4000) >> 10) | + ((m_blitter_data[0x08] & 0x0200) >> 4); + + const int d2v = ((m_blitter_data[0x0c] & 0x1f00) >> 8) | + ((m_blitter_data[0x08] & 0x0800) >> 6); + const int hflagv = (m_blitter_data[0x09] & 0x0002) ? 1 : 0; + const int dflagv = (m_blitter_data[0x08] & 0x2000) ? 1 : 0; + const int indexv = d1v | (d2v << 6) | (hflagv << 12) | (dflagv << 13); + const float scale_v = get_scale(indexv); + + if (scale_u == 0 || scale_v == 0) return; + + scale_u_step = 100.f / scale_u; + scale_v_step = 100.f / scale_v; + + + // do the draw + int y = dst_y0; + float idx_v = 0; + do + { + int x = dst_x0; + float idx_u = 0; - if (!m_is_pwball) - { - if (page >= 0x400000) /* src set to unav. page before direct write to the framebuffer */ - { - m_direct_write_x0 = dst_x0; - m_direct_write_x1 = dst_x1; - m_direct_write_y0 = dst_y0; - m_direct_write_y1 = dst_y1; - m_direct_write_idx = 0; - } - } + int yy = src_v0 + v_src_step * idx_v; - if (x_dst_step<0) + do { - if (dst_x0<=dst_x1) - { - return; - } + int xx = src_u0 + u_src_step * idx_u; - } - else - { - if (dst_x0>=dst_x1) - { - return; - } + int address = page + yy * 512 + xx; - } + int pix = rom[address & (0x1000000 - 1)]; - if (y_dst_step<0) - { - if (dst_y0<=dst_y1) - { - return; - } - } - else - { - if (dst_y0>=dst_y1) + if (pix && x >= 0 && y >= 0 && x < 512 && y < 512) { - return; + m_tmp_bitmap[vpage]->pix(y, x) = pix; } - } - - - //additional checks - - int d1, d2, hflag, dflag, index; - - d1=((m_blitter_data[0x0a]&0x1f00)>>8); - - d2=((m_blitter_data[0x0b]&0x1f00)>>8); - + x += x_dst_step; + x &= 0x1ff; + idx_u += scale_u_step; - d1|=((m_blitter_data[0x8]&0x100)>>3); - d2|=((m_blitter_data[0x8]&0x400)>>5); - hflag=(m_blitter_data[0x9]&0x1)?1:0; - dflag=(m_blitter_data[0x8]&0x1000)?1:0; - index=d1|(d2<<6)|(hflag<<12)|(dflag<<13); + } while (x != dst_x1); - const float scale_x=get_scale(index); + y += y_dst_step; + y &= 0x1ff; + idx_v += scale_v_step; + } while (y != dst_y1); +} - d1=((m_blitter_data[0x0b]&0xc000)>>14) | - ((m_blitter_data[0x0c]&0xc000)>>12) | - ((m_blitter_data[0x0a]&0x4000)>>10); - - d2=((m_blitter_data[0x0c]&0x1f00)>>8); +void wheelfir_state::do_direct_write(uint8_t sixdat) +{ + const int direct_width = m_direct_write_x1 - m_direct_write_x0 + 1; + const int direct_height = m_direct_write_y1 - m_direct_write_y0 + 1; + if (direct_width > 0 && direct_height > 0) + { + int x = m_direct_write_idx % direct_width; + int y = (m_direct_write_idx / direct_width) % direct_height; - d1|=((m_blitter_data[0x8]&0x200)>>4); - d2|=((m_blitter_data[0x8]&0x800)>>6); + x += m_direct_write_x0; + y += m_direct_write_y0; - hflag=(m_blitter_data[0x9]&0x2)?1:0; - dflag=(m_blitter_data[0x8]&0x2000)?1:0; - index=d1|(d2<<6)|(hflag<<12)|(dflag<<13); + if (x < 512 && y < 512) + { + m_tmp_bitmap[LAYER_BG]->pix(y, x) = sixdat; + } + } - const float scale_y=get_scale(index); + ++m_direct_write_idx; +} +void wheelfir_state::wheelfir_blit_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + /* + Blitter data format ( offset in words, offset in bytes ) + + 0 0 uuuuuuuu u = src_u0 bits 0-7 + 1 xxxxxxxx x = dest_x0 bits 0-7 + 1 2 -------- + 3 XXXXXXXX X = dest_x1 bits 0-7 + 2 4 vvvvvvvv v = src_v0 bits 0-7 + 5 yyyyyyyy y = dest_y0 bits 0-7 + 3 6 -------- + 7 YYYYYYYY Y = dest_y1 bits 0-7 + 4 8 -------- + 9 -------- + 5 a -------- + b -------- + 6 c --ppppvu p = page, v = src_v0 bit 8, u = src_u0 bit 8 + d DDDDDDDD D = direct bitmap/framebuffer write port + 7 e -------- + f yx-L??ff y = dest_y0 bit 8 , x = dest_x0 bit 8 , L = dest layer, ?? = used but unknown, ff = Y/X direction (src?) + 8 10 FFZzZzZz FF = Y direction/X direction (dest), Z = y scale >200% z = x scale >200%, Z = y scale data2 bit 5, z = x scale data2 bit 5, Z = y scale data1 bit 5, z = x scale data1 bit 5 + 11 Ss?----- s = scroll x of back layer bit 8, S = scroll y of back layer bit 8, ? = set on road + 9 12 -------- + 13 ----YXZz Y = dest_y1 bit 8, X = dest_x1 bit 8, Z = y scale < 50%, z = x scale < 50% + a 14 -Z-zzzzz Z = y scale data1 bit 4, z = x scale data1 bits 0-4, + 15 ssssssss s = scroll x of back layer + b 16 ZZ-zzzzz Z = y scale data1 bits 0-1, z = x scale data2 bits 0-4 + 17 SSSSSSSS S = scroll y of back layer + c 18 ZZ-ZZZZZ Z = y scale data1 bits 2-3, Z = y scale data2 bits 0-4 + 19 -------- + d 1a -------- + 1b -------- + e 1c -------- + 1d -------- + f 1e TTTTTTTT + 1f TTTTTTTT T = start blit / trigger blit (with write of 0xffff, also writes 0x0000 before filling in some params) + */ + + m_screen->update_partial(m_screen->vpos() - 1); + //uint16_t oldval = m_blitter_data[offset]; + COMBINE_DATA(&m_blitter_data[offset]); - if (scale_x==0 || scale_y==0) + if (offset == 0x6) + { + if (!ACCESSING_BITS_8_15) //LSB only! { + do_direct_write(data & 0xff); return; } + } - float scale_x_step = 100.f / scale_x; - float scale_y_step = 100.f / scale_y; - - if (m_is_pwball) + if (offset == 0xa) + { + if (!ACCESSING_BITS_8_15) //LSB only! { - scale_x_step = 1.0f; - scale_y_step = 1.0f; + // if the scroll value is written during the active frame, it must take into account + // the current yposition?? (seems to be the only way for wheelfir rasters to work?) + m_current_yscroll = (m_blitter_data[0xb] & 0x00ff) | (m_blitter_data[0x8] & 0x0080) << 1; + m_current_yscroll -= m_screen->vpos(); + return; } + } - int vpage=LAYER_FG; - if(m_blitter_data[0x7]&0x10) - { - vpage=LAYER_BG; -/* - printf("%s bg -> %d %d %d %d %d %d @ %x\n",machine().describe_context().c_str(), dst_x0,dst_y0, dst_x1,dst_y1, dst_x1-dst_x0, dst_y1-dst_y0); - - for(int i=0;i<16;++i) - { - printf("%x = %.4x\n",i,m_blitter_data[i]); - } - printf("\n"); -*/ + if (offset == 0xf) + { + if (data == 0xffff) + { + do_blit(); } - - bool endx=false; - bool endy=false; - - /* - if(m_blitter_data[0x7]&0x0c) - { - //??? - }*/ - - float idx_x = 0; - for(int x=dst_x0; !endx; x+=x_dst_step, idx_x+=scale_x_step) + else { - endy=false; - float idx_y = 0; - for(int y=dst_y0; !endy; y+=y_dst_step, idx_y+=scale_y_step) - { - endx=(x==(dst_x1+1)); - endy=(y==(dst_y1+1)); - - - const int xx=src_x0+x_src_step*idx_x; - const int yy=src_y0+y_src_step*idx_y; - - const int address=page+yy*512+xx; - - const int pix = rom[address&(0x1000000-1)]; - - int screen_x=x; - int screen_y=y; - - - /* if ((page>=0x400000) && (!m_is_pwball)) - { - //hack for clear - if(screen_x >0 && screen_y >0 && screen_x < width && screen_y pix(screen_y , screen_x ) =0; - } - } - */ - { - if (vpage == LAYER_FG) - { - screen_y &= 0xff; - } - - if (pix && screen_x >0 && screen_y >0 && screen_x < width && screen_y pix(screen_y, screen_x) = pix; - } - } - } + // writes 0x0000 before filling in some of the other params then sending 0xffff above + logerror("%s: write to offset 0xf (blit start) but with data %04x\n", machine().describe_context(), data); } } } @@ -514,23 +450,25 @@ uint32_t wheelfir_state::screen_update_wheelfir(screen_device &screen, bitmap_in { bitmap.fill(0, cliprect); - for (int y=cliprect.min_y; y < cliprect.max_y; y++) + for (int y = cliprect.min_y; y <= cliprect.max_y; y++) { - uint16_t const *const source = &m_tmp_bitmap[LAYER_BG]->pix(( (m_scanlines[y].y)&511)); - uint16_t *const dest = &bitmap.pix(y); + int scrolly = y; + scrolly += m_current_yscroll;// + scrolly &= 0x1ff; + uint16_t const* const source = &m_tmp_bitmap[LAYER_BG]->pix(scrolly); + uint16_t* const dest = &bitmap.pix(y); - for (int x = cliprect.min_x; x < cliprect.max_x; x++) + for (int x = cliprect.min_x; x <= cliprect.max_x; x++) { - dest[x] = source[(x + m_scanlines[y].x) & 511]; + int sourcex = x; + sourcex += (m_blitter_data[0xa] & 0x00ff) | (m_blitter_data[0x8] & 0x0040) << 2; + sourcex &= 0x1ff; + dest[x] = source[sourcex]; } } copybitmap_trans(bitmap, *m_tmp_bitmap[LAYER_FG], 0, 0, 0, 0, cliprect, 0); -/* - m_tmp_bitmap[LAYER_BG]->fill(0, screen.visible_area()); -*/ - return 0; } @@ -541,6 +479,9 @@ void wheelfir_state::screen_vblank_wheelfir(int state) { m_tmp_bitmap[LAYER_FG]->fill(0, m_screen->visible_area()); } + else + { + } } @@ -592,9 +533,9 @@ void wheelfir_state::coin_cnt_w(uint16_t data) void wheelfir_state::wheelfir_main(address_map &map) { map(0x000000, 0x0fffff).rom(); - map(0x200000, 0x20ffff).ram(); + map(0x200000, 0x20ffff).ram().mirror(0x010000); // kongball either needs the mirror (or has more ram?) - map(0x700000, 0x70001f).w(FUNC(wheelfir_state::wheelfir_blit_w)); + map(0x700000, 0x70001f).w(FUNC(wheelfir_state::wheelfir_blit_w)).share(m_blitter_data); map(0x720001, 0x720001).w("ramdac", FUNC(ramdac_device::index_w)); map(0x720003, 0x720003).w("ramdac", FUNC(ramdac_device::pal_w)); map(0x720005, 0x720005).w("ramdac", FUNC(ramdac_device::mask_w)); // word write? @@ -681,35 +622,52 @@ void wheelfir_state::adc_eoc_w(int state) TIMER_DEVICE_CALLBACK_MEMBER(wheelfir_state::scanline_timer_callback) { - if (param < NUM_SCANLINES) + if (param == 0) { - //copy scanline offset - const int xscroll = (m_blitter_data[0xa] & 0x00ff) | (m_blitter_data[0x8] & 0x0040) << 2; - const int yscroll = (m_blitter_data[0xb] & 0x00ff) | (m_blitter_data[0x8] & 0x0080) << 1; - - m_scanlines[param].x = xscroll; - m_scanlines[param].y = yscroll; - m_scanlines[param].unkbits = m_blitter_data[0x8] & 0xff; - - m_blitter_data[0xb]++; - - //visible scanline - m_scanline_cnt--; + // latch the current scroll value at the top of the screen? + m_current_yscroll = (m_blitter_data[0xb] & 0x00ff) | (m_blitter_data[0x8] & 0x0080) << 1; + } - if ((m_scanline_cnt==0) && (!m_disable_raster_irq)) + if (param < NUM_SCANLINES) //visible scanline + { + // raster IRQ, changes scroll values for road + + // kongball has no valid raster IRQ function, and never sets the register + // radendur also does't appear to have a proper piece of IRQ code, but sets it to 1 + // hack is needed to disable it in these cases, is there a proper way to disable it? + + // Does the actual raster line depend on something else like the bg scroll value + // and trigger when the hardware reads the framebuffer for that line, rather than the + // screen line? The older logic worked better for Wheels and Fire, but was buffering + // values in a strange way rather than using partial updates. + // + // currently we latch the scroll value at the start of a frame, and if it is written + // during a frame, we take into account the current vpos when updating it; this ALMOST + // seems ok the road in wheelfir, but not the background so much + + if (m_scanline_cnt > 0) { - m_maincpu->set_input_line(5, HOLD_LINE); // raster IRQ, changes scroll values for road + m_scanline_cnt--; + + if (m_scanline_cnt == 0) + { + if (!m_disable_raster_irq) + { + m_maincpu->set_input_line(5, HOLD_LINE); + } + } } - //m_screen->update_partial(param); - if ((param == 0) && m_is_pwball) + if ((param == 224) && m_force_extra_irq1) { + // why, this is the blitter irq? + // pwball and radendur won't boot otherwise though m_maincpu->set_input_line(1, HOLD_LINE); } } else { - if(param==NUM_SCANLINES) /* vblank */ + if (param == NUM_SCANLINES) /* vblank */ { m_maincpu->set_input_line(3, HOLD_LINE); } @@ -718,36 +676,81 @@ TIMER_DEVICE_CALLBACK_MEMBER(wheelfir_state::scanline_timer_callback) m_subcpu->set_input_line(1, HOLD_LINE); } +// see code below that is used to calculate this for wheelfir set +// as the other game ROMs are structured differently it's easier +// to just have this table here; the zooming code could be significantly +// refactored however +static const uint16_t zoom_index[400] = +{ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1801, 0x1ea1, 0x1ba1, 0x1f61, 0x19e1, + 0x19a1, 0x1961, 0x1961, 0x1921, 0x1fe2, 0x1d62, 0x1ba2, 0x1aa2, 0x1a22, 0x1ea3, + 0x1804, 0x1fe4, 0x1d64, 0x1fe5, 0x1ae4, 0x1d66, 0x1fe9, 0x1fec, 0x1eac, 0x181f, + 0x0801, 0x0fe1, 0x0ea1, 0x0ca1, 0x0ba1, 0x0ae1, 0x0f61, 0x0a21, 0x09e1, 0x09e1, + 0x09a1, 0x09a1, 0x0961, 0x0961, 0x0961, 0x0802, 0x0921, 0x0921, 0x0fe2, 0x0fa2, + 0x0d62, 0x0c22, 0x0ba2, 0x0b22, 0x0aa2, 0x08e1, 0x0a22, 0x0fe3, 0x0ea3, 0x0d23, + 0x0804, 0x0ba3, 0x0fe4, 0x0f24, 0x0d64, 0x0fe5, 0x0fe5, 0x0e25, 0x0ae4, 0x0fe7, + 0x0d66, 0x0ea7, 0x0fe9, 0x0fe9, 0x0fec, 0x0ce9, 0x0eac, 0x0ff4, 0x081f, 0x0fff, + 0x0000, 0x0fff, 0x07e0, 0x0bb6, 0x06a0, 0x0560, 0x0bbf, 0x0aba, 0x09a9, 0x0abf, + 0x0a7f, 0x0a3f, 0x09ae, 0x09ff, 0x09b3, 0x09b7, 0x09bd, 0x09bf, 0x09bf, 0x0974, + 0x01a0, 0x097e, 0x097f, 0x097f, 0x092d, 0x0160, 0x0931, 0x0934, 0x0938, 0x093e, + 0x093f, 0x093f, 0x093f, 0x08a2, 0x0120, 0x08e9, 0x08ea, 0x08eb, 0x08ec, 0x08ed, + 0x08ee, 0x08f0, 0x08f2, 0x08f4, 0x08f8, 0x08fd, 0x08ff, 0x08ff, 0x08ff, 0x08ff, + 0x00e0, 0x00e0, 0x00e0, 0x00e0, 0x00e0, 0x00e0, 0x08a4, 0x08a4, 0x08a4, 0x08a4, + 0x08a4, 0x08a4, 0x08a4, 0x08a4, 0x08a5, 0x08a5, 0x08a5, 0x08a5, 0x08a5, 0x08a6, + 0x08a6, 0x08a6, 0x08a6, 0x08a6, 0x08a7, 0x08a7, 0x08a7, 0x08a8, 0x08a8, 0x08a9, + 0x08a9, 0x08aa, 0x08aa, 0x08ab, 0x08ac, 0x08ad, 0x08ad, 0x08ae, 0x08b0, 0x08b1, + 0x08b3, 0x08b5, 0x08b8, 0x08bc, 0x08bf, 0x08bf, 0x08bf, 0x08bf, 0x08bf, 0x00a0, + 0x00a0, 0x2000, 0x2fff, 0x2fff, 0x27e0, 0x27e0, 0x2bb6, 0x2bb6, 0x26a0, 0x26a0, + 0x2560, 0x2560, 0x2bbf, 0x2bbf, 0x2aba, 0x2aba, 0x29a9, 0x29a9, 0x2abf, 0x2abf, + 0x2a7f, 0x2a7f, 0x2a3f, 0x2a3f, 0x29ae, 0x29ae, 0x29ff, 0x29ff, 0x29b3, 0x29b3, + 0x29b7, 0x29b7, 0x29bd, 0x29bd, 0x29bf, 0x29bf, 0x29bf, 0x29bf, 0x2974, 0x2974, + 0x21a0, 0x21a0, 0x297e, 0x297e, 0x297f, 0x297f, 0x297f, 0x297f, 0x292d, 0x292d, + 0x2160, 0x2160, 0x2931, 0x2931, 0x2934, 0x2934, 0x2938, 0x2938, 0x293e, 0x293e, + 0x293f, 0x293f, 0x293f, 0x293f, 0x293f, 0x293f, 0x28a2, 0x28a2, 0x2120, 0x2120, + 0x28e9, 0x28e9, 0x28ea, 0x28ea, 0x28eb, 0x28eb, 0x28ec, 0x28ec, 0x28ed, 0x28ed, + 0x28ee, 0x28ee, 0x28f0, 0x28f0, 0x28f2, 0x28f2, 0x28f4, 0x28f4, 0x28f8, 0x28f8, + 0x28fd, 0x28fd, 0x28ff, 0x28ff, 0x28ff, 0x28ff, 0x28ff, 0x28ff, 0x28ff, 0x28ff, + 0x20e0, 0x20e0, 0x20e0, 0x20e0, 0x20e0, 0x20e0, 0x20e0, 0x20e0, 0x20e0, 0x20e0, + 0x20e0, 0x20e0, 0x28a4, 0x28a4, 0x28a4, 0x28a4, 0x28a4, 0x28a4, 0x28a4, 0x28a4, + 0x28a4, 0x28a4, 0x28a4, 0x28a4, 0x28a4, 0x28a4, 0x28a4, 0x28a4, 0x28a5, 0x28a5, + 0x28a5, 0x28a5, 0x28a5, 0x28a5, 0x28a5, 0x28a5, 0x28a5, 0x28a5, 0x28a6, 0x28a6, + 0x28a6, 0x28a6, 0x28a6, 0x28a6, 0x28a6, 0x28a6, 0x28a6, 0x28a6, 0x28a7, 0x28a7, + 0x28a7, 0x28a7, 0x28a7, 0x28a7, 0x28a8, 0x28a8, 0x28a8, 0x28a8, 0x28a9, 0x28a9, + 0x28a9, 0x28a9, 0x28aa, 0x28aa, 0x28aa, 0x28aa, 0x28ab, 0x28ab, 0x28ac, 0x28ac, + 0x28ad, 0x28ad, 0x28ad, 0x28ad, 0x28ae, 0x28ae, 0x28b0, 0x28b0, 0x28b1, 0x28b1, + 0x28b3, 0x28b3, 0x28b5, 0x28b5, 0x28b8, 0x28b8, 0x28bc, 0x28bc, 0x28bf, 0x28bf, + 0x28bf, 0x28bf, 0x28bf, 0x28bf, 0x28bf, 0x28bf, 0x28bf, 0x28bf, 0x20a0, 0x20a0 +}; void wheelfir_state::machine_start() { m_zoom_table = std::make_unique(ZOOM_TABLE_SIZE); - m_blitter_data = std::make_unique(16); - - m_scanlines = std::make_unique(NUM_SCANLINES+NUM_VBLANK_LINES); - - for (int i=0;i<(ZOOM_TABLE_SIZE);++i) + for (int i = 0; i < (ZOOM_TABLE_SIZE); ++i) { - m_zoom_table[i]=-1; + m_zoom_table[i] = -1; } - uint16_t *ROM = (uint16_t *)memregion("maincpu")->base(); - - for(int j=0;j<400;++j) + for (int j = 0; j < 400; ++j) { - const int i=j<<3; - int d1=ROM[0x200+i]&0x1f; - int d0=(ROM[0x200+i]>>8)&0x1f; - - d0 |= (ROM[0x200+1+i]&1)?0x20:0; - d1 |= (ROM[0x200+1+i]&4)?0x20:0; - - const int hflag=(ROM[0x200+2+i]&0x100)?1:0; - const int dflag=(ROM[0x200+1+i]&0x10)?1:0; - - const int index=d0|(d1<<6)|(hflag<<12)|(dflag<<13); - m_zoom_table[index]=j; + /* + // calculate index for zoom + uint16_t* ROM = (uint16_t*)m_maincpurom; + int i = j << 3; + int d1 = ROM[0x200 + i] & 0x1f; + int d0 = (ROM[0x200 + i] >> 8) & 0x1f; + + d0 |= (ROM[0x200 + 1 + i] & 1) ? 0x20 : 0; + d1 |= (ROM[0x200 + 1 + i] & 4) ? 0x20 : 0; + + int hflag = (ROM[0x200 + 2 + i] & 0x100) ? 1 : 0; + int dflag = (ROM[0x200 + 1 + i] & 0x10) ? 1 : 0; + + int index = d0 | (d1 << 6) | (hflag << 12) | (dflag << 13); + */ + m_zoom_table[zoom_index[j]] = j; } } @@ -779,15 +782,15 @@ GFXDECODE_END void wheelfir_state::wheelfir(machine_config &config) { - M68000(config, m_maincpu, 32000000/2); + M68000(config, m_maincpu, 32000000 / 2); m_maincpu->set_addrmap(AS_PROGRAM, &wheelfir_state::wheelfir_main); - M68000(config, m_subcpu, 32000000/2); + M68000(config, m_subcpu, 32000000 / 2); m_subcpu->set_addrmap(AS_PROGRAM, &wheelfir_state::wheelfir_sub); - //config.set_maximum_quantum(attotime::from_hz(12000)); + config.set_maximum_quantum(attotime::from_hz(12000)); - adc0808_device &adc(ADC0808(config, "adc", 500000)); // unknown clock + adc0808_device& adc(ADC0808(config, "adc", 500000)); // unknown clock adc.eoc_ff_callback().set(FUNC(wheelfir_state::adc_eoc_w)); adc.in_callback<0>().set_ioport("STEERING"); adc.in_callback<1>().set_ioport("ACCELERATOR"); @@ -797,8 +800,10 @@ void wheelfir_state::wheelfir(machine_config &config) SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_refresh_hz(60); - m_screen->set_size(336, NUM_SCANLINES+NUM_VBLANK_LINES); - m_screen->set_visarea(0,335, 0, NUM_SCANLINES-1); + m_screen->set_size(336, NUM_SCANLINES + NUM_VBLANK_LINES); + m_screen->set_visarea(0, 335, 0, NUM_SCANLINES - 1); + //m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(3000)); + m_screen->set_screen_update(FUNC(wheelfir_state::screen_update_wheelfir)); m_screen->screen_vblank().set(FUNC(wheelfir_state::screen_vblank_wheelfir)); m_screen->set_palette(m_palette); @@ -931,20 +936,22 @@ ROM_END void wheelfir_state::init_pwball() { - // temp hack as pwball doesn't like zooming and other things (maybe different FPGA programming?) - m_is_pwball = true; + m_force_extra_irq1 = true; +// m_disable_raster_irq = true; } void wheelfir_state::init_kongball() { - init_pwball(); + m_force_extra_irq1 = true; m_disable_raster_irq = true; // the raster interrupt points outside of code } - GAME( 199?, wheelfir, 0, wheelfir, wheelfir, wheelfir_state, empty_init, ROT0, "TCH", "Wheels & Fire", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS ) GAME( 199?, pwball, 0, wheelfir, pwball, wheelfir_state, init_pwball, ROT0, "TCH", "Power Ball (prototype)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS ) // mostly complete -// these might not be fully functional games -GAME( 199?, kongball, 0, kongball, pwball, wheelfir_state, init_kongball, ROT0, "TCH", "Kong Ball (early prototype)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS ) // can't get ingame? +// sound ROMs were missing on PCB, so sound emulation is not possible at this point in time +GAME( 1997, kongball, 0, kongball, pwball, wheelfir_state, init_kongball, ROT0, "TCH / Digital Dreams Multimedia", "Kong Ball (prototype)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS ) // can't get ingame? + +// crashes (always?) when selecting track on PCB +// some courses get to gameplay in MAME right now, but crash quickly, Medium 1 is seems to work better than most others GAME( 199?, radendur, 0, wheelfir, pwball, wheelfir_state, init_kongball, ROT0, "TCH / Sator Videogames", "Radical Enduro (early prototype)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS ) // can get ingame if you overclock CPUs significantly (IRQ problems?) -- cgit v1.2.3