Updated blitter and custom from WinUAE

This commit is contained in:
Dimitris Panokostas 2020-08-18 13:49:10 +02:00
parent b90a1f3723
commit 7a595dc6a0
4 changed files with 731 additions and 110 deletions

View file

@ -11,12 +11,28 @@
#include "sysdeps.h"
#include "options.h"
#include "uae.h"
#include "memory.h"
#include "custom.h"
#include "events.h"
#include "newcpu.h"
#include "blitter.h"
#include "blit.h"
#include "savestate.h"
//#include "debug.h"
// 1 = logging
// 2 = no wait detection
// 4 = no D
// 8 = instant
// 16 = activate debugger if weird things
// 32 = logging (no line)
#if BLITTER_DEBUG
int log_blitter = 1 | 16;
#else
int log_blitter = 0;
#endif
/* we must not change ce-mode while blitter is running.. */
static int blitter_cycle_exact, immediate_blits;
@ -274,6 +290,82 @@ void build_blitfilltable (void)
}
}
STATIC_INLINE void record_dma_blit (uae_u16 reg, uae_u16 dat, uae_u32 addr, int hpos)
{
#ifdef DEBUGGER
if (debug_dma)
record_dma (reg, dat, addr, hpos, vpos, DMARECORD_BLITTER, blitline ? 2 : (blitfill ? 1 : 0));
if (memwatch_enabled) {
if (reg == 0) {
uae_u32 mask = MW_MASK_BLITTER_D_N;
if (blitfill)
mask = MW_MASK_BLITTER_D_F;
if (blitline)
mask = MW_MASK_BLITTER_D_L;
debug_wputpeekdma_chipram(addr, dat, mask, reg, 0x054);
} else if (reg == 0x70) {
debug_wgetpeekdma_chipram(addr, dat, MW_MASK_BLITTER_C, reg, 0x48);
} else if (reg == 0x72) {
debug_wgetpeekdma_chipram(addr, dat, MW_MASK_BLITTER_B, reg, 0x4c);
} else if (reg == 0x74) {
debug_wgetpeekdma_chipram(addr, dat, MW_MASK_BLITTER_A, reg, 0x52);
}
}
#endif
}
static void blitter_debugsave(int copper, uaecptr pc)
{
debug_bltcon0 = bltcon0;
debug_bltcon1 = bltcon1;
debug_bltsizev = blt_info.vblitsize;
debug_bltsizeh = blt_info.hblitsize;
debug_bltapt = bltapt;
debug_bltbpt = bltbpt;
debug_bltcpt = bltcpt;
debug_bltdpt = bltdpt;
debug_bltadat = blt_info.bltadat;
debug_bltbdat = blt_info.bltbdat;
debug_bltcdat = blt_info.bltcdat;
debug_bltamod = blt_info.bltamod;
debug_bltbmod = blt_info.bltbmod;
debug_bltcmod = blt_info.bltcmod;
debug_bltdmod = blt_info.bltdmod;
debug_bltafwm = blt_info.bltafwm;
debug_bltalwm = blt_info.bltalwm;
debug_bltpc = pc;
debug_bltcop = copper;
}
static void blitter_dump (void)
{
//int chipsize = currprefs.chipmem_size;
//console_out_f(_T("PT A=%08X B=%08X C=%08X D=%08X\n"), bltapt, bltbpt, bltcpt, bltdpt);
//console_out_f(_T("CON0=%04X CON1=%04X DAT A=%04X B=%04X C=%04X\n"),
// bltcon0, bltcon1, blt_info.bltadat, blt_info.bltbdat, blt_info.bltcdat);
//console_out_f(_T("AFWM=%04X ALWM=%04X MOD A=%04X B=%04X C=%04X D=%04X\n"),
// blt_info.bltafwm, blt_info.bltalwm,
// blt_info.bltamod & 0xffff, blt_info.bltbmod & 0xffff, blt_info.bltcmod & 0xffff, blt_info.bltdmod & 0xffff);
//console_out_f(_T("PC=%08X DMA=%d\n"), m68k_getpc(), dmaen (DMA_BLITTER));
//if (((bltcon0 & 0x800) && bltapt >= chipsize) || ((bltcon0 & 0x400) && bltbpt >= chipsize) ||
// ((bltcon0 & 0x200) && bltcpt >= chipsize) || ((bltcon0 & 0x100) && bltdpt >= chipsize))
// console_out_f(_T("PT outside of chipram\n"));
}
void blitter_debugdump(void)
{
//console_out(_T("Blitter registers at start:\n"));
//console_out_f(_T("PT A=%08X B=%08X C=%08X D=%08X\n"), debug_bltapt, debug_bltbpt, debug_bltcpt, debug_bltdpt);
//console_out_f(_T("CON0=%04X CON1=%04X DAT A=%04X B=%04X C=%04X\n"),
// debug_bltcon0, debug_bltcon1, debug_bltadat, debug_bltbdat, debug_bltcdat);
//console_out_f(_T("AFWM=%04X ALWM=%04X MOD A=%04X B=%04X C=%04X D=%04X\n"),
// debug_bltafwm, debug_bltalwm, debug_bltamod, debug_bltbmod, debug_bltcmod, debug_bltdmod);
//console_out_f(_T("COP=%d PC=%08X\n"), debug_bltcop, debug_bltpc);
//console_out(_T("Blitter registers now:\n"));
//blitter_dump();
}
STATIC_INLINE const int *get_ch (void)
{
if (blit_faulty)
@ -325,6 +417,12 @@ STATIC_INLINE int canblit (int hpos)
return 1;
}
static void markidlecycle (int hpos)
{
//if (debug_dma)
//record_dma_event (DMA_EVENT_BLITSTARTFINISH, hpos, vpos);
}
static void reset_channel_mods (void)
{
if (bltptxpos < 0)
@ -367,22 +465,23 @@ static void check_channel_mods (int hpos, int ch)
// (or cycle where last D write would have been if
// ONEDOT was active)
static void blitter_interrupt (int done)
static void blitter_interrupt (int hpos, int done)
{
if (blit_interrupt)
return;
if (!done && (!blitter_cycle_exact || immediate_blits || currprefs.cpu_model >= 68030 || currprefs.cachesize || currprefs.m68k_speed < 0))
return;
blit_interrupt = 1;
send_interrupt (6);
send_interrupt (6, 4 * CYCLE_UNIT);
}
static void blitter_done (int hpos)
{
ddat1use = ddat2use = 0;
bltstate = blit_startcycles == 0 || !blitter_cycle_exact || immediate_blits ? BLT_done : BLT_init;
blitter_interrupt (1);
blitter_interrupt (hpos, 1);
blitter_done_notify (hpos);
markidlecycle (hpos);
event2_remevent (ev2_blitter);
unset_special (SPCFLAG_BLTNASTY);
blitter_dangerous_bpl = 0;
@ -590,6 +689,8 @@ static void blitter_dofast_desc (void)
STATIC_INLINE void blitter_read (void)
{
if (bltcon0 & 0x200) {
if (!dmaen (DMA_BLITTER))
return;
blt_info.bltcdat = chipmem_wget_indirect (bltcpt);
last_custom_value1 = blt_info.bltcdat;
}
@ -602,6 +703,9 @@ STATIC_INLINE void blitter_write (void)
blt_info.blitzero = 0;
/* D-channel state has no effect on linedraw, but C must be enabled or nothing is drawn! */
if (bltcon0 & 0x200) {
if (!dmaen (DMA_BLITTER))
return;
//last_custom_value1 = blt_info.bltddat; blitter writes are not stored
chipmem_wput_indirect (bltdpt, blt_info.bltddat);
}
bltstate = BLT_next;
@ -691,7 +795,7 @@ STATIC_INLINE void blitter_nxline (void)
bltstate = BLT_read;
}
#ifdef CPUEMU_13
//#ifdef CPUEMU_13
static int blitter_cyclecounter;
static int blitter_hcounter1, blitter_hcounter2;
@ -783,7 +887,7 @@ static void decide_blitter_line (int hsync, int hpos)
reset_channel_mods ();
}
#endif
//#endif
static void actually_do_blit (void)
{
@ -819,10 +923,25 @@ static void blitter_doit (void)
blitter_done (current_hpos());
return;
}
if (log_blitter) {
if (!blitter_dontdo)
actually_do_blit ();
else
bltstate = BLT_done;
} else {
actually_do_blit ();
}
blitter_done (current_hpos ());
}
actually_do_blit();
blitter_done(current_hpos());
static int makebliteventtime(int delay)
{
if (delay) {
delay += delay - (int)(delay * (1 + currprefs.blitter_speed_throttle) + 0.5);
if (delay <= 0)
delay = 1;
}
return delay;
}
void blitter_handler (uae_u32 data)
@ -840,13 +959,192 @@ void blitter_handler (uae_u32 data)
}
blitter_stuck = 0;
if (blit_slowdown > 0 && !immediate_blits) {
event2_newevent (ev2_blitter, blit_slowdown, 0);
event2_newevent (ev2_blitter, makebliteventtime(blit_slowdown), 0);
blit_slowdown = -1;
return;
}
blitter_doit ();
}
//#ifdef CPUEMU_13
STATIC_INLINE uae_u16 blitter_doblit (void)
{
uae_u32 blitahold;
uae_u16 bltadat, ddat;
uae_u8 mt = bltcon0 & 0xFF;
bltadat = blt_info.bltadat;
if (blitter_hcounter1 == 0)
bltadat &= blt_info.bltafwm;
if (blitter_hcounter1 == blt_info.hblitsize - 1)
bltadat &= blt_info.bltalwm;
if (blitdesc)
blitahold = (((uae_u32)bltadat << 16) | blt_info.bltaold) >> blt_info.blitdownashift;
else
blitahold = (((uae_u32)blt_info.bltaold << 16) | bltadat) >> blt_info.blitashift;
blt_info.bltaold = bltadat;
ddat = blit_func (blitahold, blt_info.bltbhold, blt_info.bltcdat, mt) & 0xFFFF;
if ((bltcon1 & 0x18)) {
uae_u16 d = ddat;
int ifemode = blitife ? 2 : 0;
int fc1 = blit_filltable[d & 255][ifemode + blitfc][1];
ddat = (blit_filltable[d & 255][ifemode + blitfc][0]
+ (blit_filltable[d >> 8][ifemode + fc1][0] << 8));
blitfc = blit_filltable[d >> 8][ifemode + fc1][1];
}
if (ddat)
blt_info.blitzero = 0;
return ddat;
}
STATIC_INLINE void blitter_doddma (int hpos)
{
uae_u16 d;
if (blit_dmacount2 == 0) {
d = blitter_doblit ();
} else if (ddat2use) {
d = ddat2;
ddat2use = 0;
} else if (ddat1use) {
d = ddat1;
ddat1use = 0;
} else {
static int warn = 10;
if (warn > 0) {
warn--;
write_log (_T("BLITTER: D-channel without nothing to do?\n"));
}
return;
}
record_dma_blit (0x00, d, bltdpt, hpos);
//last_custom_value1 = d; blitter writes are not stored
chipmem_agnus_wput2 (bltdpt, d);
alloc_cycle_blitter (hpos, &bltdpt, 4);
bltdpt += blit_add;
blitter_hcounter2++;
if (blitter_hcounter2 == blt_info.hblitsize) {
blitter_hcounter2 = 0;
bltdpt += blit_modaddd;
blitter_vcounter2++;
if (blit_dmacount2 == 0) // d-only
blitter_vcounter1++;
if (blitter_vcounter2 > blitter_vcounter1)
blitter_vcounter1 = blitter_vcounter2;
}
if (blit_ch == 1)
blitter_hcounter1 = blitter_hcounter2;
}
STATIC_INLINE void blitter_dodma (int ch, int hpos)
{
uae_u16 dat, reg;
uae_u32 addr;
switch (ch)
{
case 1:
blt_info.bltadat = dat = chipmem_wget_indirect (bltapt);
last_custom_value1 = blt_info.bltadat;
addr = bltapt;
bltapt += blit_add;
reg = 0x74;
alloc_cycle_blitter (hpos, &bltapt, 1);
break;
case 2:
blt_info.bltbdat = dat = chipmem_wget_indirect (bltbpt);
last_custom_value1 = blt_info.bltbdat;
addr = bltbpt;
bltbpt += blit_add;
if (blitdesc)
blt_info.bltbhold = (((uae_u32)blt_info.bltbdat << 16) | blt_info.bltbold) >> blt_info.blitdownbshift;
else
blt_info.bltbhold = (((uae_u32)blt_info.bltbold << 16) | blt_info.bltbdat) >> blt_info.blitbshift;
blt_info.bltbold = blt_info.bltbdat;
reg = 0x72;
alloc_cycle_blitter (hpos, &bltbpt, 2);
break;
case 3:
blt_info.bltcdat = dat = chipmem_wget_indirect (bltcpt);
last_custom_value1 = blt_info.bltcdat;
addr = bltcpt;
bltcpt += blit_add;
reg = 0x70;
alloc_cycle_blitter (hpos, &bltcpt, 3);
break;
default:
abort ();
}
blitter_cyclecounter++;
if (blitter_cyclecounter >= blit_dmacount2) {
blitter_cyclecounter = 0;
ddat2 = ddat1;
ddat2use = ddat1use;
ddat1use = 0;
ddat1 = blitter_doblit ();
if (bltcon0 & 0x100)
ddat1use = 1;
blitter_hcounter1++;
if (blitter_hcounter1 == blt_info.hblitsize) {
blitter_hcounter1 = 0;
if (bltcon0 & 0x800)
bltapt += blit_modadda;
if (bltcon0 & 0x400)
bltbpt += blit_modaddb;
if (bltcon0 & 0x200)
bltcpt += blit_modaddc;
blitter_vcounter1++;
blitfc = !!(bltcon1 & 0x4);
}
}
record_dma_blit (reg, dat, addr, hpos);
}
int blitter_need (int hpos)
{
int c;
if (bltstate == BLT_done)
return 0;
if (!dmaen (DMA_BLITTER))
return 0;
c = channel_state (blit_cyclecounter);
return c;
}
static void do_startcycles (int hpos)
{
int vhpos = last_blitter_hpos;
while (vhpos < hpos) {
int v = canblit (vhpos);
vhpos++;
if (v > 0) {
blit_startcycles--;
if (blit_startcycles == 0) {
if (blit_faulty)
blit_faulty = -1;
bltstate = BLT_done;
blit_final = 0;
do_blitter(vhpos, 0, blit_waitpc);
blit_startcycles = 0;
blit_cyclecounter = 0;
blit_waitcyclecounter = 0;
if (blit_faulty)
blit_faulty = 1;
return;
}
} else {
markidlecycle (hpos);
}
}
}
void decide_blitter (int hpos)
{
int hsync = hpos < 0;
@ -856,7 +1154,7 @@ void decide_blitter (int hpos)
blt_delayed_irq--;
if (blt_delayed_irq <= 0) {
blt_delayed_irq = 0;
send_interrupt(6);
send_interrupt(6, 2 * CYCLE_UNIT);
}
}
@ -868,6 +1166,9 @@ void decide_blitter (int hpos)
return;
}
if (blit_startcycles > 0)
do_startcycles (hpos);
if (bltstate == BLT_done)
return;
@ -876,9 +1177,120 @@ void decide_blitter (int hpos)
if (hpos < 0)
hpos = maxhpos;
}
static void blitter_force_finish(void)
if (blitline) {
blt_info.got_cycle = 1;
decide_blitter_line (hsync, hpos);
return;
}
while (last_blitter_hpos < hpos) {
int c;
c = channel_state (blit_cyclecounter);
for (;;) {
int v;
v = canblit (last_blitter_hpos);
// copper bltsize write needs one cycle (any cycle) delay
if (blit_waitcyclecounter) {
blit_waitcyclecounter = 0;
markidlecycle (last_blitter_hpos);
break;
}
// idle cycles require free bus.
// Final empty cycle does not, unless it is fill mode that requires extra idle cycle
// (CPU can still use this cycle)
#if 1
if ((blit_cyclecounter < 0 || !blit_final || (blitfill && blit_cycle_diagram_fill[blit_ch][0])) && ((c == 0 && v == 0) || v < 0)) {
blit_misscyclecounter++;
blitter_nasty++;
break;
}
#else
if ((c == 0 && v == 0) || v < 0) {
if (blit_cyclecounter < 0 || !blit_final) {
blit_misscyclecounter++;
break;
}
if (blitfill && blit_cycle_diagram_fill[blit_ch][0]) {
blit_misscyclecounter++;
blitter_nasty++;
break;
}
}
#endif
if (blit_frozen) {
blit_misscyclecounter++;
break;
}
if (c == 0) {
blt_info.got_cycle = 1;
blit_cyclecounter++;
if (blit_cyclecounter == 0)
blit_final = 0;
blit_totalcyclecounter++;
/* check if blit with zero channels has ended */
if (blit_ch == 0 && blit_cyclecounter >= blit_maxcyclecounter) {
blitter_done (last_blitter_hpos);
return;
}
markidlecycle (last_blitter_hpos);
break;
}
blitter_nasty++;
if (v <= 0) {
blit_misscyclecounter++;
break;
}
blt_info.got_cycle = 1;
if (c == 4) {
blitter_doddma (last_blitter_hpos);
blit_cyclecounter++;
blit_totalcyclecounter++;
} else {
if (blitter_vcounter1 < blt_info.vblitsize) {
blitter_dodma (c, 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;
}
}
// check this after end check because last D write won't cause any problems.
check_channel_mods (last_blitter_hpos, c);
break;
}
if (dmaen (DMA_BLITTER) && !blit_final && (blitter_vcounter1 == blt_info.vblitsize || (blitter_vcounter1 == blt_info.vblitsize - 1 && blitter_hcounter1 == blt_info.hblitsize - 1 && blit_dmacount2 == 0))) {
if (channel_pos (blit_cyclecounter - 1) == blit_diag[0] - 1) {
blitter_interrupt (last_blitter_hpos, 0);
blit_cyclecounter = 0;
blit_final = 1;
}
}
last_blitter_hpos++;
}
reset_channel_mods ();
if (hsync)
last_blitter_hpos = 0;
}
//#else
//void decide_blitter (int hpos) { }
//#endif
static void blitter_force_finish(bool state)
{
uae_u16 odmacon;
if (bltstate == BLT_done)
@ -889,21 +1301,22 @@ static void blitter_force_finish(void)
*/
odmacon = dmacon;
dmacon |= DMA_MASTER | DMA_BLITTER;
if (state)
write_log (_T("forcing blitter finish\n"));
if (blitter_cycle_exact && !immediate_blits) {
int rounds = 10000;
while (bltstate != BLT_done && rounds > 0) {
memset(cycle_line, 0, sizeof cycle_line);
decide_blitter(-1);
memset (cycle_line, 0, sizeof cycle_line);
decide_blitter (-1);
rounds--;
}
if (rounds == 0)
write_log(_T("blitter froze!?\n"));
write_log (_T("blitter froze!?\n"));
blit_startcycles = 0;
} else {
actually_do_blit ();
}
else {
actually_do_blit();
}
blitter_done(current_hpos());
blitter_done (current_hpos ());
dmacon = odmacon;
}
}
@ -916,6 +1329,7 @@ static bool invstate (void)
static void blit_bltset (int con)
{
int i;
const int *olddiag = blit_diag;
if (con & 2) {
blitdesc = bltcon1 & 2;
@ -957,9 +1371,49 @@ static void blit_bltset (int con)
blit_diag = blitfill && blit_cycle_diagram_fill[blit_ch][0] ? blit_cycle_diagram_fill[blit_ch] : blit_cycle_diagram[blit_ch];
}
// 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 (!savestate_state && invstate ()) {
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 (_T("BLITTER: on the fly %d (%d) -> %d (%d) switch! PC=%08x\n"), original_ch, iseo, blit_ch, isen, M68K_GETPC);
freezes--;
}
}
if (original_fill == isen) {
blit_frozen = 0; // switched back to original fill mode? unfreeze
} else if (iseo && !isen) {
blit_frozen = 1;
write_log (_T("BLITTER: frozen! %d (%d) -> %d (%d) %08X\n"), original_ch, iseo, blit_ch, isen, M68K_GETPC);
//if (log_blitter & 16)
//activate_debugger ();
} else if (!iseo && isen) {
if (!dmaen (DMA_BLITTER)) // subtle shades / nuance bootblock bug
blit_frozen = 1;
//if (log_blitter)
//write_log (_T("BLITTER: on the fly %d (%d) -> %d (%d) switch\n"), original_ch, iseo, blit_ch, isen);
}
}
// 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 (!savestate_state && invstate ()) {
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 (_T("BLITTER: channel mode changed while active (%02X->%02X) PC=%08x\n"), o, n, M68K_GETPC);
//if (log_blitter & 16)
//activate_debugger ();
}
}
if (blit_ch == 13 && original_ch == 1) {
blit_faulty = 1;
}
@ -1062,11 +1516,20 @@ static void blitter_start_init (void)
}
}
void do_blitter (int hpos)
static void do_blitter2(int hpos, int copper, uaecptr pc)
{
int cycles;
int cleanstart;
if ((log_blitter & 2)) {
if (bltstate != BLT_done) {
if (blit_final) {
write_log (_T("blitter was already active! PC=%08x\n"), M68K_GETPC);
//activate_debugger();
}
}
}
cleanstart = 0;
if (bltstate == BLT_done) {
if (blit_faulty > 0)
@ -1105,9 +1568,9 @@ void do_blitter (int hpos)
bltstate = BLT_init;
blit_slowdown = 0;
unset_special(SPCFLAG_BLTNASTY);
if (dmaen(DMA_BLITPRI))
set_special(SPCFLAG_BLTNASTY);
unset_special (SPCFLAG_BLTNASTY);
if (dmaen (DMA_BLITPRI))
set_special (SPCFLAG_BLTNASTY);
if (dmaen (DMA_BLITTER))
bltstate = BLT_work;
@ -1115,6 +1578,27 @@ void do_blitter (int hpos)
blit_maxcyclecounter = 0x7fffffff;
blit_waitcyclecounter = 0;
if (blitter_cycle_exact) {
if (immediate_blits) {
if (dmaen (DMA_BLITTER))
blitter_doit ();
return;
}
if (log_blitter & 8) {
blitter_handler (0);
} else {
blitter_hcounter1 = blitter_hcounter2 = 0;
blitter_vcounter1 = blitter_vcounter2 = 0;
if (blit_nod)
blitter_vcounter2 = blt_info.vblitsize;
blit_cyclecounter = -BLITTER_STARTUP_CYCLES;
blit_waitcyclecounter = copper;
blit_startcycles = 0;
blit_maxcyclecounter = blt_info.hblitsize * blt_info.vblitsize + 2;
}
return;
}
if (blt_info.vblitsize == 0 || (blitline && blt_info.hblitsize != 2)) {
if (dmaen (DMA_BLITTER))
blitter_done (hpos);
@ -1132,7 +1616,7 @@ void do_blitter (int hpos)
}
blit_cyclecounter = cycles * (blit_dmacount2 + (blit_nod ? 0 : 1));
event2_newevent (ev2_blitter, blit_cyclecounter, 0);
event2_newevent (ev2_blitter, makebliteventtime(blit_cyclecounter), 0);
}
void blitter_check_start (void)
@ -1146,11 +1630,41 @@ void blitter_check_start (void)
}
}
void maybe_blit2 (int hack)
void do_blitter(int hpos, int copper, uaecptr pc)
{
if (dmaen (DMA_BLITTER)) {
if (bltstate == BLT_done || !blitter_cycle_exact) {
do_blitter2(hpos, copper, pc);
return;
}
if (!dmaen (DMA_BLITTER) || !blt_info.got_cycle)
return;
// previous blit may have last write cycle left
// and we must let it finish
blit_startcycles = BLITTER_STARTUP_CYCLES;
blit_waitcyclecounter = copper;
blit_waitpc = pc;
}
void maybe_blit (int hpos, int hack)
{
static int warned = 10;
reset_channel_mods ();
if (bltstate == BLT_done)
return;
if (savestate_state)
return;
if (dmaen (DMA_BLITTER) && (currprefs.cpu_model >= 68020 || !currprefs.cpu_memory_cycle_exact)) {
bool doit = false;
if (currprefs.waiting_blits) { // automatic
if (currprefs.waiting_blits == 3) { // always
doit = true;
} else if (currprefs.waiting_blits == 2) { // noidle
if (blit_dmacount == blit_diag[0] && (regs.spcflags & SPCFLAG_BLTNASTY))
doit = true;
} else if (currprefs.waiting_blits == 1) { // automatic
if (blit_dmacount == blit_diag[0] && (regs.spcflags & SPCFLAG_BLTNASTY))
doit = true;
else if (currprefs.m68k_speed < 0)
@ -1162,10 +1676,28 @@ void maybe_blit2 (int hack)
}
}
if (hack == 1 && (int)get_cycles() - (int)blit_firstline_cycles < 0)
return;
if (warned && dmaen (DMA_BLITTER) && blt_info.got_cycle) {
warned--;
//debugtest (DEBUGTEST_BLITTER, _T("program does not wait for blitter tc=%d\n"), blit_cyclecounter);
if (log_blitter)
warned = 0;
if (log_blitter & 2) {
warned = 10;
write_log (_T("program does not wait for blitter PC=%08x\n"), M68K_GETPC);
//activate_debugger ();
//blitter_done (hpos);
}
}
blitter_handler (0);
if (blitter_cycle_exact) {
decide_blitter (hpos);
return;
}
if (hack == 1 && (int)get_cycles() - (int)blit_firstline_cycles < 0)
return;
blitter_handler (0);
}
void check_is_blit_dangerous (uaecptr *bplpt, int planes, int words)
@ -1191,6 +1723,10 @@ int blitnasty (void)
return 0;
if (!dmaen (DMA_BLITTER))
return 0;
if (blitter_cycle_exact) {
blitter_force_finish(false);
return -1;
}
if (blit_last_cycle >= blit_diag[0] && blit_dmacount == blit_diag[0])
return 0;
cycles = (get_cycles () - blit_first_cycle) / CYCLE_UNIT;
@ -1238,6 +1774,8 @@ void blitter_reset (void)
void restore_blitter_finish (void)
{
//record_dma_reset ();
//record_dma_reset ();
if (blt_statefile_type == 0) {
blit_interrupt = 1;
if (bltstate == BLT_init) {
@ -1248,6 +1786,9 @@ void restore_blitter_finish (void)
blt_delayed_irq = 3;
intreq &= ~0x0040;
}
} else {
last_blitter_hpos = 0;
blit_modset ();
}
}
@ -1281,7 +1822,7 @@ uae_u8 *save_blitter (int *len, uae_u8 *dstptr)
if (bltstate != BLT_done && bltstate != BLT_init) {
write_log (_T("blitter is active, forcing immediate finish\n"));
/* blitter is active just now but we don't have blitter state support yet */
blitter_force_finish();
blitter_force_finish(true);
forced = 2;
}
if (dstptr)
@ -1300,18 +1841,28 @@ uae_u8 *restore_blitter_new (uae_u8 *src)
{
uae_u8 state;
blt_statefile_type = 1;
blitter_cycle_exact = restore_u8 ();
state = restore_u8 ();
blit_first_cycle = restore_u32 ();
blit_last_cycle = restore_u32 ();
blit_waitcyclecounter = restore_u32 ();
blit_startcycles = restore_u32 ();
blit_maxcyclecounter = restore_u32 ();
blit_firstline_cycles = restore_u32 ();
blit_cyclecounter = restore_u32 ();
blit_slowdown = restore_u32 ();
blit_misscyclecounter = restore_u32 ();
blitter_hcounter1 = restore_u16 ();
blitter_hcounter2 = restore_u16 ();
blitter_vcounter1 = restore_u16 ();
blitter_vcounter2 = restore_u16 ();
blit_ch = restore_u8 ();
blit_dmacount = restore_u8 ();
blit_dmacount2 = restore_u8 ();
blit_nod = restore_u8 ();
blit_final = restore_u8 ();
blitfc = restore_u8 ();
blitife = restore_u8 ();
@ -1321,6 +1872,9 @@ uae_u8 *restore_blitter_new (uae_u8 *src)
blt_info.blitdownashift = restore_u8 ();
ddat1use = restore_u8 ();
ddat2use = restore_u8 ();
ddat1 = restore_u16 ();
ddat2 = restore_u16 ();
blitline = restore_u8 ();
blitfill = restore_u8 ();
@ -1328,13 +1882,19 @@ uae_u8 *restore_blitter_new (uae_u8 *src)
blineb = restore_u16 ();
blinea_shift = restore_u8 ();
blitonedot = restore_u8 ();
blitlinepixel = restore_u8 ();
blitsing = restore_u8 ();
blitlinepixel = restore_u8 ();
blit_interrupt = restore_u8 ();
blt_delayed_irq = restore_u8 ();
blt_info.blitzero = restore_u8 ();
blt_info.got_cycle = restore_u8 ();
blit_frozen = restore_u8 ();
blit_faulty = restore_u8 ();
original_ch = restore_u8 ();
original_fill = restore_u8 ();
original_line = restore_u8 ();
blit_diag = set_cycle_diagram_type (restore_u8 ());
@ -1344,8 +1904,15 @@ uae_u8 *restore_blitter_new (uae_u8 *src)
blitter_nasty = restore_u8 ();
bltstate = BLT_done;
if (state > 0)
do_blitter (0);
if (!blitter_cycle_exact) {
if (state > 0)
do_blitter(0, 0, 0);
} else {
if (state == 1)
bltstate = BLT_init;
else if (state == 2)
bltstate = BLT_work;
}
return src;
}
@ -1358,6 +1925,7 @@ uae_u8 *save_blitter_new (int *len, uae_u8 *dstptr)
dstbak = dst = xmalloc (uae_u8, 1000);
uae_u8 state;
save_u8 (blitter_cycle_exact ? 1 : 0);
if (bltstate == BLT_done)
state = 0;
else if (bltstate == BLT_init)
@ -1372,14 +1940,23 @@ uae_u8 *save_blitter_new (int *len, uae_u8 *dstptr)
save_u32 (blit_first_cycle);
save_u32 (blit_last_cycle);
save_u32 (blit_waitcyclecounter);
save_u32 (blit_startcycles);
save_u32 (blit_maxcyclecounter);
save_u32 (blit_firstline_cycles);
save_u32 (blit_cyclecounter);
save_u32 (blit_slowdown);
save_u32 (blit_misscyclecounter);
save_u16 (blitter_hcounter1);
save_u16 (blitter_hcounter2);
save_u16 (blitter_vcounter1);
save_u16 (blitter_vcounter2);
save_u8 (blit_ch);
save_u8 (blit_dmacount);
save_u8 (blit_dmacount2);
save_u8 (blit_nod);
save_u8 (blit_final);
save_u8 (blitfc);
save_u8 (blitife);
@ -1389,6 +1966,9 @@ uae_u8 *save_blitter_new (int *len, uae_u8 *dstptr)
save_u8 (blt_info.blitdownashift);
save_u8 (ddat1use);
save_u8 (ddat2use);
save_u16 (ddat1);
save_u16 (ddat2);
save_u8 (blitline);
save_u8 (blitfill);
@ -1396,13 +1976,19 @@ uae_u8 *save_blitter_new (int *len, uae_u8 *dstptr)
save_u16 (blineb);
save_u8 (blinea_shift);
save_u8 (blitonedot);
save_u8 (blitlinepixel);
save_u8 (blitsing);
save_u8 (blitlinepixel);
save_u8 (blit_interrupt);
save_u8 (blt_delayed_irq);
save_u8 (blt_info.blitzero);
save_u8 (blt_info.got_cycle);
save_u8 (blit_frozen);
save_u8 (blit_faulty);
save_u8 (original_ch);
save_u8 (original_fill);
save_u8 (original_line);
save_u8 (get_cycle_diagram_type (blit_diag));
save_u16 (0x1234);

View file

@ -17,13 +17,15 @@
#include "options.h"
#include "uae.h"
#include "gensound.h"
#include "audio.h"
#include "sounddep/sound.h"
#include "events.h"
#include "memory.h"
#include "custom.h"
#include "newcpu.h"
#include "cia.h"
#include "disk.h"
#include "savestate.h"
#include "blitter.h"
#include "xwin.h"
#include "inputdevice.h"
@ -4249,6 +4251,7 @@ void compute_vsynctime (void)
}
if (currprefs.produce_sound > 1) {
double clk = svpos * shpos * fake_vblank_hz;
write_log (_T("SNDRATE %.1f*%.1f*%.6f=%.6f\n"), svpos, shpos, fake_vblank_hz, clk);
devices_update_sound(clk, syncadjust);
}
devices_update_sync(svpos, syncadjust);
@ -4327,11 +4330,9 @@ void compute_framesync(void)
if (islace) {
vblank_hz = vblank_hz_lace;
}
else if (lof_current) {
} else if (lof_current) {
vblank_hz = vblank_hz_lof;
}
else {
} else {
vblank_hz = vblank_hz_shf;
}
@ -4374,9 +4375,9 @@ void compute_framesync(void)
v = cr->rate;
if (v > 0) {
changed_prefs.chipset_refreshrate = currprefs.chipset_refreshrate = v;
cfgfile_parse_lines(&changed_prefs, cr->commands, -1);
cfgfile_parse_lines (&changed_prefs, cr->commands, -1);
if (cr->commands[0])
write_log(_T("CMD2: '%s'\n"), cr->commands);
write_log (_T("CMD2: '%s'\n"), cr->commands);
}
} else {
if (cr->locked == false)
@ -4403,7 +4404,7 @@ void compute_framesync(void)
vidinfo->drawbuffer.inyoffset = -1;
if (beamcon0 & 0x80) {
int res = GET_RES_AGNUS(bplcon0);
int res = GET_RES_AGNUS (bplcon0);
int vres = islace ? 1 : 0;
int res2, vres2;
@ -4434,8 +4435,7 @@ void compute_framesync(void)
vidinfo->drawbuffer.inheight = ((firstblankedline < maxvpos ? firstblankedline : maxvpos) - minfirstline + 1) << vres2;
vidinfo->drawbuffer.inheight2 = vidinfo->drawbuffer.inheight;
}
else {
} else {
vidinfo->drawbuffer.inwidth = AMIGA_WIDTH_MAX << currprefs.gfx_resolution;
vidinfo->drawbuffer.extrawidth = currprefs.gfx_extrawidth ? currprefs.gfx_extrawidth : -1;
@ -4857,7 +4857,7 @@ STATIC_INLINE uae_u16 DMACONR (int hpos)
decide_line (hpos);
decide_fetch_safe (hpos);
dmacon &= ~(0x4000 | 0x2000);
dmacon |= ((blit_interrupt || (!blit_interrupt && currprefs.cs_agnusbltbusybug)) ? 0 : 0x4000)
dmacon |= ((blit_interrupt || (!blit_interrupt && currprefs.cs_agnusbltbusybug && !blt_info.got_cycle)) ? 0 : 0x4000)
| (blt_info.blitzero ? 0x2000 : 0);
return dmacon;
}
@ -4865,10 +4865,10 @@ STATIC_INLINE uae_u16 INTENAR (void)
{
return intena;
}
//uae_u16 INTREQR (void)
//{
// return intreq;
//}
uae_u16 INTREQR (void)
{
return intreq;
}
STATIC_INLINE uae_u16 ADKCONR (void)
{
return adkcon;
@ -5444,10 +5444,13 @@ bool INTREQ_0 (uae_u16 v)
uae_u16 old = intreq;
setclr (&intreq, v);
if ((old & 0x0800) && !(intreq & 0x0800))
return false;
if ((v & 0x8000) && old != v)
if ((old & 0x0800) && !(intreq & 0x0800)) {
//serial_rbf_clear();
}
if ((v & 0x8000) && old != v) {
doint_delay();
}
return true;
}
@ -5466,6 +5469,8 @@ static void ADKCON (int hpos, uae_u16 v)
DISK_update_adkcon (hpos, v);
setclr (&adkcon, v);
audio_update_adkmasks ();
//if ((v >> 11) & 1)
//serial_uartbreak ((adkcon >> 11) & 1);
}
static void BEAMCON0 (uae_u16 v)
@ -5910,7 +5915,7 @@ static void FNULL (uae_u16 v)
static void BLTADAT (int hpos, uae_u16 v)
{
maybe_blit (0);
maybe_blit (hpos, 0);
blt_info.bltadat = v;
}
@ -5921,7 +5926,7 @@ static void BLTADAT (int hpos, uae_u16 v)
*/
static void BLTBDAT (int hpos, uae_u16 v)
{
maybe_blit(0);
maybe_blit (hpos, 0);
int shift = bltcon1 >> 12;
@ -5933,72 +5938,120 @@ static void BLTBDAT (int hpos, uae_u16 v)
blt_info.bltbdat = v;
blt_info.bltbold = v;
}
static void BLTCDAT (int hpos, uae_u16 v) { maybe_blit (0); blt_info.bltcdat = v; reset_blit(0); }
static void BLTCDAT (int hpos, uae_u16 v) { maybe_blit (hpos, 0); blt_info.bltcdat = v; reset_blit (0); }
static void BLTAMOD (int hpos, uae_u16 v) { maybe_blit (1); blt_info.bltamod = uae_s16(v & 0xFFFE); reset_blit (0); }
static void BLTBMOD (int hpos, uae_u16 v) { maybe_blit (1); blt_info.bltbmod = uae_s16(v & 0xFFFE); reset_blit (0); }
static void BLTCMOD (int hpos, uae_u16 v) { maybe_blit (1); blt_info.bltcmod = uae_s16(v & 0xFFFE); reset_blit (0); }
static void BLTDMOD (int hpos, uae_u16 v) { maybe_blit (1); blt_info.bltdmod = uae_s16(v & 0xFFFE); reset_blit (0); }
static void BLTAMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltamod = (uae_s16)(v & 0xFFFE); reset_blit (0); }
static void BLTBMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltbmod = (uae_s16)(v & 0xFFFE); reset_blit (0); }
static void BLTCMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltcmod = (uae_s16)(v & 0xFFFE); reset_blit (0); }
static void BLTDMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltdmod = (uae_s16)(v & 0xFFFE); reset_blit (0); }
static void BLTCON0 (int hpos, uae_u16 v) { maybe_blit (2); bltcon0 = v; reset_blit(1); }
static void BLTCON0 (int hpos, uae_u16 v) { maybe_blit (hpos, 2); bltcon0 = v; reset_blit (1); }
/* The next category is "Most useless hardware register".
* And the winner is... */
static void BLTCON0L (int hpos, uae_u16 v)
{
if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
return; // ei voittoa.
maybe_blit (2); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF);
maybe_blit (hpos, 2); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF);
reset_blit (1);
}
static void BLTCON1 (int hpos, uae_u16 v) { maybe_blit (2); bltcon1 = v; reset_blit (2); }
static void BLTCON1 (int hpos, uae_u16 v) { maybe_blit (hpos, 2); bltcon1 = v; reset_blit (2); }
static void BLTAFWM (int hpos, uae_u16 v) { maybe_blit (2); blt_info.bltafwm = v; reset_blit (0); }
static void BLTALWM (int hpos, uae_u16 v) { maybe_blit (2); blt_info.bltalwm = v; reset_blit (0); }
static void BLTAFWM (int hpos, uae_u16 v) { maybe_blit (hpos, 2); blt_info.bltafwm = v; reset_blit (0); }
static void BLTALWM (int hpos, uae_u16 v) { maybe_blit (hpos, 2); blt_info.bltalwm = v; reset_blit (0); }
static void BLTAPTH (int hpos, uae_u16 v)
{
maybe_blit (0);
bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16);
maybe_blit (hpos, 0);
if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
bltptx = (bltapt & 0xffff) | ((uae_u32)v << 16);
bltptxpos = hpos;
bltptxc = 1;
} else {
bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16);
}
}
static void BLTAPTL (int hpos, uae_u16 v)
{
maybe_blit (0);
bltapt = (bltapt & ~0xffff) | (v & 0xFFFE);
maybe_blit (hpos, 0);
if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
bltptx = (bltapt & ~0xffff) | (v & 0xFFFE);
bltptxpos = hpos;
bltptxc = 1;
} else {
bltapt = (bltapt & ~0xffff) | (v & 0xFFFE);
}
}
static void BLTBPTH (int hpos, uae_u16 v)
{
maybe_blit (0);
bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16);
maybe_blit (hpos, 0);
if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
bltptx = (bltbpt & 0xffff) | ((uae_u32)v << 16);
bltptxpos = hpos;
bltptxc = 2;
} else {
bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16);
}
}
static void BLTBPTL (int hpos, uae_u16 v)
{
maybe_blit (0);
bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE);
maybe_blit (hpos, 0);
if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
bltptx = (bltbpt & ~0xffff) | (v & 0xFFFE);
bltptxpos = hpos;
bltptxc = 2;
} else {
bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE);
}
}
static void BLTCPTH (int hpos, uae_u16 v)
{
maybe_blit (0);
bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16);
maybe_blit (hpos, 0);
if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
bltptx = (bltcpt & 0xffff) | ((uae_u32)v << 16);
bltptxpos = hpos;
bltptxc = 3;
} else {
bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16);
}
}
static void BLTCPTL (int hpos, uae_u16 v)
{
maybe_blit (0);
bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE);
maybe_blit (hpos, 0);
if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
bltptx = (bltcpt & ~0xffff) | (v & 0xFFFE);
bltptxpos = hpos;
bltptxc = 3;
} else {
bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE);
}
}
static void BLTDPTH (int hpos, uae_u16 v)
{
maybe_blit (0);
bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16);
maybe_blit (hpos, 0);
if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
bltptx = (bltdpt & 0xffff) | ((uae_u32)v << 16);
bltptxpos = hpos;
bltptxc = 4;
} else {
bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16);
}
}
static void BLTDPTL (int hpos, uae_u16 v)
{
maybe_blit (0);
bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE);
maybe_blit (hpos, 0);
if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
bltptx = (bltdpt & ~0xffff) | (v & 0xFFFE);
bltptxpos = hpos;
bltptxc = 4;
} else {
bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE);
}
}
static void BLTSIZE (int hpos, uae_u16 v)
{
maybe_blit (0);
maybe_blit (hpos, 0);
blt_info.vblitsize = v >> 6;
blt_info.hblitsize = v & 0x3F;
@ -6006,7 +6059,7 @@ static void BLTSIZE (int hpos, uae_u16 v)
blt_info.vblitsize = 1024;
if (!blt_info.hblitsize)
blt_info.hblitsize = 64;
do_blitter(hpos);
do_blitter(hpos, copper_access, copper_access ? cop_state.ip : M68K_GETPC);
dcheck_is_blit_dangerous ();
}
@ -6014,7 +6067,7 @@ static void BLTSIZV (int hpos, uae_u16 v)
{
if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
return;
maybe_blit (0);
maybe_blit (hpos, 0);
blt_info.vblitsize = v & 0x7FFF;
}
@ -6022,13 +6075,13 @@ static void BLTSIZH (int hpos, uae_u16 v)
{
if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
return;
maybe_blit (0);
maybe_blit (hpos, 0);
blt_info.hblitsize = v & 0x7FF;
if (!blt_info.vblitsize)
blt_info.vblitsize = 0x8000;
if (!blt_info.hblitsize)
blt_info.hblitsize = 0x0800;
do_blitter(hpos);
do_blitter(hpos, copper_access, copper_access ? cop_state.ip : M68K_GETPC);
}
STATIC_INLINE void spr_arm (int num, int state)

