From f55fb31463df75097dfde7891a1baa8baf802876 Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 20 Jan 2021 20:49:04 +0100 Subject: [PATCH] vdp renderer, improvements for 8bit fast improved 240 lines support, add setting buffer width, structural improvements --- Makefile | 2 +- pico/32x/32x.c | 2 +- pico/draw.c | 5 +- pico/draw2.c | 239 ++++++++++++++++++++++++++++-------------------- pico/pico.h | 3 +- pico/pico_int.h | 4 +- 6 files changed, 152 insertions(+), 103 deletions(-) diff --git a/Makefile b/Makefile index 7dcb1ff7..a88e8978 100644 --- a/Makefile +++ b/Makefile @@ -167,7 +167,7 @@ PLATFORM_MP3 = 1 PLATFORM_ZLIB = 1 endif ifeq "$(PLATFORM)" "psp" -CFLAGS += -DUSE_BGR565 -DDRAW2_OVERRIDE_LINE_WIDTH=512 -G8 # -DLPRINTF_STDIO -DFW15 +CFLAGS += -DUSE_BGR565 -G8 # -DLPRINTF_STDIO -DFW15 LDFLAGS := $(filter-out -lpsp%, $(LDFLAGS)) # collides with PSP image generation LDLIBS += -lpspnet_inet -lpspgu -lpspge -lpsppower -lpspaudio -lpspdisplay LDLIBS += -lpspaudiocodec -lpsprtc -lpspctrl -lpspsdk -lpspuser -lpspkernel diff --git a/pico/32x/32x.c b/pico/32x/32x.c index f19dbd58..b91310a9 100644 --- a/pico/32x/32x.c +++ b/pico/32x/32x.c @@ -224,7 +224,7 @@ static void p32x_start_blank(void) pprof_start(draw); offs = 8; lines = 224; - if ((Pico.video.reg[1] & 8) && !(PicoIn.opt & POPT_ALT_RENDERER)) { + if (Pico.video.reg[1] & 8) { offs = 0; lines = 240; } diff --git a/pico/draw.c b/pico/draw.c index deb23f9b..ce4fe1c3 100644 --- a/pico/draw.c +++ b/pico/draw.c @@ -1840,6 +1840,7 @@ PICO_INTERNAL void PicoFrameStart(void) if (!(Pico.video.reg[12] & 1)) Pico.est.rendstatus |= PDRAW_32_COLS; if (Pico.video.reg[1] & 8) { + Pico.est.rendstatus |= PDRAW_30_ROWS; offs = 0; lines = 240; } @@ -1984,7 +1985,7 @@ void PicoDrawSetOutFormat(pdso_t which, int use_32x_line_mode) { PicoDrawSetInternalBuf(NULL, 0); PicoDrawSetOutBufMD(NULL, 0); - PicoDraw2SetOutBuf(NULL); + PicoDraw2SetOutBuf(NULL, 0); switch (which) { case PDF_8BIT: @@ -2016,7 +2017,7 @@ void PicoDrawSetOutBufMD(void *dest, int increment) // kludge for no-copy mode, using ALT_RENDERER layout PicoDrawSetInternalBuf(dest, increment); } else if (FinalizeLine == NULL) { - PicoDraw2SetOutBuf(dest); + PicoDraw2SetOutBuf(dest, increment); } else if (dest != NULL) { DrawLineDestBase = dest; DrawLineDestIncrement = increment; diff --git a/pico/draw2.c b/pico/draw2.c index a1adaeea..9d65ea54 100644 --- a/pico/draw2.c +++ b/pico/draw2.c @@ -23,7 +23,7 @@ #define LINE_WIDTH 328 #endif -static unsigned char PicoDraw2FB_[(8+320) * (8+240+8) + 8]; +static unsigned char PicoDraw2FB_[LINE_WIDTH * (8+240+8) + 8]; static u32 HighCache2A[2*41*(TILE_ROWS+1)+1+1]; // caches for high layers static u32 HighCache2B[2*41*(TILE_ROWS+1)+1+1]; @@ -43,16 +43,17 @@ void DrawSpriteFull(unsigned int *sprite, struct PicoEState *est); #else -static int TileXnormYnorm(unsigned char *pd,int addr,unsigned char pal, struct PicoVideo *pvid) +static int TileXnormYnorm(unsigned char *pd,int addr,unsigned char pal, struct PicoEState *est) { unsigned int pack=0; unsigned int t=0, blank = 1; + unsigned short *vram = est->PicoMem_vram; int i, inc=2; #if INTERLACE - if ((pvid->reg[12]&6) == 6) inc = 4; + if (est->rendstatus & PDRAW_INTERLACE) inc = 4; #endif - for(i=8; i; i--, addr+=inc, pd += LINE_WIDTH) { - pack=*(u32 *)(PicoMem.vram+addr); // Get 8 pixels + for(i=8; i; i--, addr+=inc, pd += est->Draw2Width) { + pack=*(u32 *)(vram+addr); // Get 8 pixels if(!pack) continue; t=pack&0x0000f000; if (t) pd[0]=(unsigned char)((t>>12)|pal); @@ -69,16 +70,17 @@ static int TileXnormYnorm(unsigned char *pd,int addr,unsigned char pal, struct P return blank; // Tile blank? } -static int TileXflipYnorm(unsigned char *pd,int addr,unsigned char pal, struct PicoVideo *pvid) +static int TileXflipYnorm(unsigned char *pd,int addr,unsigned char pal, struct PicoEState *est) { unsigned int pack=0; unsigned int t=0, blank = 1; + unsigned short *vram = est->PicoMem_vram; int i, inc=2; #if INTERLACE - if ((pvid->reg[12]&6) == 6) inc = 4; + if (est->rendstatus & PDRAW_INTERLACE) inc = 4; #endif - for(i=8; i; i--, addr+=inc, pd += LINE_WIDTH) { - pack=*(u32 *)(PicoMem.vram+addr); // Get 8 pixels + for(i=8; i; i--, addr+=inc, pd += est->Draw2Width) { + pack=*(u32 *)(vram+addr); // Get 8 pixels if(!pack) continue; t=pack&0x000f0000; if (t) pd[0]=(unsigned char)((t>>16)|pal); @@ -94,17 +96,18 @@ static int TileXflipYnorm(unsigned char *pd,int addr,unsigned char pal, struct P return blank; // Tile blank? } -static int TileXnormYflip(unsigned char *pd,int addr,unsigned char pal, struct PicoVideo *pvid) +static int TileXnormYflip(unsigned char *pd,int addr,unsigned char pal, struct PicoEState *est) { unsigned int pack=0; unsigned int t=0, blank = 1; + unsigned short *vram = est->PicoMem_vram; int i, inc=2; #if INTERLACE - if ((pvid->reg[12]&6) == 6) inc = 4, addr += 16; + if (est->rendstatus & PDRAW_INTERLACE) inc = 4, addr += 16; #endif addr+=14; - for(i=8; i; i--, addr-=inc, pd += LINE_WIDTH) { - pack=*(u32 *)(PicoMem.vram+addr); // Get 8 pixels + for(i=8; i; i--, addr-=inc, pd += est->Draw2Width) { + pack=*(u32 *)(vram+addr); // Get 8 pixels if(!pack) continue; t=pack&0x0000f000; if (t) pd[0]=(unsigned char)((t>>12)|pal); @@ -121,17 +124,18 @@ static int TileXnormYflip(unsigned char *pd,int addr,unsigned char pal, struct P return blank; // Tile blank? } -static int TileXflipYflip(unsigned char *pd,int addr,unsigned char pal, struct PicoVideo *pvid) +static int TileXflipYflip(unsigned char *pd,int addr,unsigned char pal, struct PicoEState *est) { unsigned int pack=0; unsigned int t=0, blank = 1; + unsigned short *vram = est->PicoMem_vram; int i, inc=2; #if INTERLACE - if ((pvid->reg[12]&6) == 6) inc = 4, addr += 16; + if (est->rendstatus & PDRAW_INTERLACE) inc = 4, addr += 16; #endif addr+=14; - for(i=8; i; i--, addr-=inc, pd += LINE_WIDTH) { - pack=*(u32 *)(PicoMem.vram+addr); // Get 8 pixels + for(i=8; i; i--, addr-=inc, pd += est->Draw2Width) { + pack=*(u32 *)(vram+addr); // Get 8 pixels if(!pack) continue; t=pack&0x000f0000; if (t) pd[0]=(unsigned char)((t>>16)|pal); @@ -151,9 +155,10 @@ static int TileXflipYflip(unsigned char *pd,int addr,unsigned char pal, struct P // start: (tile_start<<16)|row_start, end: [same] static void DrawWindowFull(int start, int end, int prio, struct PicoEState *est) { - struct PicoVideo *pvid=&Pico.video; + struct PicoVideo *pvid=&est->Pico->video; int nametab, nametab_step, trow, tilex, blank=-1, code; unsigned char *scrpos = est->Draw2FB; + int scrstart = est->Draw2Start; int tile_start, tile_end; // in cells // parse ranges @@ -172,17 +177,17 @@ static void DrawWindowFull(int start, int end, int prio, struct PicoEState *est) { nametab=(pvid->reg[3]&0x3e)<<9; // 32-cell mode nametab_step = 1<<5; - if (!(PicoIn.opt&POPT_DIS_32C_BORDER)) + if (est->rendstatus & PDRAW_BORDER_32) scrpos += 32; } - nametab += nametab_step*start; + nametab += nametab_step*(start-scrstart); // check priority code=PicoMem.vram[nametab+tile_start]; if ((code>>15) != prio) return; // hack: just assume that whole window uses same priority - scrpos+=8*LINE_WIDTH+8; - scrpos+=8*LINE_WIDTH*(start-START_ROW); + scrpos+=8*est->Draw2Width+8; + scrpos+=8*est->Draw2Width*(start-scrstart); // do a window until we reach planestart row for(trow = start; trow < end; trow++, nametab+=nametab_step) { // current tile row @@ -196,21 +201,26 @@ static void DrawWindowFull(int start, int end, int prio, struct PicoEState *est) if (code==blank) continue; // Get tile address/2: - addr=(code&0x7ff)<<4; +#if INTERLACE + if (est->rendstatus & PDRAW_INTERLACE) + addr=(code&0x3ff)<<5; + else +#endif + addr=(code&0x7ff)<<4; // pal=PicoCramHigh+((code>>9)&0x30); pal=(unsigned char)((code>>9)&0x30); switch((code>>11)&3) { - case 0: zero=TileXnormYnorm(scrpos+(tilex<<3),addr,pal,pvid); break; - case 1: zero=TileXflipYnorm(scrpos+(tilex<<3),addr,pal,pvid); break; - case 2: zero=TileXnormYflip(scrpos+(tilex<<3),addr,pal,pvid); break; - case 3: zero=TileXflipYflip(scrpos+(tilex<<3),addr,pal,pvid); break; + case 0: zero=TileXnormYnorm(scrpos+(tilex<<3),addr,pal,est); break; + case 1: zero=TileXflipYnorm(scrpos+(tilex<<3),addr,pal,est); break; + case 2: zero=TileXnormYflip(scrpos+(tilex<<3),addr,pal,est); break; + case 3: zero=TileXflipYflip(scrpos+(tilex<<3),addr,pal,est); break; } if(zero) blank=code; // We know this tile is blank now } - scrpos += LINE_WIDTH*8; + scrpos += est->Draw2Width*8; } } @@ -218,11 +228,12 @@ static void DrawWindowFull(int start, int end, int prio, struct PicoEState *est) static void DrawLayerFull(int plane, u32 *hcache, int planestart, int planeend, struct PicoEState *est) { - struct PicoVideo *pvid=&Pico.video; + struct PicoVideo *pvid=&est->Pico->video; static char shift[4]={5,6,5,7}; // 32,64 or 128 sized tilemaps int width, height, ymask, htab; int nametab, hscroll=0, vscroll, cells; unsigned char *scrpos; + int scrstart = est->Draw2Start; int blank=-1, xmask, nametab_row, trow; // parse ranges @@ -257,9 +268,9 @@ static void DrawLayerFull(int plane, u32 *hcache, int planestart, int planeend, else nametab=(pvid->reg[4]&0x07)<<12; // B scrpos = est->Draw2FB; - if (!(pvid->reg[12]&1) && !(PicoIn.opt&POPT_DIS_32C_BORDER)) + if (est->rendstatus & PDRAW_BORDER_32) scrpos += 32; - scrpos+=8*LINE_WIDTH*(planestart-START_ROW); + scrpos+=8*est->Draw2Width*(planestart-scrstart); if((pvid->reg[11]&4)||(PicoMem.vsram[plane]&7)) planeend++; // we (may) have vertically clipped tiles due to vscroll, so we need 1 more row @@ -273,7 +284,8 @@ static void DrawLayerFull(int plane, u32 *hcache, int planestart, int planeend, vscroll=PicoMem.vsram[plane+0x20];//&0x1ff; #endif #if INTERLACE - if ((pvid->reg[12]&6) == 6) vscroll >>= 1; + if (est->rendstatus & PDRAW_INTERLACE) + vscroll >>= 1; #endif nametab_row = nametab + (((trow+(vscroll>>3))&ymask)<reg[11]&4) && !(vsidx&1)) { // 2-cell mode vscroll=PicoMem.vsram[vsidx+plane];//&0x1ff; #if INTERLACE - if ((pvid->reg[12]&6) == 6) vscroll >>= 1; + if (est->rendstatus & PDRAW_INTERLACE) + vscroll >>= 1; #endif nametab_row = nametab + (((trow+(vscroll>>3))&ymask)<reg[12]&6) == 6) - addr=(code&0x3ff)<<5; - else + if (est->rendstatus & PDRAW_INTERLACE) + addr=(code&0x3ff)<<5; + else #endif - addr=(code&0x7ff)<<4; + addr=(code&0x7ff)<<4; // pal=PicoCramHigh+((code>>9)&0x30); pal=(unsigned char)((code>>9)&0x30); - scroff=(8-(vscroll&7))*LINE_WIDTH; + scroff=(8-(vscroll&7))*est->Draw2Width; switch((code>>11)&3) { - case 0: zero=TileXnormYnorm(scrpos+scroff+dx,addr,pal,pvid); break; - case 1: zero=TileXflipYnorm(scrpos+scroff+dx,addr,pal,pvid); break; - case 2: zero=TileXnormYflip(scrpos+scroff+dx,addr,pal,pvid); break; - case 3: zero=TileXflipYflip(scrpos+scroff+dx,addr,pal,pvid); break; + case 0: zero=TileXnormYnorm(scrpos+scroff+dx,addr,pal,est); break; + case 1: zero=TileXflipYnorm(scrpos+scroff+dx,addr,pal,est); break; + case 2: zero=TileXnormYflip(scrpos+scroff+dx,addr,pal,est); break; + case 3: zero=TileXflipYflip(scrpos+scroff+dx,addr,pal,est); break; } if(zero) blank=code; // We know this tile is blank now } - scrpos += LINE_WIDTH*8; + scrpos += est->Draw2Width*8; } *hcache = 0; // terminate cache @@ -356,35 +369,36 @@ static void DrawTilesFromCacheF(u32 *hc, struct PicoEState *est) unsigned char pal; short blank=-1; // The tile we know is blank unsigned char *scrpos = est->Draw2FB, *pd = 0; + int scrstart = est->Draw2Start; - if (!(Pico.video.reg[12]&1) && !(PicoIn.opt&POPT_DIS_32C_BORDER)) + if (est->rendstatus & PDRAW_BORDER_32) scrpos += 32; while((code=*hc++)) { - vscroll=(*hc++)*LINE_WIDTH - START_ROW*LINE_WIDTH*8; + vscroll=(*hc++ - START_ROW*8)*est->Draw2Width; if((short)code == blank) continue; // y pos if(((unsigned)code>>27) != prevy) { prevy = (unsigned)code>>27; - pd = scrpos + prevy*LINE_WIDTH*8; + pd = scrpos + (prevy-scrstart)*est->Draw2Width*8; } // Get tile address/2: #if INTERLACE - if ((Pico.video.reg[12]&6) == 6) - addr=(code&0x3ff)<<5; + if (est->rendstatus & PDRAW_INTERLACE) + addr=(code&0x3ff)<<5; else #endif - addr=(code&0x7ff)<<4; + addr=(code&0x7ff)<<4; // pal=PicoCramHigh+((code>>9)&0x30); pal=(unsigned char)((code>>9)&0x30); switch((code>>11)&3) { - case 0: zero=TileXnormYnorm(pd+vscroll+((code>>16)&0x1ff),addr,pal,&Pico.video); break; - case 1: zero=TileXflipYnorm(pd+vscroll+((code>>16)&0x1ff),addr,pal,&Pico.video); break; - case 2: zero=TileXnormYflip(pd+vscroll+((code>>16)&0x1ff),addr,pal,&Pico.video); break; - case 3: zero=TileXflipYflip(pd+vscroll+((code>>16)&0x1ff),addr,pal,&Pico.video); break; + case 0: zero=TileXnormYnorm(pd+vscroll+((code>>16)&0x1ff),addr,pal,est); break; + case 1: zero=TileXflipYnorm(pd+vscroll+((code>>16)&0x1ff),addr,pal,est); break; + case 2: zero=TileXnormYflip(pd+vscroll+((code>>16)&0x1ff),addr,pal,est); break; + case 3: zero=TileXflipYflip(pd+vscroll+((code>>16)&0x1ff),addr,pal,est); break; } if(zero) blank=(short)code; @@ -400,16 +414,17 @@ static void DrawSpriteFull(unsigned int *sprite, struct PicoEState *est) unsigned char pal; int tile,code,tdeltax,tdeltay; unsigned char *scrpos; + int scrstart = est->Draw2Start; int sx, sy; sy=sprite[0]; height=sy>>24; #if INTERLACE - if ((Pico.video.reg[12]&6) == 6) - sy = ((sy>>1)&0x1ff)-0x78; + if (est->rendstatus & PDRAW_INTERLACE) + sy = ((sy>>1)&0x1ff)-0x78; else #endif - sy=(sy&0x1ff)-0x78; // Y + sy=(sy&0x1ff)-0x78; // Y width=(height>>2)&3; height&=3; width++; height++; // Width and height in tiles @@ -427,19 +442,18 @@ static void DrawSpriteFull(unsigned int *sprite, struct PicoEState *est) pal=(unsigned char)((code>>9)&0x30); // goto first vertically visible tile - while(sy <= START_ROW*8) { sy+=8; tile+=tdeltay; height--; } + while(sy <= scrstart*8) { sy+=8; tile+=tdeltay; height--; } scrpos = est->Draw2FB; - if (!(Pico.video.reg[12]&1) && !(PicoIn.opt&POPT_DIS_32C_BORDER)) + if (est->rendstatus&PDRAW_BORDER_32) scrpos += 32; - scrpos+=(sy-START_ROW*8)*LINE_WIDTH; + scrpos+=(sy-scrstart*8)*est->Draw2Width; for (; height > 0; height--, sy+=8, tile+=tdeltay) { - int w = width, x=sx, t=tile; - int s=4; + int w = width, x=sx, t=tile, s; - if(sy >= END_ROW*8+8) return; // offscreen + if((sy-scrstart*8) >= END_ROW*8+8) return; // offscreen for (; w; w--,x+=8,t+=tdeltax) { @@ -448,30 +462,36 @@ static void DrawSpriteFull(unsigned int *sprite, struct PicoEState *est) t&=0x7fff; // Clip tile address #if INTERLACE - if ((Pico.video.reg[12]&6) == 6) s=5; + if (est->rendstatus & PDRAW_INTERLACE) + s=5; + else #endif + s=4; switch((code>>11)&3) { - case 0: TileXnormYnorm(scrpos+x,t<Draw2Width; } } #endif -static void DrawAllSpritesFull(int prio, int maxwidth) +static void DrawAllSpritesFull(int prio, int maxwidth, struct PicoEState *est) { - struct PicoVideo *pvid=&Pico.video; + struct PicoVideo *pvid=&est->Pico->video; int table=0,maskrange=0; int i,u,link=0; unsigned int *sprites[80]; // Sprites int y_min=START_ROW*8, y_max=END_ROW*8; // for a simple sprite masking - int max_sprites = Pico.video.reg[12]&1 ? 80 : 64; + int max_sprites = pvid->reg[12]&1 ? 80 : 64; + + if (est->rendstatus & PDRAW_30_ROWS) + y_min += 8, y_max += 8; table=pvid->reg[5]&0x7f; if (pvid->reg[12]&1) table&=0x7e; // Lowest bit 0 in 40-cell mode @@ -489,11 +509,11 @@ static void DrawAllSpritesFull(int prio, int maxwidth) // check if it is not hidden vertically #if INTERLACE - if ((pvid->reg[12]&6) == 6) - sy = ((code>>1)&0x1ff)-0x80; + if (est->rendstatus & PDRAW_INTERLACE) + sy = ((code>>1)&0x1ff)-0x80; else #endif - sy = (code&0x1ff)-0x80; + sy = (code&0x1ff)-0x80; height = (((code>>24)&3)+1)<<3; if(sy+height <= y_min || sy > y_max) goto nextsprite; @@ -534,7 +554,7 @@ static void DrawAllSpritesFull(int prio, int maxwidth) // Go through sprites backwards: for (i--; i >= 0; i--) { - DrawSpriteFull(sprites[i], &Pico.est); + DrawSpriteFull(sprites[i], est); } } @@ -548,24 +568,34 @@ static void BackFillFull(void *dst, int reg7) back|=back<<8; back|=back<<16; - memset32(dst, back, LINE_WIDTH*(8+(END_ROW-START_ROW)*8)/4); + memset32(dst, back, Pico.est.Draw2Width*(8+(END_ROW-START_ROW)*8)/4); } #endif static void DrawDisplayFull(void) { struct PicoEState *est = &Pico.est; - struct PicoVideo *pvid=&Pico.video; + struct PicoVideo *pvid=&est->Pico->video; int win, edge=0, hvwin=0; // LSb->MSb: hwin&plane, vwin&plane, full - int planestart=START_ROW, planeend=END_ROW; // plane A start/end when window shares display with plane A (in tile rows or columns) - int winstart=START_ROW, winend=END_ROW; // same for window + int scrstart=START_ROW, scrend = END_ROW; // our render area + int planestart, planeend; // plane A start/end when window shares display with plane A (in tile rows or columns) + int winstart, winend; // same for window int maxw, maxcolc; // max width and col cells - if(pvid->reg[12]&1) { - maxw = 328; maxcolc = 40; - } else { + if(est->rendstatus & PDRAW_32_COLS) { maxw = 264; maxcolc = 32; + } else { + maxw = 328; maxcolc = 40; + } + if(est->rendstatus & PDRAW_30_ROWS) { + // In 240 line mode, the top and bottom 8 lines are omitted + // since this renderer always renderers 224 lines + scrstart ++, scrend ++; } + est->Draw2Start = scrstart; + + planestart = scrstart, planeend = scrend; + winstart = scrstart, winend = scrend; // 32C border for centering? (for asm) est->rendstatus &= ~PDRAW_BORDER_32; @@ -582,12 +612,12 @@ static void DrawDisplayFull(void) hvwin=4; } else if(win < 0x80) { // window on the top - if(edge <= START_ROW) hvwin=0; // window not visible in our drawing region - else if(edge >= END_ROW) hvwin=4; + if(edge <= scrstart) hvwin=0; // window not visible in our drawing region + else if(edge >= scrend) hvwin=4; else planestart = winend = edge; } else if(win > 0x80) { // window at the bottom - if(edge >= END_ROW) hvwin=0; + if(edge >= scrend) hvwin=0; else planeend = winstart = edge; } } @@ -622,19 +652,19 @@ static void DrawDisplayFull(void) HighCache2A[0] = HighCache2B[0] = 0; if (!(pvid->debug_p & PVD_KILL_B)) - DrawLayerFull(1, HighCache2B, START_ROW, (maxcolc<<16)|END_ROW, est); + DrawLayerFull(1, HighCache2B, scrstart, (maxcolc<<16)|scrend, est); if (!(pvid->debug_p & PVD_KILL_A)) switch (hvwin) { case 4: // fullscreen window - DrawWindowFull(START_ROW, (maxcolc<<16)|END_ROW, 0, est); + DrawWindowFull(scrstart, (maxcolc<<16)|scrend, 0, est); break; case 3: // we have plane A and both v and h windows DrawLayerFull(0, HighCache2A, planestart, planeend, est); DrawWindowFull( winstart&~0xff0000, (winend&~0xff0000)|(maxcolc<<16), 0, est); // h - DrawWindowFull((winstart&~0xff)|START_ROW, (winend&~0xff)|END_ROW, 0, est); // v + DrawWindowFull((winstart&~0xff)|scrstart, (winend&~0xff)|scrend, 0, est); // v break; case 2: @@ -646,11 +676,11 @@ static void DrawDisplayFull(void) default: // fullscreen plane A - DrawLayerFull(0, HighCache2A, START_ROW, (maxcolc<<16)|END_ROW, est); + DrawLayerFull(0, HighCache2A, scrstart, (maxcolc<<16)|scrend, est); break; } if (!(pvid->debug_p & PVD_KILL_S_LO)) - DrawAllSpritesFull(0, maxw); + DrawAllSpritesFull(0, maxw, est); if (HighCache2B[0]) DrawTilesFromCacheF(HighCache2B, est); if (HighCache2A[0]) DrawTilesFromCacheF(HighCache2A, est); @@ -658,13 +688,13 @@ static void DrawDisplayFull(void) { case 4: // fullscreen window - DrawWindowFull(START_ROW, (maxcolc<<16)|END_ROW, 1, est); + DrawWindowFull(scrstart, (maxcolc<<16)|scrend, 1, est); break; case 3: // we have plane A and both v and h windows DrawWindowFull( winstart&~0xff0000, (winend&~0xff0000)|(maxcolc<<16), 1, est); // h - DrawWindowFull((winstart&~0xff)|START_ROW, (winend&~0xff)|END_ROW, 1, est); // v + DrawWindowFull((winstart&~0xff)|scrstart, (winend&~0xff)|scrend, 1, est); // v break; case 2: @@ -674,7 +704,7 @@ static void DrawDisplayFull(void) break; } if (!(pvid->debug_p & PVD_KILL_S_HI)) - DrawAllSpritesFull(1, maxw); + DrawAllSpritesFull(1, maxw, est); } @@ -690,18 +720,33 @@ PICO_INTERNAL void PicoFrameFull() if (Pico.video.reg[1] & 0x40) DrawDisplayFull(); + // clear top and bottom 8 lines in 240 mode, since draw2 only does 224 + if (Pico.est.rendstatus & PDRAW_30_ROWS) { + unsigned char *pd = Pico.est.Draw2FB; + int i; + + for (i = 8; i > 0; i--, pd += Pico.est.Draw2Width) + memset32((int *)pd, 0xe0e0e0e0, 328/4); + pd += Pico.est.Draw2Width*(END_ROW-START_ROW)*8; + for (i = 8; i > 0; i--, pd += Pico.est.Draw2Width) + memset32((int *)pd, 0xe0e0e0e0, 328/4); + } + pprof_end(draw); } -void PicoDraw2SetOutBuf(void *dest) +void PicoDraw2SetOutBuf(void *dest, int incr) { - if (dest) + if (dest) { Pico.est.Draw2FB = dest; - else + Pico.est.Draw2Width = incr; + } else { Pico.est.Draw2FB = PicoDraw2FB_; + Pico.est.Draw2Width = LINE_WIDTH; + } } void PicoDraw2Init(void) { - PicoDraw2SetOutBuf(NULL); + PicoDraw2SetOutBuf(NULL, 0); } diff --git a/pico/pico.h b/pico/pico.h index 92d33971..b75a0146 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -208,9 +208,10 @@ void PicoDoHighPal555(int sh, int line, struct PicoEState *est); #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_32_COLS (1<<8) // 32 column mode +#define PDRAW_32_COLS (1<<8) // 32 columns mode #define PDRAW_BORDER_32 (1<<9) // center H32 in buffer (32 px border) #define PDRAW_SKIP_FRAME (1<<10) // frame is skipped +#define PDRAW_30_ROWS (1<<11) // 30 rows mode (240 lines) extern int rendstatus_old; extern int rendlines; diff --git a/pico/pico_int.h b/pico/pico_int.h index ce20d1ee..d66b67e2 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -359,6 +359,8 @@ struct PicoEState void *PicoMem_cram; unsigned int *PicoOpt; unsigned char *Draw2FB; + int Draw2Width; + int Draw2Start; unsigned short HighPal[0x100]; unsigned short SonicPal[0x100]; int SonicPalCount; @@ -673,7 +675,7 @@ extern int DrawLineDestIncrement; extern u32 VdpSATCache[128]; // draw2.c -void PicoDraw2SetOutBuf(void *dest); +void PicoDraw2SetOutBuf(void *dest, int incr); void PicoDraw2Init(void); PICO_INTERNAL void PicoFrameFull(); -- 2.39.5