From 5b135e6a39bf8001e5df49a51caeacd0de498746 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Thu, 30 Jul 2009 17:03:07 +0300 Subject: [PATCH] imported winuaesrc1620b3.zip --- blitter.c | 364 +++++++++++++---------- custom.c | 129 +++++--- disk.c | 39 ++- gencpu.c | 274 ++++++++++++----- include/blitter.h | 2 +- inputdevice.c | 4 +- newcpu.c | 213 ++++++++------ od-win32/bsdsock.c | 1 + od-win32/hardfile_win32.c | 22 +- od-win32/resources/resource | 6 +- od-win32/resources/winuae.rc | 75 ++--- od-win32/sounddep/sound.c | 91 +++--- od-win32/sounddep/sound.h | 6 + od-win32/win32.c | 550 +++++++++++++++++++---------------- od-win32/win32.h | 4 +- od-win32/win32gui.c | 20 +- od-win32/winuaechangelog.txt | 24 +- 17 files changed, 1094 insertions(+), 730 deletions(-) diff --git a/blitter.c b/blitter.c index d3179165..691b9848 100644 --- a/blitter.c +++ b/blitter.c @@ -41,6 +41,7 @@ static int blitonedot, blitsign; static int blit_add; static int blit_modadda, blit_modaddb, blit_modaddc, blit_modaddd; static int blit_ch; +static int vblitsize, hblitsize; #ifdef BLITTER_DEBUG static int blitter_dontdo; @@ -57,7 +58,7 @@ uae_u32 blit_masktable[BLITTER_MAX_WORDS]; enum blitter_states bltstate; static int blit_cyclecounter, blit_maxcyclecounter, blit_slowdown, blit_totalcyclecounter; -static int blit_linecyclecounter, blit_misscyclecounter; +static int blit_startcycles, blit_misscyclecounter; #ifdef CPUEMU_12 extern uae_u8 cycle_line[]; @@ -77,14 +78,15 @@ int blit_interrupt; static int last_blitter_hpos; -/* +#define BLITTER_STARTUP_CYCLES 2 - idle cycles are free cycles (available for CPU) - but for some reason they still require free bus cycle +/* + Blitter Idle Cycle: - basically every blitter cycle requires free bus cycle, - "real" cycles are used for blitter DMA, idle cycles - are free for CPU (if CPU needs bus) + Cycles that are free cycles (available for CPU) and + are not used by any other Agnus DMA channel. Blitter + idle cycle is not "used" by blitter, CPU can still use + it normally if it needs the bus. same in both block and line modes @@ -139,7 +141,7 @@ static const int blit_cycle_diagram_fill[][10] = }; /* - -C-D -C-D ... -C-D -- (? difficult to confirm in logic analyzer) + -C-D C-D- ... C-D- -- line draw takes 4 cycles (-C-D) idle cycles do the same as above, 2 dma fetches @@ -156,6 +158,13 @@ static const int blit_cycle_diagram_fill[][10] = - disabling A-channel freezes the content of BPLAPT - C-channel disabled: nothing is written + There is one tricky situation, writing to DFF058 just before + last D write cycle (which is normally free) does not distrupt + blitter operation, final D is still written correctly before + blitter starts normally (after 2 idle cycles) + + There is at least one demo that does this.. + */ // 5 = internal "processing cycle" @@ -166,9 +175,15 @@ static const int blit_cycle_diagram_line[] = static const int blit_cycle_diagram_finald[] = { - 2, 0,4, 0, 4 + 2, 0,4, 0,4 +}; + +static const int blit_cycle_diagram_finalld[] = +{ + 2, 0,0, 0,0 }; + void build_blitfilltable (void) { unsigned int d, fillmask; @@ -227,6 +242,8 @@ STATIC_INLINE int channel_state (int cycles) } STATIC_INLINE int channel_pos (int cycles) { + if (cycles < 0) + return 0; if (cycles < blit_diag[0]) return cycles; cycles -= blit_diag[0]; @@ -260,7 +277,7 @@ static void blitter_interrupt (int hpos) static void blitter_done (int hpos) { ddat1use = ddat2use = 0; - bltstate = BLT_done; + bltstate = blit_startcycles == 0 ? BLT_done : BLT_init; blitter_interrupt (hpos); blitter_done_notify (hpos); if (debug_dma) @@ -287,23 +304,23 @@ static void blitter_dofast (void) uae_u8 mt = bltcon0 & 0xFF; blit_masktable[0] = blt_info.bltafwm; - blit_masktable[blt_info.hblitsize - 1] &= blt_info.bltalwm; + blit_masktable[hblitsize - 1] &= blt_info.bltalwm; if (bltcon0 & 0x800) { bltadatptr = bltapt; - bltapt += (blt_info.hblitsize * 2 + blt_info.bltamod) * blt_info.vblitsize; + bltapt += (hblitsize * 2 + blt_info.bltamod) * vblitsize; } if (bltcon0 & 0x400) { bltbdatptr = bltbpt; - bltbpt += (blt_info.hblitsize * 2 + blt_info.bltbmod) * blt_info.vblitsize; + bltbpt += (hblitsize * 2 + blt_info.bltbmod) * vblitsize; } if (bltcon0 & 0x200) { bltcdatptr = bltcpt; - bltcpt += (blt_info.hblitsize * 2 + blt_info.bltcmod) * blt_info.vblitsize; + bltcpt += (hblitsize * 2 + blt_info.bltcmod) * vblitsize; } if (bltcon0 & 0x100) { bltddatptr = bltdpt; - bltdpt += (blt_info.hblitsize * 2 + blt_info.bltdmod) * blt_info.vblitsize; + bltdpt += (hblitsize * 2 + blt_info.bltdmod) * vblitsize; } #ifdef SPEEDUP @@ -318,9 +335,9 @@ static void blitter_dofast (void) int dodst = 0; /*if (!blitfill) write_log (L"minterm %x not present\n",mt); */ - for (j = 0; j < blt_info.vblitsize; j++) { + for (j = 0; j < vblitsize; j++) { blitfc = !!(bltcon1 & 0x4); - for (i = 0; i < blt_info.hblitsize; i++) { + for (i = 0; i < hblitsize; i++) { uae_u32 bltadat, blitahold; uae_u16 bltbdat; if (bltadatptr) { @@ -376,7 +393,7 @@ static void blitter_dofast (void) blt_info.bltbhold = blitbhold; } blit_masktable[0] = 0xFFFF; - blit_masktable[blt_info.hblitsize - 1] = 0xFFFF; + blit_masktable[hblitsize - 1] = 0xFFFF; bltstate = BLT_done; } @@ -388,23 +405,23 @@ static void blitter_dofast_desc (void) uae_u8 mt = bltcon0 & 0xFF; blit_masktable[0] = blt_info.bltafwm; - blit_masktable[blt_info.hblitsize - 1] &= blt_info.bltalwm; + blit_masktable[hblitsize - 1] &= blt_info.bltalwm; if (bltcon0 & 0x800) { bltadatptr = bltapt; - bltapt -= (blt_info.hblitsize*2 + blt_info.bltamod)*blt_info.vblitsize; + bltapt -= (hblitsize*2 + blt_info.bltamod)*vblitsize; } if (bltcon0 & 0x400) { bltbdatptr = bltbpt; - bltbpt -= (blt_info.hblitsize*2 + blt_info.bltbmod)*blt_info.vblitsize; + bltbpt -= (hblitsize*2 + blt_info.bltbmod)*vblitsize; } if (bltcon0 & 0x200) { bltcdatptr = bltcpt; - bltcpt -= (blt_info.hblitsize*2 + blt_info.bltcmod)*blt_info.vblitsize; + bltcpt -= (hblitsize*2 + blt_info.bltcmod)*vblitsize; } if (bltcon0 & 0x100) { bltddatptr = bltdpt; - bltdpt -= (blt_info.hblitsize*2 + blt_info.bltdmod)*blt_info.vblitsize; + bltdpt -= (hblitsize*2 + blt_info.bltdmod)*vblitsize; } #ifdef SPEEDUP if (blitfunc_dofast_desc[mt] && !blitfill) { @@ -417,9 +434,9 @@ static void blitter_dofast_desc (void) uaecptr dstp = 0; int dodst = 0; - for (j = 0; j < blt_info.vblitsize; j++) { + for (j = 0; j < vblitsize; j++) { blitfc = !!(bltcon1 & 0x4); - for (i = 0; i < blt_info.hblitsize; i++) { + for (i = 0; i < hblitsize; i++) { uae_u32 bltadat, blitahold; uae_u16 bltbdat; if (bltadatptr) { @@ -475,7 +492,7 @@ static void blitter_dofast_desc (void) blt_info.bltbhold = blitbhold; } blit_masktable[0] = 0xFFFF; - blit_masktable[blt_info.hblitsize - 1] = 0xFFFF; + blit_masktable[hblitsize - 1] = 0xFFFF; bltstate = BLT_done; } @@ -581,7 +598,7 @@ static void blitter_line_proc (void) STATIC_INLINE void blitter_nxline (void) { blineb = (blineb << 1) | (blineb >> 15); - blt_info.vblitsize--; + vblitsize--; bltstate = BLT_read; blit_line_pixel = 0; } @@ -595,72 +612,73 @@ static int blitter_vcounter1, blitter_vcounter2; static void decide_blitter_line (int hsync, int hpos) { - if (dmaen (DMA_BLITTER)) { + while (last_blitter_hpos < hpos) { + int c = channel_state (blit_cyclecounter); - while (last_blitter_hpos < hpos) { - int c = channel_state (blit_cyclecounter); + for (;;) { - if (blit_linecyclecounter > 0) { - blit_linecyclecounter--; + if (!canblit (last_blitter_hpos)) { + blit_misscyclecounter++; break; } + if (!dmaen (DMA_BLITTER) && (c == 3 || c == 4)) + break; - for (;;) { + blit_cyclecounter++; + blit_totalcyclecounter++; - if (!canblit (last_blitter_hpos)) { - blit_misscyclecounter++; - break; + // final 2 idle cycles? + if (blit_diag == blit_cycle_diagram_finalld) { + if (blit_cyclecounter > blit_diag[0]) { + bltdpt = bltcpt; + blitter_done (last_blitter_hpos); + return; } + break; + } - blit_cyclecounter++; - blit_totalcyclecounter++; - - /* onedot mode and no pixel = bus write access is skipped */ - if (c == 4 && blitsing && blitonedot > 1) { - if (blt_info.vblitsize == 0) { - bltdpt = bltcpt; - blitter_done (last_blitter_hpos); - return; - } - break; + /* onedot mode and no pixel = bus write access is skipped */ + if (c == 4 && blitsing && blitonedot > 1) { + if (vblitsize == 0) { + blit_diag = blit_cycle_diagram_finalld; + blit_cyclecounter = 0; } + break; + } - if (c == 3) { - - blitter_read (); - alloc_cycle_ext (last_blitter_hpos, CYCLE_BLITTER); - record_dma_blit (0x70, blt_info.bltcdat, bltcpt, last_blitter_hpos); - - } else if (c == 5) { - - if (ddat1use) { - bltdpt = bltcpt; - } - ddat1use = 1; - blitter_line (); - blitter_line_proc (); - blitter_nxline (); + if (c == 3) { - } else if (c == 4) { + blitter_read (); + alloc_cycle_ext (last_blitter_hpos, CYCLE_BLITTER); + record_dma_blit (0x70, blt_info.bltcdat, bltcpt, last_blitter_hpos); - blitter_write (); - alloc_cycle_ext (last_blitter_hpos, CYCLE_BLITTER); - record_dma_blit (0x00, blt_info.bltddat, bltdpt, last_blitter_hpos); - if (blt_info.vblitsize == 0) { - bltdpt = bltcpt; - blitter_done (last_blitter_hpos); - return; - } + } else if (c == 5) { + if (ddat1use) { + bltdpt = bltcpt; + } + ddat1use = 1; + blitter_line (); + blitter_line_proc (); + blitter_nxline (); + + } else if (c == 4) { + + blitter_write (); + alloc_cycle_ext (last_blitter_hpos, CYCLE_BLITTER); + record_dma_blit (0x00, blt_info.bltddat, bltdpt, last_blitter_hpos); + if (vblitsize == 0) { + blit_diag = blit_cycle_diagram_finalld; + blit_cyclecounter = 0; + break; } - break; } - last_blitter_hpos++; + + break; } - } else { - last_blitter_hpos = hpos; + last_blitter_hpos++; } if (hsync) last_blitter_hpos = 0; @@ -678,7 +696,7 @@ static void actually_do_blit (void) blitter_write (); bltdpt = bltcpt; blitter_nxline (); - if (blt_info.vblitsize == 0) + if (vblitsize == 0) bltstate = BLT_done; } while (bltstate != BLT_done); } else { @@ -734,7 +752,7 @@ STATIC_INLINE uae_u16 blitter_doblit (void) bltadat = blt_info.bltadat; if (blitter_hcounter1 == 0) bltadat &= blt_info.bltafwm; - if (blitter_hcounter1 == blt_info.hblitsize - 1) + if (blitter_hcounter1 == hblitsize - 1) bltadat &= blt_info.bltalwm; if (blitdesc) blitahold = (((uae_u32)bltadat << 16) | preva) >> blt_info.blitdownashift; @@ -784,7 +802,7 @@ STATIC_INLINE int blitter_doddma (int hpos) chipmem_agnus_wput2 (bltdpt, d); bltdpt += blit_add; blitter_hcounter2++; - if (blitter_hcounter2 == blt_info.hblitsize) { + if (blitter_hcounter2 == hblitsize) { blitter_hcounter2 = 0; bltdpt += blit_modaddd; blitter_vcounter2++; @@ -792,7 +810,7 @@ STATIC_INLINE int blitter_doddma (int hpos) blitter_vcounter1 = blitter_vcounter2; } #if 0 - if (blitter_hcounter1 == 0 && blitter_vcounter1 == blt_info.vblitsize) { + if (blitter_hcounter1 == 0 && blitter_vcounter1 == vblitsize) { if (blit_diag != blit_cycle_diagram_finald) { blit_cyclecounter = -1; blit_diag = blit_cycle_diagram_finald; @@ -849,7 +867,7 @@ STATIC_INLINE void blitter_dodma (int ch, int hpos) if (bltcon0 & 0x100) ddat1use = 1; blitter_hcounter1++; - if (blitter_hcounter1 == blt_info.hblitsize) { + if (blitter_hcounter1 == hblitsize) { blitter_hcounter1 = 0; if (bltcon0 & 0x800) bltapt += blit_modadda; @@ -876,10 +894,32 @@ int blitter_need (int hpos) return c; } +static void do_startcycles (int hpos) +{ + int vhpos = last_blitter_hpos; + while (vhpos < hpos) { + int v = canblit (vhpos); + vhpos++; + if (v) { + blit_startcycles--; + if (blit_startcycles == 0) { + bltstate = BLT_done; + do_blitter (vhpos, 0); + blit_startcycles = 0; + blit_cyclecounter = 0; + return; + } + } + } +} + void decide_blitter (int hpos) { int hsync = hpos < 0; + if (blit_startcycles > 0) + do_startcycles (hpos); + if (bltstate == BLT_done) return; #ifdef BLITTER_DEBUG @@ -900,86 +940,75 @@ void decide_blitter (int hpos) return; } - if (dmaen (DMA_BLITTER)) { - while (last_blitter_hpos < hpos) { - int c; + while (last_blitter_hpos < hpos) { + int c; - c = channel_state (blit_cyclecounter); + c = channel_state (blit_cyclecounter); - for (;;) { - int v; + for (;;) { + int v; - if (blit_linecyclecounter > 0) { - blit_linecyclecounter--; - break; - } + v = canblit (last_blitter_hpos); - v = canblit (last_blitter_hpos); - - // idle cycles require free bus.. - // (CPU can still use this cycle) - if (c == 0 && v == 0) { - blitter_nasty++; - blit_misscyclecounter++; - break; - } + // idle cycles require free bus.. + // (CPU can still use this cycle) + if (c == 0 && v == 0) { + blitter_nasty++; + blit_misscyclecounter++; + break; + } - if (c == 0) { - blt_info.got_cycle = 1; - blit_cyclecounter++; - blit_totalcyclecounter++; - /* check if blit with zero channels has ended */ - if (blit_ch == 0 && blit_cyclecounter >= blit_maxcyclecounter) { - blitter_done (last_blitter_hpos); - return; - } - break; + if (c == 0) { + blt_info.got_cycle = 1; + blit_cyclecounter++; + blit_totalcyclecounter++; + /* check if blit with zero channels has ended */ + if (blit_ch == 0 && blit_cyclecounter >= blit_maxcyclecounter) { + blitter_done (last_blitter_hpos); + return; } + break; + } - blitter_nasty++; + blitter_nasty++; - if (v == 0) { - blit_misscyclecounter++; - break; - } + if (!dmaen (DMA_BLITTER) || v == 0) { + blit_misscyclecounter++; + break; + } - blt_info.got_cycle = 1; - if (c == 4) { - if (blitter_doddma (last_blitter_hpos)) { - blit_cyclecounter++; - blit_totalcyclecounter++; - } - } else { - if (blitter_vcounter1 < blt_info.vblitsize) { - blitter_dodma (c, last_blitter_hpos); - } + blt_info.got_cycle = 1; + if (c == 4) { + if (blitter_doddma (last_blitter_hpos)) { blit_cyclecounter++; blit_totalcyclecounter++; } - - if (blitter_vcounter1 >= blt_info.vblitsize && blitter_vcounter2 >= blt_info.vblitsize) { - if (!ddat1use && !ddat2use) { - blitter_done (last_blitter_hpos); - return; - } + } else { + if (blitter_vcounter1 < vblitsize) { + blitter_dodma (c, last_blitter_hpos); } - break; + blit_cyclecounter++; + blit_totalcyclecounter++; } - if (blitter_vcounter1 == blt_info.vblitsize && channel_pos (blit_cyclecounter - 1) == blit_diag[0] - 1) { - if (blit_diag != blit_cycle_diagram_finald) { - blitter_interrupt (last_blitter_hpos); - blit_cyclecounter = 0; - blit_diag = blit_cycle_diagram_finald; + if (blitter_vcounter1 >= vblitsize && blitter_vcounter2 >= vblitsize) { + if (!ddat1use && !ddat2use) { + blitter_done (last_blitter_hpos); + return; } } - last_blitter_hpos++; + break; + } + if (blitter_vcounter1 == vblitsize && channel_pos (blit_cyclecounter - 1) == blit_diag[0] - 1) { + if (blit_diag != blit_cycle_diagram_finald) { + blitter_interrupt (last_blitter_hpos); + blit_cyclecounter = 0; + blit_diag = blit_cycle_diagram_finald; + } } - } else { - last_blitter_hpos = hpos; + last_blitter_hpos++; } - if (hsync) last_blitter_hpos = 0; } @@ -1022,22 +1051,23 @@ static void blit_bltset (int con) blitdesc = bltcon1 & 2; + if (bltstate != BLT_done) + return; + + blinea_shift = bltcon0 >> 12; blt_info.blitashift = bltcon0 >> 12; blt_info.blitdownashift = 16 - blt_info.blitashift; blt_info.blitbshift = bltcon1 >> 12; blt_info.blitdownbshift = 16 - blt_info.blitbshift; - if (bltstate != BLT_done && con == 2) - return; - blitline = bltcon1 & 1; blitfill = bltcon1 & 0x18; blit_ch = (bltcon0 & 0x0f00) >> 8; if (blitline) { - if (blt_info.hblitsize != 2) + if (hblitsize != 2) debugtest (DEBUGTEST_BLITTER, L"weird hblitsize in linemode: %d vsize=%d\n", - blt_info.hblitsize, blt_info.vblitsize); + hblitsize, vblitsize); blit_diag = blit_cycle_diagram_line; } else { if (con & 2) { @@ -1083,8 +1113,6 @@ static void blit_modset (void) void reset_blit (int bltcon) { - if (bltcon == 1) - blinea_shift = bltcon0 >> 12; if (bltstate == BLT_done) return; if (bltcon) @@ -1092,19 +1120,22 @@ void reset_blit (int bltcon) blit_modset (); } -void do_blitter (int hpos) +static void do_blitter2 (int hpos, int copper) { int cycles; #ifdef BLITTER_DEBUG_NOWAIT if (bltstate != BLT_done) { + if (blit_diag == blit_cycle_diagram_finald) write_log (L"blitter was already active! PC=%08x\n", M68K_GETPC); } #endif + bltstate = BLT_done; + hblitsize = blt_info.hblitsize; + vblitsize = blt_info.vblitsize; blitter_cycle_exact = currprefs.blitter_cycle_exact; blt_info.blitzero = 1; - bltstate = BLT_init; preva = 0; prevb = 0; blt_info.got_cycle = 0; @@ -1113,7 +1144,7 @@ void do_blitter (int hpos) blit_misscyclecounter = 0; blit_last_cycle = 0; blit_maxcyclecounter = 0; - last_blitter_hpos = hpos; + last_blitter_hpos = hpos + 1; blit_cyclecounter = 0; blit_totalcyclecounter = 0; @@ -1128,10 +1159,10 @@ void do_blitter (int hpos) blineb = (blt_info.bltbdat >> blt_info.blitbshift) | (blt_info.bltbdat << (16 - blt_info.blitbshift)); blitsign = bltcon1 & 0x40; blitonedot = 0; - cycles = blt_info.vblitsize; + cycles = vblitsize; } else { - blit_firstline_cycles = blit_first_cycle + (blit_diag[0] * blt_info.hblitsize + cpu_cycles) * CYCLE_UNIT; - cycles = blt_info.vblitsize * blt_info.hblitsize; + blit_firstline_cycles = blit_first_cycle + (blit_diag[0] * hblitsize + cpu_cycles) * CYCLE_UNIT; + cycles = vblitsize * hblitsize; } #ifdef BLITTER_DEBUG @@ -1147,18 +1178,20 @@ void do_blitter (int hpos) if (blit_ch & 8) ch++; write_log (L"blitstart: %dx%d ch=%d %d*%d=%d d=%d f=%02X n=%d pc=%p l=%d dma=%04X\n", - blt_info.hblitsize, blt_info.vblitsize, ch, blit_diag[0], cycles, blit_diag[0] * cycles, + hblitsize, vblitsize, ch, blit_diag[0], cycles, blit_diag[0] * cycles, blitdesc ? 1 : 0, blitfill, dmaen (DMA_BLITPRI) ? 1 : 0, M68K_GETPC, blitline, dmacon); blitter_dump (); } #endif + + bltstate = BLT_init; blit_slowdown = 0; unset_special (®s, SPCFLAG_BLTNASTY); if (dmaen (DMA_BLITPRI)) set_special (®s, SPCFLAG_BLTNASTY); - if (blt_info.vblitsize == 0 || (blitline && blt_info.hblitsize != 2)) { + if (vblitsize == 0 || (blitline && hblitsize != 2)) { blitter_done (hpos); return; } @@ -1182,10 +1215,10 @@ void do_blitter (int hpos) blitter_hcounter1 = blitter_hcounter2 = 0; blitter_vcounter1 = blitter_vcounter2 = 0; if (blit_nod) - blitter_vcounter2 = blt_info.vblitsize; - blit_linecyclecounter = 3; // delay before blitter starts - blitter_cyclecounter = 0; - blit_maxcyclecounter = blt_info.hblitsize * blt_info.vblitsize + 2; + blitter_vcounter2 = vblitsize; + blit_cyclecounter = -(BLITTER_STARTUP_CYCLES + (copper ? 1 : 0)); + blit_startcycles = 0; + blit_maxcyclecounter = hblitsize * vblitsize + 2; return; } @@ -1197,6 +1230,17 @@ void do_blitter (int hpos) event2_newevent (ev2_blitter, blit_cyclecounter); } +void do_blitter (int hpos, int copper) +{ + if (bltstate == BLT_done || !currprefs.blitter_cycle_exact) { + do_blitter2 (hpos, copper); + return; + } + // previous blit may be have last write cycle left + // we must let it finish + blit_startcycles = BLITTER_STARTUP_CYCLES + (copper ? 1 : 0); +} + void maybe_blit (int hpos, int hack) { static int warned; @@ -1216,7 +1260,7 @@ void maybe_blit (int hpos, int hack) #ifdef BLITTER_DEBUG_NOWAIT warned = 0; write_log (L"program does not wait for blitter PC=%08x\n", M68K_GETPC); - //activate_debugger (); + activate_debugger (); #endif } diff --git a/custom.c b/custom.c index 88ea26b6..6efaa5c8 100644 --- a/custom.c +++ b/custom.c @@ -51,7 +51,7 @@ #include "a2091.h" #include "ncr_scsi.h" -//#define CUSTOM_DEBUG +#define CUSTOM_DEBUG 0 #define SPRITE_DEBUG 0 #define SPRITE_DEBUG_MINY 0xb0 #define SPRITE_DEBUG_MAXY 0xf8 @@ -261,6 +261,7 @@ int diwfirstword_total, diwlastword_total; int firstword_bplcon1; static int last_copper_hpos; +static int copper_access; /* Sprite collisions */ static unsigned int clxdat, clxcon, clxcon2, clxcon_bpl_enable, clxcon_bpl_match; @@ -277,6 +278,7 @@ enum copper_states { COP_skip1, COP_strobe_delay1, COP_strobe_delay2, + COP_start_delay }; struct copper { @@ -780,7 +782,7 @@ static uae_u32 fetched_aga1[MAX_PLANES]; /* Expansions from bplcon0/bplcon1. */ static int toscr_res, toscr_nr_planes, toscr_nr_planes2, fetchwidth; -static int toscr_delay1, toscr_delay2; +static int toscr_delay1, toscr_delay2, toscr_delay1x, toscr_delay2x; /* The number of bits left from the last fetched words. This is an optimization - conceptually, we have to make sure the result is @@ -886,10 +888,10 @@ static void compute_toscr_delay_1 (void) delay1 += delayoffset; delay2 += delayoffset; delaymask = (fetchwidth - 1) >> toscr_res; - toscr_delay1 = (delay1 & delaymask) << toscr_res; - toscr_delay1 |= shdelay1 >> (RES_MAX - toscr_res); - toscr_delay2 = (delay2 & delaymask) << toscr_res; - toscr_delay2 |= shdelay2 >> (RES_MAX - toscr_res); + toscr_delay1x = (delay1 & delaymask) << toscr_res; + toscr_delay1x |= shdelay1 >> (RES_MAX - toscr_res); + toscr_delay2x = (delay2 & delaymask) << toscr_res; + toscr_delay2x |= shdelay2 >> (RES_MAX - toscr_res); } static void compute_toscr_delay (int hpos) @@ -904,6 +906,8 @@ STATIC_INLINE void maybe_first_bpl1dat (int hpos) thisline_decision.plfleft = hpos; compute_delay_offset (); compute_toscr_delay_1 (); + toscr_delay1 = toscr_delay1x; + toscr_delay2 = toscr_delay2x; } } @@ -1195,6 +1199,8 @@ STATIC_INLINE void beginning_of_plane_block (int hpos, int fm) todisplay[i][0] = fetched_aga0[i]; } #endif + toscr_delay1 = toscr_delay1x; + toscr_delay2 = toscr_delay2x; update_denise (hpos); maybe_first_bpl1dat (hpos); compute_toscr_delay (hpos); @@ -1695,10 +1701,14 @@ static void maybe_start_bpl_dma (int hpos) STATIC_INLINE void decide_line (int hpos) { /* Take care of the vertical DIW. */ - if (vpos == plffirstline) + if (vpos == plffirstline) { diwstate = DIW_waiting_stop; - if (vpos == plflastline) + ddf_change = vpos; + } + if (vpos == plflastline) { diwstate = DIW_waiting_start; + ddf_change = vpos; + } if (hpos <= last_decide_line_hpos) return; @@ -2311,12 +2321,13 @@ STATIC_INLINE int color_changes_differ (struct draw_info *dip, struct draw_info /* End of a horizontal scan line. Finish off all decisions that were not * made yet. */ -static void finish_decisions (int hpos) +static void finish_decisions (void) { struct draw_info *dip; struct draw_info *dip_old; struct decision *dp; int changed; + int hpos = maxhpos; if (nodraw ()) return; @@ -2898,7 +2909,7 @@ static void COPJMP (int num, int vblank) cop_state.ignore_next = 0; if (!oldstrobe) cop_state.state_prev = cop_state.state; - cop_state.state = vblank ? COP_strobe_delay2 : COP_strobe_delay1; + cop_state.state = vblank ? COP_start_delay : COP_strobe_delay1; cop_state.vpos = vpos; cop_state.hpos = current_hpos () & ~1; copper_enabled_thisline = 0; @@ -3481,8 +3492,6 @@ static void BLTCPTL (int hpos, uae_u16 v) { maybe_blit (hpos, 0); bltcpt = (bltc static void BLTDPTH (int hpos, uae_u16 v) { maybe_blit (hpos, 0); bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16); } static void BLTDPTL (int hpos, uae_u16 v) { maybe_blit (hpos, 0); bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE); } -// copper writing to BLTSIZE = 5 cycle delay before copper starts (6th cycle is first copper cycle) -// CPU writing to BLTSIZE = 3 cycle delay static void BLTSIZE (int hpos, uae_u16 v) { maybe_blit (hpos, 0); @@ -3493,7 +3502,7 @@ static void BLTSIZE (int hpos, uae_u16 v) blt_info.vblitsize = 1024; if (!blt_info.hblitsize) blt_info.hblitsize = 64; - do_blitter (hpos); + do_blitter (hpos, copper_access); } static void BLTSIZV (int hpos, uae_u16 v) @@ -3514,7 +3523,7 @@ static void BLTSIZH (int hpos, uae_u16 v) blt_info.vblitsize = 32768; if (!blt_info.hblitsize) blt_info.hblitsize = 0x800; - do_blitter (hpos); + do_blitter (hpos, copper_access); } STATIC_INLINE void spr_arm (int num, int state) @@ -3824,8 +3833,13 @@ STATIC_INLINE int copper_cant_read (int hpos) static int custom_wput_copper (int hpos, uaecptr addr, uae_u32 value, int noget) { + int v; + debug_wputpeek (0xdff000 + (cop_state.saved_i1 & 0x1fe), cop_state.saved_i2); - return custom_wput_1 (hpos, addr, value, noget); + copper_access = 1; + v = custom_wput_1 (hpos, addr, value, noget); + copper_access = 0; + return v; } static void dump_copper (TCHAR *error, int until_hpos) @@ -3842,14 +3856,14 @@ static void dump_copper (TCHAR *error, int until_hpos) // use only copper to write BPLCON1 etc.. (exception is HulkaMania/TSP..) static int customdelay[]= { 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* 32 0x00 - 0x3e */ - 0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, /* 0x40 - 0x5e */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x40 - 0x5e */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x60 - 0x7e */ 0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0, /* 0x80 - 0x9e */ 1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0, /* 32 0xa0 - 0xde */ /* BPLxPTH/BPLxPTL */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 16 */ /* BPLCON0-3,BPLMOD1-2 */ - 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 16 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 16 */ /* SPRxPTH/SPRxPTL */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 16 */ /* SPRxPOS/SPRxCTL/SPRxDATA/SPRxDATB */ @@ -3947,6 +3961,14 @@ static void update_copper (int until_hpos) if (debug_dma) record_dma (0x1fe, chipmem_agnus_wget (cop_state.ip + 2), cop_state.ip + 2, old_hpos, vpos); break; + case COP_start_delay: + if (copper_cant_read (old_hpos)) + continue; + cop_state.state = COP_read1; + alloc_cycle (old_hpos, CYCLE_COPPER); + if (debug_dma) + record_dma (0x1fe, 0, 0xffffffff, old_hpos, vpos); + break; case COP_read1: if (copper_cant_read (old_hpos)) @@ -4156,14 +4178,28 @@ static void compute_spcflag_copper (int hpos) set_special (®s, SPCFLAG_COPPER); } +/* + Copper writes to BLTSIZE: 2 blitter idle cycles, blitter normal cycle starts + BFD=0 wait: blitter interrupt, 4 cycles, copper fetches next word +*/ void blitter_done_notify (int hpos) { + int vp = vpos; + if (cop_state.state != COP_bltwait) return; - cop_state.hpos = (hpos + 2) & ~1; - cop_state.vpos = vpos; + + hpos += 4; + hpos &= ~1; + if (hpos >= maxhpos) { + hpos -= maxhpos; + vp++; + } + cop_state.hpos = hpos; + cop_state.vpos = vp; cop_state.state = COP_read1; - if (dmaen (DMA_COPPER)) { + + if (dmaen (DMA_COPPER) && vp == vpos) { copper_enabled_thisline = 1; set_special (®s, SPCFLAG_COPPER); } @@ -4280,8 +4316,6 @@ STATIC_INLINE void do_sprites_1 (int num, int cycle, int hpos) } #endif } - if (!dmaen (DMA_SPRITE)) - return; if (cycle && !s->dmacycle) return; /* Superfrog intro flashing bee fix */ @@ -4393,22 +4427,26 @@ static void do_sprites (int hpos) if (minspr < SPR0_HPOS) minspr = SPR0_HPOS; - for (i = minspr; i <= maxspr; i++) { - int cycle = -1; - int num = (i - SPR0_HPOS) / 4; - switch ((i - SPR0_HPOS) & 3) - { - case 0: - cycle = 0; - spr[num].dmacycle = 0; - break; - case 2: - cycle = 1; - break; + if (dmaen (DMA_SPRITE)) { + + for (i = minspr; i <= maxspr; i++) { + int cycle = -1; + int num = (i - SPR0_HPOS) / 4; + switch ((i - SPR0_HPOS) & 3) + { + case 0: + cycle = 0; + spr[num].dmacycle = 0; + break; + case 2: + cycle = 1; + break; + } + if (cycle >= 0 && num >= 0 && num < MAX_SPRITES) + do_sprites_1 (num, cycle, i); } - if (cycle >= 0 && num >= 0 && num < MAX_SPRITES) - do_sprites_1 (num, cycle, i); } + last_sprite_hpos = hpos; #else for (i = 0; i < MAX_SPRITES * 2; i++) { @@ -4846,7 +4884,7 @@ static void hsync_scandoubler (void) } curr_color_changes[next_color_change].regno = -1; - finish_decisions (maxhpos); + finish_decisions (); hsync_record_line_state (next_lineno, nln_normal, thisline_changed); hardware_line_completed (next_lineno); scandoubled_line = 0; @@ -4864,7 +4902,7 @@ static void hsync_handler (void) if (!nocustom ()) { sync_copper_with_cpu (maxhpos, 0); last_copper_hpos = 0; - finish_decisions (hpos); + finish_decisions (); if (thisline_decision.plfleft != -1) { if (currprefs.collision_level > 1) do_sprite_collisions (); @@ -4976,7 +5014,7 @@ static void hsync_handler (void) alloc_cycle (hp, i == 0 ? CYCLE_STROBE : CYCLE_REFRESH); /* strobe */ #ifdef DEBUGGER if (debug_dma) - record_dma (i == 0 ? (vpos + 1 == maxvpos + lof ? 0x3a : 0x3c) : 0x1fe, 0xffff, 0xffffffff, hp, vpos); + record_dma (i == 0 ? (vpos + 1 == maxvpos + lof ? 0x38 : 0x3c) : 0x1fe, 0xffff, 0xffffffff, hp, vpos); #endif hp += 2; if (hp >= maxhpos) @@ -5562,7 +5600,7 @@ STATIC_INLINE uae_u32 REGPARAM2 custom_wget_1 (int hpos, uaecptr addr, int noput special_mem |= S_READ; #endif addr &= 0xfff; -#ifdef CUSTOM_DEBUG +#if CUSTOM_DEBUG > 2 write_log (L"%d:%d:wget: %04X=%04X pc=%p\n", current_hpos(), vpos, addr, addr & 0x1fe, m68k_getpc ()); #endif switch (addr & 0x1fe) { @@ -5611,6 +5649,9 @@ STATIC_INLINE uae_u32 REGPARAM2 custom_wget_1 (int hpos, uaecptr addr, int noput decide_line (hpos); decide_fetch (hpos); decide_blitter (hpos); +#if CUSTOM_DEBUG > 0 + write_log (L"%04X read!\n", addr); +#endif r = custom_wput_copper (hpos, addr, last_custom_value, 1); if (currprefs.chipset_mask & CSMASK_AGA) { v = last_custom_value; @@ -5876,8 +5917,12 @@ static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int n /* writing to read-only register causes read access */ default: - if (!noget) + if (!noget) { +#if CUSTOM_DEBUG > 0 + write_log (L"%04X written!\n", addr); +#endif custom_wget_1 (hpos, addr, 1); + } return 1; } return 0; @@ -5889,7 +5934,7 @@ static void REGPARAM2 custom_wput (uaecptr addr, uae_u32 value) #ifdef JIT special_mem |= S_WRITE; #endif -#ifdef CUSTOM_DEBUG +#if CUSTOM_DEBUG > 2 write_log (L"%d:%d:wput: %04X %04X pc=%p\n", hpos, vpos, addr & 0x01fe, value & 0xffff, m68k_getpc ()); #endif sync_copper_with_cpu (hpos, 1); diff --git a/disk.c b/disk.c index e9b18e48..4ba5b7ca 100644 --- a/disk.c +++ b/disk.c @@ -2563,6 +2563,30 @@ void DISK_handler (uae_u32 data) #endif } +#ifdef CPUEMU_12 +extern uae_u8 cycle_line[256]; + +static void diskdma (uae_u32 pt, uae_u16 w, int write) +{ + int i, got; + + got = 0; + for (i = 7; i <= 11; i += 2) { + if (!cycle_line[i]) { + cycle_line[i] = CYCLE_MISC; + if (debug_dma) + record_dma (write ? 0x26 : 0x08, w, pt, i, vpos); + got = 1; + break; + } +// if (cycle_line[i] != CYCLE_MISC) +// write_log (L"%d!?\n", cycle_line[i]); + } +// if (!got) +// write_log (L"disk dma cycle overflow!?\n"); +} +#endif + static void disk_doupdate_write (drive * drv, int floppybits) { int dr; @@ -2592,6 +2616,9 @@ static void disk_doupdate_write (drive * drv, int floppybits) for (dr = 0; dr < MAX_FLOPPY_DRIVES ; dr++) { drive *drv2 = &floppy[dr]; uae_u16 w = get_word (dskpt); +#ifdef CPUEMU_12 + diskdma (dskpt, w, 1); +#endif if (drives[dr]) { drv2->bigmfmbuf[drv2->mfmpos >> 4] = w; drv2->bigmfmbuf[(drv2->mfmpos >> 4) + 1] = 0x5555; @@ -2693,10 +2720,6 @@ static void disk_doupdate_predict (drive * drv, int startcycle) } } -#ifdef CPUEMU_12 -extern uae_u8 cycle_line[256]; -#endif - static void disk_doupdate_read_nothing (int floppybits) { int j = 0, k = 1, l = 0; @@ -2706,6 +2729,9 @@ static void disk_doupdate_read_nothing (int floppybits) if (bitoffset == 15 && dma_enable && dskdmaen == 2 && dsklength >= 0) { if (dsklength > 0) { put_word (dskpt, word); +#ifdef CPUEMU_12 + diskdma (dskpt, word, 0); +#endif dskpt += 2; } dsklength--; @@ -2769,11 +2795,10 @@ static void disk_doupdate_read (drive * drv, int floppybits) if (bitoffset == 15 && dma_enable && dskdmaen == 2 && dsklength >= 0) { if (dsklength > 0) { put_word (dskpt, word); - dskpt += 2; #ifdef CPUEMU_12 - cycle_line[7] |= CYCLE_MISC; - cycle_line[9] |= CYCLE_MISC; + diskdma (dskpt, word, 0); #endif + dskpt += 2; } #if 0 dma_tab[j++] = word; diff --git a/gencpu.c b/gencpu.c index 6e3f867b..565cb80e 100644 --- a/gencpu.c +++ b/gencpu.c @@ -35,6 +35,8 @@ static int using_prefetch, using_indirect, using_mmu; static int using_exception_3; static int using_ce; static int cpu_level; +static int count_read, count_write, count_cycles, count_ncycles; +static int count_read_ea, count_write_ea, count_cycles_ea; static int optimized_flags; @@ -122,16 +124,19 @@ static void addcycles (int cycles) { if (!using_ce) return; printf ("\tdo_cycles_ce (%d * CYCLE_UNIT / 2);\n", cycles); + count_cycles += cycles; } static void addcycles2 (char *s, int cycles) { if (!using_ce) return; printf ("%sdo_cycles_ce (%d * CYCLE_UNIT / 2);\n", s, cycles); + count_cycles += cycles; } static void addcycles3 (char *s) { if (!using_ce) return; printf ("%sif (cycles > 0) do_cycles_ce (cycles);\n", s); + count_ncycles++; } static int isreg(amodes mode) @@ -198,20 +203,26 @@ static void gen_nextilong (char *type, char *name, int norefill) /* we must do this because execution order of (something | something2) is not defined */ if (norefill) { printf ("\t%s = get_word_ce_prefetch (regs, %d) << 16;\n", name, r + 2); + count_read++; printf ("\t%s |= regs->irc;\n", name); } else { printf ("\t%s = get_word_ce_prefetch (regs, %d) << 16;\n", name, r + 2); + count_read++; printf ("\t%s |= get_word_ce_prefetch (regs, %d);\n", name, r + 4); + count_read++; } } else { if (using_prefetch) { if (norefill) { printf ("\t%s %s;\n", type, name); printf ("\t%s = get_word_prefetch (regs, %d) << 16;\n", name, r + 2); + count_read++; printf ("\t%s |= regs->irc;\n", name); insn_n_cycles += 4; } else { printf ("\t%s %s = get_long_prefetch (regs, %d);\n", type, name, r + 2); + count_read++; + count_read++; insn_n_cycles += 8; } } else if (using_indirect) { @@ -234,16 +245,19 @@ static const char *gen_nextiword (int norefill) m68k_pc_offset += 2; if (using_ce) { - if (norefill) + if (norefill) { strcpy (buffer, "regs->irc"); - else + } else { sprintf (buffer, "get_word_ce_prefetch (regs, %d)", r + 2); + count_read++; + } } else { if (using_prefetch) { if (norefill) { sprintf (buffer, "regs->irc", r); } else { sprintf (buffer, "get_word_prefetch (regs, %d)", r + 2); + count_read++; insn_n_cycles += 4; } } else if (using_indirect) { @@ -267,10 +281,12 @@ static const char *gen_nextibyte (int norefill) m68k_pc_offset += 2; if (using_ce) { - if (norefill) + if (norefill) { strcpy (buffer, "(uae_u8)regs->irc"); - else + } else { sprintf (buffer, "(uae_u8)get_word_ce_prefetch (regs, %d)", r + 2); + count_read++; + } } else { insn_n_cycles += 4; if (using_prefetch) { @@ -279,6 +295,7 @@ static const char *gen_nextibyte (int norefill) } else { sprintf (buffer, "(uae_u8)get_word_prefetch (regs, %d)", r + 2); insn_n_cycles += 4; + count_read++; } } else if (using_indirect) { sprintf (buffer, "get_ibytei (%d)", r); @@ -312,6 +329,7 @@ static void fill_prefetch_2 (void) else printf ("\tget_word_prefetch (regs, %d);\n", m68k_pc_offset + 2); did_prefetch = 1; + count_read++; insn_n_cycles += 4; } @@ -325,6 +343,7 @@ static void fill_prefetch_1 (int o) printf ("\tget_word_prefetch (regs, %d);\n", o); } did_prefetch = 1; + count_read++; insn_n_cycles += 4; } @@ -344,6 +363,7 @@ static void fill_prefetch_0 (void) else printf ("\tget_word_prefetch (regs, 0);\n"); did_prefetch = 1; + count_read++; insn_n_cycles += 4; } @@ -475,10 +495,12 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g if (!(flags & GF_APDI)) { addcycles (2); insn_n_cycles += 2; + count_cycles_ea += 2; } break; case Ad16: printf ("\tuaecptr %sa = m68k_areg (regs, %s) + (uae_s32)(uae_s16)%s;\n", name, reg, gen_nextiword (flags & GF_NOREFILL)); + count_read_ea++; break; case Ad8r: printf ("\tuaecptr %sa;\n", name); @@ -495,10 +517,12 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g printf ("\t%sa = get_disp_ea_020 (regs, m68k_areg (regs, %s), next_iword (regs));\n", name, reg); } else { printf ("\t%sa = get_disp_ea_000 (regs, m68k_areg (regs, %s), %s);\n", name, reg, gen_nextiword (flags & GF_NOREFILL)); + count_read_ea++; } if (!(flags & GF_AD8R)) { addcycles (2); insn_n_cycles += 2; + count_cycles_ea += 2; } break; case PC16: @@ -527,6 +551,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g if (!(flags & GF_PC8R)) { addcycles (2); insn_n_cycles += 2; + count_cycles_ea += 2; } break; @@ -535,6 +560,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g break; case absl: gen_nextilong ("uaecptr", namea, flags & GF_NOREFILL); + count_read_ea += 2; break; case imm: if (getv != 1) @@ -542,12 +568,15 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g switch (size) { case sz_byte: printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte (flags & GF_NOREFILL)); + count_read_ea++; break; case sz_word: printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword (flags & GF_NOREFILL)); + count_read_ea++; break; case sz_long: gen_nextilong ("uae_s32", name, flags & GF_NOREFILL); + count_read_ea += 2; break; default: abort (); @@ -557,16 +586,19 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g if (getv != 1) abort (); printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte (flags & GF_NOREFILL)); + count_read_ea++; return; case imm1: if (getv != 1) abort (); printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword (flags & GF_NOREFILL)); + count_read_ea++; return; case imm2: if (getv != 1) abort (); gen_nextilong ("uae_s32", name, flags & GF_NOREFILL); + count_read_ea += 2; return; case immi: if (getv != 1) @@ -597,9 +629,9 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g start_brace (); if (using_ce) { switch (size) { - case sz_byte: printf ("\tuae_s8 %s = get_byte_ce (%sa);\n", name, name); break; - case sz_word: printf ("\tuae_s16 %s = get_word_ce (%sa);\n", name, name); break; - case sz_long: printf ("\tuae_s32 %s = get_word_ce (%sa) << 16; %s |= get_word_ce (%sa + 2);\n", name, name, name, name); break; + case sz_byte: printf ("\tuae_s8 %s = get_byte_ce (%sa);\n", name, name); count_read++; break; + case sz_word: printf ("\tuae_s16 %s = get_word_ce (%sa);\n", name, name); count_read++; break; + case sz_long: printf ("\tuae_s32 %s = get_word_ce (%sa) << 16; %s |= get_word_ce (%sa + 2);\n", name, name, name, name); count_read += 2; break; default: abort (); } } else if (using_mmu) { @@ -611,9 +643,9 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g } } else { switch (size) { - case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = get_byte (%sa);\n", name, name); break; - case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = get_word (%sa);\n", name, name); break; - case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = get_long (%sa);\n", name, name); break; + case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = get_byte (%sa);\n", name, name); count_read++; break; + case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = get_word (%sa);\n", name, name); count_read++; break; + case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = get_long (%sa);\n", name, name); count_read += 2; break; default: abort (); } } @@ -698,11 +730,13 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha switch (size) { case sz_byte: printf ("\tput_byte_ce (%sa,%s);\n", to, from); + count_write++; break; case sz_word: if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) abort (); printf ("\tput_word_ce (%sa,%s);\n", to, from); + count_write++; break; case sz_long: if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) @@ -711,6 +745,7 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha printf ("\tput_word_ce (%sa + 2, %s); put_word_ce (%sa, %s >> 16);\n", to, from, to, from); else printf ("\tput_word_ce (%sa, %s >> 16); put_word_ce (%sa + 2, %s);\n", to, from, to, from); + count_write += 2; break; default: abort (); @@ -741,18 +776,21 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha case sz_byte: insn_n_cycles += 4; printf ("\tput_byte (%sa,%s);\n", to, from); + count_write++; break; case sz_word: insn_n_cycles += 4; if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) abort (); printf ("\tput_word (%sa,%s);\n", to, from); + count_write++; break; case sz_long: insn_n_cycles += 8; if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) abort (); printf ("\tput_long (%sa,%s);\n", to, from); + count_write += 2; break; default: abort (); @@ -799,18 +837,22 @@ static void genmovemel (uae_u16 opcode) strcpy (getcode, "(uae_s32)(uae_s16)get_word (srca)"); } } + count_read += table68k[opcode].size == sz_long ? 2 : 1; printf ("\tuae_u16 mask = %s;\n", gen_nextiword (0)); printf ("\tunsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1, 0); - fill_prefetch_next (); start_brace (); printf ("\twhile (dmask) { m68k_dreg (regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask]; }\n", getcode, size); printf ("\twhile (amask) { m68k_areg (regs, movem_index1[amask]) = %s; srca += %d; amask = movem_next[amask]; }\n", getcode, size); - if (table68k[opcode].dmode == Aipi) + if (table68k[opcode].dmode == Aipi) { printf ("\tm68k_areg (regs, dstreg) = srca;\n"); + count_read++; + } + fill_prefetch_next (); + count_ncycles++; } static void genmovemel_ce (uae_u16 opcode) @@ -820,7 +862,6 @@ static void genmovemel_ce (uae_u16 opcode) printf ("\tunsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); printf ("\tuae_u32 v;\n"); genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1, GF_AA); - fill_prefetch_next (); if (table68k[opcode].dmode == Ad8r || table68k[opcode].dmode == PC8r) addcycles (2); start_brace (); @@ -836,8 +877,11 @@ static void genmovemel_ce (uae_u16 opcode) size); } printf ("\tget_word_ce (srca);\n"); // and final extra word fetch that goes nowhere.. + count_read++; if (table68k[opcode].dmode == Aipi) printf ("\tm68k_areg (regs, dstreg) = srca;\n"); + fill_prefetch_next (); + count_ncycles++; } static void genmovemle (uae_u16 opcode) @@ -858,14 +902,10 @@ static void genmovemle (uae_u16 opcode) strcpy (putcode, "put_word (srca"); } } + count_write += table68k[opcode].size == sz_long ? 2 : 1; printf ("\tuae_u16 mask = %s;\n", gen_nextiword (0)); genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1, 0); - if (using_prefetch) { - sync_m68k_pc (); - fill_prefetch_next (); - } - start_brace (); if (table68k[opcode].dmode == Apdi) { printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n"); @@ -886,6 +926,11 @@ static void genmovemle (uae_u16 opcode) printf ("\twhile (amask) { %s, m68k_areg (regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n", putcode, size); } + if (using_prefetch) { + sync_m68k_pc (); + fill_prefetch_next (); + } + count_ncycles++; } static void genmovemle_ce (uae_u16 opcode) @@ -894,9 +939,9 @@ static void genmovemle_ce (uae_u16 opcode) printf ("\tuae_u16 mask = %s;\n", gen_nextiword (0)); genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1, GF_AA); - if (table68k[opcode].dmode == Ad8r || table68k[opcode].dmode == PC8r) + if (table68k[opcode].dmode == Ad8r || table68k[opcode].dmode == PC8r) { addcycles (2); - fill_prefetch_next (); + } start_brace (); if (table68k[opcode].size == sz_long) { if (table68k[opcode].dmode == Apdi) { @@ -929,6 +974,8 @@ static void genmovemle_ce (uae_u16 opcode) size); } } + fill_prefetch_next (); + count_ncycles++; } static void duplicate_carry (int n) @@ -1205,11 +1252,13 @@ static int source_is_imm1_8 (struct instr *i) static void shift_ce (amodes dmode, int size) { if (using_ce && isreg (dmode)) { + int c = size == sz_long ? 4 : 2; printf ("\t{\n"); - printf ("\t\tint cycles = %d * CYCLE_UNIT / 2;\n", size == sz_long ? 4 : 2); + printf ("\t\tint cycles = %d * CYCLE_UNIT / 2;\n", c); printf ("\t\tcycles += 2 * CYCLE_UNIT / 2 * ccnt;\n"); addcycles3 ("\t\t"); printf ("\t}\n"); + count_cycles += c; } } @@ -1222,15 +1271,17 @@ static void bsetcycles (struct instr *curi) printf ("\tsrc &= 31;\n"); if (isreg (curi->dmode)) { addcycles (2); - if (curi->mnemo != i_BTST) + if (curi->mnemo != i_BTST) { printf ("\tif (src > 15) do_cycles_ce (2 * CYCLE_UNIT / 2);\n"); + count_ncycles++; + } } } } static int islongimm (struct instr *curi) { - return (curi->size == sz_long && (isreg (curi->smode) || curi->smode == imm || curi->smode == immi)); + return (curi->size == sz_long && (curi->smode == Dreg || curi->smode == imm)); } static void gen_opcode (unsigned long int opcode) @@ -1271,10 +1322,25 @@ static void gen_opcode (unsigned long int opcode) genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0); printf ("\tsrc %c= dst;\n", curi->mnemo == i_OR ? '|' : curi->mnemo == i_AND ? '&' : '^'); genflags (flag_logical, curi->size, "src", "", ""); - if (curi->size == sz_long) { - int c = (curi->mnemo == i_EOR ? 4 : 2); - if (curi->mnemo != i_EOR && islongimm (curi)) - c += 2; + if (curi->smode == imm) { + int c = 0; + if (curi->size == sz_long && curi->dmode == Dreg) { + // op.L #,Dn = +2 cycles (AND), +4 cycles (EOR,OR) + if (curi->mnemo == i_EOR || curi->mnemo == i_OR) + c += 4; + else + c += 2; + } + if (c > 0) + addcycles (c); + } else if (curi->smode == Dreg) { + int c = 0; + if (curi->dmode == Dreg) { + if (curi->size == sz_long) + c += 2; + if (curi->size == sz_long && curi->smode == Dreg) + c += 2; + } if (c > 0) addcycles (c); } @@ -1307,11 +1373,11 @@ static void gen_opcode (unsigned long int opcode) case i_SUB: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0); genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0); - if (isreg (curi->dmode)) { + if (curi->dmode == Dreg) { int c = 0; if (curi->size == sz_long) { c += 2; - if (islongimm (curi)) + if (curi->smode == imm || curi->smode == immi || curi->smode == Dreg) c += 2; } if (c > 0) @@ -1325,7 +1391,11 @@ static void gen_opcode (unsigned long int opcode) case i_SUBA: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0); genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0, 0); - if (isreg (curi->dmode)) { + if (curi->smode == immi) { + int c = 4; + if (c > 0) + addcycles (c); + } else { int c = curi->size == sz_long ? 2 : 4; if (islongimm (curi)) c += 2; @@ -1340,12 +1410,10 @@ static void gen_opcode (unsigned long int opcode) case i_SUBX: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA); genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA); - if (curi->size == sz_long) { - if (isreg (curi->smode)) - addcycles (4); - else - addcycles (2); - } + if (curi->size == sz_long && isreg (curi->smode)) + addcycles (4); + if (!isreg (curi->smode)) + addcycles (2); fill_prefetch_next (); start_brace (); printf ("\tuae_u32 newv = dst - src - (GET_XFLG (®s->ccrflags) ? 1 : 0);\n"); @@ -1382,11 +1450,11 @@ static void gen_opcode (unsigned long int opcode) case i_ADD: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0); genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0); - if (isreg (curi->dmode)) { + if (curi->dmode == Dreg) { int c = 0; if (curi->size == sz_long) { c += 2; - if (islongimm (curi)) + if (curi->smode == imm || curi->smode == immi || curi->smode == Dreg) c += 2; } if (c > 0) @@ -1400,7 +1468,13 @@ static void gen_opcode (unsigned long int opcode) case i_ADDA: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0); genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0, 0); - if (isreg (curi->dmode)) { + if (curi->smode == immi) { + int c = curi->size == sz_long ? 4 : 0; + if (islongimm (curi)) + c += 2; + if (c > 0) + addcycles (c); + } else { int c = curi->size == sz_long ? 2 : 4; if (islongimm (curi)) c += 2; @@ -1415,12 +1489,10 @@ static void gen_opcode (unsigned long int opcode) case i_ADDX: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA); genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA); - if (curi->size == sz_long) { - if (isreg (curi->smode)) - addcycles (4); - else - addcycles (2); - } + if (curi->size == sz_long && isreg (curi->smode)) + addcycles (4); + if (!isreg (curi->smode)) + addcycles (2); fill_prefetch_next (); start_brace (); printf ("\tuae_u32 newv = dst + src + (GET_XFLG (®s->ccrflags) ? 1 : 0);\n"); @@ -1539,7 +1611,7 @@ static void gen_opcode (unsigned long int opcode) genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0); genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0); bsetcycles (curi); - if (curi->mnemo == i_BCLR) + if (curi->mnemo == i_BCLR && curi->dmode == Dreg) addcycles (2); fill_prefetch_next (); if (curi->mnemo == i_BCHG) { @@ -1564,10 +1636,8 @@ static void gen_opcode (unsigned long int opcode) case i_CMP: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0); genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0); - if (isreg (curi->dmode)) { - if (curi->dmode == Areg || (curi->dmode == Dreg && curi->size == sz_long)) - addcycles (2); - } + if (curi->dmode == Dreg && curi->size == sz_long) + addcycles (2); fill_prefetch_next (); start_brace (); genflags (flag_cmp, curi->size, "newv", "src", "dst"); @@ -1575,52 +1645,57 @@ static void gen_opcode (unsigned long int opcode) case i_CMPA: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0); genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0, 0); - if (isreg (curi->dmode)) { - if (curi->dmode == Areg || (curi->dmode == Dreg && curi->size == sz_long)) - addcycles (2); - } + addcycles (2); fill_prefetch_next (); start_brace (); genflags (flag_cmp, sz_long, "newv", "src", "dst"); break; /* The next two are coded a little unconventional, but they are doing * weird things... */ - case i_MVPRM: + case i_MVPRM: // MOVEP R->M genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0); printf ("\tuaecptr memp = m68k_areg (regs, dstreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword (0)); if (using_ce) { if (curi->size == sz_word) { printf ("\tput_byte_ce (memp, src >> 8); put_byte_ce (memp + 2, src);\n"); + count_write += 2; } else { printf ("\tput_byte_ce (memp, src >> 24); put_byte_ce (memp + 2, src >> 16);\n"); printf ("\tput_byte_ce (memp + 4, src >> 8); put_byte_ce (memp + 6, src);\n"); + count_write += 4; } } else { if (curi->size == sz_word) { printf ("\tput_byte (memp, src >> 8); put_byte (memp + 2, src);\n"); + count_write += 2; } else { printf ("\tput_byte (memp, src >> 24); put_byte (memp + 2, src >> 16);\n"); printf ("\tput_byte (memp + 4, src >> 8); put_byte (memp + 6, src);\n"); + count_write += 4; } } fill_prefetch_next (); break; - case i_MVPMR: // MOVEP + case i_MVPMR: // MOVEP M->R printf ("\tuaecptr memp = m68k_areg (regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword (0)); genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0, 0); if (using_ce) { if (curi->size == sz_word) { printf ("\tuae_u16 val = (get_byte_ce (memp) << 8) + get_byte_ce (memp + 2);\n"); + count_read += 2; } else { printf ("\tuae_u32 val = (get_byte_ce (memp) << 24) + (get_byte_ce (memp + 2) << 16)\n"); printf (" + (get_byte_ce (memp + 4) << 8) + get_byte_ce (memp + 6);\n"); + count_read += 4; } } else { if (curi->size == sz_word) { printf ("\tuae_u16 val = (get_byte (memp) << 8) + get_byte (memp + 2);\n"); + count_read += 2; } else { printf ("\tuae_u32 val = (get_byte (memp) << 24) + (get_byte (memp + 2) << 16)\n"); printf (" + (get_byte (memp + 4) << 8) + get_byte (memp + 6);\n"); + count_read += 4; } } fill_prefetch_next (); @@ -1742,7 +1817,8 @@ static void gen_opcode (unsigned long int opcode) break; case i_RESET: fill_prefetch_next (); - printf ("\tcpureset();\n"); + printf ("\tcpureset ();\n"); + addcycles (128); if (using_prefetch) printf ("\tregs->irc = get_iword (regs, 4);\n"); break; @@ -1848,16 +1924,17 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_do_rtsi(regs);\n"); else printf ("\tm68k_do_rts(regs);\n"); + count_read += 2; m68k_pc_offset = 0; fill_prefetch_full (); break; case i_TRAPV: sync_m68k_pc (); + fill_prefetch_next (); printf ("\tif (GET_VFLG (®s->ccrflags)) {\n"); printf ("\t\tException (7, regs, m68k_getpc (regs));\n"); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); - fill_prefetch_next (); need_endlabel = 1; break; case i_RTR: @@ -1881,9 +1958,13 @@ static void gen_opcode (unsigned long int opcode) printf ("\t}\n"); need_endlabel = 1; } + if (curi->smode == Ad16 || curi->smode == absw || curi->smode == PC16) + addcycles (2); printf ("\tm68k_setpc (regs, srca);\n"); m68k_pc_offset = 0; fill_prefetch_1 (0); + if (curi->smode == Ad8r || curi->smode == PC8r) + addcycles (6); printf("\tm68k_areg (regs, 7) -= 4;\n"); if (using_ce) { printf("\tput_word_ce (m68k_areg (regs, 7), oldpc >> 16);\n"); @@ -1891,10 +1972,11 @@ static void gen_opcode (unsigned long int opcode) } else { printf("\tput_long (m68k_areg (regs, 7), oldpc);\n"); } + count_write += 2; fill_prefetch_next (); break; case i_JMP: - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA|GF_NOREFILL); + genamode (curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA | ((curi->smode == Ad8r || curi->smode == PC8r) ? 0 : GF_NOREFILL)); if (using_exception_3) { printf ("\tif (srca & 1) {\n"); printf ("\t\texception3i (opcode, m68k_getpc (regs) + 6, srca);\n"); @@ -1904,6 +1986,7 @@ static void gen_opcode (unsigned long int opcode) } if (curi->smode == Ad16 || curi->smode == Ad8r || curi->smode == absw || curi->smode == PC16 || curi->smode == PC8r) addcycles (2); +// if (using_ce && (curi->smode == Ad8r || curi->smode == PC8r)) printf ("\tm68k_setpc (regs, srca);\n"); m68k_pc_offset = 0; fill_prefetch_full (); @@ -1926,6 +2009,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_do_bsri (regs, m68k_getpc (regs) + %d, s);\n", m68k_pc_offset); else printf ("\tm68k_do_bsr (regs, m68k_getpc (regs) + %d, s);\n", m68k_pc_offset); + count_write += 2; m68k_pc_offset = 0; fill_prefetch_full (); break; @@ -1979,25 +2063,33 @@ static void gen_opcode (unsigned long int opcode) addcycles (2); irc2ir (); fill_prefetch_2 (); - } else + } else if (curi->size == sz_word) { + addcycles (2); fill_prefetch_full (); + } else { + fill_prefetch_full (); + } insn_n_cycles = curi->size == sz_byte ? 8 : 12; break; case i_LEA: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA); genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0, GF_AA); if (curi->smode == Ad8r || curi->smode == PC8r) - addcycles (4); + addcycles (2); fill_prefetch_next (); + if (curi->smode == Ad8r || curi->smode == PC8r) + addcycles (2); genastore ("srca", curi->dmode, "dstreg", curi->size, "dst"); break; case i_PEA: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA); genamode (Apdi, "7", sz_long, "dst", 2, 0, GF_AA); if (curi->smode == Ad8r || curi->smode == PC8r) - addcycles (4); + addcycles (2); if (!(curi->smode == absw || curi->smode == absl)) fill_prefetch_next (); + if (curi->smode == Ad8r || curi->smode == PC8r) + addcycles (2); genastore ("srca", Apdi, "7", sz_long, "dst"); if ((curi->smode == absw || curi->smode == absl)) fill_prefetch_next (); @@ -2068,8 +2160,10 @@ static void gen_opcode (unsigned long int opcode) printf ("\t} else {\n"); printf ("\t\tuae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;\n"); printf ("\t\tuae_u32 rem = (uae_u32)dst %% (uae_u32)(uae_u16)src;\n"); + fill_prefetch_next (); if (using_ce) { - printf ("\t\tint cycles = getDivu68kCycles((uae_u32)dst, (uae_u16)src) * CYCLE_UNIT / 2;\n"); + start_brace (); + printf ("\t\tint cycles = (getDivu68kCycles((uae_u32)dst, (uae_u16)src) - 4) * CYCLE_UNIT / 2;\n"); addcycles3 ("\t\t"); } /* The N flag appears to be set each time there is an overflow. @@ -2087,9 +2181,9 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\t\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n"); printf ("\t\t"); genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); printf ("\t\t}\n"); - fill_prefetch_next (); sync_m68k_pc (); printf ("\t}\n"); + count_ncycles++; insn_n_cycles += 136 - (136 - 76) / 2; /* average */ need_endlabel = 1; break; @@ -2112,8 +2206,10 @@ static void gen_opcode (unsigned long int opcode) printf ("\t} else {\n"); printf ("\t\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n"); printf ("\t\tuae_u16 rem = (uae_s32)dst %% (uae_s32)(uae_s16)src;\n"); + fill_prefetch_next (); if (using_ce) { - printf ("\t\tint cycles = getDivs68kCycles((uae_s32)dst, (uae_s16)src) * CYCLE_UNIT / 2;\n"); + start_brace (); + printf ("\t\tint cycles = (getDivs68kCycles((uae_s32)dst, (uae_s16)src) - 4) * CYCLE_UNIT / 2;\n"); addcycles3 ("\t\t"); } printf ("\t\tif ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) {\n"); @@ -2130,9 +2226,9 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\t\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n"); printf ("\t\t"); genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); printf ("\t\t}\n"); - fill_prefetch_next (); sync_m68k_pc (); printf ("\t}\n"); + count_ncycles++; insn_n_cycles += 156 - (156 - 120) / 2; /* average */ need_endlabel = 1; break; @@ -2143,7 +2239,7 @@ static void gen_opcode (unsigned long int opcode) start_brace (); printf ("\tuae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;\n"); if (using_ce) - printf ("\tint cycles = 36 * CYCLE_UNIT / 2, bits;\n"); + printf ("\tint cycles = (38 - 4) * CYCLE_UNIT / 2, bits;\n"); genflags (flag_logical, sz_long, "newv", "", ""); if (using_ce) { printf ("\tfor(bits = 0; bits < 16 && src; bits++, src >>= 1)\n"); @@ -2152,6 +2248,8 @@ static void gen_opcode (unsigned long int opcode) } genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); sync_m68k_pc (); + count_cycles += 38 - 4; + count_ncycles++; insn_n_cycles += (70 - 38) / 2 + 38; /* average */ break; case i_MULS: @@ -2161,7 +2259,7 @@ static void gen_opcode (unsigned long int opcode) start_brace (); printf ("\tuae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;\n"); if (using_ce) { - printf ("\tint cycles = 36 * CYCLE_UNIT / 2, bits;\n"); + printf ("\tint cycles = (38 - 4) * CYCLE_UNIT / 2, bits;\n"); printf ("\tuae_u32 usrc;\n"); } genflags (flag_logical, sz_long, "newv", "", ""); @@ -2172,6 +2270,8 @@ static void gen_opcode (unsigned long int opcode) addcycles3 ("\t"); } genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); + count_cycles += 38 - 4; + count_ncycles++; insn_n_cycles += (70 - 38) / 2 + 38; /* average */ break; case i_CHK: @@ -2179,17 +2279,19 @@ static void gen_opcode (unsigned long int opcode) genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0); genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0); sync_m68k_pc (); - fill_prefetch_next (); - addcycles (6); - printf ("\tif ((uae_s32)dst < 0) {\n"); - printf ("\t\tSET_NFLG (®s->ccrflags, 1);\n"); + addcycles (4); + printf ("\tif (dst > src) {\n"); + printf ("\t\tSET_NFLG (®s->ccrflags, 0);\n"); printf ("\t\tException (6, regs, oldpc);\n"); printf ("\t\tgoto %s;\n", endlabelstr); - printf ("\t} else if (dst > src) {\n"); - printf ("\t\tSET_NFLG (®s->ccrflags, 0);\n"); + printf ("\t}\n"); + addcycles (2); + printf ("\tif ((uae_s32)dst < 0) {\n"); + printf ("\t\tSET_NFLG (®s->ccrflags, 1);\n"); printf ("\t\tException (6, regs, oldpc);\n"); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); + fill_prefetch_next (); need_endlabel = 1; break; case i_CHK2: @@ -2361,7 +2463,7 @@ static void gen_opcode (unsigned long int opcode) case i_ROL: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0); genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0, 0); - fill_prefetch_next(); + fill_prefetch_next (); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -2391,7 +2493,7 @@ static void gen_opcode (unsigned long int opcode) case i_ROR: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0); genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0, 0); - fill_prefetch_next(); + fill_prefetch_next (); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -2421,7 +2523,7 @@ static void gen_opcode (unsigned long int opcode) case i_ROXL: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0); genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0, 0); - fill_prefetch_next(); + fill_prefetch_next (); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -2454,7 +2556,7 @@ static void gen_opcode (unsigned long int opcode) case i_ROXR: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0); genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0, 0); - fill_prefetch_next(); + fill_prefetch_next (); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -3133,6 +3235,8 @@ static char *outopcode (int opcode) strcpy (out, s); xfree (s); } + if (ins->smode == immi) + strcat (out, "Q"); if (ins->size == sz_byte) strcat (out,".B"); if (ins->size == sz_word) @@ -3255,11 +3359,23 @@ static void generate_one_opcode (int rp) need_endlabel = 0; endlabelno++; sprintf (endlabelstr, "endlabel%d", endlabelno); + count_read = count_write = count_ncycles = count_cycles = 0; + count_read_ea = count_write_ea = count_cycles_ea = 0; gen_opcode (opcode); if (need_endlabel) printf ("%s: ;\n", endlabelstr); returncycles ("", insn_n_cycles); - printf ("}\n"); + printf ("}"); + if (using_ce || using_prefetch) { + if (count_read + count_write + count_cycles == 0) + count_cycles = 4; + printf (" /* %d%s (%d/%d)", + (count_read + count_write) * 4 + count_cycles, count_ncycles ? "+" : "", count_read, count_write); + printf (" */\n"); + } else { + printf("\n"); + } + printf ("\n"); if (i68000) printf("#endif\n"); opcode_next_clev[rp] = next_cpu_level; diff --git a/include/blitter.h b/include/blitter.h index 8d642a26..8eaebd7d 100644 --- a/include/blitter.h +++ b/include/blitter.h @@ -35,7 +35,7 @@ extern int blitnasty (void); extern int blitnnasty (int); extern void blitter_handler (uae_u32); extern void build_blitfilltable (void); -extern void do_blitter (int); +extern void do_blitter (int, int); extern void decide_blitter (int hpos); extern int blitter_need (int hpos); extern void blitter_done_notify (int hpos); diff --git a/inputdevice.c b/inputdevice.c index f57a3b69..6c4b08d5 100644 --- a/inputdevice.c +++ b/inputdevice.c @@ -1925,13 +1925,13 @@ static int inputdelay; void inputdevice_hsync (void) { - + static int cnt; cap_check (); #ifdef CATWEASEL catweasel_hsync (); #endif - if ((vpos & 31) == 31 && handle_msgpump ()) { + if ((++cnt & 63) == 63 && handle_msgpump ()) { idev[IDTYPE_MOUSE].read (); idev[IDTYPE_JOYSTICK].read (); idev[IDTYPE_KEYBOARD].read (); diff --git a/newcpu.c b/newcpu.c index 03cd3b2f..39ff49d6 100644 --- a/newcpu.c +++ b/newcpu.c @@ -892,72 +892,124 @@ static void exception_debug (int nr) /* cycle-exact exception handler, 68000 only */ +/* + +Address/Bus Error: + +- 6 idle cycles +- write PC low word +- write SR +- write PC high word +- write instruction word +- write fault address low word +- write status code +- write fault address high word +- 2 idle cycles +- read exception address high word +- read exception address low word +- prefetch +- 2 idle cycles +- prefetch + +Division by Zero: + +- 6 idle cycles +- write PC low word +- write SR +- write PC high word +- read exception address high word +- read exception address low word +- prefetch +- 2 idle cycles +- prefetch + +Traps: + +- 2 idle cycles +- write PC low word +- write SR +- write PC high word +- read exception address high word +- read exception address low word +- prefetch +- 2 idle cycles +- prefetch + +TrapV: + +- write PC low word +- write SR +- write PC high word +- read exception address high word +- read exception address low word +- prefetch +- 2 idle cycles +- prefetch + +CHK: + +- 6 idle cycles +- write PC low word +- write SR +- write PC high word +- read exception address high word +- read exception address low word +- prefetch +- 2 idle cycles +- prefetch + +Illegal Instruction: + +- 2 idle cycles +- write PC low word +- write SR +- write PC high word +- read exception address high word +- read exception address low word +- prefetch +- 2 idle cycles +- prefetch + +Interrupt cycle diagram: + +- 6 idle cycles +- read exception number byte from (0xfffff1 | (interrupt number << 1)) +- write PC low word +- write SR +- 4 idle cycles +- write PC high word +- read exception address high word +- read exception address low word +- prefetch +- 2 idle cycles +- prefetch + +*/ + static void Exception_ce (int nr, struct regstruct *regs, uaecptr oldpc) { uae_u32 currpc = m68k_getpc (regs), newpc; - int c; int sv = regs->s; + int start; + + start = 6; + if (nr == 7) // TRAPV + start = 0; + else if (nr >= 32 && nr < 32 + 16) // TRAP #x + start = 2; + else if (nr == 4 || nr == 8) // ILLG & PRIVIL VIOL + start = 2; + + if (start) + do_cycles_ce (start * CYCLE_UNIT / 2); + + if (nr >= 24 && nr < 24 + 8) { // fetch interrupt vector number + nr = get_byte_ce (0x00fffff1 | ((nr - 24) << 1)); + } exception_debug (nr); MakeSR (regs); - c = 0; - switch (nr) - { - case 2: /* bus */ - case 3: /* address */ - c = 6; - break; - case 4: /* illegal instruction */ - c = 6; - break; - case 5: /* divide by zero */ - c = 10; - break; - case 6: /* chk */ - c = 12; - break; - case 7: /* trapv */ - c = 6; - break; - case 8: /* privilege */ - c = 6; - break; - case 9: /* trace */ - c = 6; - break; - case 25: /* interrupts */ - case 26: - case 27: - case 28: - case 29: - case 30: - case 31: - c = 12; - break; - case 32: /* traps */ - case 33: - case 34: - case 35: - case 36: - case 37: - case 38: - case 39: - case 40: - case 41: - case 42: - case 43: - case 44: - case 45: - case 46: - case 47: - c = 6; - break; - } - /* some delays are interleaved with stack pushes, not bothered yet.. - */ - if (c) - do_cycles_ce (c * CYCLE_UNIT / 2); if (!regs->s) { regs->usp = m68k_areg (regs, 7); m68k_areg (regs, 7) = regs->isp; @@ -975,16 +1027,17 @@ static void Exception_ce (int nr, struct regstruct *regs, uaecptr oldpc) put_word_ce (m68k_areg (regs, 7) + 4, last_fault_for_exception_3); put_word_ce (m68k_areg (regs, 7) + 0, mode); put_word_ce (m68k_areg (regs, 7) + 2, last_fault_for_exception_3 >> 16); + do_cycles_ce (2 * CYCLE_UNIT / 2); write_log (L"Exception %d (%x) at %x -> %x!\n", nr, oldpc, currpc, get_long (4 * nr)); goto kludge_me_do; } m68k_areg (regs, 7) -= 6; - put_word_ce (m68k_areg (regs, 7) + 4, currpc); - put_word_ce (m68k_areg (regs, 7) + 0, regs->sr); - put_word_ce (m68k_areg (regs, 7) + 2, currpc >> 16); + put_word_ce (m68k_areg (regs, 7) + 4, currpc); // write low address + put_word_ce (m68k_areg (regs, 7) + 0, regs->sr); // write SR + put_word_ce (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address kludge_me_do: - newpc = get_word_ce (4 * nr) << 16; - newpc |= get_word_ce (4 * nr + 2); + newpc = get_word_ce (4 * nr) << 16; // read high address + newpc |= get_word_ce (4 * nr + 2); // read low address if (newpc & 1) { if (nr == 2 || nr == 3) uae_reset (1); /* there is nothing else we can do.. */ @@ -993,7 +1046,9 @@ kludge_me_do: return; } m68k_setpc (regs, newpc); - fill_prefetch_slow (regs); + regs->ir = get_word_ce (m68k_getpc (regs)); // prefetch 1 + do_cycles_ce (2 * CYCLE_UNIT / 2); + regs->irc = get_word_ce (m68k_getpc (regs) + 2); // prefetch 2 set_special (regs, SPCFLAG_END_COMPILE); exception_trace (nr); } @@ -1004,6 +1059,9 @@ static void Exception_normal (int nr, struct regstruct *regs, uaecptr oldpc) uae_u32 currpc = m68k_getpc (regs), newpc; int sv = regs->s; + if (nr >= 24 && nr < 24 + 8 && currprefs.cpu_model <= 68010) + nr = get_byte (0x00fffff1 | (nr << 1)); + exception_debug (nr); MakeSR (regs); @@ -1123,12 +1181,6 @@ kludge_me_do: void REGPARAM2 Exception (int nr, struct regstruct *regs, uaecptr oldpc) { -#if 0 - //if (nr < 24) - if (nr == 24 + 3) - write_log (L"exception %d %08X %08X (%04X %04X)\n", - nr, oldpc, m68k_getpc (regs), intena, intreq); -#endif #ifdef CPUEMU_12 if (currprefs.cpu_cycle_exact && currprefs.cpu_model == 68000) Exception_ce (nr, regs, oldpc); @@ -1139,24 +1191,11 @@ void REGPARAM2 Exception (int nr, struct regstruct *regs, uaecptr oldpc) STATIC_INLINE void do_interrupt (int nr, struct regstruct *regs) { - int vector; -#if 0 - if (nr == 2) - write_log (L"."); - //write_log (L"irq %d at %x (%04X) ", nr, m68k_getpc (regs), intena & intreq); -#endif regs->stopped = 0; unset_special (regs, SPCFLAG_STOP); assert (nr < 8 && nr >= 0); - if (currprefs.cpu_cycle_exact) - vector = get_byte_ce (0x00fffff1 | (nr << 1)); - else if (currprefs.cpu_model <= 68010) - vector = get_byte (0x00fffff1 | (nr << 1)); - else - vector = nr + 24; - - Exception (vector, regs, 0); + Exception (nr + 24, regs, 0); regs->intmask = nr; doint (); @@ -3310,9 +3349,9 @@ int getDivu68kCycles (uae_u32 dividend, uae_u16 divisor) // Overflow if ((dividend >> 16) >= divisor) - return (mcycles = 5 - 2) * 2; + return (mcycles = 5) * 2; - mcycles = 38 - 2; + mcycles = 38; hdivisor = divisor << 16; for (i = 0; i < 15; i++) { @@ -3344,7 +3383,7 @@ int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor) if (divisor == 0) return 0; - mcycles = 6 - 2; + mcycles = 6; if (dividend < 0) mcycles++; diff --git a/od-win32/bsdsock.c b/od-win32/bsdsock.c index ae293481..62eb0ada 100644 --- a/od-win32/bsdsock.c +++ b/od-win32/bsdsock.c @@ -2298,6 +2298,7 @@ kludge: BSDTRACE((L"OK (%s)\n", h->h_name)); bsdsocklib_seterrno(sb, 0); + bsdsocklib_setherrno(sb, 0); } else { BSDTRACE((L"failed (%d/%d)\n", sb->sb_errno, sb->sb_herrno)); diff --git a/od-win32/hardfile_win32.c b/od-win32/hardfile_win32.c index a4d368be..3ab3e4f3 100644 --- a/od-win32/hardfile_win32.c +++ b/od-win32/hardfile_win32.c @@ -1113,7 +1113,8 @@ static BOOL GetDevicePropertyFromName(const TCHAR *DevicePath, DWORD Index, DWOR PARTITION_INFORMATION *pi = &dli->PartitionEntry[i]; if (pi->PartitionType == PARTITION_ENTRY_UNUSED) continue; - write_log (L"%d: num: %d type: %02X offset: %I64d size: %I64d, ", i, pi->PartitionNumber, pi->PartitionType, pi->StartingOffset.QuadPart, pi->PartitionLength.QuadPart); + write_log (L"%d: num: %d type: %02X offset: %I64d size: %I64d, ", i, + pi->PartitionNumber, pi->PartitionType, pi->StartingOffset.QuadPart, pi->PartitionLength.QuadPart); if (pi->RecognizedPartition == 0) { write_log (L"unrecognized\n"); continue; @@ -1128,12 +1129,10 @@ static BOOL GetDevicePropertyFromName(const TCHAR *DevicePath, DWORD Index, DWOR udi->offset = pi->StartingOffset.QuadPart; udi->size = pi->PartitionLength.QuadPart; write_log (L"used\n"); - if (safetycheck (hDevice, udi->device_path, udi->offset, buffer, dg.BytesPerSector) <= 0) { - _stprintf (udi->device_name, L"HD_P#%d_%s", pi->PartitionNumber, orgname); - udi++; - (*index2)++; - safepart = 1; - } + _stprintf (udi->device_name, L"HD_P#%d_%s", pi->PartitionNumber, orgname); + udi++; + (*index2)++; + safepart = 1; gotpart = 1; } if (!nonzeropart) { @@ -1146,10 +1145,11 @@ static BOOL GetDevicePropertyFromName(const TCHAR *DevicePath, DWORD Index, DWOR } else { write_log (L"no MBR partition table detected, checking for RDB\n"); } - - udi->dangerous = safetycheck (hDevice, udi->device_path, 0, buffer, dg.BytesPerSector); - if (udi->dangerous > 0) - goto end; + if (udi->offset == 0) { + udi->dangerous = safetycheck (hDevice, udi->device_path, 0, buffer, dg.BytesPerSector); + if (udi->dangerous > 0) + goto end; + } amipartfound: _stprintf (udi->device_name, L"HD_%s", orgname); { diff --git a/od-win32/resources/resource b/od-win32/resources/resource index 31d7e2e9..8c962921 100644 --- a/od-win32/resources/resource +++ b/od-win32/resources/resource @@ -829,6 +829,7 @@ #define IDC_PATHS_CONFIGS 1662 #define IDC_SOUNDSWAP 1662 #define IDC_PATHS_SCREENSHOTS 1663 +#define IDC_SOUNDFREQ2 1663 #define IDC_PATHS_SAVESTATES 1664 #define IDC_SOUNDSTEREOSWAPTXT 1664 #define IDC_SOUNDSWAPTXT 1664 @@ -893,18 +894,21 @@ #define IDC_SOUND_AUTO 1709 #define IDC_FILTERKEEPASPECT 1709 #define IDC_CS_RTC 1710 -#define IDC_SOUND_AUTO2 1710 #define IDC_SOUND_EXCLUSIVE 1710 #define IDC_CS_CIAA_TOD1 1711 #define IDC_CS_CIAA_TOD2 1712 #define IDC_CS_EXT 1712 #define IDC_CS_CIAA_TOD3 1713 +#define IDC_SOUND_DS 1713 #define IDC_CS_COMPATIBLE 1714 #define IDC_CS_RAMSEYREV 1715 +#define IDC_SOUND_WASAPI 1715 #define IDC_CS_KSMIRROR_E0 1716 #define IDC_STRINGBOXEDIT 1716 +#define IDC_SOUND_OPENAL 1716 #define IDC_CS_CD32CD 1717 #define IDC_CS_CD32C2P 1718 +#define IDC_SOUND_PORTAUDIO 1718 #define IDC_CS_CD32NVRAM 1719 #define IDC_CS_CDTVCD 1720 #define IDC_CS_CDTVRAM 1721 diff --git a/od-win32/resources/winuae.rc b/od-win32/resources/winuae.rc index ff763611..d4dcb9cc 100644 --- a/od-win32/resources/winuae.rc +++ b/od-win32/resources/winuae.rc @@ -293,44 +293,49 @@ BEGIN "Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,203,100,10 END -IDD_SOUND DIALOGEX 0, 0, 300, 231 +IDD_SOUND DIALOGEX 0, 0, 300, 237 STYLE DS_LOCALEDIT | DS_SETFONT | DS_3DLOOK | DS_CONTROL | WS_CHILD FONT 8, "MS Sans Serif", 0, 0, 0x1 BEGIN - COMBOBOX IDC_SOUNDCARDLIST,5,9,291,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - GROUPBOX "Sound Emulation",IDC_SOUNDSETTINGS,5,26,120,85 - CONTROL "Disabled",IDC_SOUND0,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,13,41,101,10 - CONTROL "Disabled, but emulated",IDC_SOUND1,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,54,102,10 - CONTROL "Enabled",IDC_SOUND2,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,67,102,10 - CONTROL "Enabled, 100% accurate",IDC_SOUND3,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,80,101,10 - GROUPBOX "Volume",IDC_STATIC,132,42,164,31 - CONTROL "",IDC_SOUNDVOLUME,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,137,50,105,20 - EDITTEXT IDC_SOUNDVOLUME2,247,53,40,12,ES_CENTER | ES_READONLY - GROUPBOX "Sound Buffer Size",IDC_STATIC,132,79,164,31 - CONTROL "Slider1",IDC_SOUNDBUFFERRAM,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,137,87,105,19 - EDITTEXT IDC_SOUNDBUFFERMEM,247,90,40,12,ES_CENTER | ES_READONLY - GROUPBOX "Settings",IDC_SOUNDINTERPOLATION2,6,114,290,60 - LTEXT "Frequency:",IDC_SOUNDFREQTXT,11,148,53,8,SS_CENTERIMAGE - COMBOBOX IDC_SOUNDFREQ,13,157,51,75,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP - LTEXT "Audio filter:",IDC_SOUNDFILTERTXT,209,148,77,8,SS_CENTERIMAGE - COMBOBOX IDC_SOUNDFILTER,209,157,80,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Channel mode:",IDC_SOUNDSTEREOTXT,11,124,57,8,SS_CENTERIMAGE - COMBOBOX IDC_SOUNDSTEREO,13,133,122,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Interpolation:",IDC_SOUNDINTERPOLATIONTXT,209,124,75,8,SS_CENTERIMAGE - COMBOBOX IDC_SOUNDINTERPOLATION,209,133,80,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Stereo separation:",IDC_SOUNDSTEREOSEPTXT,141,124,63,8,SS_CENTERIMAGE - COMBOBOX IDC_SOUNDSTEREOSEP,142,133,62,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Stereo delay:",IDC_SOUNDSTEREOMIXTXT,141,148,63,8,SS_CENTERIMAGE - COMBOBOX IDC_SOUNDSTEREOMIX,142,157,62,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - GROUPBOX "Floppy Drive Sound Emulation",IDC_STATIC,6,177,290,46 - CONTROL "",IDC_SOUNDDRIVEVOLUME,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,14,185,107,19 - EDITTEXT IDC_SOUNDDRIVEVOLUME2,124,187,40,12,ES_CENTER | ES_READONLY - COMBOBOX IDC_SOUNDDRIVE,237,187,46,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_SOUNDDRIVESELECT,18,205,265,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_SOUNDSWAP,73,157,62,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Swap channels:",IDC_SOUNDSWAPTXT,74,148,61,8,SS_CENTERIMAGE - CONTROL "Automatic switching",IDC_SOUND_AUTO,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,14,95,103,10 - CONTROL "Exclusive mode",IDC_SOUND_EXCLUSIVE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,137,31,154,10 + COMBOBOX IDC_SOUNDCARDLIST,5,3,291,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Sound Emulation",IDC_SOUNDSETTINGS,5,20,120,85 + CONTROL "Disabled",IDC_SOUND0,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,13,35,101,10 + CONTROL "Disabled, but emulated",IDC_SOUND1,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,48,102,10 + CONTROL "Enabled",IDC_SOUND2,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,61,102,10 + CONTROL "Enabled, 100% accurate",IDC_SOUND3,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,74,101,10 + GROUPBOX "Volume",IDC_STATIC,132,36,164,31 + CONTROL "",IDC_SOUNDVOLUME,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,137,44,105,20 + EDITTEXT IDC_SOUNDVOLUME2,247,47,40,12,ES_CENTER | ES_READONLY + GROUPBOX "Sound Buffer Size",IDC_STATIC,132,73,164,31 + CONTROL "Slider1",IDC_SOUNDBUFFERRAM,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,137,81,105,19 + EDITTEXT IDC_SOUNDBUFFERMEM,247,84,40,12,ES_CENTER | ES_READONLY + GROUPBOX "Settings",IDC_SOUNDINTERPOLATION2,6,106,290,60 + LTEXT "Frequency:",IDC_SOUNDFREQTXT,11,140,53,8,SS_CENTERIMAGE + COMBOBOX IDC_SOUNDFREQ,13,149,51,75,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + LTEXT "Audio filter:",IDC_SOUNDFILTERTXT,209,140,77,8,SS_CENTERIMAGE + COMBOBOX IDC_SOUNDFILTER,209,149,80,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Channel mode:",IDC_SOUNDSTEREOTXT,11,116,57,8,SS_CENTERIMAGE + COMBOBOX IDC_SOUNDSTEREO,13,125,122,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Interpolation:",IDC_SOUNDINTERPOLATIONTXT,209,116,75,8,SS_CENTERIMAGE + COMBOBOX IDC_SOUNDINTERPOLATION,209,125,80,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Stereo separation:",IDC_SOUNDSTEREOSEPTXT,141,116,63,8,SS_CENTERIMAGE + COMBOBOX IDC_SOUNDSTEREOSEP,142,125,62,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Stereo delay:",IDC_SOUNDSTEREOMIXTXT,141,140,63,8,SS_CENTERIMAGE + COMBOBOX IDC_SOUNDSTEREOMIX,142,149,62,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Floppy Drive Sound Emulation",IDC_STATIC,6,172,220,60 + CONTROL "",IDC_SOUNDDRIVEVOLUME,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,14,186,107,19 + EDITTEXT IDC_SOUNDDRIVEVOLUME2,124,188,40,12,ES_CENTER | ES_READONLY + COMBOBOX IDC_SOUNDDRIVE,173,187,46,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_SOUNDDRIVESELECT,18,209,202,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_SOUNDSWAP,73,149,62,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Swap channels:",IDC_SOUNDSWAPTXT,74,140,61,8,SS_CENTERIMAGE + CONTROL "Automatic switching",IDC_SOUND_AUTO,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,14,89,103,10 + CONTROL "Exclusive mode",IDC_SOUND_EXCLUSIVE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,137,25,154,10 + CONTROL "DirectSound",IDC_SOUND_DS,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,235,181,55,10 + CONTROL "WASAPI",IDC_SOUND_WASAPI,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,235,193,53,10 + CONTROL "OpenAL",IDC_SOUND_OPENAL,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,235,205,53,10 + CONTROL "PortAudio",IDC_SOUND_PORTAUDIO,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,235,217,58,10 + GROUPBOX "Drivers",IDC_STATIC,230,172,66,60 END IDD_LOADSAVE DIALOGEX 0, 0, 302, 241 diff --git a/od-win32/sounddep/sound.c b/od-win32/sounddep/sound.c index 107f8bce..21e3c47d 100644 --- a/od-win32/sounddep/sound.c +++ b/od-win32/sounddep/sound.c @@ -113,6 +113,7 @@ struct sound_dp int sound_debug = 0; int sound_mode_skip = 0; +int sounddrivermask; static int have_sound; static int statuscnt; @@ -2139,61 +2140,65 @@ int enumerate_sound_devices (void) if (!num_sound_devices) { HMODULE l = NULL; write_log (L"Enumerating DirectSound devices..\n"); - if (os_vista) + if (os_vista && (sounddrivermask & SOUNDDRIVER_WASAPI)) wasapi_enum (sound_devices); - if (1 || force_directsound || !os_vista) { + if ((1 || force_directsound || !os_vista) && (sounddrivermask & SOUNDDRIVER_DS)) { DirectSoundEnumerate ((LPDSENUMCALLBACK)DSEnumProc, sound_devices); //DirectSoundCaptureEnumerate ((LPDSENUMCALLBACK)DSEnumProc, record_devices); } - __try { - if (isdllversion (L"openal32.dll", 6, 14, 357, 22)) { - write_log (L"Enumerating OpenAL devices..\n"); - if (alcIsExtensionPresent (NULL, "ALC_ENUMERATION_EXT")) { - const char* ppDefaultDevice = alcGetString (NULL, ALC_DEFAULT_DEVICE_SPECIFIER); - const char* pDeviceNames = alcGetString (NULL, ALC_DEVICE_SPECIFIER); - if (alcIsExtensionPresent (NULL, "ALC_ENUMERATE_ALL_EXT")) - pDeviceNames = alcGetString (NULL, ALC_ALL_DEVICES_SPECIFIER); - OpenALEnumerate (sound_devices, pDeviceNames, ppDefaultDevice, FALSE); -#if 0 - ppDefaultDevice = alcGetString (NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER); - pDeviceNames = alcGetString (NULL, ALC_CAPTURE_DEVICE_SPECIFIER); - OpenALEnumerate (record_devices, pDeviceNames, ppDefaultDevice, TRUE); -#endif + if (sounddrivermask & SOUNDDRIVER_OPENAL) { + __try { + if (isdllversion (L"openal32.dll", 6, 14, 357, 22)) { + write_log (L"Enumerating OpenAL devices..\n"); + if (alcIsExtensionPresent (NULL, "ALC_ENUMERATION_EXT")) { + const char* ppDefaultDevice = alcGetString (NULL, ALC_DEFAULT_DEVICE_SPECIFIER); + const char* pDeviceNames = alcGetString (NULL, ALC_DEVICE_SPECIFIER); + if (alcIsExtensionPresent (NULL, "ALC_ENUMERATE_ALL_EXT")) + pDeviceNames = alcGetString (NULL, ALC_ALL_DEVICES_SPECIFIER); + OpenALEnumerate (sound_devices, pDeviceNames, ppDefaultDevice, FALSE); + #if 0 + ppDefaultDevice = alcGetString (NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER); + pDeviceNames = alcGetString (NULL, ALC_CAPTURE_DEVICE_SPECIFIER); + OpenALEnumerate (record_devices, pDeviceNames, ppDefaultDevice, TRUE); + #endif + } } + } __except(ExceptionFilter (GetExceptionInformation (), GetExceptionCode ())) { + write_log (L"OpenAL enumeration crashed!\n"); + flush_log (); } - } __except(ExceptionFilter (GetExceptionInformation (), GetExceptionCode ())) { - write_log (L"OpenAL enumeration crashed!\n"); - flush_log (); - } + } #if PORTAUDIO - __try { - HMODULE hm = WIN32_LoadLibrary (L"portaudio_x86.dll"); - if (hm) { - TCHAR *s; - PaError err; - write_log (L"Enumerating PortAudio devices..\n"); - s = au (Pa_GetVersionText ()); - write_log (L"%s (%d)\n", s, Pa_GetVersion ()); - xfree (s); - if (Pa_GetVersion () >= 1899) { - err = Pa_Initialize (); - if (err == paNoError) { - PortAudioEnumerate (sound_devices); + if (sounddrivermask & SOUNDDRIVER_PORTAUDIO) { + __try { + HMODULE hm = WIN32_LoadLibrary (L"portaudio_x86.dll"); + if (hm) { + TCHAR *s; + PaError err; + write_log (L"Enumerating PortAudio devices..\n"); + s = au (Pa_GetVersionText ()); + write_log (L"%s (%d)\n", s, Pa_GetVersion ()); + xfree (s); + if (Pa_GetVersion () >= 1899) { + err = Pa_Initialize (); + if (err == paNoError) { + PortAudioEnumerate (sound_devices); + } else { + s = au (Pa_GetErrorText (err)); + write_log (L"Portaudio initialization failed: %d (%s)\n", + err, s); + xfree (s); + FreeLibrary (hm); + } } else { - s = au (Pa_GetErrorText (err)); - write_log (L"Portaudio initialization failed: %d (%s)\n", - err, s); - xfree (s); + write_log (L"Too old PortAudio library\n"); + flush_log (); FreeLibrary (hm); } - } else { - write_log (L"Too old PortAudio library\n"); - flush_log (); - FreeLibrary (hm); } + } __except(ExceptionFilter (GetExceptionInformation (), GetExceptionCode ())) { + write_log (L"Portaudio enumeration crashed!\n"); } - } __except(ExceptionFilter (GetExceptionInformation (), GetExceptionCode ())) { - write_log (L"Portaudio enumeration crashed!\n"); } #endif write_log (L"Enumeration end\n"); diff --git a/od-win32/sounddep/sound.h b/od-win32/sounddep/sound.h index 3bbef36c..215af0d4 100644 --- a/od-win32/sounddep/sound.h +++ b/od-win32/sounddep/sound.h @@ -143,3 +143,9 @@ struct dsaudiomodes { int ch; DWORD ksmode; }; + +extern int sounddrivermask; +#define SOUNDDRIVER_DS 1 +#define SOUNDDRIVER_WASAPI 2 +#define SOUNDDRIVER_OPENAL 4 +#define SOUNDDRIVER_PORTAUDIO 8 diff --git a/od-win32/win32.c b/od-win32/win32.c index f9ea889f..8aff34b8 100644 --- a/od-win32/win32.c +++ b/od-win32/win32.c @@ -1883,7 +1883,7 @@ static int WIN32_InitLibraries (void) LARGE_INTEGER freq; SETCURRENTPROCESSEXPLICITAPPUSERMODEIDD pSetCurrentProcessExplicitAppUserModelID; - CoInitialize (0); + CoInitializeEx (NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); /* Determine our processor speed and capabilities */ if (!init_mmtimer ()) { pre_gui_message (L"MMTimer initialization failed, exiting.."); @@ -2097,28 +2097,296 @@ static get_aspi (int old) return UAESCSI_SPTI; } + +/*** +*static void parse_cmdline(cmdstart, argv, args, numargs, numchars) +* +*Purpose: +* Parses the command line and sets up the argv[] array. +* On entry, cmdstart should point to the command line, +* argv should point to memory for the argv array, args +* points to memory to place the text of the arguments. +* If these are NULL, then no storing (only counting) +* is done. On exit, *numargs has the number of +* arguments (plus one for a final NULL argument), +* and *numchars has the number of bytes used in the buffer +* pointed to by args. +* +*Entry: +* _TSCHAR *cmdstart - pointer to command line of the form +* +* _TSCHAR **argv - where to build argv array; NULL means don't +* build array +* _TSCHAR *args - where to place argument text; NULL means don't +* store text +* +*Exit: +* no return value +* int *numargs - returns number of argv entries created +* int *numchars - number of characters used in args buffer +* +*Exceptions: +* +*******************************************************************************/ + +#define NULCHAR _T('\0') +#define SPACECHAR _T(' ') +#define TABCHAR _T('\t') +#define DQUOTECHAR _T('\"') +#define SLASHCHAR _T('\\') + + +static void __cdecl wparse_cmdline ( + _TSCHAR *cmdstart, + _TSCHAR **argv, + _TSCHAR *args, + int *numargs, + int *numchars + ) +{ + _TSCHAR *p; + _TUCHAR c; + int inquote; /* 1 = inside quotes */ + int copychar; /* 1 = copy char to *args */ + unsigned numslash; /* num of backslashes seen */ + + *numchars = 0; + *numargs = 1; /* the program name at least */ + + /* first scan the program name, copy it, and count the bytes */ + p = cmdstart; + if (argv) + *argv++ = args; + +#ifdef WILDCARD + /* To handle later wild card expansion, we prefix each entry by + it's first character before quote handling. This is done + so _[w]cwild() knows whether to expand an entry or not. */ + if (args) + *args++ = *p; + ++*numchars; + +#endif /* WILDCARD */ + + /* A quoted program name is handled here. The handling is much + simpler than for other arguments. Basically, whatever lies + between the leading double-quote and next one, or a terminal null + character is simply accepted. Fancier handling is not required + because the program name must be a legal NTFS/HPFS file name. + Note that the double-quote characters are not copied, nor do they + contribute to numchars. */ + inquote = FALSE; + do { + if (*p == DQUOTECHAR ) + { + inquote = !inquote; + c = (_TUCHAR) *p++; + continue; + } + ++*numchars; + if (args) + *args++ = *p; + + c = (_TUCHAR) *p++; +#ifdef _MBCS + if (_ismbblead(c)) { + ++*numchars; + if (args) + *args++ = *p; /* copy 2nd byte too */ + p++; /* skip over trail byte */ + } +#endif /* _MBCS */ + + } while ( (c != NULCHAR && (inquote || (c !=SPACECHAR && c != TABCHAR))) ); + + if ( c == NULCHAR ) { + p--; + } else { + if (args) + *(args-1) = NULCHAR; + } + + inquote = 0; + + /* loop on each argument */ + for(;;) { + + if ( *p ) { + while (*p == SPACECHAR || *p == TABCHAR) + ++p; + } + + if (*p == NULCHAR) + break; /* end of args */ + + /* scan an argument */ + if (argv) + *argv++ = args; /* store ptr to arg */ + ++*numargs; + +#ifdef WILDCARD + /* To handle later wild card expansion, we prefix each entry by + it's first character before quote handling. This is done + so _[w]cwild() knows whether to expand an entry or not. */ + if (args) + *args++ = *p; + ++*numchars; + +#endif /* WILDCARD */ + + /* loop through scanning one argument */ + for (;;) { + copychar = 1; + /* Rules: 2N backslashes + " ==> N backslashes and begin/end quote + 2N+1 backslashes + " ==> N backslashes + literal " + N backslashes ==> N backslashes */ + numslash = 0; + while (*p == SLASHCHAR) { + /* count number of backslashes for use below */ + ++p; + ++numslash; + } + if (*p == DQUOTECHAR) { + /* if 2N backslashes before, start/end quote, otherwise + copy literally */ + if (numslash % 2 == 0) { + if (inquote && p[1] == DQUOTECHAR) { + p++; /* Double quote inside quoted string */ + } else { /* skip first quote char and copy second */ + copychar = 0; /* don't copy quote */ + inquote = !inquote; + } + } + numslash /= 2; /* divide numslash by two */ + } + + /* copy slashes */ + while (numslash--) { + if (args) + *args++ = SLASHCHAR; + ++*numchars; + } + + /* if at end of arg, break loop */ + if (*p == NULCHAR || (!inquote && (*p == SPACECHAR || *p == TABCHAR))) + break; + + /* copy character into argument */ +#ifdef _MBCS + if (copychar) { + if (args) { + if (_ismbblead(*p)) { + *args++ = *p++; + ++*numchars; + } + *args++ = *p; + } else { + if (_ismbblead(*p)) { + ++p; + ++*numchars; + } + } + ++*numchars; + } + ++p; +#else /* _MBCS */ + if (copychar) { + if (args) + *args++ = *p; + ++*numchars; + } + ++p; +#endif /* _MBCS */ + } + + /* null-terminate the argument */ + + if (args) + *args++ = NULCHAR; /* terminate string */ + ++*numchars; + } + + /* We put one last argument in -- a null ptr */ + if (argv) + *argv++ = NULL; + ++*numargs; +} + +#define MAX_ARGUMENTS 128 + +static TCHAR **parseargstring (TCHAR *s) +{ + TCHAR **p; + int numa, numc; + + if (_tcslen (s) == 0) + return NULL; + wparse_cmdline (s, NULL, NULL, &numa, &numc); + numa++; + p = xcalloc (numa * sizeof (TCHAR*) + numc * sizeof (TCHAR), 1); + wparse_cmdline (s, (wchar_t **)p, (wchar_t *)(((char *)p) + numa * sizeof(wchar_t *)), &numa, &numc); + if (numa > MAX_ARGUMENTS) + p[MAX_ARGUMENTS] = NULL; + return p; +} + + static void shellexecute (TCHAR *command) { - SHELLEXECUTEINFO sei = { 0 }; - TCHAR *f = command; - TCHAR *sf, *s, *p; + STARTUPINFO si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; - sf = s = xcalloc (_tcslen (f) + 1 + 1, sizeof (TCHAR)); - if (!s) - return; - _tcscpy (s, f); - for (;;) { - p = _tcschr (s, ';'); - if (!p) - break; - *p = 0; + si.cb = sizeof si; + si.wShowWindow = SW_HIDE; + si.dwFlags = STARTF_USESHOWWINDOW; + if (CreateProcess (NULL, + command, + NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { + WaitForSingleObject (pi.hProcess, INFINITE); + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + } else { + write_log (L"CreateProcess('%s') failed, %d\n", + command, GetLastError ()); } - while (s[0]) { +} + +#if 0 +static void shellexecute (TCHAR *command) +{ + SHELLEXECUTEINFO sei = { 0 }; + TCHAR **args; + int i; + + i = 0; + args = parseargstring (command); + while (args && args[i]) { + int j; + int len; + TCHAR *cmd = args[i++]; + TCHAR *s = NULL; + sei.cbSize = sizeof sei; - sei.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; - sei.lpFile = s; + sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI; + sei.lpFile = cmd; sei.nShow = SW_HIDE; - write_log (L"ShellExecuteEx('%s')\n", s); + j = i; + len = 0; + while (args[i] && _tcscmp (args[i], L";")) { + len += _tcslen (args[i]) + 1; + i++; + } + if (i > j) { + s = xcalloc (len + 1, sizeof (TCHAR)); + while (j < i) { + if (s[0]) + _tcscat (s, L" "); + _tcscat (s, args[j]); + j++; + } + sei.lpParameters = s; + } + write_log (L"ShellExecuteEx('%s','%s')\n", cmd, s ? s : L""); if (ShellExecuteEx (&sei)) { HANDLE h = sei.hProcess; if (h) { @@ -2129,10 +2397,11 @@ static void shellexecute (TCHAR *command) } else { write_log (L"Failed. ERR=%d\n", GetLastError ()); } - s += _tcslen (s) + 1; + xfree (s); } - xfree (sf); + xfree (args); } +#endif void target_run (void) { @@ -3092,6 +3361,12 @@ static void WIN32_HandleRegistryStuff (void) } regqueryint (NULL, L"DirectDraw_Secondary", &ddforceram); + if (regexists (NULL, L"SoundDriverMask")) { + regqueryint (NULL, L"SoundDriverMask", &sounddrivermask); + } else { + sounddrivermask = 15; + regsetint (NULL, L"SoundDriverMask", sounddrivermask); + } if (regexists (NULL, L"ConfigurationCache")) regqueryint (NULL, L"ConfigurationCache", &configurationcache); else @@ -3555,8 +3830,6 @@ static void makeverstr (TCHAR *s) } } -#define MAX_ARGUMENTS 128 - static int parseargs (const TCHAR *arg, const TCHAR *np, const TCHAR *np2) { if (!_tcscmp (arg, L"-convert") && np && np2) { @@ -3752,239 +4025,6 @@ static int parseargs (const TCHAR *arg, const TCHAR *np, const TCHAR *np2) return 0; } -/*** -*static void parse_cmdline(cmdstart, argv, args, numargs, numchars) -* -*Purpose: -* Parses the command line and sets up the argv[] array. -* On entry, cmdstart should point to the command line, -* argv should point to memory for the argv array, args -* points to memory to place the text of the arguments. -* If these are NULL, then no storing (only counting) -* is done. On exit, *numargs has the number of -* arguments (plus one for a final NULL argument), -* and *numchars has the number of bytes used in the buffer -* pointed to by args. -* -*Entry: -* _TSCHAR *cmdstart - pointer to command line of the form -* -* _TSCHAR **argv - where to build argv array; NULL means don't -* build array -* _TSCHAR *args - where to place argument text; NULL means don't -* store text -* -*Exit: -* no return value -* int *numargs - returns number of argv entries created -* int *numchars - number of characters used in args buffer -* -*Exceptions: -* -*******************************************************************************/ - -#define NULCHAR _T('\0') -#define SPACECHAR _T(' ') -#define TABCHAR _T('\t') -#define DQUOTECHAR _T('\"') -#define SLASHCHAR _T('\\') - - -static void __cdecl wparse_cmdline ( - _TSCHAR *cmdstart, - _TSCHAR **argv, - _TSCHAR *args, - int *numargs, - int *numchars - ) -{ - _TSCHAR *p; - _TUCHAR c; - int inquote; /* 1 = inside quotes */ - int copychar; /* 1 = copy char to *args */ - unsigned numslash; /* num of backslashes seen */ - - *numchars = 0; - *numargs = 1; /* the program name at least */ - - /* first scan the program name, copy it, and count the bytes */ - p = cmdstart; - if (argv) - *argv++ = args; - -#ifdef WILDCARD - /* To handle later wild card expansion, we prefix each entry by - it's first character before quote handling. This is done - so _[w]cwild() knows whether to expand an entry or not. */ - if (args) - *args++ = *p; - ++*numchars; - -#endif /* WILDCARD */ - - /* A quoted program name is handled here. The handling is much - simpler than for other arguments. Basically, whatever lies - between the leading double-quote and next one, or a terminal null - character is simply accepted. Fancier handling is not required - because the program name must be a legal NTFS/HPFS file name. - Note that the double-quote characters are not copied, nor do they - contribute to numchars. */ - inquote = FALSE; - do { - if (*p == DQUOTECHAR ) - { - inquote = !inquote; - c = (_TUCHAR) *p++; - continue; - } - ++*numchars; - if (args) - *args++ = *p; - - c = (_TUCHAR) *p++; -#ifdef _MBCS - if (_ismbblead(c)) { - ++*numchars; - if (args) - *args++ = *p; /* copy 2nd byte too */ - p++; /* skip over trail byte */ - } -#endif /* _MBCS */ - - } while ( (c != NULCHAR && (inquote || (c !=SPACECHAR && c != TABCHAR))) ); - - if ( c == NULCHAR ) { - p--; - } else { - if (args) - *(args-1) = NULCHAR; - } - - inquote = 0; - - /* loop on each argument */ - for(;;) { - - if ( *p ) { - while (*p == SPACECHAR || *p == TABCHAR) - ++p; - } - - if (*p == NULCHAR) - break; /* end of args */ - - /* scan an argument */ - if (argv) - *argv++ = args; /* store ptr to arg */ - ++*numargs; - -#ifdef WILDCARD - /* To handle later wild card expansion, we prefix each entry by - it's first character before quote handling. This is done - so _[w]cwild() knows whether to expand an entry or not. */ - if (args) - *args++ = *p; - ++*numchars; - -#endif /* WILDCARD */ - - /* loop through scanning one argument */ - for (;;) { - copychar = 1; - /* Rules: 2N backslashes + " ==> N backslashes and begin/end quote - 2N+1 backslashes + " ==> N backslashes + literal " - N backslashes ==> N backslashes */ - numslash = 0; - while (*p == SLASHCHAR) { - /* count number of backslashes for use below */ - ++p; - ++numslash; - } - if (*p == DQUOTECHAR) { - /* if 2N backslashes before, start/end quote, otherwise - copy literally */ - if (numslash % 2 == 0) { - if (inquote && p[1] == DQUOTECHAR) { - p++; /* Double quote inside quoted string */ - } else { /* skip first quote char and copy second */ - copychar = 0; /* don't copy quote */ - inquote = !inquote; - } - } - numslash /= 2; /* divide numslash by two */ - } - - /* copy slashes */ - while (numslash--) { - if (args) - *args++ = SLASHCHAR; - ++*numchars; - } - - /* if at end of arg, break loop */ - if (*p == NULCHAR || (!inquote && (*p == SPACECHAR || *p == TABCHAR))) - break; - - /* copy character into argument */ -#ifdef _MBCS - if (copychar) { - if (args) { - if (_ismbblead(*p)) { - *args++ = *p++; - ++*numchars; - } - *args++ = *p; - } else { - if (_ismbblead(*p)) { - ++p; - ++*numchars; - } - } - ++*numchars; - } - ++p; -#else /* _MBCS */ - if (copychar) { - if (args) - *args++ = *p; - ++*numchars; - } - ++p; -#endif /* _MBCS */ - } - - /* null-terminate the argument */ - - if (args) - *args++ = NULCHAR; /* terminate string */ - ++*numchars; - } - - /* We put one last argument in -- a null ptr */ - if (argv) - *argv++ = NULL; - ++*numargs; -} - - - - -static TCHAR **parseargstring (TCHAR *s) -{ - TCHAR **p; - int numa, numc; - - if (_tcslen (s) == 0) - return NULL; - wparse_cmdline (s, NULL, NULL, &numa, &numc); - numa++; - p = xcalloc (numa * sizeof (TCHAR*) + numc * sizeof (TCHAR), 1); - wparse_cmdline (s, (wchar_t **)p, (wchar_t *)(((char *)p) + numa * sizeof(wchar_t *)), &numa, &numc); - if (numa > MAX_ARGUMENTS) - p[MAX_ARGUMENTS] = NULL; - return p; -} - static TCHAR **parseargstrings (TCHAR *s, TCHAR **xargv) { int cnt, i, xargc; @@ -4164,6 +4204,7 @@ static int PASCAL WinMain2 (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR DEVMODE devmode; DWORD i; + WIN32_HandleRegistryStuff (); DirectDraw_Release (); write_log (L"Enumerating display devices.. \n"); enumeratedisplays (multi_display); @@ -4190,7 +4231,6 @@ static int PASCAL WinMain2 (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR else default_freq = 60; } - WIN32_HandleRegistryStuff (); WIN32_InitLang (); WIN32_InitHtmlHelp (); DirectDraw_Release (); diff --git a/od-win32/win32.h b/od-win32/win32.h index f6a54f1a..ad08b766 100644 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -17,8 +17,8 @@ #define WINUAEPUBLICBETA 1 -#define WINUAEBETA L"Beta 2" -#define WINUAEDATE MAKEBD(2009, 7, 25) +#define WINUAEBETA L"Beta 3" +#define WINUAEDATE MAKEBD(2009, 7, 30) #define WINUAEEXTRA L"" #define WINUAEREV L"" diff --git a/od-win32/win32gui.c b/od-win32/win32gui.c index e9b0f81c..bf1c2732 100644 --- a/od-win32/win32gui.c +++ b/od-win32/win32gui.c @@ -7073,6 +7073,7 @@ static void update_soundgui (HWND hDlg) } static int soundfreqs[] = { 11025, 15000, 22050, 32000, 44100, 48000, 0 }; +static int sounddrivers[] = { IDC_SOUND_DS, IDC_SOUND_WASAPI, IDC_SOUND_OPENAL, IDC_SOUND_PORTAUDIO, 0 }; static void values_to_sounddlg (HWND hDlg) { @@ -7249,7 +7250,7 @@ static void values_from_sounddlg (HWND hDlg) { TCHAR txt[10]; LRESULT idx; - int soundcard; + int soundcard, i; idx = SendDlgItemMessage (hDlg, IDC_SOUNDFREQ, CB_GETCURSEL, 0, 0); if (idx >= 0) { @@ -7320,6 +7321,15 @@ static void values_from_sounddlg (HWND hDlg) workprefs.sound_stereo_swap_paula = (SendDlgItemMessage (hDlg, IDC_SOUNDSWAP, CB_GETCURSEL, 0, 0) & 1) ? 1 : 0; workprefs.sound_stereo_swap_ahi = (SendDlgItemMessage (hDlg, IDC_SOUNDSWAP, CB_GETCURSEL, 0, 0) & 2) ? 1 : 0; + for (i = 0; sounddrivers[i]; i++) { + int old = sounddrivermask; + sounddrivermask &= ~(1 << i); + if (IsDlgButtonChecked (hDlg, sounddrivers[i])) + sounddrivermask |= 1 << i; + if (old != sounddrivermask) + regsetint (NULL, L"SoundDriverMask", sounddrivermask); + } + idx = SendDlgItemMessage (hDlg, IDC_SOUNDDRIVE, CB_GETCURSEL, 0, 0); if (idx != CB_ERR && idx >= 0) { LRESULT res = SendDlgItemMessage (hDlg, IDC_SOUNDDRIVESELECT, CB_GETCURSEL, 0, 0); @@ -7340,13 +7350,11 @@ static void values_from_sounddlg (HWND hDlg) } } -extern int sound_calibrate (HWND, struct uae_prefs*); - static INT_PTR CALLBACK SoundDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { static int recursive = 0; int numdevs; - int card; + int card, i; switch (msg) { case WM_INITDIALOG: @@ -7365,6 +7373,10 @@ static INT_PTR CALLBACK SoundDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM SendDlgItemMessage (hDlg, IDC_SOUNDADJUST, TBM_SETRANGE, TRUE, MAKELONG (-100, +30)); SendDlgItemMessage (hDlg, IDC_SOUNDADJUST, TBM_SETPAGESIZE, 0, 1); + for (i = 0; i < sounddrivers[i]; i++) { + CheckDlgButton (hDlg, sounddrivers[i], (sounddrivermask & (1 << i)) ? TRUE : FALSE); + } + SendDlgItemMessage (hDlg, IDC_SOUNDCARDLIST, CB_RESETCONTENT, 0, 0L); numdevs = enumerate_sound_devices (); for (card = 0; card < numdevs; card++) { diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index ecf687dc..b8333832 100644 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -1,4 +1,26 @@ +Beta 3: + +Two main compatibility testing demos work perfectly now: +Final Bobs/Complex and Hulkamania/TSP. (Rampage/TEK still won't work..) + +Both require very exact CPU/DMA timing to work. First has "scrambling" +that uses vertical beam position as a key, main demo has already worked +if "scrambling" was bypassed, and second writes to BPLxPTs with CPU when +display DMA is already fetching data.. Yes, sane coders use copper..) + +- lots more cycle-exact CPU cycle count updates +- some more blitter updates (correct startup and copper wake-up delays) +- non-DMA mode sprites were always reset during vblank (I remember that + this was working long long time ago, possibly broke during Superfrog + "intro bee" fix or something) Fixes B2 world rotozoomer graphic glitch + +- added sound driver use/do not use GUI to sound panel (stored to + registry/.ini) Faster startup. +- exec* command lines should work better. Check the log if problems +- 0x76/0x30 partition types are always available read/write +- bsdsocket fix, cvs (SR) + Beta 2: Background information: @@ -28,7 +50,7 @@ is known but I am not sure how to implement the fix) blitter finished. (not necessarily exactly same thing) - chipset bitplane/copper/blitter cycle exact mode DMA sequence - routines rewritten. Emulation may be much due to missing + routines rewritten. Emulation may be slower due to missing optimizations. Later. - blitter cycle diagrams rechecked with logic analyzer, errors fixed -- 2.47.3