From 9761a7d0d41ad429d53c64ff35fe061c38092dbf Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 1 Jul 2008 16:12:04 +0000 Subject: [PATCH] PicoVideoRead optimization git-svn-id: file:///home/notaz/opt/svn/PicoDrive@511 be3aeb3a-fb24-0410-a615-afba39da0efa --- Pico/Memory.c | 6 ++-- Pico/Memory.s | 8 +---- Pico/Memory_amips.s | 4 ++- Pico/Pico.c | 3 +- Pico/Pico/Memory.c | 3 +- Pico/PicoFrameHints.c | 30 +++++++++++----- Pico/PicoInt.h | 4 ++- Pico/VideoPort.c | 79 ++++++++++++++++++++++++++++--------------- Pico/cd/Memory.c | 6 ++-- Pico/cd/Memory.s | 9 ++--- 10 files changed, 89 insertions(+), 63 deletions(-) diff --git a/Pico/Memory.c b/Pico/Memory.c index 22bd7ad..290dba4 100644 --- a/Pico/Memory.c +++ b/Pico/Memory.c @@ -344,9 +344,9 @@ PICO_INTERNAL_ASM u32 PicoRead8(u32 a) log_io(a, 8, 0); if ((a&0xff4000)==0xa00000) { d=z80Read8(a); goto end; } // Z80 Ram - if ((a&0xe700e0)==0xc00000) // VDP - d=PicoVideoRead(a); - else d=OtherRead16(a&~1, 8); + if ((a&0xe700e0)==0xc00000) { d=PicoVideoRead8(a); goto end; } // VDP + + d=OtherRead16(a&~1, 8); if ((a&1)==0) d>>=8; end: diff --git a/Pico/Memory.s b/Pico/Memory.s index a042d81..cf2036d 100644 --- a/Pico/Memory.s +++ b/Pico/Memory.s @@ -415,13 +415,7 @@ m_read8_vdp: tst r0, #0x70000 tsteq r0, #0x000e0 bxne lr @ invalid read - stmfd sp!,{r0,lr} - bic r0, r0, #1 - bl PicoVideoRead - ldmfd sp!,{r1,lr} - tst r1, #1 - moveq r0, r0, lsr #8 - bx lr + b PicoVideoRead8 m_read8_ram: ldr r1, =Pico diff --git a/Pico/Memory_amips.s b/Pico/Memory_amips.s index 5a6b768..e6247c6 100644 --- a/Pico/Memory_amips.s +++ b/Pico/Memory_amips.s @@ -469,7 +469,9 @@ m_read8_vdp: andi $t1, $a0, 0xe0 or $t0, $t1 bnez $t0, m_read_null # invalid address - m_read8_call16 PicoVideoRead + nop + j PicoVideoRead8 + nop m_read8_ram: lui $t0, %hi(Pico) diff --git a/Pico/Pico.c b/Pico/Pico.c index c85c78a..9f5a361 100644 --- a/Pico/Pico.c +++ b/Pico/Pico.c @@ -218,7 +218,8 @@ PICO_INTERNAL int CheckDMA(void) if(Pico.video.reg[12] & 1) dma_op |= 4; // 40 cell mode? if(!(Pico.video.status&8)&&(Pico.video.reg[1]&0x40)) dma_op|=8; // active display? xfers_can = dma_timings[dma_op]; - if(xfers <= xfers_can) { + if(xfers <= xfers_can) + { if(dma_op&2) Pico.video.status&=~2; // dma no longer busy else { burn = xfers * dma_bsycles[dma_op] >> 8; // have to be approximate because can't afford division.. diff --git a/Pico/Pico/Memory.c b/Pico/Pico/Memory.c index 8c4674b..13cff62 100644 --- a/Pico/Pico/Memory.c +++ b/Pico/Pico/Memory.c @@ -22,8 +22,7 @@ static u32 PicoReadPico8(u32 a) a&=0xffffff; if ((a&0xfffff0)==0xc00000) { // VDP - d=PicoVideoRead(a); - if ((a&1)==0) d>>=8; + d=PicoVideoRead8(a); goto end; } diff --git a/Pico/PicoFrameHints.c b/Pico/PicoFrameHints.c index 962f9dc..9fecc0c 100644 --- a/Pico/PicoFrameHints.c +++ b/Pico/PicoFrameHints.c @@ -35,10 +35,10 @@ static int PicoFrameHints(void) { struct PicoVideo *pv=&Pico.video; - int lines, y, lines_vis = 224, line_sample, skip; + int lines, y, lines_vis = 224, line_sample, skip, vcnt_wrap; int hint; // Hint counter - Pico.m.scanline = 0; + pv->v_counter = Pico.m.scanline = 0; if ((PicoOpt&POPT_ALT_RENDERER) && !PicoSkipFrame && (pv->reg[1]&0x40)) { // fast rend., display enabled // draw a frame just after vblank in alternative render mode @@ -53,7 +53,7 @@ static int PicoFrameHints(void) if (Pico.m.pal) { line_sample = 68; - if(pv->reg[1]&8) lines_vis = 240; + if (pv->reg[1]&8) lines_vis = 240; } else { line_sample = 93; } @@ -75,7 +75,12 @@ static int PicoFrameHints(void) for (y = 0; y < lines_vis; y++) { - Pico.m.scanline = y; + pv->v_counter = Pico.m.scanline = y; + if ((pv->reg[12]&6) == 6) { // interlace mode 2 + pv->v_counter <<= 1; + pv->v_counter |= pv->v_counter >> 8; + pv->v_counter &= 0xff; + } // VDP FIFO pv->lwrite_cnt -= 12; @@ -138,6 +143,11 @@ static int PicoFrameHints(void) #endif } + // V-int line (224 or 240) + Pico.m.scanline = y; + pv->v_counter = 0xe0; // bad for 240 mode + if ((pv->reg[12]&6) == 6) pv->v_counter = 0xc1; + if (!skip) { if (DrawScanline < y) @@ -147,9 +157,6 @@ static int PicoFrameHints(void) #endif } - // V-int line (224 or 240) - Pico.m.scanline = y; - // VDP FIFO pv->lwrite_cnt=0; Pico.video.status|=0x200; @@ -168,7 +175,6 @@ static int PicoFrameHints(void) if (pv->reg[0]&0x10) SekInterrupt(4); } - // V-Interrupt: pv->status|=0x08; // go into vblank pv->pending_ints|=0x20; @@ -212,10 +218,16 @@ 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; + vcnt_wrap = Pico.m.pal ? 0x103 : 0xEB; // based on Gens for (y++; y < lines; y++) { - Pico.m.scanline = y; + pv->v_counter = Pico.m.scanline = y; + if (y >= vcnt_wrap) + pv->v_counter -= Pico.m.pal ? 56 : 6; + if ((pv->reg[12]&6) == 6) + pv->v_counter = (pv->v_counter << 1) | 1; + pv->v_counter &= 0xff; PAD_DELAY #ifdef PICO_CD diff --git a/Pico/PicoInt.h b/Pico/PicoInt.h index 664c2f2..4994ffc 100644 --- a/Pico/PicoInt.h +++ b/Pico/PicoInt.h @@ -237,7 +237,8 @@ struct PicoVideo int status; // Status bits unsigned char pending_ints; // pending interrupts: ??VH???? signed char lwrite_cnt; // VDP write count during active display line - unsigned char pad[0x12]; + unsigned short v_counter; // V-counter + unsigned char pad[0x10]; }; struct PicoMisc @@ -504,6 +505,7 @@ void ym2612_unpack_state(void); // VideoPort.c PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d); PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a); +PICO_INTERNAL_ASM unsigned int PicoVideoRead8(unsigned int a); extern int (*PicoDmaHook)(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp); // Misc.c diff --git a/Pico/VideoPort.c b/Pico/VideoPort.c index db7b2b7..7a38ea9 100644 --- a/Pico/VideoPort.c +++ b/Pico/VideoPort.c @@ -449,24 +449,19 @@ PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a) { a&=0x1c; - if (a==0x00) // data port - { - 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 + //if (PicoOpt&POPT_ALT_RENDERER) d|=0x0020; // sprite collision (Shadow of the Beast) if (SekCyclesLeft < 84+4) d|=0x0004; // H-Blank (Sonic3 vs) - d|=(pv->pending_ints&0x20)<<2; // V-int pending? + d |= ((pv->reg[1]&0x40)^0x40) >> 3; // set V-Blank if display is disabled + d |= (pv->pending_ints&0x20)<<2; // V-int pending? if (d&0x100) pv->status&=~0x100; // FIFO no longer full - pv->pending=0; // ctrl port reads clear write-pending flag (Charles MacDonald) + pv->pending = 0; // ctrl port reads clear write-pending flag (Charles MacDonald) elprintf(EL_SR, "SR read: %04x @ %06x", d, SekPc); return d; @@ -489,32 +484,60 @@ 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, d; + unsigned int d; int lineCycles; lineCycles = (488-SekCyclesLeft)&0x1ff; - d = Pico.m.scanline; // V-Counter - if (Pico.video.reg[12]&1) - hc=hcounts_40[lineCycles]; - else hc=hcounts_32[lineCycles]; + d = hcounts_40[lineCycles]; + else d = hcounts_32[lineCycles]; - if (Pico.m.pal) { - if (d >= 0x103) d-=56; // based on Gens - } else { - if (d >= 0xEB) d-=6; - } + elprintf(EL_HVCNT, "hv: %02x %02x (%i) @ %06x", d, Pico.video.v_counter, SekCyclesDone(), SekPc); + return d | (Pico.video.v_counter << 8); + } - if ((Pico.video.reg[12]&6) == 6) { - // interlace mode 2 (Combat Cars (UE) [!]) - d <<= 1; - if (d&0xf00) d|= 1; - } + if (a==0x00) // data port + { + return VideoRead(); + } - elprintf(EL_HVCNT, "hv: %02x %02x (%i) @ %06x", hc, d, SekCyclesDone(), SekPc); - d&=0xff; d<<=8; - d|=hc; - return d; + return 0; +} + +unsigned int PicoVideoRead8(unsigned int a) +{ + unsigned int d; + a&=0x1d; + + switch (a) + { + case 0: return VideoRead() >> 8; + case 1: return VideoRead() & 0xff; + case 4: // control port/status reg + d = Pico.video.status >> 8; + if (d&1) Pico.video.status&=~0x100; // FIFO no longer full + Pico.video.pending = 0; + elprintf(EL_SR, "SR read (h): %02x @ %06x", d, SekPc); + return d; + case 5: + d = Pico.video.status & 0xff; + //if (PicoOpt&POPT_ALT_RENDERER) d|=0x0020; // sprite collision (Shadow of the Beast) + d |= ((Pico.video.reg[1]&0x40)^0x40) >> 3; // set V-Blank if display is disabled + d |= (Pico.video.pending_ints&0x20)<<2; // V-int pending? + if (SekCyclesLeft < 84+4) d |= 4; // H-Blank + Pico.video.pending = 0; + elprintf(EL_SR, "SR read (l): %02x @ %06x", d, SekPc); + return d; + case 8: // hv counter + elprintf(EL_HVCNT, "vcounter: %02x (%i) @ %06x", Pico.video.v_counter, SekCyclesDone(), SekPc); + return Pico.video.v_counter; + case 9: + d = (488-SekCyclesLeft)&0x1ff; + if (Pico.video.reg[12]&1) + d = hcounts_40[d]; + else d = hcounts_32[d]; + elprintf(EL_HVCNT, "hcounter: %02x (%i) @ %06x", d, SekCyclesDone(), SekPc); + return d; } return 0; diff --git a/Pico/cd/Memory.c b/Pico/cd/Memory.c index 2b419b7..b404ae7 100644 --- a/Pico/cd/Memory.c +++ b/Pico/cd/Memory.c @@ -501,10 +501,8 @@ u32 PicoReadM68k8(u32 a) case 0xd0>>1: case 0xd2>>1: case 0xd4>>1: case 0xd6>>1: case 0xd8>>1: case 0xda>>1: case 0xdc>>1: case 0xde>>1: // VDP - if ((a&0xe700e0)==0xc00000) { - d=PicoVideoRead(a); - if ((a&1)==0) d>>=8; - } + if ((a&0xe700e0)==0xc00000) + d=PicoVideoRead8(a); break; case 0xe0>>1: case 0xe2>>1: case 0xe4>>1: case 0xe6>>1: case 0xe8>>1: case 0xea>>1: case 0xec>>1: case 0xee>>1: diff --git a/Pico/cd/Memory.s b/Pico/cd/Memory.s index 1b9fe96..9aba56d 100644 --- a/Pico/cd/Memory.s +++ b/Pico/cd/Memory.s @@ -126,6 +126,7 @@ m_s68k_decode_write_table: .extern z80Read8 .extern OtherRead16 .extern PicoVideoRead +.extern PicoVideoRead8 .extern Read_CDC_Host .extern m68k_reg_write8 .extern OtherWrite16 @@ -611,13 +612,7 @@ m_m68k_read8_vdp: tst r0, #0x70000 tsteq r0, #0x000e0 bxne lr @ invalid read - stmfd sp!,{r0,lr} - bic r0, r0, #1 - bl PicoVideoRead @ TODO: implement it in asm - ldmfd sp!,{r1,lr} - tst r1, #1 - moveq r0, r0, lsr #8 - bx lr + b PicoVideoRead8 m_m68k_read8_ram: -- 2.39.2