line draw deferment implemented

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@508 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
notaz 2008-07-01 13:42:12 +00:00
parent 1a65e3b161
commit b6d7ac7090
8 changed files with 120 additions and 99 deletions

View file

@ -39,7 +39,7 @@ static int HighPreSpr[80*2+1]; // slightly preprocessed sprites
int *HighCacheS_ptr;
int rendstatus = 0;
int Scanline = 0; // Scanline
int DrawScanline = 0;
static int SpriteBlocks;
static int skip_next_line=0;
@ -252,7 +252,7 @@ void DrawStripVSRam(struct TileStrip *ts, int plane_sh, int cellskip)
{
int tilex,dx,code=0,addr=0,cell=0;
int oldcode=-1,blank=-1; // The tile we know is blank
int pal=0,scan=Scanline;
int pal=0,scan=DrawScanline;
// Draw tiles across screen:
tilex=(-ts->hscroll)>>3;
@ -387,7 +387,7 @@ static void DrawLayer(int plane_sh, int *hcache, int cellskip, int maxcells)
else ts.nametab=(pvid->reg[2]&0x38)<< 9; // A
htab=pvid->reg[13]<<9; // Horizontal scroll table address
if ( pvid->reg[11]&2) htab+=Scanline<<1; // Offset by line
if ( pvid->reg[11]&2) htab+=DrawScanline<<1; // Offset by line
if ((pvid->reg[11]&1)==0) htab&=~0xf; // Offset by tile
htab+=plane_sh&1; // A or B
@ -399,7 +399,7 @@ static void DrawLayer(int plane_sh, int *hcache, int cellskip, int maxcells)
vscroll=Pico.vsram[plane_sh&1]; // Get vertical scroll value
// Find the line in the name table
ts.line=(vscroll+(Scanline<<1))&((ymask<<1)|1);
ts.line=(vscroll+(DrawScanline<<1))&((ymask<<1)|1);
ts.nametab+=(ts.line>>4)<<shift[width];
DrawStripInterlace(&ts);
@ -412,7 +412,7 @@ static void DrawLayer(int plane_sh, int *hcache, int cellskip, int maxcells)
vscroll=Pico.vsram[plane_sh&1]; // Get vertical scroll value
// Find the line in the name table
ts.line=(vscroll+Scanline)&ymask;
ts.line=(vscroll+DrawScanline)&ymask;
ts.nametab+=(ts.line>>3)<<shift[width];
DrawStrip(&ts, plane_sh, cellskip);
@ -433,12 +433,12 @@ static void DrawWindow(int tstart, int tend, int prio, int sh) // int *hcache
if (pvid->reg[12]&1)
{
nametab=(pvid->reg[3]&0x3c)<<9; // 40-cell mode
nametab+=(Scanline>>3)<<6;
nametab+=(DrawScanline>>3)<<6;
}
else
{
nametab=(pvid->reg[3]&0x3e)<<9; // 32-cell mode
nametab+=(Scanline>>3)<<5;
nametab+=(DrawScanline>>3)<<5;
}
tilex=tstart<<1;
@ -451,7 +451,7 @@ static void DrawWindow(int tstart, int tend, int prio, int sh) // int *hcache
}
tend<<=1;
ty=(Scanline&7)<<1; // Y-Offset into tile
ty=(DrawScanline&7)<<1; // Y-Offset into tile
// Draw tiles across screen:
if (!sh)
@ -643,7 +643,7 @@ static void DrawSprite(int *sprite, int sh, int as)
height=(sy>>24)&7; // Width and height in tiles
sy=(sy<<16)>>16; // Y
row=Scanline-sy; // Row of the sprite we are on
row=DrawScanline-sy; // Row of the sprite we are on
if (code&0x1000) row=(height<<3)-1-row; // Flip Y
@ -699,7 +699,7 @@ static void DrawSpriteInterlace(unsigned int *sprite)
width=(height>>2)&3; height&=3;
width++; height++; // Width and height in tiles
row=(Scanline<<1)-sy; // Row of the sprite we are on
row=(DrawScanline<<1)-sy; // Row of the sprite we are on
code=sprite[1];
sx=((code>>16)&0x1ff)-0x78; // X
@ -731,7 +731,7 @@ static void DrawSpriteInterlace(unsigned int *sprite)
static void DrawAllSpritesInterlace(int *hcache, int maxwidth, int pri, int sh)
{
struct PicoVideo *pvid=&Pico.video;
int i,u,table,link=0,sline=Scanline<<1;
int i,u,table,link=0,sline=DrawScanline<<1;
unsigned int *sprites[80]; // Sprite index
table=pvid->reg[5]&0x7f;
@ -1020,7 +1020,7 @@ static void DrawAllSprites(int *hcache, int maxwidth, int prio, int sh)
int ntiles = 0; // tile counter for sprite limit emulation
int *sprites[40]; // Sprites to draw in fast mode
int max_line_sprites = 20; // 20 sprites, 40 tiles
int *ps, pack, rs = rendstatus, scan = Scanline;
int *ps, pack, rs = rendstatus, scan = DrawScanline;
if (rs & (PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES)) {
//dprintf("PrepareSprites(%i) [%i]", (rs>>4)&1, scan);
@ -1212,7 +1212,7 @@ static void FinalizeLine8bit(int sh)
int len, rs = rendstatus;
static int dirty_count;
if (!sh && !(rs & PDRAW_ACC_SPRITES) && Pico.m.dirtyPal == 1 && Scanline < 222)
if (!sh && !(rs & PDRAW_ACC_SPRITES) && Pico.m.dirtyPal == 1 && DrawScanline < 222)
{
// a hack for mid-frame palette changes
if (!(rs & PDRAW_SONIC_MODE))
@ -1247,14 +1247,14 @@ static void FinalizeLine8bit(int sh)
static void (*FinalizeLine)(int sh) = FinalizeLineBGR444;
// hblank was enabled early during prev line processng -
// it should have been blanked
static void handle_early_blank(int scanline, int sh)
// --------------------------------------------
static void DrawBlankedLine(void)
{
scanline--;
int sh=(Pico.video.reg[0xC]&8)>>3; // shadow/hilight?
if (PicoScanBegin != NULL)
PicoScanBegin(scanline);
PicoScanBegin(DrawScanline);
BackFill(Pico.video.reg[7], sh);
@ -1262,11 +1262,9 @@ static void handle_early_blank(int scanline, int sh)
FinalizeLine(sh);
if (PicoScanEnd != NULL)
PicoScanEnd(scanline);
PicoScanEnd(DrawScanline);
}
// --------------------------------------------
static int DrawDisplay(int sh, int as)
{
struct PicoVideo *pvid=&Pico.video;
@ -1285,8 +1283,8 @@ static int DrawDisplay(int sh, int as)
win=pvid->reg[0x12];
edge=(win&0x1f)<<3;
if (win&0x80) { if (Scanline>=edge) hvwind=1; }
else { if (Scanline< edge) hvwind=1; }
if (win&0x80) { if (DrawScanline>=edge) hvwind=1; }
else { if (DrawScanline< edge) hvwind=1; }
if (!hvwind) { // we might have a vertical window here
win=pvid->reg[0x11];
@ -1327,7 +1325,7 @@ static int DrawDisplay(int sh, int as)
int *c, a, b;
for (a = 0, c = HighCacheA; *c; c++, a++);
for (b = 0, c = HighCacheB; *c; c++, b++);
printf("%i:%03i: a=%i, b=%i\n", Pico.m.frame_count, Scanline, a, b);
printf("%i:%03i: a=%i, b=%i\n", Pico.m.frame_count, DrawScanline, a, b);
}
#endif
@ -1354,24 +1352,19 @@ PICO_INTERNAL void PicoFrameStart(void)
PrepareSprites(1);
skip_next_line=0;
DrawScanline=0;
}
PICO_INTERNAL int PicoLine(int scan)
static void PicoLine(void)
{
int sh, as = 0;
if (skip_next_line>0) { skip_next_line--; return 0; } // skip_next_line rendering lines
if (skip_next_line>0) { skip_next_line--; return; } // skip rendering lines
Scanline=scan;
sh=(Pico.video.reg[0xC]&8)>>3; // shadow/hilight?
if (rendstatus & PDRAW_ACC_SPRITES) as|=1; // accurate sprites
if (rendstatus & PDRAW_EARLY_BLANK) {
if (scan > 0) handle_early_blank(scan, sh);
rendstatus &= ~PDRAW_EARLY_BLANK;
}
if (PicoScanBegin != NULL)
skip_next_line = PicoScanBegin(scan);
skip_next_line = PicoScanBegin(DrawScanline);
// Draw screen:
BackFill(Pico.video.reg[7], sh|as);
@ -1382,11 +1375,32 @@ PICO_INTERNAL int PicoLine(int scan)
FinalizeLine(sh);
if (PicoScanEnd != NULL)
PicoScanEnd(scan);
return 0;
PicoScanEnd(DrawScanline);
}
void PicoDrawSync(int to, int blank_last_line)
{
for (; DrawScanline < to; DrawScanline++)
{
#if !CAN_HANDLE_240_LINES
if (DrawScanline >= 224) break;
#endif
PicoLine();
}
#if !CAN_HANDLE_240_LINES
if (DrawScanline >= 224) DrawScanline = 240, return;
#endif
// last line
if (DrawScanline <= to)
{
if (blank_last_line)
DrawBlankedLine();
else PicoLine();
DrawScanline++;
}
}
void PicoDrawSetColorFormat(int which)
{

View file

@ -11,7 +11,7 @@
.extern Pico
.extern PicoOpt
.extern HighCol
.extern Scanline
.extern DrawScanline
.extern HighSprZ
.extern rendstatus
.extern DrawLineDest
@ -316,7 +316,7 @@ DrawLayer:
ldreqb r12, [r11, #2]
ldrneb r12, [r11, #4]
ldr r2, =Scanline @ trying to make good use of pipeline here
ldr r2, =DrawScanline @ trying to make good use of pipeline here
ldr lr, =(Pico+0x10000) @ lr=Pico.vram
moveq r12, r12, lsl #10
@ -330,7 +330,7 @@ DrawLayer:
mov r4, r8, lsr #8 @ pvid->reg[13]
mov r4, r4, lsl #10 @ htab=pvid->reg[13]<<9; (halfwords)
tst r7, #2
addne r4, r4, r2, lsl #2 @ htab+=Scanline<<1; // Offset by line
addne r4, r4, r2, lsl #2 @ htab+=DrawScanline<<1; // Offset by line
tst r7, #1
biceq r4, r4, #0x1f @ htab&=~0xf; // Offset by tile
add r4, r4, r0, lsl #1 @ htab+=plane
@ -513,7 +513,7 @@ DrawLayer:
bic r8, r8, #0x3fc00000
orr r8, r8, r5, lsl #25 @ r8=(xmask[31:25]|had_output[24]|tilex[21:0])
ldr r4, =Scanline
ldr r4, =DrawScanline
orr r5, r1, r10, lsl #24
ldr r4, [r4]
sub r1, r3, #1
@ -690,7 +690,7 @@ DrawLayer:
movne r7, r7, lsl #5
@ Find the line in the name table
add r2, r7, r2, lsl #22 @ r2=(vscroll+(Scanline<<1))<<21 (11 bits);
add r2, r7, r2, lsl #22 @ r2=(vscroll+(DrawScanline<<1))<<21 (11 bits);
orr r1, r1, #0x80000000
and r2, r2, r1, ror #10 @ &((ymask<<1)|1)<<21;
mov r2, r2, lsr #21
@ -1097,7 +1097,7 @@ DrawSprite:
orr r8, r2, r1, lsl #4
ldr r3, [r0] @ sprite[0]
ldr r7, =Scanline
ldr r7, =DrawScanline
mov r6, r3, lsr #28
sub r6, r6, #1 @ r6=width-1 (inc later)
mov r5, r3, lsr #24
@ -1107,7 +1107,7 @@ DrawSprite:
ldr r7, [r7]
ldr r9, [r0, #4]
sub r7, r7, r4, asr #16 @ r7=row=Scanline-sy
sub r7, r7, r4, asr #16 @ r7=row=DrawScanline-sy
mov r2, r9, asr #16 @ r2=sx
mov r9, r9, lsl #16
@ -1266,7 +1266,7 @@ DrawWindow:
stmfd sp!, {r4-r11,lr}
ldr r11, =(Pico+0x22228) @ Pico.video
ldr r10, =Scanline
ldr r10, =DrawScanline
ldrb r12, [r11, #3] @ pvid->reg[3]
ldr r10, [r10]

View file

@ -424,6 +424,7 @@ static int PicoFrameSimple(void)
if (!(PicoOpt&POPT_ALT_RENDERER))
{
// Draw the screen
#if 0
#if CAN_HANDLE_240_LINES
if (pv->reg[1]&8) {
for (y=0;y<240;y++) PicoLine(y);
@ -432,6 +433,7 @@ static int PicoFrameSimple(void)
}
#else
for (y=0;y<224;y++) PicoLine(y);
#endif
#endif
}
else PicoFrameFull();

View file

@ -167,7 +167,6 @@ void vidConvCpyRGB565(void *to, void *from, int pixels);
#define PDRAW_SONIC_MODE (1<<5) // mid-frame palette changes for 8bit renderer
#define PDRAW_PLANE_HI_PRIO (1<<6) // have layer with all hi prio tiles (mk3)
#define PDRAW_SHHI_DONE (1<<7) // layer sh/hi already processed
#define PDRAW_EARLY_BLANK (1<<8) // blanking enabled at the start of prev line
extern int rendstatus;
extern unsigned short HighPal[0x100];

View file

@ -73,7 +73,7 @@ static int PicoFrameHints(void)
// This is to make active scan longer (needed for Double Dragon 2, mainly)
CPUS_RUN(CYCLES_M68K_ASD, CYCLES_S68K_ASD);
for (y=0;y<lines_vis;y++)
for (y = 0; y < lines_vis; y++)
{
Pico.m.scanline=(short)y;
@ -101,10 +101,9 @@ static int PicoFrameHints(void)
}
// decide if we draw this line
if (!skip)
if (!skip && (PicoOpt & POPT_ALT_RENDERER))
{
if (PicoOpt&POPT_ALT_RENDERER) {
// find the right moment for fast renderer, when display is no longer blanked
// find the right moment for frame renderer, when display is no longer blanked
if ((pv->reg[1]&0x40) || y > 100) {
PicoFrameFull();
#ifdef DRAW_FINISH_FUNC
@ -113,14 +112,6 @@ static int PicoFrameHints(void)
skip = 1;
}
}
else
{
#if !CAN_HANDLE_240_LINES
if (y < 224)
#endif
PicoLine(y);
}
}
#ifndef PICO_CD
// get samples from sound chips
@ -147,10 +138,14 @@ static int PicoFrameHints(void)
#endif
}
#ifdef DRAW_FINISH_FUNC
if (!skip)
{
if (DrawScanline < y)
PicoDrawSync(y - 1, 0);
#ifdef DRAW_FINISH_FUNC
DRAW_FINISH_FUNC();
#endif
}
// V-int line (224 or 240)
Pico.m.scanline=(short)y;
@ -218,7 +213,7 @@ static int PicoFrameHints(void)
// PAL line count might actually be 313 according to Steve Snake, but that would complicate things.
lines = Pico.m.pal ? 312 : 262;
for (y++;y<lines;y++)
for (y++; y < lines; y++)
{
Pico.m.scanline=(short)y;

View file

@ -394,8 +394,9 @@ extern void (*PicoCartUnloadHook)(void);
int CM_compareRun(int cyc, int is_sub);
// Draw.c
PICO_INTERNAL int PicoLine(int scan);
PICO_INTERNAL void PicoFrameStart(void);
void PicoDrawSync(int to, int blank_last_line);
extern int DrawScanline;
// Draw2.c
PICO_INTERNAL void PicoFrameFull();

View file

@ -323,14 +323,32 @@ static void CommandChange(void)
if (cmd&0x80) CommandDma();
}
static __inline void DrawSync(int blank_on)
{
if (Pico.m.scanline < 224 && !(PicoOpt & POPT_ALT_RENDERER) &&
!PicoSkipFrame && DrawScanline <= Pico.m.scanline) {
elprintf(EL_ANOMALY, "sync");
PicoDrawSync(Pico.m.scanline, blank_on);
}
}
PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d)
{
struct PicoVideo *pvid=&Pico.video;
if (Pico.m.scanline < 224)
elprintf(EL_STATUS, "PicoVideoWrite [%06x] %04x", a, d);
a&=0x1c;
if (a==0x00) // Data port 0 or 2
{
// try avoiding the sync..
if (Pico.m.scanline < 224 && (pvid->reg[1]&0x40) &&
!(!pvid->pending &&
((pvid->command & 0xc00000f0) == 0x40000010 && Pico.vsram[pvid->addr>>1] == d))
)
DrawSync(0);
if (pvid->pending) {
CommandChange();
pvid->pending=0;
@ -344,7 +362,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d)
else
{
// preliminary FIFO emulation for Chaos Engine, The (E)
if(!(pvid->status&8) && (pvid->reg[1]&0x40) && Pico.m.scanline!=-1 && !(PicoOpt&POPT_DIS_VDP_FIFO)) // active display, accurate mode?
if (!(pvid->status&8) && (pvid->reg[1]&0x40) && Pico.m.scanline!=-1 && !(PicoOpt&POPT_DIS_VDP_FIFO)) // active display, accurate mode?
{
pvid->status&=~0x200; // FIFO no longer empty
pvid->lwrite_cnt++;
@ -362,8 +380,9 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d)
if (a==0x04) // Control (command) port 4 or 6
{
if(pvid->pending)
if (pvid->pending)
{
if (d & 0x80) DrawSync(0); // only need sync for DMA
// Low word of command:
pvid->command&=0xffff0000;
pvid->command|=d;
@ -377,24 +396,26 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d)
// Register write:
int num=(d>>8)&0x1f;
int dold=pvid->reg[num];
int update_irq = 0, blank_on = 0;
pvid->type=0; // register writes clear command (else no Sega logo in Golden Axe II)
if (num > 0x0a && !(pvid->reg[1]&4)) {
elprintf(EL_ANOMALY, "%02x written to reg %02x in SMS mode @ %06x", d, num, SekPc);
return;
} else
pvid->reg[num]=(unsigned char)d;
}
switch (num)
{
case 0x00:
elprintf(EL_INTSW, "hint_onoff: %i->%i [%i] pend=%i @ %06x", (dold&0x10)>>4,
(d&0x10)>>4, SekCyclesDone(), (pvid->pending_ints&0x10)>>4, SekPc);
goto update_irq;
update_irq = 1;
break;
case 0x01:
elprintf(EL_INTSW, "vint_onoff: %i->%i [%i] pend=%i @ %06x", (dold&0x20)>>5,
(d&0x20)>>5, SekCyclesDone(), (pvid->pending_ints&0x20)>>5, SekPc);
if (!(d&0x40) && SekCyclesLeft > 390) rendstatus |= PDRAW_EARLY_BLANK;
goto update_irq;
if (!(d&0x40) && SekCyclesLeft > 390) blank_on = 1;
update_irq = 1;
break;
case 0x05:
if (d^dold) rendstatus |= PDRAW_SPRITES_MOVED;
break;
@ -403,21 +424,19 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d)
if ((d^dold)&8) Pico.m.dirtyPal = 2;
break;
}
return;
DrawSync(blank_on);
pvid->reg[num]=(unsigned char)d;
if (!update_irq) return;
update_irq:;
#ifndef EMU_CORE_DEBUG
// update IRQ level (Lemmings, Wiz 'n' Liz intro, ... )
// may break if done improperly:
// International Superstar Soccer Deluxe (crash), Street Racer (logos), Burning Force (gfx),
// Fatal Rewind (crash), Sesame Street Counting Cafe
// update IRQ level
if (!SekShouldInterrupt) // hack
{
int lines, pints, irq=0;
lines = (pvid->reg[1] & 0x20) | (pvid->reg[0] & 0x10);
pints = (pvid->pending_ints&lines);
if(pints & 0x20) irq = 6;
else if(pints & 0x10) irq = 4;
if (pints & 0x20) irq = 6;
else if (pints & 0x10) irq = 4;
SekInterrupt(irq); // update line
if (irq && Pico.m.scanline!=-1) SekEndRun(24); // make it delayed
@ -437,20 +456,17 @@ update_irq:;
PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a)
{
unsigned int d=0;
a&=0x1c;
if (a==0x00) // data port
{
d=VideoRead();
goto end;
return VideoRead();
}
if (a==0x04) // control port
{
struct PicoVideo *pv=&Pico.video;
unsigned int d;
d=pv->status;
if (PicoOpt&POPT_ALT_RENDERER) d|=0x0020; // sprite collision (Shadow of the Beast)
if (!(pv->reg[1]&0x40)) d|=0x0008; // set V-Blank if display is disabled
@ -462,7 +478,7 @@ PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a)
pv->pending=0; // ctrl port reads clear write-pending flag (Charles MacDonald)
elprintf(EL_SR, "SR read: %04x @ %06x", d, SekPc);
goto end;
return d;
}
// H-counter info (based on Generator):
@ -482,9 +498,10 @@ PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a)
// check: Sonic 3D Blast bonus, Cannon Fodder, Chase HQ II, 3 Ninjas kick back, Road Rash 3, Skitchin', Wheel of Fortune
if ((a&0x1c)==0x08)
{
unsigned int hc;
unsigned int hc, d;
if(Pico.m.scanline != -1) {
if (Pico.m.scanline != -1)
{
int lineCycles=(488-SekCyclesLeft)&0x1ff;
d=Pico.m.scanline; // V-Counter
@ -500,9 +517,9 @@ PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a)
}
if(Pico.m.pal) {
if(d >= 0x103) d-=56; // based on Gens
if (d >= 0x103) d-=56; // based on Gens
} else {
if(d >= 0xEB) d-=6;
if (d >= 0xEB) d-=6;
}
if((Pico.video.reg[12]&6) == 6) {
@ -514,10 +531,8 @@ PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a)
elprintf(EL_HVCNT, "hv: %02x %02x (%i) @ %06x", hc, d, SekCyclesDone(), SekPc);
d&=0xff; d<<=8;
d|=hc;
goto end;
return d;
}
end:
return d;
return 0;
}

View file

@ -1833,12 +1833,7 @@ int YM2612Write_(unsigned int a, unsigned int v)
ret = OPNWriteReg(addr, v);
break;
}
/*
if(ret) {
extern int Scanline;
dprintf("ymw [%i]", Scanline);
}
*/
return ret;
}