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;
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[];
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
};
/*
- -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
- 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"
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;
}
STATIC_INLINE int channel_pos (int cycles)
{
+ if (cycles < 0)
+ return 0;
if (cycles < blit_diag[0])
return cycles;
cycles -= blit_diag[0];
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)
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
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) {
blt_info.bltbhold = blitbhold;
}
blit_masktable[0] = 0xFFFF;
- blit_masktable[blt_info.hblitsize - 1] = 0xFFFF;
+ blit_masktable[hblitsize - 1] = 0xFFFF;
bltstate = BLT_done;
}
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) {
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) {
blt_info.bltbhold = blitbhold;
}
blit_masktable[0] = 0xFFFF;
- blit_masktable[blt_info.hblitsize - 1] = 0xFFFF;
+ blit_masktable[hblitsize - 1] = 0xFFFF;
bltstate = BLT_done;
}
STATIC_INLINE void blitter_nxline (void)
{
blineb = (blineb << 1) | (blineb >> 15);
- blt_info.vblitsize--;
+ vblitsize--;
bltstate = BLT_read;
blit_line_pixel = 0;
}
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;
blitter_write ();
bltdpt = bltcpt;
blitter_nxline ();
- if (blt_info.vblitsize == 0)
+ if (vblitsize == 0)
bltstate = BLT_done;
} while (bltstate != BLT_done);
} else {
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;
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++;
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;
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;
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
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;
}
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) {
void reset_blit (int bltcon)
{
- if (bltcon == 1)
- blinea_shift = bltcon0 >> 12;
if (bltstate == BLT_done)
return;
if (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;
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;
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
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;
}
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;
}
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;
#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
}
#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
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;
COP_skip1,
COP_strobe_delay1,
COP_strobe_delay2,
+ COP_start_delay
};
struct copper {
/* 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
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)
thisline_decision.plfleft = hpos;
compute_delay_offset ();
compute_toscr_delay_1 ();
+ toscr_delay1 = toscr_delay1x;
+ toscr_delay2 = toscr_delay2x;
}
}
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);
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;
/* 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;
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;
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);
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)
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)
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)
// 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 */
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))
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);
}
}
#endif
}
- if (!dmaen (DMA_SPRITE))
- return;
if (cycle && !s->dmacycle)
return; /* Superfrog intro flashing bee fix */
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++) {
}
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;
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 ();
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)
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) {
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;
/* 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;
#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);
#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;
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;
}
}
-#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;
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--;
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;
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;
{
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)
/* 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) {
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) {
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) {
} 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);
else
printf ("\tget_word_prefetch (regs, %d);\n", m68k_pc_offset + 2);
did_prefetch = 1;
+ count_read++;
insn_n_cycles += 4;
}
printf ("\tget_word_prefetch (regs, %d);\n", o);
}
did_prefetch = 1;
+ count_read++;
insn_n_cycles += 4;
}
else
printf ("\tget_word_prefetch (regs, 0);\n");
did_prefetch = 1;
+ count_read++;
insn_n_cycles += 4;
}
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);
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:
if (!(flags & GF_PC8R)) {
addcycles (2);
insn_n_cycles += 2;
+ count_cycles_ea += 2;
}
break;
break;
case absl:
gen_nextilong ("uaecptr", namea, flags & GF_NOREFILL);
+ count_read_ea += 2;
break;
case imm:
if (getv != 1)
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 ();
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)
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) {
}
} 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 ();
}
}
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))
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 ();
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 ();
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)
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 ();
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)
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");
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)
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) {
size);
}
}
+ fill_prefetch_next ();
+ count_ncycles++;
}
static void duplicate_carry (int n)
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;
}
}
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)
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);
}
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)
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;
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");
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)
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;
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");
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) {
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");
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 ();
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;
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:
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");
} 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");
}
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 ();
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;
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 ();
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.
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;
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");
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;
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");
}
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:
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", "", "");
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:
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:
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;
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;
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;
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;
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)
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;
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);
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 ();
/* 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;
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.. */
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);
}
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);
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);
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 ();
// 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++) {
if (divisor == 0)
return 0;
- mcycles = 6 - 2;
+ mcycles = 6;
if (dividend < 0)
mcycles++;
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));
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;
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) {
} 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);
{
#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
#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
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,203,100,10\r
END\r
\r
-IDD_SOUND DIALOGEX 0, 0, 300, 231\r
+IDD_SOUND DIALOGEX 0, 0, 300, 237\r
STYLE DS_LOCALEDIT | DS_SETFONT | DS_3DLOOK | DS_CONTROL | WS_CHILD\r
FONT 8, "MS Sans Serif", 0, 0, 0x1\r
BEGIN\r
- COMBOBOX IDC_SOUNDCARDLIST,5,9,291,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
- GROUPBOX "Sound Emulation",IDC_SOUNDSETTINGS,5,26,120,85\r
- CONTROL "Disabled",IDC_SOUND0,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,13,41,101,10\r
- CONTROL "Disabled, but emulated",IDC_SOUND1,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,54,102,10\r
- CONTROL "Enabled",IDC_SOUND2,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,67,102,10\r
- CONTROL "Enabled, 100% accurate",IDC_SOUND3,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,80,101,10\r
- GROUPBOX "Volume",IDC_STATIC,132,42,164,31\r
- CONTROL "",IDC_SOUNDVOLUME,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,137,50,105,20\r
- EDITTEXT IDC_SOUNDVOLUME2,247,53,40,12,ES_CENTER | ES_READONLY\r
- GROUPBOX "Sound Buffer Size",IDC_STATIC,132,79,164,31\r
- CONTROL "Slider1",IDC_SOUNDBUFFERRAM,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,137,87,105,19\r
- EDITTEXT IDC_SOUNDBUFFERMEM,247,90,40,12,ES_CENTER | ES_READONLY\r
- GROUPBOX "Settings",IDC_SOUNDINTERPOLATION2,6,114,290,60\r
- LTEXT "Frequency:",IDC_SOUNDFREQTXT,11,148,53,8,SS_CENTERIMAGE\r
- COMBOBOX IDC_SOUNDFREQ,13,157,51,75,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP\r
- LTEXT "Audio filter:",IDC_SOUNDFILTERTXT,209,148,77,8,SS_CENTERIMAGE\r
- COMBOBOX IDC_SOUNDFILTER,209,157,80,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
- LTEXT "Channel mode:",IDC_SOUNDSTEREOTXT,11,124,57,8,SS_CENTERIMAGE\r
- COMBOBOX IDC_SOUNDSTEREO,13,133,122,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
- LTEXT "Interpolation:",IDC_SOUNDINTERPOLATIONTXT,209,124,75,8,SS_CENTERIMAGE\r
- COMBOBOX IDC_SOUNDINTERPOLATION,209,133,80,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
- LTEXT "Stereo separation:",IDC_SOUNDSTEREOSEPTXT,141,124,63,8,SS_CENTERIMAGE\r
- COMBOBOX IDC_SOUNDSTEREOSEP,142,133,62,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
- LTEXT "Stereo delay:",IDC_SOUNDSTEREOMIXTXT,141,148,63,8,SS_CENTERIMAGE\r
- COMBOBOX IDC_SOUNDSTEREOMIX,142,157,62,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
- GROUPBOX "Floppy Drive Sound Emulation",IDC_STATIC,6,177,290,46\r
- CONTROL "",IDC_SOUNDDRIVEVOLUME,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,14,185,107,19\r
- EDITTEXT IDC_SOUNDDRIVEVOLUME2,124,187,40,12,ES_CENTER | ES_READONLY\r
- COMBOBOX IDC_SOUNDDRIVE,237,187,46,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
- COMBOBOX IDC_SOUNDDRIVESELECT,18,205,265,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
- COMBOBOX IDC_SOUNDSWAP,73,157,62,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
- LTEXT "Swap channels:",IDC_SOUNDSWAPTXT,74,148,61,8,SS_CENTERIMAGE\r
- CONTROL "Automatic switching",IDC_SOUND_AUTO,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,14,95,103,10\r
- CONTROL "Exclusive mode",IDC_SOUND_EXCLUSIVE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,137,31,154,10\r
+ COMBOBOX IDC_SOUNDCARDLIST,5,3,291,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
+ GROUPBOX "Sound Emulation",IDC_SOUNDSETTINGS,5,20,120,85\r
+ CONTROL "Disabled",IDC_SOUND0,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,13,35,101,10\r
+ CONTROL "Disabled, but emulated",IDC_SOUND1,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,48,102,10\r
+ CONTROL "Enabled",IDC_SOUND2,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,61,102,10\r
+ CONTROL "Enabled, 100% accurate",IDC_SOUND3,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,13,74,101,10\r
+ GROUPBOX "Volume",IDC_STATIC,132,36,164,31\r
+ CONTROL "",IDC_SOUNDVOLUME,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,137,44,105,20\r
+ EDITTEXT IDC_SOUNDVOLUME2,247,47,40,12,ES_CENTER | ES_READONLY\r
+ GROUPBOX "Sound Buffer Size",IDC_STATIC,132,73,164,31\r
+ CONTROL "Slider1",IDC_SOUNDBUFFERRAM,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,137,81,105,19\r
+ EDITTEXT IDC_SOUNDBUFFERMEM,247,84,40,12,ES_CENTER | ES_READONLY\r
+ GROUPBOX "Settings",IDC_SOUNDINTERPOLATION2,6,106,290,60\r
+ LTEXT "Frequency:",IDC_SOUNDFREQTXT,11,140,53,8,SS_CENTERIMAGE\r
+ COMBOBOX IDC_SOUNDFREQ,13,149,51,75,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP\r
+ LTEXT "Audio filter:",IDC_SOUNDFILTERTXT,209,140,77,8,SS_CENTERIMAGE\r
+ COMBOBOX IDC_SOUNDFILTER,209,149,80,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
+ LTEXT "Channel mode:",IDC_SOUNDSTEREOTXT,11,116,57,8,SS_CENTERIMAGE\r
+ COMBOBOX IDC_SOUNDSTEREO,13,125,122,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
+ LTEXT "Interpolation:",IDC_SOUNDINTERPOLATIONTXT,209,116,75,8,SS_CENTERIMAGE\r
+ COMBOBOX IDC_SOUNDINTERPOLATION,209,125,80,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
+ LTEXT "Stereo separation:",IDC_SOUNDSTEREOSEPTXT,141,116,63,8,SS_CENTERIMAGE\r
+ COMBOBOX IDC_SOUNDSTEREOSEP,142,125,62,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
+ LTEXT "Stereo delay:",IDC_SOUNDSTEREOMIXTXT,141,140,63,8,SS_CENTERIMAGE\r
+ COMBOBOX IDC_SOUNDSTEREOMIX,142,149,62,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
+ GROUPBOX "Floppy Drive Sound Emulation",IDC_STATIC,6,172,220,60\r
+ CONTROL "",IDC_SOUNDDRIVEVOLUME,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,14,186,107,19\r
+ EDITTEXT IDC_SOUNDDRIVEVOLUME2,124,188,40,12,ES_CENTER | ES_READONLY\r
+ COMBOBOX IDC_SOUNDDRIVE,173,187,46,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
+ COMBOBOX IDC_SOUNDDRIVESELECT,18,209,202,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
+ COMBOBOX IDC_SOUNDSWAP,73,149,62,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\r
+ LTEXT "Swap channels:",IDC_SOUNDSWAPTXT,74,140,61,8,SS_CENTERIMAGE\r
+ CONTROL "Automatic switching",IDC_SOUND_AUTO,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,14,89,103,10\r
+ CONTROL "Exclusive mode",IDC_SOUND_EXCLUSIVE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,137,25,154,10\r
+ CONTROL "DirectSound",IDC_SOUND_DS,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,235,181,55,10\r
+ CONTROL "WASAPI",IDC_SOUND_WASAPI,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,235,193,53,10\r
+ CONTROL "OpenAL",IDC_SOUND_OPENAL,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,235,205,53,10\r
+ CONTROL "PortAudio",IDC_SOUND_PORTAUDIO,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,235,217,58,10\r
+ GROUPBOX "Drivers",IDC_STATIC,230,172,66,60\r
END\r
\r
IDD_LOADSAVE DIALOGEX 0, 0, 302, 241\r
int sound_debug = 0;
int sound_mode_skip = 0;
+int sounddrivermask;
static int have_sound;
static int statuscnt;
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");
int ch;
DWORD ksmode;
};
+
+extern int sounddrivermask;
+#define SOUNDDRIVER_DS 1
+#define SOUNDDRIVER_WASAPI 2
+#define SOUNDDRIVER_OPENAL 4
+#define SOUNDDRIVER_PORTAUDIO 8
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..");
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
+* <progname><nul><args><nul>
+* _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"<NULL>");
if (ShellExecuteEx (&sei)) {
HANDLE h = sei.hProcess;
if (h) {
} else {
write_log (L"Failed. ERR=%d\n", GetLastError ());
}
- s += _tcslen (s) + 1;
+ xfree (s);
}
- xfree (sf);
+ xfree (args);
}
+#endif
void target_run (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
}
}
-#define MAX_ARGUMENTS 128
-
static int parseargs (const TCHAR *arg, const TCHAR *np, const TCHAR *np2)
{
if (!_tcscmp (arg, L"-convert") && np && 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
-* <progname><nul><args><nul>
-* _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;
DEVMODE devmode;
DWORD i;
+ WIN32_HandleRegistryStuff ();
DirectDraw_Release ();
write_log (L"Enumerating display devices.. \n");
enumeratedisplays (multi_display);
else
default_freq = 60;
}
- WIN32_HandleRegistryStuff ();
WIN32_InitLang ();
WIN32_InitHtmlHelp ();
DirectDraw_Release ();
#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""
}
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)
{
{
TCHAR txt[10];
LRESULT idx;
- int soundcard;
+ int soundcard, i;
idx = SendDlgItemMessage (hDlg, IDC_SOUNDFREQ, CB_GETCURSEL, 0, 0);
if (idx >= 0) {
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);
}
}
-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:
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++) {
+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:
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