mirror of
https://github.com/Oibaf66/uae-wii.git
synced 2024-11-22 10:39:19 +01:00
1217 lines
30 KiB
C
1217 lines
30 KiB
C
/*
|
||
* UAE - The Un*x Amiga Emulator
|
||
*
|
||
* Custom chip emulation
|
||
*
|
||
* (c) 1995 Bernd Schmidt, Alessandro Bissacco
|
||
* (c) 2002 - 2005 Toni Wilen
|
||
*/
|
||
|
||
//#define BLITTER_DEBUG
|
||
//#define BLITTER_SLOWDOWNDEBUG 4
|
||
|
||
#define SPEEDUP
|
||
|
||
#include "sysconfig.h"
|
||
#include "sysdeps.h"
|
||
|
||
#include "options.h"
|
||
#include "uae.h"
|
||
#include "memory.h"
|
||
#include "custom.h"
|
||
#include "custom_private.h"
|
||
#include "events.h"
|
||
#include "newcpu.h"
|
||
#include "blitter.h"
|
||
#include "blit.h"
|
||
#include "savestate.h"
|
||
|
||
/* we must not change ce-mode while blitter is running.. */
|
||
static int blitter_cycle_exact;
|
||
|
||
uae_u16 bltcon0, bltcon1;
|
||
uae_u32 bltapt, bltbpt, bltcpt, bltdpt;
|
||
|
||
unsigned int blinea_shift;
|
||
static uae_u16 blinea, blineb;
|
||
static unsigned int blitline, blitfc, blitfill, blitife, blitsing, blitdesc;
|
||
static unsigned int blitonedot, blitsign;
|
||
static int blit_add;
|
||
static int blit_modadda, blit_modaddb, blit_modaddc, blit_modaddd;
|
||
static unsigned int blit_ch;
|
||
|
||
#ifdef BLITTER_DEBUG
|
||
static int blitter_dontdo;
|
||
static int blitter_delayed_debug;
|
||
#endif
|
||
#ifdef BLITTER_SLOWDOWNDEBUG
|
||
static int blitter_slowdowndebug;
|
||
#endif
|
||
|
||
struct bltinfo blt_info;
|
||
|
||
static uae_u8 blit_filltable[256][4][2];
|
||
uae_u32 blit_masktable[BLITTER_MAX_WORDS];
|
||
|
||
enum blitter_states bltstate;
|
||
|
||
static unsigned int blit_cyclecounter;
|
||
static unsigned int blit_maxcyclecounter;
|
||
static int blit_slowdown;
|
||
#ifdef BLITTER_DEBUG
|
||
static int blit_misscyclecounter;
|
||
#endif
|
||
|
||
#ifdef CPUEMU_6
|
||
extern uae_u8 cycle_line[];
|
||
#endif
|
||
|
||
static unsigned long blit_firstline_cycles;
|
||
static unsigned long blit_first_cycle;
|
||
static unsigned int blit_last_cycle, blit_dmacount, blit_dmacount2;
|
||
|
||
static unsigned int blit_nod;
|
||
|
||
static const uae_s8 *blit_diag;
|
||
|
||
static uae_u16 ddat1, ddat2;
|
||
static unsigned int ddat1use, ddat2use;
|
||
|
||
/*
|
||
|
||
Confirmed blitter <20>formation by Toni Wilen
|
||
(order of channels or position of idle cycles are not confirmed)
|
||
|
||
1=BLTCON0 channel mask
|
||
2=total cycles per blitted word
|
||
[3=steals all cycles if BLTNASTY=1 (always if A-channel is enabled. this is illogical..)]
|
||
4=total cycles per blitted word in fillmode
|
||
5=cycle diagram (first cycle)
|
||
6=main cycle diagram (ABCD=channels,-=idle cycle,x=idle cycle but bus allocated)
|
||
|
||
1 234 5 6
|
||
|
||
F 4*4*ABC- ABCD
|
||
E 4*4*ABC- ABC-
|
||
D 3*4 AB- ABD
|
||
C 3*3 AB- AB-
|
||
B 3*3*AC- ACD
|
||
A 2*2*AC AC
|
||
9 2*3 A- AD
|
||
8 2*2 A- A-
|
||
7 4 4 -BC- -BCD
|
||
6 4 4 -BC- -BC-
|
||
5 3 4 -B- -BD
|
||
4 3 3 -B- -B-
|
||
3 3 3 -C- -CD
|
||
2 3 3 -C- -C-
|
||
1 2 3 -D -D
|
||
0 2 3 -- --
|
||
|
||
NOTES: (BLTNASTY=1)
|
||
|
||
- Blitter ALWAYS needs free bus cycle, even if it is running an "idle" cycle.
|
||
Exception: possible extra fill mode idle cycle is "real" idle cycle.
|
||
Can someone explain this? Why does idle cycles need bus cycles?
|
||
- Fill mode may add one extra real idle cycle.(depends on channel mask)
|
||
- All blits with channel A enabled use all available bus cycles
|
||
(stops CPU accesses to Agnus bus if BLTNASTY=1) WTF? I did another test
|
||
and this can't be true... Maybe I am becoming crazy..
|
||
- idle cycles (no A-channel enabled) are not "used" by blitter, they are freely
|
||
available for CPU.
|
||
|
||
BLTNASTY=0 makes things even more interesting..
|
||
|
||
- even zero channel blits get slower if BLTNASTY=0 depending on the number of
|
||
active bitplanes. ALSO "2 cycle" blits with one real cycle and one idle cycle
|
||
have the exact same speed as zero channel blit in all situations -> only the
|
||
total number of cycles count, number of active channels does not matter.
|
||
|
||
*/
|
||
|
||
|
||
/* -1 = idle cycle and allocate bus */
|
||
|
||
static const uae_s8 blit_cycle_diagram[][10] =
|
||
{
|
||
{ 0, 2, 0,0 }, /* 0 */
|
||
{ 0, 2, 0,4 }, /* 1 */
|
||
{ 0, 3, 0,3,0 }, /* 2 */
|
||
{ 2, 3, 0,3,4, 3,0 }, /* 3 */
|
||
{ 0, 3, 0,2,0 }, /* 4 */
|
||
{ 2, 3, 0,2,4, 2,0 }, /* 5 */
|
||
{ 0, 4, 0,2,3,0 }, /* 6 */
|
||
{ 3, 4, 0,2,3,4, 2,3,0 }, /* 7 */
|
||
{ 0, 2, 1,0 }, /* 8 */
|
||
{ 2, 2, 1,4, 1,0 }, /* 9 */
|
||
{ 0, 2, 1,3 }, /* A */
|
||
{ 3, 3, 1,3,4, 1,3,0 }, /* B */
|
||
{ 2, 3, 1,2,0, 1,2 }, /* C */
|
||
{ 3, 3, 1,2,4, 1,2,0 }, /* D */
|
||
{ 0, 4, 1,2,3,0 }, /* E */
|
||
{ 4, 4, 1,2,3,4, 1,2,3,0 } /* F */
|
||
};
|
||
|
||
/* 5 = fill mode idle cycle ("real" idle cycle) */
|
||
|
||
static const uae_s8 blit_cycle_diagram_fill[][10] =
|
||
{
|
||
{ 0, 3, 0,5,0 }, /* 0 */
|
||
{ 0, 3, 3,5,4 }, /* 1 */
|
||
{ 0, 3, 0,3,0 }, /* 2 */
|
||
{ 2, 3, 3,5,4, 3,0 }, /* 3 */
|
||
{ 0, 3, 0,2,5 }, /* 4 */
|
||
{ 3, 4, 0,2,5,4, 2,0,0 }, /* 5 */
|
||
{ 0, 4, 2,3,5,0 }, /* 6 */
|
||
{ 3, 4, 2,3,5,4, 2,3,0 }, /* 7 */
|
||
{ 0, 2, 1,5 }, /* 8 */
|
||
{ 2, 3, 1,5,4, 1,0}, /* 9 */
|
||
{ 0, 2, 1,3 }, /* A */
|
||
{ 3, 3, 1,3,4, 1,3,0 }, /* B */
|
||
{ 2, 3, 1,2,5, 1,2 }, /* C */
|
||
{ 3, 4, 1,2,5,4, 1,2,0 }, /* D */
|
||
{ 0, 4, 1,2,3,0 }, /* E */
|
||
{ 4, 4, 1,2,3,4, 1,2,3,0 } /* F */
|
||
};
|
||
|
||
/*
|
||
|
||
line draw takes 4 cycles (-X-X)
|
||
it also have real idle cycles and only 2 dma fetches
|
||
(read from C, write to D, but see below)
|
||
|
||
Oddities:
|
||
|
||
- first word is written to address pointed by BLTDPT
|
||
but all following writes go to address pointed by BLTCPT!
|
||
- BLTDMOD is ignored by blitter (BLTCMOD is used)
|
||
- state of D-channel enable bit does not matter!
|
||
- disabling A-channel freezes the content of BPLAPT
|
||
|
||
*/
|
||
|
||
static const uae_s8 blit_cycle_diagram_line[] =
|
||
{
|
||
0, 4, 0,3,0,4, 0,0,0,0,0,0,0,0,0,0 /* guessed */
|
||
};
|
||
|
||
static const uae_s8 blit_cycle_diagram_finald[] =
|
||
{ 0, 2, 0,4 };
|
||
|
||
void build_blitfilltable (void)
|
||
{
|
||
unsigned int d, fillmask;
|
||
unsigned int i;
|
||
|
||
for (i = 0; i < BLITTER_MAX_WORDS; i++)
|
||
blit_masktable[i] = 0xFFFF;
|
||
|
||
for (d = 0; d < 256; d++) {
|
||
for (i = 0; i < 4; i++) {
|
||
unsigned int fc = i & 1;
|
||
uae_u8 data = d;
|
||
for (fillmask = 1; fillmask != 0x100; fillmask <<= 1) {
|
||
uae_u16 tmp = data;
|
||
if (fc) {
|
||
if (i & 2)
|
||
data |= fillmask;
|
||
else
|
||
data ^= fillmask;
|
||
}
|
||
if (tmp & fillmask) fc = !fc;
|
||
}
|
||
blit_filltable[d][i][0] = data;
|
||
blit_filltable[d][i][1] = fc;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void blitter_dump (void)
|
||
{
|
||
write_log ("APT=%08.8X BPT=%08.8X CPT=%08.8X DPT=%08.8X\n", bltapt, bltbpt, bltcpt, bltdpt);
|
||
write_log ("CON0=%04.4X CON1=%04.4X ADAT=%04.4X BDAT=%04.4X CDAT=%04.4X\n",
|
||
bltcon0, bltcon1, blt_info.bltadat, blt_info.bltbdat, blt_info.bltcdat);
|
||
write_log ("AFWM=%04.4X ALWM=%04.4X AMOD=%04.4X BMOD=%04.4X CMOD=%04.4X DMOD=%04.4X\n",
|
||
blt_info.bltafwm, blt_info.bltalwm,
|
||
blt_info.bltamod & 0xffff, blt_info.bltbmod & 0xffff, blt_info.bltcmod & 0xffff, blt_info.bltdmod & 0xffff);
|
||
}
|
||
|
||
STATIC_INLINE int channel_state (unsigned int cycles)
|
||
{
|
||
if ((int)cycles < blit_diag[0])
|
||
return blit_diag[blit_diag[1] + 2 + cycles];
|
||
return blit_diag[((cycles - blit_diag[0]) % blit_diag[1]) + 2];
|
||
}
|
||
|
||
#ifdef CPUEMU_6
|
||
STATIC_INLINE int canblit (unsigned int hpos)
|
||
{
|
||
if (is_bitplane_dma (hpos))
|
||
return 0;
|
||
if (cycle_line[hpos] == 0)
|
||
return 1;
|
||
if (cycle_line[hpos] & CYCLE_REFRESH)
|
||
return -1;
|
||
return 0;
|
||
}
|
||
#endif
|
||
|
||
static void blitter_done (void)
|
||
{
|
||
ddat1use = ddat2use = 0;
|
||
bltstate = BLT_done;
|
||
blitter_done_notify ();
|
||
INTREQ(0x8040);
|
||
eventtab[ev_blitter].active = 0;
|
||
unset_special (®s, SPCFLAG_BLTNASTY);
|
||
#ifdef BLITTER_DEBUG
|
||
write_log ("vpos=%d, cycles %d, missed %d, total %d\n",
|
||
vpos, blit_cyclecounter, blit_misscyclecounter, blit_cyclecounter + blit_misscyclecounter);
|
||
#endif
|
||
}
|
||
|
||
static void blitter_dofast (void)
|
||
{
|
||
int i,j;
|
||
uaecptr bltadatptr = 0, bltbdatptr = 0, bltcdatptr = 0, bltddatptr = 0;
|
||
uae_u8 mt = bltcon0 & 0xFF;
|
||
|
||
blit_masktable[0] = blt_info.bltafwm;
|
||
blit_masktable[blt_info.hblitsize - 1] &= blt_info.bltalwm;
|
||
|
||
if (bltcon0 & 0x800) {
|
||
bltadatptr = bltapt;
|
||
bltapt += (blt_info.hblitsize*2 + blt_info.bltamod)*blt_info.vblitsize;
|
||
}
|
||
if (bltcon0 & 0x400) {
|
||
bltbdatptr = bltbpt;
|
||
bltbpt += (blt_info.hblitsize*2 + blt_info.bltbmod)*blt_info.vblitsize;
|
||
}
|
||
if (bltcon0 & 0x200) {
|
||
bltcdatptr = bltcpt;
|
||
bltcpt += (blt_info.hblitsize*2 + blt_info.bltcmod)*blt_info.vblitsize;
|
||
}
|
||
if (bltcon0 & 0x100) {
|
||
bltddatptr = bltdpt;
|
||
bltdpt += (blt_info.hblitsize*2 + blt_info.bltdmod)*blt_info.vblitsize;
|
||
}
|
||
|
||
#ifdef SPEEDUP
|
||
if (blitfunc_dofast[mt] && !blitfill) {
|
||
(*blitfunc_dofast[mt])(bltadatptr, bltbdatptr, bltcdatptr, bltddatptr, &blt_info);
|
||
} else
|
||
#endif
|
||
{
|
||
uae_u32 blitbhold = blt_info.bltbhold;
|
||
uae_u32 preva = 0, prevb = 0;
|
||
uaecptr dstp = 0;
|
||
int dodst = 0;
|
||
|
||
/*if (!blitfill) write_log ("minterm %x not present\n",mt); */
|
||
for (j = 0; j < blt_info.vblitsize; j++) {
|
||
blitfc = !!(bltcon1 & 0x4);
|
||
for (i = 0; i < blt_info.hblitsize; i++) {
|
||
uae_u32 bltadat, blitahold;
|
||
uae_u16 bltbdat;
|
||
if (bltadatptr) {
|
||
blt_info.bltadat = bltadat = chipmem_wget (bltadatptr);
|
||
bltadatptr += 2;
|
||
} else
|
||
bltadat = blt_info.bltadat;
|
||
bltadat &= blit_masktable[i];
|
||
blitahold = (((uae_u32)preva << 16) | bltadat) >> blt_info.blitashift;
|
||
preva = bltadat;
|
||
|
||
if (bltbdatptr) {
|
||
blt_info.bltbdat = bltbdat = chipmem_wget (bltbdatptr);
|
||
bltbdatptr += 2;
|
||
blitbhold = (((uae_u32)prevb << 16) | bltbdat) >> blt_info.blitbshift;
|
||
prevb = bltbdat;
|
||
}
|
||
|
||
if (bltcdatptr) {
|
||
blt_info.bltcdat = chipmem_wget (bltcdatptr);
|
||
bltcdatptr += 2;
|
||
}
|
||
if (dodst) chipmem_wput (dstp, blt_info.bltddat);
|
||
blt_info.bltddat = blit_func (blitahold, blitbhold, blt_info.bltcdat, mt) & 0xFFFF;
|
||
if (blitfill) {
|
||
uae_u16 d = blt_info.bltddat;
|
||
int ifemode = blitife ? 2 : 0;
|
||
int fc1 = blit_filltable[d & 255][ifemode + blitfc][1];
|
||
blt_info.bltddat = (blit_filltable[d & 255][ifemode + blitfc][0]
|
||
+ (blit_filltable[d >> 8][ifemode + fc1][0] << 8));
|
||
blitfc = blit_filltable[d >> 8][ifemode + fc1][1];
|
||
}
|
||
if (blt_info.bltddat)
|
||
blt_info.blitzero = 0;
|
||
if (bltddatptr) {
|
||
dodst = 1;
|
||
dstp = bltddatptr;
|
||
bltddatptr += 2;
|
||
}
|
||
}
|
||
if (bltadatptr) bltadatptr += blt_info.bltamod;
|
||
if (bltbdatptr) bltbdatptr += blt_info.bltbmod;
|
||
if (bltcdatptr) bltcdatptr += blt_info.bltcmod;
|
||
if (bltddatptr) bltddatptr += blt_info.bltdmod;
|
||
}
|
||
if (dodst) chipmem_wput (dstp, blt_info.bltddat);
|
||
blt_info.bltbhold = blitbhold;
|
||
}
|
||
blit_masktable[0] = 0xFFFF;
|
||
blit_masktable[blt_info.hblitsize - 1] = 0xFFFF;
|
||
|
||
bltstate = BLT_done;
|
||
}
|
||
|
||
static void blitter_dofast_desc (void)
|
||
{
|
||
int i,j;
|
||
uaecptr bltadatptr = 0, bltbdatptr = 0, bltcdatptr = 0, bltddatptr = 0;
|
||
uae_u8 mt = bltcon0 & 0xFF;
|
||
|
||
blit_masktable[0] = blt_info.bltafwm;
|
||
blit_masktable[blt_info.hblitsize - 1] &= blt_info.bltalwm;
|
||
|
||
if (bltcon0 & 0x800) {
|
||
bltadatptr = bltapt;
|
||
bltapt -= (blt_info.hblitsize*2 + blt_info.bltamod)*blt_info.vblitsize;
|
||
}
|
||
if (bltcon0 & 0x400) {
|
||
bltbdatptr = bltbpt;
|
||
bltbpt -= (blt_info.hblitsize*2 + blt_info.bltbmod)*blt_info.vblitsize;
|
||
}
|
||
if (bltcon0 & 0x200) {
|
||
bltcdatptr = bltcpt;
|
||
bltcpt -= (blt_info.hblitsize*2 + blt_info.bltcmod)*blt_info.vblitsize;
|
||
}
|
||
if (bltcon0 & 0x100) {
|
||
bltddatptr = bltdpt;
|
||
bltdpt -= (blt_info.hblitsize*2 + blt_info.bltdmod)*blt_info.vblitsize;
|
||
}
|
||
#ifdef SPEEDUP
|
||
if (blitfunc_dofast_desc[mt] && !blitfill) {
|
||
(*blitfunc_dofast_desc[mt])(bltadatptr, bltbdatptr, bltcdatptr, bltddatptr, &blt_info);
|
||
} else
|
||
#endif
|
||
{
|
||
uae_u32 blitbhold = blt_info.bltbhold;
|
||
uae_u32 preva = 0, prevb = 0;
|
||
uaecptr dstp = 0;
|
||
int dodst = 0;
|
||
|
||
for (j = 0; j < blt_info.vblitsize; j++) {
|
||
blitfc = !!(bltcon1 & 0x4);
|
||
for (i = 0; i < blt_info.hblitsize; i++) {
|
||
uae_u32 bltadat, blitahold;
|
||
uae_u16 bltbdat;
|
||
if (bltadatptr) {
|
||
bltadat = blt_info.bltadat = chipmem_wget (bltadatptr);
|
||
bltadatptr -= 2;
|
||
} else
|
||
bltadat = blt_info.bltadat;
|
||
bltadat &= blit_masktable[i];
|
||
blitahold = (((uae_u32)bltadat << 16) | preva) >> blt_info.blitdownashift;
|
||
preva = bltadat;
|
||
|
||
if (bltbdatptr) {
|
||
blt_info.bltbdat = bltbdat = chipmem_wget (bltbdatptr);
|
||
bltbdatptr -= 2;
|
||
blitbhold = (((uae_u32)bltbdat << 16) | prevb) >> blt_info.blitdownbshift;
|
||
prevb = bltbdat;
|
||
}
|
||
|
||
if (bltcdatptr) {
|
||
blt_info.bltcdat = blt_info.bltbdat = chipmem_wget (bltcdatptr);
|
||
bltcdatptr -= 2;
|
||
}
|
||
if (dodst) chipmem_wput (dstp, blt_info.bltddat);
|
||
blt_info.bltddat = blit_func (blitahold, blitbhold, blt_info.bltcdat, mt) & 0xFFFF;
|
||
if (blitfill) {
|
||
uae_u16 d = blt_info.bltddat;
|
||
int ifemode = blitife ? 2 : 0;
|
||
int fc1 = blit_filltable[d & 255][ifemode + blitfc][1];
|
||
blt_info.bltddat = (blit_filltable[d & 255][ifemode + blitfc][0]
|
||
+ (blit_filltable[d >> 8][ifemode + fc1][0] << 8));
|
||
blitfc = blit_filltable[d >> 8][ifemode + fc1][1];
|
||
}
|
||
if (blt_info.bltddat)
|
||
blt_info.blitzero = 0;
|
||
if (bltddatptr) {
|
||
dstp = bltddatptr;
|
||
dodst = 1;
|
||
bltddatptr -= 2;
|
||
}
|
||
}
|
||
if (bltadatptr) bltadatptr -= blt_info.bltamod;
|
||
if (bltbdatptr) bltbdatptr -= blt_info.bltbmod;
|
||
if (bltcdatptr) bltcdatptr -= blt_info.bltcmod;
|
||
if (bltddatptr) bltddatptr -= blt_info.bltdmod;
|
||
}
|
||
if (dodst) chipmem_wput (dstp, blt_info.bltddat);
|
||
blt_info.bltbhold = blitbhold;
|
||
}
|
||
blit_masktable[0] = 0xFFFF;
|
||
blit_masktable[blt_info.hblitsize - 1] = 0xFFFF;
|
||
|
||
bltstate = BLT_done;
|
||
}
|
||
|
||
STATIC_INLINE void blitter_read (void)
|
||
{
|
||
if (bltcon0 & 0x200) {
|
||
if (!dmaen(DMA_BLITTER))
|
||
return;
|
||
blt_info.bltcdat = chipmem_bank.wget(bltcpt);
|
||
}
|
||
bltstate = BLT_work;
|
||
}
|
||
|
||
STATIC_INLINE void blitter_write (void)
|
||
{
|
||
if (blt_info.bltddat)
|
||
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;
|
||
chipmem_bank.wput(bltdpt, blt_info.bltddat);
|
||
}
|
||
bltstate = BLT_next;
|
||
}
|
||
|
||
STATIC_INLINE void blitter_line_incx (void)
|
||
{
|
||
if (++blinea_shift == 16) {
|
||
blinea_shift = 0;
|
||
bltcpt += 2;
|
||
}
|
||
}
|
||
|
||
STATIC_INLINE void blitter_line_decx (void)
|
||
{
|
||
if (blinea_shift-- == 0) {
|
||
blinea_shift = 15;
|
||
bltcpt -= 2;
|
||
}
|
||
}
|
||
|
||
STATIC_INLINE void blitter_line_decy (void)
|
||
{
|
||
bltcpt -= blt_info.bltcmod;
|
||
blitonedot = 0;
|
||
}
|
||
|
||
STATIC_INLINE void blitter_line_incy (void)
|
||
{
|
||
bltcpt += blt_info.bltcmod;
|
||
blitonedot = 0;
|
||
}
|
||
|
||
static void blitter_line (void)
|
||
{
|
||
uae_u16 blitahold = blinea >> blinea_shift;
|
||
uae_u16 blitbhold = blineb & 1 ? 0xFFFF : 0;
|
||
uae_u16 blitchold = blt_info.bltcdat;
|
||
|
||
if (blitsing && blitonedot)
|
||
blitahold = 0;
|
||
blitonedot = 1;
|
||
blt_info.bltddat = blit_func(blitahold, blitbhold, blitchold, bltcon0 & 0xFF);
|
||
}
|
||
|
||
static void blitter_line_proc (void)
|
||
{
|
||
if (!blitsign) {
|
||
if (bltcon0 & 0x800)
|
||
bltapt += (uae_s16)blt_info.bltamod;
|
||
if (bltcon1 & 0x10){
|
||
if (bltcon1 & 0x8)
|
||
blitter_line_decy();
|
||
else
|
||
blitter_line_incy();
|
||
} else {
|
||
if (bltcon1 & 0x8)
|
||
blitter_line_decx();
|
||
else
|
||
blitter_line_incx();
|
||
}
|
||
} else {
|
||
if (bltcon0 & 0x800)
|
||
bltapt += (uae_s16)blt_info.bltbmod;
|
||
}
|
||
if (bltcon1 & 0x10){
|
||
if (bltcon1 & 0x4)
|
||
blitter_line_decx();
|
||
else
|
||
blitter_line_incx();
|
||
} else {
|
||
if (bltcon1 & 0x4)
|
||
blitter_line_decy();
|
||
else
|
||
blitter_line_incy();
|
||
}
|
||
blitsign = 0 > (uae_s16)bltapt;
|
||
bltstate = BLT_write;
|
||
}
|
||
|
||
STATIC_INLINE void blitter_nxline (void)
|
||
{
|
||
blineb = (blineb << 1) | (blineb >> 15);
|
||
blt_info.vblitsize--;
|
||
bltstate = BLT_read;
|
||
}
|
||
|
||
#ifdef CPUEMU_6
|
||
|
||
static unsigned int blit_last_hpos;
|
||
|
||
static unsigned int blitter_cyclecounter;
|
||
static int blitter_hcounter1, blitter_hcounter2;
|
||
static int blitter_vcounter1, blitter_vcounter2;
|
||
|
||
static void decide_blitter_line (unsigned int hpos)
|
||
{
|
||
hpos++;
|
||
if (dmaen (DMA_BLITTER)) {
|
||
while (blit_last_hpos < hpos) {
|
||
int c = channel_state (blit_cyclecounter);
|
||
for (;;) {
|
||
if (c) {
|
||
if (!canblit (blit_last_hpos))
|
||
break;
|
||
}
|
||
blit_cyclecounter++;
|
||
if (c == 3) {
|
||
blitter_read();
|
||
cycle_line[blit_last_hpos] |= CYCLE_BLITTER;
|
||
} else if (c == 4) {
|
||
if (ddat1use) {
|
||
bltdpt = bltcpt;
|
||
}
|
||
ddat1use = 1;
|
||
blitter_line();
|
||
blitter_line_proc();
|
||
blitter_nxline();
|
||
blitter_write();
|
||
cycle_line[blit_last_hpos] |= CYCLE_BLITTER;
|
||
if (blt_info.vblitsize == 0) {
|
||
bltdpt = bltcpt;
|
||
blitter_done();
|
||
return;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
blit_last_hpos++;
|
||
}
|
||
} else {
|
||
blit_last_hpos = hpos;
|
||
}
|
||
if (blit_last_hpos > maxhpos)
|
||
blit_last_hpos = 0;
|
||
}
|
||
|
||
#endif
|
||
|
||
static void actually_do_blit (void)
|
||
{
|
||
if (blitline) {
|
||
do {
|
||
blitter_read ();
|
||
blitter_line ();
|
||
blitter_line_proc ();
|
||
blitter_write ();
|
||
bltdpt = bltcpt;
|
||
blitter_nxline ();
|
||
if (blt_info.vblitsize == 0)
|
||
bltstate = BLT_done;
|
||
} while (bltstate != BLT_done);
|
||
} else {
|
||
if (blitdesc)
|
||
blitter_dofast_desc ();
|
||
else
|
||
blitter_dofast ();
|
||
bltstate = BLT_done;
|
||
}
|
||
}
|
||
|
||
void blitter_handler (void)
|
||
{
|
||
static int blitter_stuck;
|
||
if (!dmaen (DMA_BLITTER)) {
|
||
eventtab[ev_blitter].active = 1;
|
||
eventtab[ev_blitter].oldcycles = get_cycles ();
|
||
eventtab[ev_blitter].evtime = 10 * CYCLE_UNIT + get_cycles (); /* wait a little */
|
||
blitter_stuck++;
|
||
if (blitter_stuck < 20000 || !currprefs.immediate_blits)
|
||
return; /* gotta come back later. */
|
||
/* "free" blitter in immediate mode if it has been "stuck" ~3 frames
|
||
* fixes some JIT game incompatibilities
|
||
*/
|
||
write_log ("Blitter force-unstuck!\n");
|
||
}
|
||
blitter_stuck = 0;
|
||
if (blit_slowdown > 0 && !currprefs.immediate_blits) {
|
||
eventtab[ev_blitter].active = 1;
|
||
eventtab[ev_blitter].oldcycles = get_cycles ();
|
||
eventtab[ev_blitter].evtime = blit_slowdown * CYCLE_UNIT + get_cycles ();
|
||
blit_slowdown = -1;
|
||
return;
|
||
}
|
||
#ifdef BLITTER_DEBUG
|
||
if (!blitter_dontdo)
|
||
actually_do_blit ();
|
||
else
|
||
bltstate = BLT_done;
|
||
#else
|
||
actually_do_blit ();
|
||
#endif
|
||
blitter_done ();
|
||
}
|
||
|
||
#ifdef CPUEMU_6
|
||
|
||
static uae_u32 preva, prevb;
|
||
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) | preva) >> blt_info.blitdownashift;
|
||
else
|
||
blitahold = (((uae_u32)preva << 16) | bltadat) >> blt_info.blitashift;
|
||
preva = 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 int blitter_doddma (void)
|
||
{
|
||
int wd;
|
||
uae_u16 d;
|
||
|
||
wd = 0;
|
||
if (blit_dmacount2 == 0) {
|
||
d = blitter_doblit ();
|
||
wd = -1;
|
||
} else if (ddat2use) {
|
||
d = ddat2;
|
||
ddat2use = 0;
|
||
wd = 2;
|
||
} else if (ddat1use) {
|
||
d = ddat1;
|
||
ddat1use = 0;
|
||
wd = 1;
|
||
}
|
||
if (wd) {
|
||
chipmem_wput (bltdpt, d);
|
||
bltdpt += blit_add;
|
||
blitter_hcounter2++;
|
||
if (blitter_hcounter2 == blt_info.hblitsize) {
|
||
blitter_hcounter2 = 0;
|
||
bltdpt += blit_modaddd;
|
||
blitter_vcounter2++;
|
||
if (blitter_vcounter2 > blitter_vcounter1)
|
||
blitter_vcounter1 = blitter_vcounter2;
|
||
}
|
||
if (blit_ch == 1)
|
||
blitter_hcounter1 = blitter_hcounter2;
|
||
}
|
||
return wd;
|
||
}
|
||
|
||
STATIC_INLINE void blitter_dodma (unsigned int ch)
|
||
{
|
||
|
||
switch (ch)
|
||
{
|
||
case 1:
|
||
blt_info.bltadat = chipmem_wget (bltapt);
|
||
bltapt += blit_add;
|
||
break;
|
||
case 2:
|
||
blt_info.bltbdat = chipmem_wget (bltbpt);
|
||
bltbpt += blit_add;
|
||
if (blitdesc)
|
||
blt_info.bltbhold = (((uae_u32)blt_info.bltbdat << 16) | prevb) >> blt_info.blitdownbshift;
|
||
else
|
||
blt_info.bltbhold = (((uae_u32)prevb << 16) | blt_info.bltbdat) >> blt_info.blitbshift;
|
||
prevb = blt_info.bltbdat;
|
||
break;
|
||
case 3:
|
||
blt_info.bltcdat = chipmem_wget (bltcpt);
|
||
bltcpt += blit_add;
|
||
break;
|
||
}
|
||
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
|
||
void decide_blitter (unsigned int hpos)
|
||
{
|
||
if (bltstate == BLT_done)
|
||
return;
|
||
#ifdef BLITTER_DEBUG
|
||
if (blitter_delayed_debug) {
|
||
blitter_delayed_debug = 0;
|
||
blitter_dump ();
|
||
}
|
||
#endif
|
||
if (!blitter_cycle_exact)
|
||
return;
|
||
if (blitline) {
|
||
decide_blitter_line (hpos);
|
||
return;
|
||
}
|
||
hpos++;
|
||
if (dmaen (DMA_BLITTER)) {
|
||
while (blit_last_hpos < hpos) {
|
||
int c = channel_state (blit_cyclecounter);
|
||
#ifdef BLITTER_SLOWDOWNDEBUG
|
||
blitter_slowdowndebug--;
|
||
if (blitter_slowdowndebug < 0) {
|
||
cycle_line[blit_last_hpos] |= CYCLE_BLITTER;
|
||
blitter_slowdowndebug = BLITTER_SLOWDOWNDEBUG;
|
||
}
|
||
#endif
|
||
for (;;) {
|
||
int v;
|
||
|
||
if (c == 5) { /* real idle cycle */
|
||
blit_cyclecounter++;
|
||
break;
|
||
}
|
||
|
||
/* all cycles need free bus, even idle cycles (except fillmode idle) */
|
||
v = canblit (blit_last_hpos);
|
||
if (v < 0 && c == 0) {
|
||
blit_cyclecounter++;
|
||
break;
|
||
}
|
||
if (v <= 0) {
|
||
#ifdef BLITTER_DEBUG
|
||
blit_misscyclecounter++;
|
||
#endif
|
||
break;
|
||
}
|
||
|
||
if (c < 0) { /* no channel but bus still needs to be allocated.. */
|
||
cycle_line[blit_last_hpos] |= CYCLE_BLITTER;
|
||
blit_cyclecounter++;
|
||
} else if (c == 4) {
|
||
if (blitter_doddma ()) {
|
||
cycle_line[blit_last_hpos] |= CYCLE_BLITTER;
|
||
blit_cyclecounter++;
|
||
}
|
||
} else if (c) {
|
||
if (blitter_vcounter1 < blt_info.vblitsize) {
|
||
cycle_line[blit_last_hpos] |= CYCLE_BLITTER;
|
||
blitter_dodma (c);
|
||
}
|
||
blit_cyclecounter++;
|
||
} else {
|
||
blit_cyclecounter++;
|
||
/* check if blit with zero channels has ended */
|
||
if (blit_cyclecounter >= blit_maxcyclecounter) {
|
||
blitter_done ();
|
||
return;
|
||
}
|
||
}
|
||
if (blitter_vcounter1 >= blt_info.vblitsize && blitter_vcounter2 >= blt_info.vblitsize) {
|
||
if (!ddat1use && !ddat2use) {
|
||
blitter_done ();
|
||
return;
|
||
}
|
||
if (blit_diag != blit_cycle_diagram_finald) {
|
||
blit_cyclecounter = 0;
|
||
blit_diag = blit_cycle_diagram_finald;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
blit_last_hpos++;
|
||
}
|
||
} else {
|
||
blit_last_hpos = hpos;
|
||
}
|
||
if (blit_last_hpos > maxhpos)
|
||
blit_last_hpos = 0;
|
||
}
|
||
#else
|
||
void decide_blitter (unsigned int hpos) { }
|
||
#endif
|
||
|
||
static void blitter_force_finish (void)
|
||
{
|
||
uae_u16 odmacon;
|
||
if (bltstate == BLT_done)
|
||
return;
|
||
if (bltstate != BLT_done) {
|
||
/* blitter is currently running
|
||
* force finish (no blitter state support yet)
|
||
*/
|
||
odmacon = dmacon;
|
||
dmacon |= DMA_MASTER | DMA_BLITTER;
|
||
write_log ("forcing blitter finish\n");
|
||
#ifdef CPUEMU_6
|
||
if (currprefs.blitter_cycle_exact) {
|
||
int rounds = 10000;
|
||
while (bltstate != BLT_done && rounds > 0) {
|
||
memset (cycle_line, 0, maxhpos);
|
||
decide_blitter (maxhpos);
|
||
rounds--;
|
||
}
|
||
if (rounds == 0)
|
||
write_log ("blitter froze!?\n");
|
||
} else
|
||
#endif
|
||
actually_do_blit ();
|
||
|
||
blitter_done ();
|
||
dmacon = odmacon;
|
||
}
|
||
}
|
||
|
||
static void blit_bltset (unsigned int con)
|
||
{
|
||
int i;
|
||
|
||
blitline = bltcon1 & 1;
|
||
blitfill = bltcon1 & 0x18;
|
||
blitdesc = bltcon1 & 2;
|
||
blit_ch = (bltcon0 & 0x0f00) >> 8;
|
||
|
||
if (blitline) {
|
||
if (blt_info.hblitsize != 2)
|
||
write_log ("weird hblitsize in linemode: %d vsize=%d PC%=%x\n",
|
||
blt_info.hblitsize, blt_info.vblitsize, m68k_getpc (®s));
|
||
blit_diag = blit_cycle_diagram_line;
|
||
} else {
|
||
if (con & 2) {
|
||
blitfc = !!(bltcon1 & 0x4);
|
||
blitife = bltcon1 & 0x8;
|
||
if ((bltcon1 & 0x18) == 0x18) {
|
||
/* Digital "Trash" demo does this; others too. Apparently, no
|
||
* negative effects. */
|
||
static int warn = 1;
|
||
if (warn)
|
||
write_log ("warning: weird fill mode (further messages suppressed) PC=%x\n",
|
||
m68k_getpc (®s));
|
||
warn = 0;
|
||
blitife = 0;
|
||
}
|
||
}
|
||
if (blitfill && !blitdesc) {
|
||
static int warn = 1;
|
||
if (warn)
|
||
write_log ("warning: blitter fill without desc (further messages suppressed) PC=%x\n",
|
||
m68k_getpc (®s));
|
||
warn = 0;
|
||
}
|
||
blit_diag = blitfill ? blit_cycle_diagram_fill[blit_ch] : blit_cycle_diagram[blit_ch];
|
||
}
|
||
if ((bltcon1 & 0x80) && (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
|
||
write_log("warning: BLTCON1 DOFF-bit set\n");
|
||
|
||
ddat1use = ddat2use = 0;
|
||
blit_dmacount = blit_dmacount2 = 0;
|
||
blit_nod = 1;
|
||
for (i = 0; i < blit_diag[1]; i++) {
|
||
int v = blit_diag[2 + i];
|
||
if (v)
|
||
blit_dmacount++;
|
||
if (v > 0 && v < 4)
|
||
blit_dmacount2++;
|
||
if (v == 4)
|
||
blit_nod = 0;
|
||
}
|
||
|
||
blt_info.blitashift = bltcon0 >> 12;
|
||
blt_info.blitdownashift = 16 - blt_info.blitashift;
|
||
blt_info.blitbshift = bltcon1 >> 12;
|
||
blt_info.blitdownbshift = 16 - blt_info.blitbshift;
|
||
}
|
||
|
||
static void blit_modset (void)
|
||
{
|
||
int mult;
|
||
|
||
blit_add = blitdesc ? -2 : 2;
|
||
mult = blitdesc ? -1 : 1;
|
||
blit_modadda = mult * blt_info.bltamod;
|
||
blit_modaddb = mult * blt_info.bltbmod;
|
||
blit_modaddc = mult * blt_info.bltcmod;
|
||
blit_modaddd = mult * blt_info.bltdmod;
|
||
}
|
||
|
||
void reset_blit (unsigned int bltcon)
|
||
{
|
||
if (bltstate == BLT_done)
|
||
return;
|
||
if (bltcon)
|
||
blit_bltset (bltcon);
|
||
blit_modset ();
|
||
}
|
||
|
||
void do_blitter (unsigned int hpos)
|
||
{
|
||
unsigned int cycles;
|
||
#ifdef BLITTER_DEBUG
|
||
enum blitter_states oldstate = bltstate;
|
||
#endif
|
||
|
||
blitter_cycle_exact = currprefs.blitter_cycle_exact;
|
||
blt_info.blitzero = 1;
|
||
bltstate = BLT_init;
|
||
|
||
#ifdef CPUEMU_6
|
||
preva = 0;
|
||
prevb = 0;
|
||
#endif
|
||
|
||
blit_firstline_cycles = blit_first_cycle = get_cycles ();
|
||
#ifdef BLITTER_DEBUG
|
||
blit_misscyclecounter = 0;
|
||
#endif
|
||
blit_last_cycle = 0;
|
||
blit_maxcyclecounter = 0;
|
||
blit_cyclecounter = 0;
|
||
#ifdef CPUEMU_6
|
||
blit_last_hpos = hpos;
|
||
#endif
|
||
|
||
reset_blit (1|2);
|
||
|
||
if (blitline) {
|
||
blitsing = bltcon1 & 0x2;
|
||
blinea = blt_info.bltadat;
|
||
blineb = (blt_info.bltbdat >> blt_info.blitbshift) | (blt_info.bltbdat << (16 - blt_info.blitbshift));
|
||
blitsign = bltcon1 & 0x40;
|
||
blitonedot = 0;
|
||
cycles = blt_info.vblitsize;
|
||
} else {
|
||
blit_firstline_cycles = blit_first_cycle + blit_diag[1] * blt_info.hblitsize * CYCLE_UNIT;
|
||
cycles = blt_info.vblitsize * blt_info.hblitsize;
|
||
}
|
||
|
||
#ifdef BLITTER_DEBUG
|
||
blitter_dontdo = 0;
|
||
if (1) {
|
||
if (oldstate != BLT_done)
|
||
write_log ("blitter was already active!\n");
|
||
write_log("blitstart: v=%03.3d h=%03.3d %dx%d %d (%d) d=%d f=%02.2X n=%d pc=%p l=%d dma=%d\n",
|
||
vpos, hpos, blt_info.hblitsize, blt_info.vblitsize, cycles, blit_ch,
|
||
blitdesc ? 1 : 0, blitfill,
|
||
dmaen(DMA_BLITPRI) ? 1 : 0, m68k_getpc (®s), blitline, dmaen(DMA_BLITTER));
|
||
blitter_dump ();
|
||
}
|
||
#endif
|
||
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)) {
|
||
blitter_done ();
|
||
return;
|
||
}
|
||
|
||
if (dmaen (DMA_BLITTER))
|
||
bltstate = BLT_work;
|
||
|
||
blit_maxcyclecounter = 0x7fffffff;
|
||
|
||
#ifdef CPUEMU_6
|
||
if (currprefs.blitter_cycle_exact) {
|
||
blitter_hcounter1 = blitter_hcounter2 = 0;
|
||
blitter_vcounter1 = blitter_vcounter2 = 0;
|
||
if (blit_nod)
|
||
blitter_vcounter2 = blt_info.vblitsize;
|
||
if (blit_ch == 0)
|
||
blit_maxcyclecounter = blt_info.hblitsize * blt_info.vblitsize;
|
||
return;
|
||
}
|
||
#endif
|
||
|
||
if (currprefs.immediate_blits)
|
||
cycles = 1;
|
||
|
||
eventtab[ev_blitter].active = 1;
|
||
eventtab[ev_blitter].oldcycles = get_cycles ();
|
||
eventtab[ev_blitter].evtime = cycles * blit_diag[1] * CYCLE_UNIT + get_cycles ();
|
||
events_schedule();
|
||
}
|
||
|
||
|
||
void maybe_blit (unsigned int hpos, int hack)
|
||
{
|
||
static int warned;
|
||
|
||
if (bltstate == BLT_done)
|
||
return;
|
||
|
||
if (!warned && dmaen (DMA_BLITTER)) {
|
||
#ifndef BLITTER_DEBUG
|
||
warned = 1;
|
||
#endif
|
||
if (m68k_getpc (®s) < 0xe0000 || m68k_getpc (®s) >= 0x10000000)
|
||
write_log ("warning: Program does not wait for blitter %p vpos=%d tc=%d\n",
|
||
m68k_getpc (®s), vpos, blit_cyclecounter);
|
||
}
|
||
|
||
if (blitter_cycle_exact) {
|
||
decide_blitter (hpos);
|
||
goto end;
|
||
}
|
||
|
||
if (!eventtab[ev_blitter].active)
|
||
write_log ("FOO!!?\n");
|
||
if (hack == 1 && get_cycles() < blit_firstline_cycles)
|
||
goto end;
|
||
|
||
blitter_handler ();
|
||
end:;
|
||
#ifdef BLITTER_DEBUG
|
||
blitter_delayed_debug = 1;
|
||
#endif
|
||
}
|
||
|
||
unsigned int blitnasty (void)
|
||
{
|
||
unsigned int cycles, ccnt;
|
||
if (bltstate == BLT_done)
|
||
return 0;
|
||
if (!dmaen(DMA_BLITTER))
|
||
return 0;
|
||
if ((int)blit_last_cycle >= blit_diag[0] && (int)blit_dmacount == blit_diag[1])
|
||
return 0;
|
||
cycles = (get_cycles () - blit_first_cycle) / CYCLE_UNIT;
|
||
ccnt = 0;
|
||
while (blit_last_cycle < cycles) {
|
||
int c = channel_state (blit_last_cycle++);
|
||
if (!c)
|
||
ccnt++;
|
||
}
|
||
return ccnt;
|
||
}
|
||
|
||
/* very approximate emulation of blitter slowdown caused by bitplane DMA */
|
||
void blitter_slowdown (int ddfstrt, int ddfstop, unsigned int totalcycles, unsigned int freecycles)
|
||
{
|
||
static int oddfstrt, oddfstop;
|
||
static unsigned ototal, ofree;
|
||
static int slow;
|
||
|
||
if (!totalcycles || ddfstrt < 0 || ddfstop < 0)
|
||
return;
|
||
if (ddfstrt != oddfstrt || ddfstop != oddfstop || totalcycles != ototal || ofree != freecycles) {
|
||
int linecycles = ((ddfstop - ddfstrt + totalcycles - 1) / totalcycles) * totalcycles;
|
||
int freelinecycles = ((ddfstop - ddfstrt + totalcycles - 1) / totalcycles) * freecycles;
|
||
int dmacycles = (linecycles * blit_dmacount) / blit_diag[1];
|
||
oddfstrt = ddfstrt;
|
||
oddfstop = ddfstop;
|
||
ototal = totalcycles;
|
||
ofree = freecycles;
|
||
slow = 0;
|
||
if (dmacycles > freelinecycles)
|
||
slow = dmacycles - freelinecycles;
|
||
}
|
||
if (blit_slowdown < 0 || blitline)
|
||
return;
|
||
blit_slowdown += slow;
|
||
#ifdef BLITTER_DEBUG
|
||
blit_misscyclecounter += slow;
|
||
#endif
|
||
}
|
||
|
||
#ifdef SAVESTATE
|
||
|
||
const uae_u8 *restore_blitter (const uae_u8 *src)
|
||
{
|
||
uae_u32 flags = restore_u32 ();
|
||
|
||
bltstate = (flags & 1) ? BLT_init : BLT_done;
|
||
if (flags & 2) {
|
||
write_log ("blitter was force-finished when this statefile was saved\n");
|
||
write_log ("contact the author if restored program freezes\n");
|
||
}
|
||
return src;
|
||
}
|
||
|
||
void restore_blitter_finish (void)
|
||
{
|
||
if (bltstate == BLT_init) {
|
||
write_log ("blitter was started but DMA was inactive during save\n");
|
||
do_blitter (0);
|
||
}
|
||
}
|
||
|
||
uae_u8 *save_blitter (uae_u32 *len, uae_u8 *dstptr)
|
||
{
|
||
uae_u8 *dstbak, *dst;
|
||
int forced;
|
||
|
||
forced = 0;
|
||
if (bltstate != BLT_done && bltstate != BLT_init) {
|
||
write_log ("blitter is active, forcing immediate finish\n");
|
||
/* blitter is active just now but we don't have blitter state support yet */
|
||
blitter_force_finish ();
|
||
forced = 2;
|
||
}
|
||
if (dstptr)
|
||
dstbak = dst = dstptr;
|
||
else
|
||
dstbak = dst = malloc (16);
|
||
save_u32 (((bltstate != BLT_done) ? 0 : 1) | forced);
|
||
*len = dst - dstbak;
|
||
return dstbak;
|
||
}
|
||
|
||
#endif /* SAVESTATE */
|