View file

@ -9,7 +9,6 @@
#ifndef UAE_BLITTER_H
#define UAE_BLITTER_H
#include "savestate.h"
#include "uae/types.h"
struct bltinfo {
@ -39,23 +38,13 @@ extern uae_u32 bltptx;
extern int bltptxpos, bltptxc;
extern int blit_singlechannel;
extern void maybe_blit2 (int);
STATIC_INLINE void maybe_blit(int hack)
{
if (bltstate == BLT_done)
return;
if (savestate_state)
return;
maybe_blit2(hack);
}
extern void maybe_blit (int, int);
extern void reset_blit (int);
extern int blitnasty (void);
extern int blitnnasty (int);
extern void blitter_handler (uae_u32);
extern void build_blitfilltable (void);
extern void do_blitter (int);
extern void do_blitter (int, int, uaecptr);
extern void decide_blitter (int hpos);
extern int blitter_need (int hpos);
extern void blitter_done_notify (int hpos);

View file

@ -85,19 +85,11 @@ extern uae_u16 adkcon;
extern unsigned int joy0dir, joy1dir;
extern int joy0button, joy1button;
extern void INTREQ (uae_u16);
extern bool INTREQ_0 (uae_u16);
extern void INTREQ_f (uae_u16);
STATIC_INLINE void send_interrupt (int num)
{
INTREQ_0 (0x8000 | (1 << num));
}
extern void INTREQ(uae_u16);
extern bool INTREQ_0(uae_u16);
extern void INTREQ_f(uae_u16);
extern void send_interrupt(int num, int delay);
extern void rethink_uae_int(void);
STATIC_INLINE uae_u16 INTREQR(void)
{
return intreq;
}
STATIC_INLINE void safe_interrupt_set(bool i6)
{
uae_u16 v = i6 ? 0x2000 : 0x0008;
@ -105,6 +97,7 @@ STATIC_INLINE void safe_interrupt_set(bool i6)
INTREQ_0(0x8000 | v);
}
}
extern uae_u16 INTREQR(void);
/* maximums for statically allocated tables */
#ifdef UAE_MINI