uae_u32 bltapt, bltbpt, bltcpt, bltdpt;
int blitter_nasty;
+static int original_ch, original_fill, original_line;
+
static int blinea_shift;
static uae_u16 blinea, blineb;
static int blitline, blitfc, blitfill, blitife, blitsing, blitdesc;
static int blit_linecycles, blit_extracycles, blit_nod;
static const int *blit_diag;
static int blit_line_pixel;
+static int blit_frozen, blit_faulty;
+static int blit_final;
static uae_u16 ddat1, ddat2;
static int ddat1use, ddat2use;
blt_info.bltamod & 0xffff, blt_info.bltbmod & 0xffff, blt_info.bltcmod & 0xffff, blt_info.bltdmod & 0xffff);
}
+STATIC_INLINE const int *get_ch (void)
+{
+ if (blit_faulty)
+ return &blit_diag[0];
+ if (blit_final)
+ return blit_cycle_diagram_finald;
+ return blit_diag;
+}
+
STATIC_INLINE int channel_state (int cycles)
{
+ const int *diag = get_ch ();
if (cycles < 0)
return 0;
- if (cycles < blit_diag[0])
- return blit_diag[1 + cycles];
- cycles -= blit_diag[0];
- cycles %= blit_diag[0];
- return blit_diag[1 + blit_diag[0] + cycles];
+ if (cycles < diag[0])
+ return diag[1 + cycles];
+ cycles -= diag[0];
+ cycles %= diag[0];
+ return diag[1 + diag[0] + cycles];
}
STATIC_INLINE int channel_pos (int cycles)
{
+ const int *diag = get_ch ();
if (cycles < 0)
return 0;
- if (cycles < blit_diag[0])
+ if (cycles < diag[0])
return cycles;
- cycles -= blit_diag[0];
- cycles %= blit_diag[0];
+ cycles -= diag[0];
+ cycles %= diag[0];
return cycles;
}
// blitter interrupt is set when last "main" cycle
// has been finished, any non-linedraw D-channel blit
// still needs 2 more cycles before final D is written
-static void blitter_interrupt (int hpos)
+static void blitter_interrupt (int hpos, int done)
{
if (blit_interrupt)
return;
+ if (!done && !currprefs.blitter_cycle_exact)
+ return;
blit_interrupt = 1;
INTREQ (0x8040);
if (debug_dma)
{
ddat1use = ddat2use = 0;
bltstate = blit_startcycles == 0 ? BLT_done : BLT_init;
- blitter_interrupt (hpos);
+ blitter_interrupt (hpos, 1);
blitter_done_notify (hpos);
if (debug_dma)
record_dma_event (DMA_EVENT_BLITFINISHED, hpos, vpos);
if (blitter_vcounter2 > blitter_vcounter1)
blitter_vcounter1 = blitter_vcounter2;
}
-#if 0
- if (blitter_hcounter1 == 0 && blitter_vcounter1 == vblitsize) {
- if (blit_diag != blit_cycle_diagram_finald) {
- blit_cyclecounter = -1;
- blit_diag = blit_cycle_diagram_finald;
- }
- }
-#endif
if (blit_ch == 1)
blitter_hcounter1 = blitter_hcounter2;
}
+ blit_final = 0;
return wd;
}
if (v) {
blit_startcycles--;
if (blit_startcycles == 0) {
+ if (blit_faulty)
+ blit_faulty = -1;
bltstate = BLT_done;
do_blitter (vhpos, 0);
blit_startcycles = 0;
blit_cyclecounter = 0;
+ if (blit_faulty)
+ blit_faulty = 1;
return;
}
}
if (blit_startcycles > 0)
do_startcycles (hpos);
- if (bltstate == BLT_done)
+ if (bltstate == BLT_done || blit_frozen)
return;
#ifdef BLITTER_DEBUG
if (blitter_delayed_debug) {
}
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);
+ if (!blit_final) {
+ blitter_interrupt (last_blitter_hpos, 0);
blit_cyclecounter = 0;
- blit_diag = blit_cycle_diagram_finald;
+ blit_final = 1;
}
}
last_blitter_hpos++;
static void blit_bltset (int con)
{
int i;
+ const int *olddiag = blit_diag;
- blitdesc = bltcon1 & 2;
-
- if (bltstate != BLT_done)
- return;
+ if (con & 2) {
+ blitdesc = bltcon1 & 2;
+ blt_info.blitbshift = bltcon1 >> 12;
+ blt_info.blitdownbshift = 16 - blt_info.blitbshift;
+ }
- 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 (con & 1) {
+ blt_info.blitashift = bltcon0 >> 12;
+ blt_info.blitdownashift = 16 - blt_info.blitashift;
+ }
+ blit_ch = (bltcon0 & 0x0f00) >> 8;
blitline = bltcon1 & 1;
blitfill = bltcon1 & 0x18;
- blit_ch = (bltcon0 & 0x0f00) >> 8;
if (blitline) {
if (hblitsize != 2)
if ((bltcon1 & 0x80) && (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
debugtest (DEBUGTEST_BLITTER, L"ECS BLTCON1 DOFF-bit set\n");
+ // on the fly switching fillmode from extra cycle to non-extra: blitter freezes
+ // non-extra cycle to extra cycle: does not freeze but cycle diagram goes weird,
+ // extra free cycle changes to another D write..
+ // (Absolute Inebriation vector cube inside semi-filled vector object requires freezing blitter.)
+ if (bltstate != BLT_done) {
+ static int freezes = 10;
+ int isen = blit_diag >= &blit_cycle_diagram_fill[0][0] && blit_diag <= &blit_cycle_diagram_fill[15][0];
+ int iseo = olddiag >= &blit_cycle_diagram_fill[0][0] && olddiag <= &blit_cycle_diagram_fill[15][0];
+ if (iseo != isen) {
+ if (freezes > 0) {
+ write_log (L"BLITTER: on the fly %d (%d) -> %d (%d) switch!\n", original_ch, iseo, blit_ch, isen);
+ freezes--;
+ }
+ }
+ if (iseo && !isen) {
+ blit_frozen = 1;
+ } else if (!iseo && isen) {
+#ifdef BLITTER_DEBUG_NOWAIT
+ write_log (L"BLITTER: on the fly %d (%d) -> %d (%d) switch\n", oldch, iseo, blit_ch, isen);
+#endif
+ }
+ }
+
+ // on the fly switching from CH=1 to CH=D -> blitter stops writing (Rampage/TEK)
+ // currently just switch to no-channels mode, better than crashing the demo..
+ if (bltstate != BLT_done) {
+ static uae_u8 changetable[32 * 32];
+ int o = original_ch + (original_fill ? 16 : 0);
+ int n = blit_ch + (blitfill ? 16 : 0);
+ if (o != n) {
+ if (changetable[o * 32 + n] < 10) {
+ changetable[o * 32 + n]++;
+ write_log (L"BLITTER: channel mode changed while active (%02X->%02X)\n", o, n);
+ }
+ }
+ if (blit_ch == 13 && original_ch == 1) {
+ blit_faulty = 1;
+ }
+ }
+
+ if (blit_faulty) {
+ blit_ch = 0;
+ blit_diag = blit_cycle_diagram[blit_ch];
+ }
+
blit_dmacount = blit_dmacount2 = 0;
blit_nod = 1;
for (i = 0; i < blit_diag[0]; i++) {
void reset_blit (int bltcon)
{
+ if (bltcon & 1)
+ blinea_shift = bltcon0 >> 12;
if (bltstate == BLT_done)
return;
if (bltcon)
static void do_blitter2 (int hpos, int copper)
{
int cycles;
+ int cleanstart;
#ifdef BLITTER_DEBUG_NOWAIT
if (bltstate != BLT_done) {
write_log (L"blitter was already active! PC=%08x\n", M68K_GETPC);
}
#endif
+ cleanstart = 0;
+ if (bltstate == BLT_done) {
+ if (blit_faulty > 0)
+ blit_faulty = 0;
+ cleanstart = 1;
+ }
+
bltstate = BLT_done;
hblitsize = blt_info.hblitsize;
preva = 0;
prevb = 0;
blt_info.got_cycle = 0;
+ blit_frozen = 0;
blit_firstline_cycles = blit_first_cycle = get_cycles ();
blit_misscyclecounter = 0;
blit_cyclecounter = 0;
blit_totalcyclecounter = 0;
- blit_bltset (1|2);
+ blit_bltset (1 | 2);
blit_modset ();
ddat1use = ddat2use = 0;
blit_interrupt = 0;
cycles = vblitsize * hblitsize;
}
+ if (cleanstart) {
+ original_ch = blit_ch;
+ original_fill = blitfill;
+ original_line = blitline;
+ }
+
#ifdef BLITTER_DEBUG
blitter_dontdo = 0;
if (1) {
void maybe_blit (int hpos, int hack)
{
- static int warned;
+ static int warned = 10;
if (bltstate == BLT_done)
return;
if (savestate_state)
return;
- if (!warned && dmaen (DMA_BLITTER) && blt_info.got_cycle) {
- warned = 1;
+ if (warned && dmaen (DMA_BLITTER) && blt_info.got_cycle) {
+ warned--;
debugtest (DEBUGTEST_BLITTER, L"program does not wait for blitter tc=%d\n",
blit_cyclecounter);
#ifdef BLITTER_DEBUG
warned = 0;
#endif
#ifdef BLITTER_DEBUG_NOWAIT
- warned = 0;
+ warned = 10;
write_log (L"program does not wait for blitter PC=%08x\n", M68K_GETPC);
- activate_debugger ();
+ //activate_debugger ();
+ //blitter_done (hpos);
#endif
}
#define SPRBORDER 0
-STATIC_INLINE int nocustom(void)
+STATIC_INLINE int nocustom (void)
{
if (picasso_on && currprefs.picasso96_nocustom)
return 1;
static unsigned int ddfstrt, ddfstop, ddfstrt_old_hpos, ddfstrt_old_vpos;
static int ddf_change, badmode;
static int fmode;
+static int bplcon1_hpos;
/* The display and data fetch windows */
int strobe; /* COPJMP1 / COPJMP2 accessed */
int last_write, last_write_hpos;
int moveaddr, movedata, movedelay;
+ int movedata100, movedelay100;
};
static struct copper cop_state;
/* Expansions from bplcon0/bplcon1. */
static int toscr_res, toscr_nr_planes, toscr_nr_planes2, fetchwidth;
-static int toscr_delay1, toscr_delay2, toscr_delay1x, toscr_delay2x;
+static int toscr_delay1, toscr_delay2;
/* 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_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);
+ 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);
}
static void compute_toscr_delay (int hpos)
if (thisline_decision.plfleft == -1) {
thisline_decision.plfleft = hpos;
compute_delay_offset ();
- compute_toscr_delay_1 ();
- toscr_delay1 = toscr_delay1x;
- toscr_delay2 = toscr_delay2x;
}
}
fetch_state = fetch_started;
}
+
/* Called when all planes have been fetched, i.e. when a new block
of data is available to be displayed. The data in fetched[] is
moved into todisplay[]. */
STATIC_INLINE void beginning_of_plane_block (int hpos, int fm)
{
int i;
+ int oleft = thisline_decision.plfleft;
flush_display (fm);
+
if (fm == 0)
for (i = 0; i < MAX_PLANES; i++) {
todisplay[i][0] |= fetched[i];
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);
+
+ // writing to BPLCON1 1 cycle after BPL1DAT access will
+ // not (except first BPL1DAT write) affect the display
+ // until next display block
+ if (bplcon1_hpos != hpos || oleft < 0)
+ compute_toscr_delay (hpos);
}
#ifdef SPEEDUP
ok = 1;
/* hack warning.. Writing to DDFSTRT when DMA should start must be ignored
* (correct fix would be emulate this delay for every custom register, but why bother..) */
- if (hpos - 2 == ddfstrt_old_hpos && ddfstrt_old_vpos == vpos)
- ok = 0;
+ if (ddfstrt_old_vpos == vpos)
+ if (hpos - 2 == ddfstrt_old_hpos)
+ ok = 0;
}
if (ok && dmaen (DMA_BITPLANE)) {
start_bpl_dma (hpos, plfstrt);
last_sprite_point = 0;
fetch_state = fetch_not_started;
+ bplcon1_hpos = -1;
if (plf_state > plf_active)
plf_state = plf_idle;
{
int oldstrobe = cop_state.strobe;
+#if CUSTOM_DEBUG > 0
+ if (dmaen (DMA_COPPER) && (cop_state.saved_i1 != 0xffff || cop_state.saved_i2 != 0xfffe))
+ write_log (L"vblank without copper ending %08x (%08x %08x)\n", cop_state.ip, cop1lc, cop2lc);
+#endif
+
unset_special (®s, SPCFLAG_COPPER);
cop_state.ignore_next = 0;
if (!oldstrobe)
#endif
if (bplcon0 == v)
return;
-
+
if ((bplcon0 & 2) && !(v & 2)) {
vpos_previous = vpos;
hpos_previous = hpos;
expand_fmodes ();
- record_register_change (hpos, 0x100, v | 0x80);
+ record_register_change (hpos, 0x100, v);
calcdiw ();
estimate_last_fetch_cycle (hpos);
}
+static void BPLCON0_f (uae_u32 d)
+{
+ BPLCON0 (d >> 16, d & 0xffff);
+}
+
STATIC_INLINE void BPLCON1 (int hpos, uae_u16 v)
{
if (!(currprefs.chipset_mask & CSMASK_AGA))
ddf_change = vpos;
decide_line (hpos);
decide_fetch (hpos);
+ bplcon1_hpos = hpos;
bplcon1 = v;
}
v &= 0xfe;
if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
v &= 0xfc;
- if (ddfstrt == v)
+ if (ddfstrt == v && hpos + 2 != ddfstrt)
return;
ddf_change = vpos;
decide_line (hpos);
v &= 0xfe;
if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
v &= 0xfc;
- if (ddfstop == v)
+ if (ddfstop == v && hpos + 2 != ddfstop)
return;
ddf_change = vpos;
decide_line (hpos);
STATIC_INLINE int copper_cant_read (int hpos)
{
- if (hpos + 1 >= maxhpos)
+ if (hpos + 1 >= maxhpos) // first refresh slot
return 1;
return is_bitplane_dma_inline (hpos);
}
{
int v;
- debug_wputpeek (0xdff000 + (cop_state.saved_i1 & 0x1fe), cop_state.saved_i2);
+ debug_wputpeek (0xdff000 + addr, value);
copper_access = 1;
v = custom_wput_1 (hpos, addr, value, noget);
copper_access = 0;
// "emulate" chip internal delays, not the right place but fast and 99.9% programs
// use only copper to write BPLCON1 etc.. (exception is HulkaMania/TSP..)
+// this table should be filled with zeros and done somewhere else..
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,0,0,0,0, /* 0x40 - 0x5e */
if (cop_state.movedelay > 0) {
cop_state.movedelay--;
- if (cop_state.movedelay == 1 && cop_state.moveaddr == 0x100) {
+ if (cop_state.movedelay == 0) {
+ custom_wput_copper (c_hpos, cop_state.moveaddr, cop_state.movedata, 0);
+ }
+ }
+#if 1
+ if (cop_state.movedelay100 > 0) {
+ cop_state.movedelay100--;
+ if (cop_state.movedelay100 == 1) {
// Denise reacts to BPLCON0 change a bit earlier than Agnus
- BPLCON0_Denise (old_hpos, cop_state.movedata);
+ BPLCON0_Denise (c_hpos, cop_state.movedata100);
}
- if (cop_state.movedelay == 0) {
- custom_wput_copper (old_hpos, cop_state.moveaddr, cop_state.movedata, 0);
+ if (cop_state.movedelay100 == 0) {
+ decide_line (c_hpos);
+ decide_fetch (c_hpos);
+ custom_wput_copper (c_hpos, 0x100, cop_state.movedata100, 0);
}
}
-
+#endif
c_hpos += 2;
if (cop_state.strobe) {
break;
case COP_strobe_delay2:
// second cycle after COPJMP is like second read cycle except
- // there is 0x1FE in logic analyzer as a target register
- // (next word is still read normally and tossed away)
+ // there is 0x1FE as a target register
+ // (following word is still read normally and tossed away)
if (copper_cant_read (old_hpos))
continue;
cop_state.state = COP_read1;
#endif
} else { // MOVE
unsigned int reg = cop_state.i1 & 0x1FE;
+ uae_u16 data = cop_state.i2;
cop_state.state = COP_read1;
- cop_state.movedata = cop_state.i2;
#ifdef DEBUGGER
if (debug_dma)
- record_dma (reg, cop_state.i2, cop_state.ip - 2, old_hpos, vpos);
+ record_dma (reg, data, cop_state.ip - 2, old_hpos, vpos);
#endif
test_copper_dangerous (reg);
if (! copper_enabled_thisline)
cop_state.ignore_next = 0;
}
- cop_state.moveaddr = reg;
- cop_state.movedelay = 0;
cop_state.last_write = reg;
cop_state.last_write_hpos = old_hpos;
if (reg == 0x88) {
cop_state.ip = cop2lc;
cop_state.state = COP_strobe_delay1;
} else {
- if (cop_state.moveaddr == 0x100) {
+ // FIX: all copper writes happen 1 cycle later than CPU writes
+ if (reg == 0x100) {
// special case BPLCON0 BPL DMA sequence delay
- cop_state.movedelay = 2;
- } else if (customdelay[cop_state.moveaddr / 2]) {
+ // dma sequence does not change until 1+4 cycles after the write
+ cop_state.movedelay100 = 2;
+ cop_state.movedata100 = data;
+ if (thisline_decision.plfleft == -1)
+ BPLCON0_Denise (old_hpos, data);
+ } else if (customdelay[reg / 2]) {
+ cop_state.moveaddr = reg;
+ cop_state.movedata = data;
cop_state.movedelay = customdelay[cop_state.moveaddr / 2];
} else {
int hpos2 = old_hpos;
- custom_wput_copper (hpos2, reg, cop_state.movedata, 0);
+ custom_wput_copper (hpos2, reg, data, 0);
hpos2++;
if (!nocustom () && reg >= 0x140 && reg < 0x180 && hpos2 >= SPR0_HPOS && hpos2 < SPR0_HPOS + 4 * MAX_SPRITES) {
do_sprites (hpos2);
}
/*
- Copper writes to BLTSIZE: 2 blitter idle cycles, blitter normal cycle starts
+ Copper writes to BLTSIZE: 3 blitter idle cycles, blitter normal cycle starts
BFD=0 wait: blitter interrupt, 4 cycles, copper fetches next word
+ (CPU write to BLTSIZE only have 2 idle cycles at start)
*/
void blitter_done_notify (int hpos)
{
struct sprite *s = &spr[num];
int dma, posctl = 0;
uae_u16 data;
+ int isdma = dmaen (DMA_SPRITE);
- if (vpos == sprite_vblank_endline)
+ if (isdma && vpos == sprite_vblank_endline)
spr_arm (num, 0);
#ifdef AGA
- if (s->dblscan && (fmode & 0x8000) && (vpos & 1) != (s->vstart & 1) && s->dmastate) {
+ if (isdma && s->dblscan && (fmode & 0x8000) && (vpos & 1) != (s->vstart & 1) && s->dmastate) {
spr_arm (num, 1);
return;
}
}
#endif
}
+
+ if (!isdma)
+ return;
if (cycle && !s->dmacycle)
return; /* Superfrog intro flashing bee fix */
if (minspr < SPR0_HPOS)
minspr = SPR0_HPOS;
- 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);
+ 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);
}
last_sprite_hpos = hpos;
STATIC_INLINE void event2_newevent_x (int no, evt t, uae_u32 data, evfunc2 func)
{
- evt et = t * CYCLE_UNIT + get_cycles ();
+ evt et;
+
+ if (((int)t) <= 0) {
+ func (data);
+ return;
+ }
+
+ et = t * CYCLE_UNIT + get_cycles ();
if (no < 0) {
for (no = ev2_misc; no < ev2_max; no++) {
write_log (L"hd ignored, read error %d!\n", GetLastError ());
return 2;
}
+ if (offset > 0)
+ return -5;
if (j == 0 && buf[0] == 0x39 && buf[1] == 0x10 && buf[2] == 0xd3 && buf[3] == 0x12) {
// ADIDE "CPRM" hidden block..
if (do_rdbdump)
udi->size = pi->PartitionLength.QuadPart;
write_log (L"used\n");
_stprintf (udi->device_name, L"HD_P#%d_%s", pi->PartitionNumber, orgname);
+ udi->dangerous = -5;
udi++;
(*index2)++;
safepart = 1;
*dangerousdrive = 0;
switch (uae_drives[index].dangerous)
{
+ case -5:
+ dang = L"[PART]";
+ break;
case -6:
dang = L"[MBR]";
break;
{
STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi = { 0 };
+ TCHAR **arg;
+ int i, j, k, stop;
- 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 ());
- }
-}
-
-#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_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI;
- sei.lpFile = cmd;
- sei.nShow = SW_HIDE;
+ if (_tcslen (command) == 0)
+ return;
+ i = j = 0;
+ stop = 0;
+ arg = parseargstring (command);
+ while (!stop) {
+ TCHAR *cmd, *exec;
+ int len = 1;
j = i;
- len = 0;
- while (args[i] && _tcscmp (args[i], L";")) {
- len += _tcslen (args[i]) + 1;
+ while (arg[i] && _tcscmp (arg[i], L";")) {
+ len += _tcslen (arg[i]) + 3;
i++;
}
- if (i > j) {
- s = xcalloc (len + 1, sizeof (TCHAR));
- while (j < i) {
- if (s[0])
- _tcscat (s, L" ");
- _tcscat (s, args[j]);
- j++;
+ exec = NULL;
+ cmd = xcalloc (len, sizeof (TCHAR));
+ for (k = j; k < i; k++) {
+ int quote = 0;
+ if (_tcslen (cmd) > 0)
+ _tcscat (cmd, L" ");
+ if (_tcschr (arg[k], ' '))
+ quote = 1;
+ if (quote)
+ _tcscat (cmd, L"\"");
+ _tcscat (cmd, arg[k]);
+ if (quote)
+ _tcscat (cmd, L"\"");
+ if (!exec && !_tcsicmp (cmd, L"cmd.exe")) {
+ int size;
+ size = GetEnvironmentVariable (L"ComSpec", NULL, 0);
+ if (size > 0) {
+ exec = xcalloc (size + 1, sizeof (TCHAR));
+ GetEnvironmentVariable (L"ComSpec", exec, size);
+ }
+ cmd[0] = 0;
}
- sei.lpParameters = s;
}
- write_log (L"ShellExecuteEx('%s','%s')\n", cmd, s ? s : L"<NULL>");
- if (ShellExecuteEx (&sei)) {
- HANDLE h = sei.hProcess;
- if (h) {
- WaitForSingleObject (h, INFINITE);
- CloseHandle (h);
- }
- write_log (L"Succeeded\n");
+ if (arg[i++] == 0)
+ stop = 1;
+ si.cb = sizeof si;
+ //si.wShowWindow = SW_HIDE;
+ //si.dwFlags = STARTF_USESHOWWINDOW;
+ if (CreateProcess (exec,
+ cmd,
+ NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
+ WaitForSingleObject (pi.hProcess, INFINITE);
+ CloseHandle (pi.hProcess);
+ CloseHandle (pi.hThread);
} else {
- write_log (L"Failed. ERR=%d\n", GetLastError ());
+ write_log (L"CreateProcess('%s' '%s') failed, %d\n",
+ exec, cmd, GetLastError ());
}
- xfree (s);
+ xfree (exec);
+ xfree (cmd);
}
- xfree (args);
+ xfree (arg);
}
-#endif
void target_run (void)
{
#define WINUAEPUBLICBETA 1
-#define WINUAEBETA L"Beta 3"
-#define WINUAEDATE MAKEBD(2009, 7, 30)
+#define WINUAEBETA L"Beta 4"
+#define WINUAEDATE MAKEBD(2009, 8, 3)
#define WINUAEEXTRA L""
#define WINUAEREV L""
+Beta 4:
+
+- 0x76/0x30 partition types are marked as "PART" in GUI and read/write
+ should really really work..
+- exec* command line didn't support command separation (;) characters,
+ batch files supported ("cmd.exe /c <batch file>")
+- fixed very old left border graphics error in Absolute Inebriation
+- b3 sprite fix broke other programs, fixed again
+- Brian the Lion "dialog screen" problem is not anything AGA-specific,
+ BPLCON0 write needs 5 cycle delay, not 4 when written by copper.
+ Not fixed yet, waiting odd number of cycles in copper emulation isn't
+ currently possible
+
+and few buggy demos fixed, doing weird things with the blitter and work
+only accidentally.. For the first time ever Rampage/TEK works!
+
+- Absolute Inebriation/VD "red linevector cube inside white object" part
+ now works. Bug in blitter wait, rewrites blitter registers when old blit
+ is still active, normally this would mess up the blit but it worked
+ because write to BLTCON1 freezes the blitter if it causes switch from
+ "extra" cycle fillmode to normal mode.
+- Rampage/TEK blitter feature workaround added, another buggy demo, it
+ changes blitter channel mode from 0x01 to 0x0D while blit is already
+ active, result is blitter getting confused and changing to weird cycle
+ diagram without D-channel. No writes, no memory corruption, no crash...
+- above cases (blitter channel mode changing while active) also writes
+ message to log. I am not going to test all combinations :)
+
+Random freezing not yet fixed.
+
+I guess version will be renamed to 1.7 or 2.0 because of huge A500
+compatibility increase..
+
+btw, I only have single non fully working A500 test statefile remaining,
+I need more non-working A500 game/demo reports :)
+
Beta 3:
Two main compatibility testing demos work perfectly now: