diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 7c9e8a437..e8bda30b7 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -407,6 +407,7 @@ extern int machine_at_cmdpc_init(const machine_t *); extern int machine_at_portableii_init(const machine_t *); extern int machine_at_portableiii_init(const machine_t *); extern int machine_at_portableiii386_init(const machine_t *); +extern int machine_at_deskpro386_init(const machine_t *); #ifdef EMU_DEVICE_H extern const device_t *at_cpqiii_get_device(void); #endif diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 41316bd50..851230bc8 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -892,3 +892,19 @@ machine_at_portableiii386_init(const machine_t *model) return ret; } + +int +machine_at_deskpro386_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linearr("roms/machines/deskpro386/1986-09-04-HI.json.bin", + 0x000fc000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_compaq_init(model, COMPAQ_DESKPRO386); + + return ret; +} diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 982218e2d..feddea136 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -303,6 +303,7 @@ const machine_t machines[] = { /* Has IBM AT KBC firmware. */ { "[C&T 386] Samsung SPC-6000A", "spc6000a", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_spc6000a_init, NULL }, /* Uses Compaq KBC firmware. */ + { "[ISA] Compaq Deskpro 386", "deskpro386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 14336, 1024, 127, machine_at_deskpro386_init, NULL }, { "[ISA] Compaq Portable III (386)", "portableiii386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO, 1024, 14336, 1024, 127, machine_at_portableiii386_init, at_cpqiii_get_device }, /* Has IBM AT KBC firmware. */ { "[ISA] Micronics 09-00021", "micronics386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 032cb7e26..d8029e8da 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -94,8 +94,7 @@ typedef struct mach64_t uint8_t regs[256]; int index; - int type, pci, - bit32; + int type, pci; uint8_t pci_regs[256]; uint8_t int_line; @@ -172,9 +171,11 @@ typedef struct mach64_t uint32_t src_y_x_start; uint32_t src_height1_width1, src_height2_width2; + uint32_t write_mask; + uint32_t chain_mask; uint32_t linear_base, old_linear_base; - uint32_t io_base; + uint32_t io_base; struct { @@ -205,6 +206,7 @@ typedef struct mach64_t uint32_t dp_bkgd_clr; uint32_t dp_frgd_clr; + uint32_t write_mask; uint32_t clr_cmp_clr; uint32_t clr_cmp_mask; @@ -215,6 +217,13 @@ typedef struct mach64_t int poly_draw; } accel; + fifo_entry_t fifo[FIFO_SIZE]; + volatile int fifo_read_idx, fifo_write_idx; + + thread_t *fifo_thread; + event_t *wake_fifo_thread; + event_t *fifo_not_full_event; + int blitter_busy; uint64_t blitter_time; uint64_t status_time; @@ -248,7 +257,7 @@ typedef struct mach64_t int overlay_v_acc; - uint8_t thread_run; + uint8_t thread_run; void *i2c, *ddc; } mach64_t; @@ -280,7 +289,8 @@ enum BPP_8 = 2, BPP_15 = 3, BPP_16 = 4, - BPP_32 = 5 + BPP_24 = 5, + BPP_32 = 6 }; enum @@ -485,34 +495,34 @@ void mach64_recalctimings(svga_t *svga) ati68860_ramdac_set_render(svga->ramdac, svga); switch ((mach64->crtc_gen_cntl >> 8) & 7) { - case 1: + case BPP_4: if (mach64->type != MACH64_GX) svga->render = svga_render_4bpp_highres; svga->hdisp *= 8; break; - case 2: + case BPP_8: if (mach64->type != MACH64_GX) svga->render = svga_render_8bpp_highres; svga->hdisp *= 8; svga->rowoffset /= 2; break; - case 3: + case BPP_15: if (mach64->type != MACH64_GX) svga->render = svga_render_15bpp_highres; svga->hdisp *= 8; break; - case 4: + case BPP_16: if (mach64->type != MACH64_GX) svga->render = svga_render_16bpp_highres; svga->hdisp *= 8; break; - case 5: + case BPP_24: if (mach64->type != MACH64_GX) svga->render = svga_render_24bpp_highres; svga->hdisp *= 8; svga->rowoffset = (svga->rowoffset * 3) / 2; break; - case 6: + case BPP_32: if (mach64->type != MACH64_GX) svga->render = svga_render_32bpp_highres; svga->hdisp *= 8; @@ -618,7 +628,6 @@ static void mach64_update_irqs(mach64_t *mach64) pci_clear_irq(mach64->card, PCI_INTA); } -#if 0 static __inline void wake_fifo_thread(mach64_t *mach64) { thread_set_event(mach64->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ @@ -632,7 +641,6 @@ static void mach64_wait_fifo_idle(mach64_t *mach64) thread_wait_event(mach64->fifo_not_full_event, 1); } } -#endif #define READ8(addr, var) switch ((addr) & 3) \ { \ @@ -819,6 +827,12 @@ static void mach64_accel_write_fifo(mach64_t *mach64, uint32_t addr, uint8_t val case 0x2c4: case 0x2c5: case 0x2c6: case 0x2c7: WRITE8(addr, mach64->dp_frgd_clr, val); break; + case 0x2c8: case 0x2c9: case 0x2ca: case 0x2cb: + WRITE8(addr, mach64->write_mask, val); + break; + case 0x2cc: case 0x2cd: case 0x2ce: case 0x2cf: + WRITE8(addr, mach64->chain_mask, val); + break; case 0x2d0: case 0x2d1: case 0x2d2: case 0x2d3: WRITE8(addr, mach64->dp_pix_width, val); @@ -917,7 +931,6 @@ static void mach64_accel_write_fifo_l(mach64_t *mach64, uint32_t addr, uint32_t } } -#if 0 static void fifo_thread(void *param) { mach64_t *mach64 = (mach64_t *)param; @@ -981,12 +994,7 @@ static void mach64_queue(mach64_t *mach64, uint32_t addr, uint32_t val, uint32_t if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) wake_fifo_thread(mach64); } -#endif -void mach64_cursor_dump(mach64_t *mach64) -{ - return; -} void mach64_start_fill(mach64_t *mach64) { @@ -1106,6 +1114,7 @@ void mach64_start_fill(mach64_t *mach64) mach64->accel.dp_frgd_clr = mach64->dp_frgd_clr; mach64->accel.dp_bkgd_clr = mach64->dp_bkgd_clr; + mach64->accel.write_mask = mach64->write_mask; mach64->accel.clr_cmp_clr = mach64->clr_cmp_clr & mach64->clr_cmp_mask; mach64->accel.clr_cmp_mask = mach64->clr_cmp_mask; @@ -1182,6 +1191,7 @@ void mach64_start_line(mach64_t *mach64) mach64->accel.dp_frgd_clr = mach64->dp_frgd_clr; mach64->accel.dp_bkgd_clr = mach64->dp_bkgd_clr; + mach64->accel.write_mask = mach64->write_mask; mach64->accel.x_count = mach64->dst_bres_lnth & 0x7fff; mach64->accel.err = (mach64->dst_bres_err & 0x3ffff) | ((mach64->dst_bres_err & 0x40000) ? 0xfffc0000 : 0); @@ -1191,6 +1201,9 @@ void mach64_start_line(mach64_t *mach64) mach64->accel.clr_cmp_fn = mach64->clr_cmp_cntl & 7; mach64->accel.clr_cmp_src = mach64->clr_cmp_cntl & (1 << 24); + mach64->accel.xinc = (mach64->dst_cntl & DST_X_DIR) ? 1 : -1; + mach64->accel.yinc = (mach64->dst_cntl & DST_Y_DIR) ? 1 : -1; + mach64->accel.busy = 1; mach64_log("mach64_start_line\n"); @@ -1221,6 +1234,7 @@ void mach64_start_line(mach64_t *mach64) case 0xd: dest_dat = src_dat & ~dest_dat; break; \ case 0xe: dest_dat = ~src_dat & dest_dat; break; \ case 0xf: dest_dat = ~(src_dat | dest_dat); break; \ + case 0x17: dest_dat = (dest_dat + src_dat) >> 1; \ } #define WRITE(addr, width) if (width == 0) \ @@ -1271,6 +1285,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) { uint32_t src_dat, dest_dat; uint32_t host_dat = 0; + uint32_t old_dest_dat; int mix = 0; int dst_x = (mach64->accel.dst_x + mach64->accel.dst_x_start) & 0xfff; int dst_y = (mach64->accel.dst_y + mach64->accel.dst_y_start) & 0xfff; @@ -1347,10 +1362,26 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) READ(mach64->accel.src_offset + (src_y * mach64->accel.src_pitch) + src_x, src_dat, mach64->accel.src_size); break; case SRC_FG: - src_dat = mach64->accel.dp_frgd_clr; + if ((mach64->dst_cntl & (DST_LAST_PEL | DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)) == (DST_LAST_PEL | DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)) { + if ((mach64->accel.x_count % 3) == 2) + src_dat = mach64->accel.dp_frgd_clr & 0xff; + else if ((mach64->accel.x_count % 3) == 1) + src_dat = (mach64->accel.dp_frgd_clr >> 8) & 0xff; + else if ((mach64->accel.x_count % 3) == 0) + src_dat = (mach64->accel.dp_frgd_clr >> 16) & 0xff; + } else + src_dat = mach64->accel.dp_frgd_clr; break; case SRC_BG: - src_dat = mach64->accel.dp_bkgd_clr; + if ((mach64->dst_cntl & (DST_LAST_PEL | DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)) == (DST_LAST_PEL | DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)) { + if ((mach64->accel.x_count % 3) == 2) + src_dat = mach64->accel.dp_bkgd_clr & 0xff; + else if ((mach64->accel.x_count % 3) == 1) + src_dat = (mach64->accel.dp_bkgd_clr >> 8) & 0xff; + else if ((mach64->accel.x_count % 3) == 0) + src_dat = (mach64->accel.dp_bkgd_clr >> 16) & 0xff; + } else + src_dat = mach64->accel.dp_bkgd_clr; break; case SRC_PAT: if (mach64->pat_cntl & 2) { @@ -1364,6 +1395,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) src_dat = 0; break; } + if (mach64->dst_cntl & DST_POLYGON_EN) { int poly_src; @@ -1371,6 +1403,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) if (poly_src) mach64->accel.poly_draw = !mach64->accel.poly_draw; } + if (!(mach64->dst_cntl & DST_POLYGON_EN) || mach64->accel.poly_draw) { READ(mach64->accel.dst_offset + (dst_y * mach64->accel.dst_pitch) + dst_x, dest_dat, mach64->accel.dst_size); @@ -1388,17 +1421,24 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) break; } - if (!cmp_clr) + { + if (!cmp_clr) { + old_dest_dat = dest_dat; MIX + dest_dat = (dest_dat & mach64->accel.write_mask) | (old_dest_dat & ~mach64->accel.write_mask); + } - WRITE(mach64->accel.dst_offset + (dst_y * mach64->accel.dst_pitch) + dst_x, mach64->accel.dst_size); + WRITE(mach64->accel.dst_offset + (dst_y * mach64->accel.dst_pitch) + dst_x, mach64->accel.dst_size); + } } } - if (mach64->dst_cntl & DST_24_ROT_EN) - { + if (((mach64->crtc_gen_cntl >> 8) & 7) == BPP_24) { + if ((mach64->dst_cntl & (DST_LAST_PEL | DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)) != (DST_LAST_PEL | DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)) { mach64->accel.dp_frgd_clr = ((mach64->accel.dp_frgd_clr >> 8) & 0xffff) | (mach64->accel.dp_frgd_clr << 16); mach64->accel.dp_bkgd_clr = ((mach64->accel.dp_bkgd_clr >> 8) & 0xffff) | (mach64->accel.dp_bkgd_clr << 16); + mach64->accel.write_mask = ((mach64->accel.write_mask >> 8) & 0xffff) | (mach64->accel.write_mask << 16); + } } mach64->accel.src_x += mach64->accel.xinc; @@ -1420,7 +1460,6 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) } mach64->accel.x_count--; - if (mach64->accel.x_count <= 0) { mach64->accel.x_count = mach64->accel.dst_width; @@ -1478,12 +1517,12 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) break; case OP_LINE: - while (count) - { + if (((mach64->crtc_gen_cntl >> 8) & 7) == BPP_24) { + int x = 0; + while (count) { uint32_t src_dat = 0, dest_dat; uint32_t host_dat = 0; int mix = 0; - int draw_pixel = !(mach64->dst_cntl & DST_POLYGON_EN); if (mach64->accel.source_host) { @@ -1509,129 +1548,266 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) switch (mach64->accel.source_mix) { case MONO_SRC_HOST: - mix = cpu_dat >> 31; - cpu_dat <<= 1; + if (mach64->dp_pix_width & DP_BYTE_PIX_ORDER) + { + mix = cpu_dat & 1; + cpu_dat >>= 1; + } + else + { + mix = cpu_dat >> 31; + cpu_dat <<= 1; + } break; case MONO_SRC_PAT: mix = mach64->accel.pattern[mach64->accel.dst_y & 7][mach64->accel.dst_x & 7]; break; case MONO_SRC_1: - default: mix = 1; break; - } - - if (mach64->dst_cntl & DST_POLYGON_EN) - { - if (mach64->dst_cntl & DST_Y_MAJOR) - draw_pixel = 1; - else if ((mach64->dst_cntl & DST_X_DIR) && mach64->accel.err < (mach64->dst_bres_dec + mach64->dst_bres_inc)) /*X+*/ - draw_pixel = 1; - else if (!(mach64->dst_cntl & DST_X_DIR) && mach64->accel.err >= 0) /*X-*/ - draw_pixel = 1; - } - - if (mach64->accel.x_count == 1 && !(mach64->dst_cntl & DST_LAST_PEL)) - draw_pixel = 0; - - if (mach64->accel.dst_x >= mach64->accel.sc_left && mach64->accel.dst_x <= mach64->accel.sc_right && - mach64->accel.dst_y >= mach64->accel.sc_top && mach64->accel.dst_y <= mach64->accel.sc_bottom && draw_pixel) - { - switch (mix ? mach64->accel.source_fg : mach64->accel.source_bg) - { - case SRC_HOST: - src_dat = host_dat; - break; - case SRC_BLITSRC: - READ(mach64->accel.src_offset + (mach64->accel.src_y * mach64->accel.src_pitch) + mach64->accel.src_x, src_dat, mach64->accel.src_size); - break; - case SRC_FG: - src_dat = mach64->accel.dp_frgd_clr; - break; - case SRC_BG: - src_dat = mach64->accel.dp_bkgd_clr; - break; - default: - src_dat = 0; - break; - } - - READ(mach64->accel.dst_offset + (mach64->accel.dst_y * mach64->accel.dst_pitch) + mach64->accel.dst_x, dest_dat, mach64->accel.dst_size); - - switch (mach64->accel.clr_cmp_fn) - { - case 1: /*TRUE*/ - cmp_clr = 1; - break; - case 4: /*DST_CLR != CLR_CMP_CLR*/ - cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) != mach64->accel.clr_cmp_clr; - break; - case 5: /*DST_CLR == CLR_CMP_CLR*/ - cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) == mach64->accel.clr_cmp_clr; - break; - } - - if (!cmp_clr) - MIX - - WRITE(mach64->accel.dst_offset + (mach64->accel.dst_y * mach64->accel.dst_pitch) + mach64->accel.dst_x, mach64->accel.dst_size); - } - - mach64->accel.x_count--; - if (mach64->accel.x_count <= 0) - { - /*Blit finished*/ - mach64_log("mach64 blit finished\n"); - mach64->accel.busy = 0; - return; - } - - switch (mach64->dst_cntl & 7) - { - case 0: case 2: - mach64->accel.src_x--; - mach64->accel.dst_x--; - break; - case 1: case 3: - mach64->accel.src_x++; - mach64->accel.dst_x++; - break; - case 4: case 5: - mach64->accel.src_y--; - mach64->accel.dst_y--; - break; - case 6: case 7: - mach64->accel.src_y++; - mach64->accel.dst_y++; + case MONO_SRC_BLITSRC: + READ(mach64->accel.src_offset + (mach64->accel.src_y * mach64->accel.src_pitch) + mach64->accel.src_x, mix, WIDTH_1BIT); break; } - mach64_log("x %i y %i err %i inc %i dec %i\n", mach64->accel.dst_x, mach64->accel.dst_y, mach64->accel.err, mach64->dst_bres_inc, mach64->dst_bres_dec); - if (mach64->accel.err >= 0) - { + + if ((mach64->accel.dst_x >= mach64->accel.sc_left) && (mach64->accel.dst_x <= mach64->accel.sc_right) && + (mach64->accel.dst_y >= mach64->accel.sc_top) && (mach64->accel.dst_y <= mach64->accel.sc_bottom)) { + switch (mix ? mach64->accel.source_fg : mach64->accel.source_bg) + { + case SRC_HOST: + src_dat = host_dat; + break; + case SRC_BLITSRC: + READ(mach64->accel.src_offset + (mach64->accel.src_y * mach64->accel.src_pitch) + mach64->accel.src_x, src_dat, mach64->accel.src_size); + break; + case SRC_FG: + src_dat = mach64->accel.dp_frgd_clr; + break; + case SRC_BG: + src_dat = mach64->accel.dp_bkgd_clr; + break; + case SRC_PAT: + if (mach64->pat_cntl & 2) { + src_dat = mach64->accel.pattern_clr4x2[mach64->accel.dst_y & 1][mach64->accel.dst_x & 3]; + break; + } else if (mach64->pat_cntl & 4) { + src_dat = mach64->accel.pattern_clr8x1[mach64->accel.dst_x & 7]; + break; + } + default: + src_dat = 0; + break; + } + + READ(mach64->accel.dst_offset + (mach64->accel.dst_y * mach64->accel.dst_pitch) + mach64->accel.dst_x, dest_dat, mach64->accel.dst_size); + + switch (mach64->accel.clr_cmp_fn) { + case 1: /*TRUE*/ + cmp_clr = 1; + break; + case 4: /*DST_CLR != CLR_CMP_CLR*/ + cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) != mach64->accel.clr_cmp_clr; + break; + case 5: /*DST_CLR == CLR_CMP_CLR*/ + cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) == mach64->accel.clr_cmp_clr; + break; + } + + if (!cmp_clr) + MIX + + if (!(mach64->dst_cntl & DST_Y_MAJOR)) { + if (x == 0) + dest_dat &= ~1; + } else { + if (x == (mach64->accel.x_count - 1)) + dest_dat &= ~1; + } + + WRITE(mach64->accel.dst_offset + (mach64->accel.dst_y * mach64->accel.dst_pitch) + mach64->accel.dst_x, mach64->accel.dst_size); + } + + x++; + if (x >= mach64->accel.x_count) { + mach64->accel.busy = 0; + mach64_log("mach64 line24 finished\n"); + return; + } + + if (mach64->dst_cntl & DST_Y_MAJOR) { + mach64->accel.dst_y += mach64->accel.yinc; + if (mach64->accel.err >= 0) { mach64->accel.err += mach64->dst_bres_dec; - - switch (mach64->dst_cntl & 7) - { - case 0: case 1: - mach64->accel.src_y--; - mach64->accel.dst_y--; - break; - case 2: case 3: - mach64->accel.src_y++; - mach64->accel.dst_y++; - break; - case 4: case 6: - mach64->accel.src_x--; - mach64->accel.dst_x--; - break; - case 5: case 7: - mach64->accel.src_x++; - mach64->accel.dst_x++; - break; - } - } - else + mach64->accel.dst_x += mach64->accel.xinc; + } else { mach64->accel.err += mach64->dst_bres_inc; + } + } else { + mach64->accel.dst_x += mach64->accel.xinc; + if (mach64->accel.err >= 0) { + mach64->accel.err += mach64->dst_bres_dec; + mach64->accel.dst_y += mach64->accel.yinc; + } else { + mach64->accel.err += mach64->dst_bres_inc; + } + } + } + } else { + while (count) + { + uint32_t src_dat = 0, dest_dat; + uint32_t host_dat = 0; + int mix = 0; + int draw_pixel = !(mach64->dst_cntl & DST_POLYGON_EN); + + if (mach64->accel.source_host) + { + host_dat = cpu_dat; + switch (mach64->accel.src_size) + { + case 0: + cpu_dat >>= 8; + count -= 8; + break; + case 1: + cpu_dat >>= 16; + count -= 16; + break; + case 2: + count -= 32; + break; + } + } + else + count--; + + switch (mach64->accel.source_mix) + { + case MONO_SRC_HOST: + mix = cpu_dat >> 31; + cpu_dat <<= 1; + break; + case MONO_SRC_PAT: + mix = mach64->accel.pattern[mach64->accel.dst_y & 7][mach64->accel.dst_x & 7]; + break; + case MONO_SRC_1: + default: + mix = 1; + break; + } + + if (mach64->dst_cntl & DST_POLYGON_EN) + { + if (mach64->dst_cntl & DST_Y_MAJOR) + draw_pixel = 1; + else if ((mach64->dst_cntl & DST_X_DIR) && mach64->accel.err < (mach64->dst_bres_dec + mach64->dst_bres_inc)) /*X+*/ + draw_pixel = 1; + else if (!(mach64->dst_cntl & DST_X_DIR) && mach64->accel.err >= 0) /*X-*/ + draw_pixel = 1; + } + + if (mach64->accel.x_count == 1 && !(mach64->dst_cntl & DST_LAST_PEL)) + draw_pixel = 0; + + if (mach64->accel.dst_x >= mach64->accel.sc_left && mach64->accel.dst_x <= mach64->accel.sc_right && + mach64->accel.dst_y >= mach64->accel.sc_top && mach64->accel.dst_y <= mach64->accel.sc_bottom && draw_pixel) + { + switch (mix ? mach64->accel.source_fg : mach64->accel.source_bg) + { + case SRC_HOST: + src_dat = host_dat; + break; + case SRC_BLITSRC: + READ(mach64->accel.src_offset + (mach64->accel.src_y * mach64->accel.src_pitch) + mach64->accel.src_x, src_dat, mach64->accel.src_size); + break; + case SRC_FG: + src_dat = mach64->accel.dp_frgd_clr; + break; + case SRC_BG: + src_dat = mach64->accel.dp_bkgd_clr; + break; + default: + src_dat = 0; + break; + } + + READ(mach64->accel.dst_offset + (mach64->accel.dst_y * mach64->accel.dst_pitch) + mach64->accel.dst_x, dest_dat, mach64->accel.dst_size); + + switch (mach64->accel.clr_cmp_fn) + { + case 1: /*TRUE*/ + cmp_clr = 1; + break; + case 4: /*DST_CLR != CLR_CMP_CLR*/ + cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) != mach64->accel.clr_cmp_clr; + break; + case 5: /*DST_CLR == CLR_CMP_CLR*/ + cmp_clr = (((mach64->accel.clr_cmp_src) ? src_dat : dest_dat) & mach64->accel.clr_cmp_mask) == mach64->accel.clr_cmp_clr; + break; + } + + if (!cmp_clr) + MIX + + WRITE(mach64->accel.dst_offset + (mach64->accel.dst_y * mach64->accel.dst_pitch) + mach64->accel.dst_x, mach64->accel.dst_size); + } + + mach64->accel.x_count--; + if (mach64->accel.x_count <= 0) + { + /*Blit finished*/ + mach64_log("mach64 blit finished\n"); + mach64->accel.busy = 0; + return; + } + + switch (mach64->dst_cntl & 7) + { + case 0: case 2: + mach64->accel.src_x--; + mach64->accel.dst_x--; + break; + case 1: case 3: + mach64->accel.src_x++; + mach64->accel.dst_x++; + break; + case 4: case 5: + mach64->accel.src_y--; + mach64->accel.dst_y--; + break; + case 6: case 7: + mach64->accel.src_y++; + mach64->accel.dst_y++; + break; + } + mach64_log("x %i y %i err %i inc %i dec %i\n", mach64->accel.dst_x, mach64->accel.dst_y, mach64->accel.err, mach64->dst_bres_inc, mach64->dst_bres_dec); + if (mach64->accel.err >= 0) + { + mach64->accel.err += mach64->dst_bres_dec; + + switch (mach64->dst_cntl & 7) + { + case 0: case 1: + mach64->accel.src_y--; + mach64->accel.dst_y--; + break; + case 2: case 3: + mach64->accel.src_y++; + mach64->accel.dst_y++; + break; + case 4: case 6: + mach64->accel.src_x--; + mach64->accel.dst_x--; + break; + case 5: case 7: + mach64->accel.src_x++; + mach64->accel.dst_x++; + break; + } + } + else + mach64->accel.err += mach64->dst_bres_inc; + } } break; } @@ -1929,15 +2105,19 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p) break; case 0x100: case 0x101: case 0x102: case 0x103: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_off_pitch); break; case 0x104: case 0x105: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_y_x); break; case 0x108: case 0x109: case 0x11c: case 0x11d: + mach64_wait_fifo_idle(mach64); READ8(addr + 2, mach64->dst_y_x); break; case 0x10c: case 0x10d: case 0x10e: case 0x10f: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_y_x); break; case 0x110: case 0x111: @@ -1946,152 +2126,207 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p) case 0x114: case 0x115: case 0x118: case 0x119: case 0x11a: case 0x11b: case 0x11e: case 0x11f: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_height_width); break; case 0x120: case 0x121: case 0x122: case 0x123: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_bres_lnth); break; case 0x124: case 0x125: case 0x126: case 0x127: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_bres_err); break; case 0x128: case 0x129: case 0x12a: case 0x12b: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_bres_inc); break; case 0x12c: case 0x12d: case 0x12e: case 0x12f: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_bres_dec); break; case 0x130: case 0x131: case 0x132: case 0x133: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_cntl); break; case 0x180: case 0x181: case 0x182: case 0x183: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_off_pitch); break; case 0x184: case 0x185: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_y_x); break; case 0x188: case 0x189: + mach64_wait_fifo_idle(mach64); READ8(addr + 2, mach64->src_y_x); break; case 0x18c: case 0x18d: case 0x18e: case 0x18f: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_y_x); break; case 0x190: case 0x191: + mach64_wait_fifo_idle(mach64); READ8(addr + 2, mach64->src_height1_width1); break; case 0x194: case 0x195: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_height1_width1); break; case 0x198: case 0x199: case 0x19a: case 0x19b: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_height1_width1); break; case 0x19c: case 0x19d: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_y_x_start); break; case 0x1a0: case 0x1a1: + mach64_wait_fifo_idle(mach64); READ8(addr + 2, mach64->src_y_x_start); break; case 0x1a4: case 0x1a5: case 0x1a6: case 0x1a7: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_y_x_start); break; case 0x1a8: case 0x1a9: + mach64_wait_fifo_idle(mach64); READ8(addr + 2, mach64->src_height2_width2); break; case 0x1ac: case 0x1ad: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_height2_width2); break; case 0x1b0: case 0x1b1: case 0x1b2: case 0x1b3: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_height2_width2); break; case 0x1b4: case 0x1b5: case 0x1b6: case 0x1b7: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_cntl); break; case 0x240: case 0x241: case 0x242: case 0x243: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->host_cntl); break; case 0x280: case 0x281: case 0x282: case 0x283: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->pat_reg0); break; case 0x284: case 0x285: case 0x286: case 0x287: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->pat_reg1); break; case 0x288: case 0x289: case 0x28a: case 0x28b: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->pat_cntl); break; case 0x2a0: case 0x2a1: case 0x2a8: case 0x2a9: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_left_right); break; case 0x2a4: case 0x2a5: addr += 2; /*FALLTHROUGH*/ case 0x2aa: case 0x2ab: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_left_right); break; case 0x2ac: case 0x2ad: case 0x2b4: case 0x2b5: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_top_bottom); break; case 0x2b0: case 0x2b1: addr += 2; /*FALLTHROUGH*/ case 0x2b6: case 0x2b7: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_top_bottom); break; case 0x2c0: case 0x2c1: case 0x2c2: case 0x2c3: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dp_bkgd_clr); break; case 0x2c4: case 0x2c5: case 0x2c6: case 0x2c7: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dp_frgd_clr); break; + case 0x2c8: case 0x2c9: case 0x2ca: case 0x2cb: + mach64_wait_fifo_idle(mach64); + READ8(addr, mach64->write_mask); + break; + + case 0x2cc: case 0x2cd: case 0x2ce: case 0x2cf: + mach64_wait_fifo_idle(mach64); + READ8(addr, mach64->chain_mask); + break; + case 0x2d0: case 0x2d1: case 0x2d2: case 0x2d3: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dp_pix_width); break; case 0x2d4: case 0x2d5: case 0x2d6: case 0x2d7: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dp_mix); break; case 0x2d8: case 0x2d9: case 0x2da: case 0x2db: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dp_src); break; case 0x300: case 0x301: case 0x302: case 0x303: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->clr_cmp_clr); break; case 0x304: case 0x305: case 0x306: case 0x307: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->clr_cmp_mask); break; case 0x308: case 0x309: case 0x30a: case 0x30b: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->clr_cmp_cntl); break; - case 0x310: case 0x311: + case 0x310: + case 0x311: + if (!FIFO_EMPTY) + wake_fifo_thread(mach64); ret = 0; + if (FIFO_FULL) + ret = 0xff; break; case 0x320: case 0x321: case 0x322: case 0x323: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->context_mask); break; case 0x330: case 0x331: + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_cntl); break; case 0x332: + mach64_wait_fifo_idle(mach64); READ8(addr - 2, mach64->src_cntl); break; case 0x333: + mach64_wait_fifo_idle(mach64); READ8(addr - 3, mach64->pat_cntl); break; case 0x338: - ret = 0; + ret = FIFO_EMPTY ? 0 : 1; break; default: @@ -2228,7 +2463,7 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) } else if (addr & 0x300) { - mach64_accel_write_fifo(mach64, addr & 0x3ff, val); + mach64_queue(mach64, addr & 0x3ff, val, FIFO_WRITE_BYTE); } else switch (addr & 0x3ff) { @@ -2291,19 +2526,16 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) case 0x68: case 0x69: case 0x6a: case 0x6b: WRITE8(addr, mach64->cur_offset, val); svga->dac_hwcursor.addr = (mach64->cur_offset & 0xfffff) * 8; - mach64_cursor_dump(mach64); break; case 0x6c: case 0x6d: case 0x6e: case 0x6f: WRITE8(addr, mach64->cur_horz_vert_posn, val); svga->dac_hwcursor.x = mach64->cur_horz_vert_posn & 0x7ff; svga->dac_hwcursor.y = (mach64->cur_horz_vert_posn >> 16) & 0x7ff; - mach64_cursor_dump(mach64); break; case 0x70: case 0x71: case 0x72: case 0x73: WRITE8(addr, mach64->cur_horz_vert_off, val); svga->dac_hwcursor.xoff = mach64->cur_horz_vert_off & 0x3f; svga->dac_hwcursor.yoff = (mach64->cur_horz_vert_off >> 16) & 0x3f; - mach64_cursor_dump(mach64); break; case 0x80: case 0x81: case 0x82: case 0x83: @@ -2357,14 +2589,13 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) svga_set_ramdac_type(svga, (mach64->dac_cntl & 0x100) ? RAMDAC_8BIT : RAMDAC_6BIT); ati68860_set_ramdac_type(mach64->svga.ramdac, (mach64->dac_cntl & 0x100) ? RAMDAC_8BIT : RAMDAC_6BIT); i2c_gpio_set(mach64->i2c, !(mach64->dac_cntl & 0x20000000) || (mach64->dac_cntl & 0x04000000), !(mach64->dac_cntl & 0x10000000) || (mach64->dac_cntl & 0x02000000)); - break; + break; case 0xd0: case 0xd1: case 0xd2: case 0xd3: WRITE8(addr, mach64->gen_test_cntl, val); ati_eeprom_write(&mach64->eeprom, mach64->gen_test_cntl & 0x10, mach64->gen_test_cntl & 2, mach64->gen_test_cntl & 1); mach64->gen_test_cntl = (mach64->gen_test_cntl & ~8) | (ati_eeprom_read(&mach64->eeprom) ? 8 : 0); svga->dac_hwcursor.ena = mach64->gen_test_cntl & 0x80; - mach64_cursor_dump(mach64); break; case 0xdc: case 0xdd: case 0xde: case 0xdf: @@ -2384,14 +2615,14 @@ void mach64_ext_writew(uint32_t addr, uint16_t val, void *p) mach64_log("mach64_ext_writew : addr %08X val %04X\n", addr, val); if (!(addr & 0x400)) { - mach64_log("nmach64_ext_writew: addr=%04x val=%04x\n", addr, val); + mach64_log("mach64_ext_writew: addr=%04x val=%04x\n", addr, val); mach64_ext_writeb(addr, val, p); mach64_ext_writeb(addr + 1, val >> 8, p); } else if (addr & 0x300) { - mach64_accel_write_fifo_w(mach64, addr & 0x3fe, val); + mach64_queue(mach64, addr & 0x3fe, val, FIFO_WRITE_WORD); } else switch (addr & 0x3fe) { @@ -2408,14 +2639,14 @@ void mach64_ext_writel(uint32_t addr, uint32_t val, void *p) mach64_log("mach64_ext_writel : addr %08X val %08X\n", addr, val); if (!(addr & 0x400)) { - mach64_log("nmach64_ext_writel: addr=%04x val=%08x\n", addr, val); + mach64_log("mach64_ext_writel: addr=%04x val=%08x\n", addr, val); mach64_ext_writew(addr, val, p); mach64_ext_writew(addr + 2, val >> 16, p); } else if (addr & 0x300) { - mach64_accel_write_fifo_l(mach64, addr & 0x3fc, val); + mach64_queue(mach64, addr & 0x3fc, val, FIFO_WRITE_DWORD); } else switch (addr & 0x3fc) { @@ -3324,15 +3555,20 @@ static void *mach64_common_init(const device_t *info) mach64->pci_regs[0x33] = 0x00; mach64->svga.ramdac = device_add(&ati68860_ramdac_device); - mach64->svga.dac_hwcursor_draw = ati68860_hwcursor_draw; + mach64->svga.dac_hwcursor_draw = ati68860_hwcursor_draw; - mach64->svga.clock_gen = device_add(&ics2595_device); + mach64->svga.clock_gen = device_add(&ics2595_device); mach64->dst_cntl = 3; mach64->i2c = i2c_gpio_init("ddc_ati_mach64"); mach64->ddc = ddc_init(i2c_gpio_get_bus(mach64->i2c)); + mach64->wake_fifo_thread = thread_create_event(); + mach64->fifo_not_full_event = thread_create_event(); + mach64->thread_run = 1; + mach64->fifo_thread = thread_create(fifo_thread, mach64); + return mach64; } @@ -3419,6 +3655,12 @@ void mach64_close(void *p) { mach64_t *mach64 = (mach64_t *)p; + mach64->thread_run = 0; + thread_set_event(mach64->wake_fifo_thread); + thread_wait(mach64->fifo_thread); + thread_destroy_event(mach64->fifo_not_full_event); + thread_destroy_event(mach64->wake_fifo_thread); + svga_close(&mach64->svga); ddc_close(mach64->ddc);