From: notaz Date: Thu, 5 Feb 2015 23:29:00 +0000 (+0200) Subject: Merge branch 'upstream' into libretro X-Git-Tag: r24l~889^2 X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=commitdiff_plain;h=2af7e74feec67c0a798ac190774cb4b3e925be76;hp=cebb70f24ab54693b12aaa27b85a52689e26e1ff Merge branch 'upstream' into libretro --- diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..7c4eafbd --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: cpp +compiler: + - gcc + - clang +before_install: + - sudo apt-get update -qq + - sudo apt-get install -y libsdl1.2-dev libasound2-dev libpng-dev libz-dev +script: ./configure && make diff --git a/README b/README.md similarity index 83% rename from README rename to README.md index 23ae219f..99644108 100644 --- a/README +++ b/README.md @@ -1,12 +1,16 @@ PCSX-ReARMed - yet another PCSX fork -------------------------------- +==================================== + +[![Build Status](https://travis-ci.org/notaz/pcsx_rearmed.svg?branch=master)](https://travis-ci.org/notaz/pcsx_rearmed) + +*see [readme.txt](readme.txt) for more complete documentation* PCSX ReARMed is yet another PCSX fork based on the PCSX-Reloaded project, which itself contains code from PCSX, PCSX-df and PCSX-Revolution. This version is ARM architecture oriented and features MIPS->ARM recompiler by Ari64, NEON GTE code and more performance improvements. It was created for Pandora handheld, but should be usable on other devices after some code -adjustments (N900, GPH Wiz/Caanoo versions are also available). +adjustments (N900, GPH Wiz/Caanoo, PlayBook versions are also available). PCSX ReARMed features ARM NEON GPU by Exophase, that in many cases produces pixel perfect graphics at very high performance. There is also Una-i's GPU @@ -14,7 +18,7 @@ plugin from PCSX4ALL project, and traditional P.E.Op.S. one. PCSX-Reloaded -------------------------------- +============= PCSX-Reloaded is a forked version of the dead PCSX emulator, with a nicer interface and several improvements to stability and functionality. diff --git a/frontend/libpicofe b/frontend/libpicofe index 515ac0b9..9fec8a91 160000 --- a/frontend/libpicofe +++ b/frontend/libpicofe @@ -1 +1 @@ -Subproject commit 515ac0b9d2c4d45a465335d54b8c49830914fcea +Subproject commit 9fec8a91c9b19856ac0b51de53b847b38ed8dc61 diff --git a/frontend/libretro.c b/frontend/libretro.c index 38514b5c..acc64a12 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -283,7 +283,7 @@ void retro_get_system_info(struct retro_system_info *info) { memset(info, 0, sizeof(*info)); info->library_name = "PCSX-ReARMed"; - info->library_version = "r21"; + info->library_version = "r22"; info->valid_extensions = "bin|cue|img|mdf|pbp|toc|cbn|m3u"; info->need_fullpath = true; } @@ -1255,6 +1255,7 @@ void retro_init(void) cycle_multiplier = 200; #endif pl_rearmed_cbs.gpu_peops.iUseDither = 1; + spu_config.iUseFixedUpdates = 1; McdDisable[0] = 0; McdDisable[1] = 1; diff --git a/frontend/plat_omap.c b/frontend/plat_omap.c index 4e3ea795..f25f31cc 100644 --- a/frontend/plat_omap.c +++ b/frontend/plat_omap.c @@ -111,10 +111,11 @@ void *plat_gvideo_set_mode(int *w_in, int *h_in, int *bpp) } } - vout_fbdev_clear(layer_fb); buf = vout_fbdev_resize(layer_fb, w, h, *bpp, l, r, t, b, 3); + vout_fbdev_clear(layer_fb); + omap_enable_layer(1); return buf; diff --git a/frontend/plugin_lib.c b/frontend/plugin_lib.c index 56da763e..ab4d4152 100644 --- a/frontend/plugin_lib.c +++ b/frontend/plugin_lib.c @@ -34,6 +34,8 @@ #include "../libpcsxcore/psxmem_map.h" #include "../plugins/dfinput/externals.h" +#define HUD_HEIGHT 10 + int in_type1, in_type2; int in_a1[2] = { 127, 127 }, in_a2[2] = { 127, 127 }; int in_adev[2] = { -1, -1 }, in_adev_axis[2][2] = {{ 0, 1 }, { 0, 1 }}; @@ -101,20 +103,20 @@ static void hud_printf(void *fb, int w, int x, int y, const char *texto, ...) static void print_msg(int h, int border) { - hud_print(pl_vout_buf, pl_vout_w, border + 2, h - 10, hud_msg); + hud_print(pl_vout_buf, pl_vout_w, border + 2, h - HUD_HEIGHT, hud_msg); } static void print_fps(int h, int border) { - hud_printf(pl_vout_buf, pl_vout_w, border + 2, h - 10, + hud_printf(pl_vout_buf, pl_vout_w, border + 2, h - HUD_HEIGHT, "%2d %4.1f", pl_rearmed_cbs.flips_per_sec, pl_rearmed_cbs.vsps_cur); } static void print_cpu_usage(int w, int h, int border) { - hud_printf(pl_vout_buf, pl_vout_w, pl_vout_w - border - 28, h - 10, - "%3d", pl_rearmed_cbs.cpu_usage); + hud_printf(pl_vout_buf, pl_vout_w, pl_vout_w - border - 28, + h - HUD_HEIGHT, "%3d", pl_rearmed_cbs.cpu_usage); } // draw 192x8 status of 24 sound channels @@ -126,7 +128,7 @@ static __attribute__((noinline)) void draw_active_chans(int vout_w, int vout_h) static const unsigned short colors[2] = { 0x1fe3, 0x0700 }; unsigned short *dest = (unsigned short *)pl_vout_buf + - vout_w * (vout_h - 10) + vout_w / 2 - 192/2; + vout_w * (vout_h - HUD_HEIGHT) + vout_w / 2 - 192/2; unsigned short *d, p; int c, x, y; diff --git a/include/arm_features.h b/include/arm_features.h index fdec5229..bb48a2bf 100644 --- a/include/arm_features.h +++ b/include/arm_features.h @@ -3,7 +3,7 @@ #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ - || defined(__ARM_ARCH_7EM__) + || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7S__) #define HAVE_ARMV7 #define HAVE_ARMV6 diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index 3a2eb1f6..556b512f 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -1413,13 +1413,15 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) { psxCpu->Clear(madr, cdsize / 4); pTransfer += cdsize; - - // burst vs normal if( chcr == 0x11400100 ) { + HW_DMA3_MADR = SWAPu32(madr + cdsize); CDRDMA_INT( (cdsize/4) / 4 ); } else if( chcr == 0x11000000 ) { - CDRDMA_INT( (cdsize/4) * 1 ); + // CDRDMA_INT( (cdsize/4) * 1 ); + // halted + psxRegs.cycle += (cdsize/4) * 24/2; + CDRDMA_INT(16); } return; diff --git a/libpcsxcore/gte_arm.S b/libpcsxcore/gte_arm.S index 3ef876dd..d6fc1ab8 100644 --- a/libpcsxcore/gte_arm.S +++ b/libpcsxcore/gte_arm.S @@ -11,7 +11,7 @@ .align 2 .macro sgnxt16 rd rs -#ifdef HAVE_ARMV7 +#ifdef HAVE_ARMV6 sxth \rd, \rs #else lsl \rd, \rs, #16 @@ -28,7 +28,7 @@ .endm .macro ssatx rd wr bit -#ifdef HAVE_ARMV7 +#ifdef HAVE_ARMV6 ssat \rd, #\bit, \rd #else cmp \rd, \wr @@ -52,7 +52,7 @@ .endm .macro usat16_ rd rs -#ifdef HAVE_ARMV7 +#ifdef HAVE_ARMV6 usat \rd, #16, \rs #else subs \rd, \rs, #0 diff --git a/libpcsxcore/mdec.c b/libpcsxcore/mdec.c index bed4e53b..d6c7ab68 100644 --- a/libpcsxcore/mdec.c +++ b/libpcsxcore/mdec.c @@ -32,7 +32,7 @@ * 320x240x16@60Hz => 9.216 MB/s * so 2.0 to 4.0 should be fine. */ -#define MDEC_BIAS 2.0f +#define MDEC_BIAS 2 #define DSIZE 8 #define DSIZE2 (DSIZE * DSIZE) @@ -545,15 +545,13 @@ void psxDma1(u32 adr, u32 bcr, u32 chcr) { int blk[DSIZE2 * 6]; u8 * image; int size; - int dmacnt; + u32 words; if (chcr != 0x01000200) return; - size = (bcr >> 16) * (bcr & 0xffff); + words = (bcr >> 16) * (bcr & 0xffff); /* size in byte */ - size *= 4; - /* I guess the memory speed is limitating */ - dmacnt = size; + size = words * 4; if (!(mdec.reg1 & MDEC1_BUSY)) { /* add to pending */ @@ -625,7 +623,7 @@ void psxDma1(u32 adr, u32 bcr, u32 chcr) { } /* define the power of mdec */ - MDECOUTDMA_INT((int) ((dmacnt* MDEC_BIAS))); + MDECOUTDMA_INT(words * MDEC_BIAS); } } diff --git a/libpcsxcore/new_dynarec/assem_arm.c b/libpcsxcore/new_dynarec/assem_arm.c index 9ee832ef..6853e9e5 100644 --- a/libpcsxcore/new_dynarec/assem_arm.c +++ b/libpcsxcore/new_dynarec/assem_arm.c @@ -1285,7 +1285,7 @@ void emit_andimm(int rs,int imm,int rt) assem_debug("bic %s,%s,#%d\n",regname[rt],regname[rs],imm); output_w32(0xe3c00000|rd_rn_rm(rt,rs,0)|armval); }else if(imm==65535) { - #ifndef HAVE_ARMV7 + #ifndef HAVE_ARMV6 assem_debug("bic %s,%s,#FF000000\n",regname[rt],regname[rs]); output_w32(0xe3c00000|rd_rn_rm(rt,rs,0)|0x4FF); assem_debug("bic %s,%s,#00FF0000\n",regname[rt],regname[rt]); @@ -1418,7 +1418,7 @@ void emit_shrdimm(int rs,int rs2,u_int imm,int rt) void emit_signextend16(int rs,int rt) { - #ifndef HAVE_ARMV7 + #ifndef HAVE_ARMV6 emit_shlimm(rs,16,rt); emit_sarimm(rt,16,rt); #else @@ -1429,7 +1429,7 @@ void emit_signextend16(int rs,int rt) void emit_signextend8(int rs,int rt) { - #ifndef HAVE_ARMV7 + #ifndef HAVE_ARMV6 emit_shlimm(rs,24,rt); emit_sarimm(rt,24,rt); #else diff --git a/libpcsxcore/new_dynarec/emu_if.c b/libpcsxcore/new_dynarec/emu_if.c index 092c8ae9..22db5d11 100644 --- a/libpcsxcore/new_dynarec/emu_if.c +++ b/libpcsxcore/new_dynarec/emu_if.c @@ -378,7 +378,7 @@ static void ari64_clear(u32 addr, u32 size) { u32 start, end, main_ram; - size *= 4; /* PCSX uses DMA units */ + size *= 4; /* PCSX uses DMA units (words) */ evprintf("ari64_clear %08x %04x\n", addr, size); diff --git a/libpcsxcore/ppf.c b/libpcsxcore/ppf.c index 0d80107b..edebdd03 100644 --- a/libpcsxcore/ppf.c +++ b/libpcsxcore/ppf.c @@ -347,8 +347,10 @@ int LoadSBI(const char *fname, int sector_count) { return -1; sbi_sectors = calloc(1, sector_count / 8); - if (sbi_sectors == NULL) + if (sbi_sectors == NULL) { + fclose(sbihandle); return -1; + } // 4-byte SBI header fread(buffer, 1, 4, sbihandle); diff --git a/libpcsxcore/psxdma.c b/libpcsxcore/psxdma.c index ff7d6a3b..03ee5639 100644 --- a/libpcsxcore/psxdma.c +++ b/libpcsxcore/psxdma.c @@ -37,7 +37,7 @@ void spuInterrupt() { void psxDma4(u32 madr, u32 bcr, u32 chcr) { // SPU u16 *ptr; - u32 size; + u32 words; switch (chcr) { case 0x01000201: //cpu to spu transfer @@ -51,8 +51,10 @@ void psxDma4(u32 madr, u32 bcr, u32 chcr) { // SPU #endif break; } - SPU_writeDMAMem(ptr, (bcr >> 16) * (bcr & 0xffff) * 2, psxRegs.cycle); - SPUDMA_INT((bcr >> 16) * (bcr & 0xffff) / 2); + words = (bcr >> 16) * (bcr & 0xffff); + SPU_writeDMAMem(ptr, words * 2, psxRegs.cycle); + HW_DMA4_MADR = SWAPu32(madr + words * 4); + SPUDMA_INT(words / 2); return; case 0x01000200: //spu to cpu transfer @@ -66,10 +68,13 @@ void psxDma4(u32 madr, u32 bcr, u32 chcr) { // SPU #endif break; } - size = (bcr >> 16) * (bcr & 0xffff) * 2; - SPU_readDMAMem(ptr, size, psxRegs.cycle); - psxCpu->Clear(madr, size); - break; + words = (bcr >> 16) * (bcr & 0xffff); + SPU_readDMAMem(ptr, words * 2, psxRegs.cycle); + psxCpu->Clear(madr, words); + + HW_DMA4_MADR = SWAPu32(madr + words * 4); + SPUDMA_INT(words / 2); + return; #ifdef PSXDMA_LOG default: @@ -124,6 +129,7 @@ static u32 gpuDmaChainSize(u32 addr) { void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU u32 *ptr; + u32 words; u32 size; switch (chcr) { @@ -139,12 +145,14 @@ void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU break; } // BA blocks * BS words (word = 32-bits) - size = (bcr >> 16) * (bcr & 0xffff); - GPU_readDataMem(ptr, size); - psxCpu->Clear(madr, size); + words = (bcr >> 16) * (bcr & 0xffff); + GPU_readDataMem(ptr, words); + psxCpu->Clear(madr, words); + + HW_DMA2_MADR = SWAPu32(madr + words * 4); // already 32-bit word size ((size * 4) / 4) - GPUDMA_INT(size / 4); + GPUDMA_INT(words / 4); return; case 0x01000201: // mem2vram @@ -159,11 +167,13 @@ void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU break; } // BA blocks * BS words (word = 32-bits) - size = (bcr >> 16) * (bcr & 0xffff); - GPU_writeDataMem(ptr, size); + words = (bcr >> 16) * (bcr & 0xffff); + GPU_writeDataMem(ptr, words); + + HW_DMA2_MADR = SWAPu32(madr + words * 4); // already 32-bit word size ((size * 4) / 4) - GPUDMA_INT(size / 4); + GPUDMA_INT(words / 4); return; case 0x01000401: // dma chain @@ -175,7 +185,11 @@ void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU if ((int)size <= 0) size = gpuDmaChainSize(madr); HW_GPU_STATUS &= ~PSXGPU_nBUSY; - + + // we don't emulate progress, just busy flag and end irq, + // so pretend we're already at the last block + HW_DMA2_MADR = SWAPu32(0xffffff); + // Tekken 3 = use 1.0 only (not 1.5x) // Einhander = parse linked list in pieces (todo) @@ -206,7 +220,7 @@ void gpuInterrupt() { } void psxDma6(u32 madr, u32 bcr, u32 chcr) { - u32 size; + u32 words; u32 *mem = (u32 *)PSXM(madr); #ifdef PSXDMA_LOG @@ -224,7 +238,7 @@ void psxDma6(u32 madr, u32 bcr, u32 chcr) { } // already 32-bit size - size = bcr; + words = bcr; while (bcr--) { *mem-- = SWAP32((madr - 4) & 0xffffff); @@ -232,7 +246,10 @@ void psxDma6(u32 madr, u32 bcr, u32 chcr) { } mem++; *mem = 0xffffff; - GPUOTCDMA_INT(size); + //GPUOTCDMA_INT(size); + // halted + psxRegs.cycle += words; + GPUOTCDMA_INT(16); return; } #ifdef PSXDMA_LOG diff --git a/plugins/dfsound/Makefile.c64p b/plugins/dfsound/Makefile.c64p index 45fe76a4..5b977810 100644 --- a/plugins/dfsound/Makefile.c64p +++ b/plugins/dfsound/Makefile.c64p @@ -5,7 +5,9 @@ endif include $(C64_TOOLS_DSP_ROOT)/install.mk TARGET_BASENAME = pcsxr_spu -OPTFLAGS += -O2 +OPTFLAGS += -o3 +CFLAGS += -mo +#CFLAGS += -k -mw CFLAGS += -DNO_OS -DWANT_THREAD_CODE OBJ = \ diff --git a/plugins/dfsound/dma.c b/plugins/dfsound/dma.c index 4798a19b..43019f1d 100644 --- a/plugins/dfsound/dma.c +++ b/plugins/dfsound/dma.c @@ -71,6 +71,7 @@ void CALLBACK SPUwriteDMA(unsigned short val) spu.spuAddr += 2; spu.spuAddr &= 0x7fffe; + spu.bMemDirty = 1; } //////////////////////////////////////////////////////////////////////// @@ -83,6 +84,7 @@ void CALLBACK SPUwriteDMAMem(unsigned short *pusPSXMem, int iSize, int i; do_samples_if_needed(cycles, 1); + spu.bMemDirty = 1; if(spu.spuAddr + iSize*2 < 0x80000) { diff --git a/plugins/dfsound/externals.h b/plugins/dfsound/externals.h index f6fc4409..2db75ac2 100644 --- a/plugins/dfsound/externals.h +++ b/plugins/dfsound/externals.h @@ -162,14 +162,8 @@ typedef struct int dirty; // registers changed - // normalized offsets - int nIIR_DEST_A0, nIIR_DEST_A1, nIIR_DEST_B0, nIIR_DEST_B1, - nACC_SRC_A0, nACC_SRC_A1, nACC_SRC_B0, nACC_SRC_B1, - nIIR_SRC_A0, nIIR_SRC_A1, nIIR_SRC_B0, nIIR_SRC_B1, - nACC_SRC_C0, nACC_SRC_C1, nACC_SRC_D0, nACC_SRC_D1, - nMIX_DEST_A0, nMIX_DEST_A1, nMIX_DEST_B0, nMIX_DEST_B1; // MIX_DEST_xx - FB_SRC_x - int nFB_SRC_A0, nFB_SRC_A1, nFB_SRC_B0, nFB_SRC_B1; + int FB_SRC_A0, FB_SRC_A1, FB_SRC_B0, FB_SRC_B1; } REVERBInfo; /////////////////////////////////////////////////////////// @@ -195,6 +189,7 @@ typedef struct int decode_dirty_ch; unsigned int bSpuInit:1; unsigned int bSPUIsOpen:1; + unsigned int bMemDirty:1; // had external write to SPU RAM unsigned int dwNoiseVal; // global noise generator unsigned int dwNoiseCount; diff --git a/plugins/dfsound/freeze.c b/plugins/dfsound/freeze.c index 5b4267bf..43e6535c 100644 --- a/plugins/dfsound/freeze.c +++ b/plugins/dfsound/freeze.c @@ -231,6 +231,8 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF, if(!pF) return 0; // first check + do_samples(cycles, 1); + if(ulFreezeMode) // info or save? {//--------------------------------------------------// if(ulFreezeMode==1) @@ -242,8 +244,6 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF, if(ulFreezeMode==2) return 1; // info mode? ok, bye // save mode: - do_samples(cycles, 1); - memcpy(pF->cSPURam,spu.spuMem,0x80000); // copy common infos memcpy(pF->cSPUPort,spu.regArea,0x200); @@ -279,6 +279,7 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF, memcpy(spu.spuMem,pF->cSPURam,0x80000); // get ram memcpy(spu.regArea,pF->cSPUPort,0x200); + spu.bMemDirty = 1; if(pF->xaS.nsamples<=4032) // start xa again SPUplayADPCMchannel(&pF->xaS); diff --git a/plugins/dfsound/registers.c b/plugins/dfsound/registers.c index 4588fa7c..91bcaf86 100644 --- a/plugins/dfsound/registers.c +++ b/plugins/dfsound/registers.c @@ -145,17 +145,6 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val, break; //-------------------------------------------------// case H_SPUReverbAddr: - if(val==0xFFFF || val<=0x200) - {spu.rvb->StartAddr=spu.rvb->CurrAddr=0;} - else - { - const long iv=(unsigned long)val<<2; - if(spu.rvb->StartAddr!=iv) - { - spu.rvb->StartAddr=(unsigned long)val<<2; - spu.rvb->CurrAddr=spu.rvb->StartAddr; - } - } goto rvbd; //-------------------------------------------------// case H_SPUirqAddr: @@ -246,38 +235,38 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val, ReverbOn(16,24,val); break; //-------------------------------------------------// - case H_Reverb+0 : spu.rvb->FB_SRC_A=val*4; goto rvbd; - case H_Reverb+2 : spu.rvb->FB_SRC_B=val*4; goto rvbd; - case H_Reverb+4 : spu.rvb->IIR_ALPHA=(short)val; goto rvbd; - case H_Reverb+6 : spu.rvb->ACC_COEF_A=(short)val; goto rvbd; - case H_Reverb+8 : spu.rvb->ACC_COEF_B=(short)val; goto rvbd; - case H_Reverb+10 : spu.rvb->ACC_COEF_C=(short)val; goto rvbd; - case H_Reverb+12 : spu.rvb->ACC_COEF_D=(short)val; goto rvbd; - case H_Reverb+14 : spu.rvb->IIR_COEF=(short)val; goto rvbd; - case H_Reverb+16 : spu.rvb->FB_ALPHA=(short)val; goto rvbd; - case H_Reverb+18 : spu.rvb->FB_X=(short)val; goto rvbd; - case H_Reverb+20 : spu.rvb->IIR_DEST_A0=val*4; goto rvbd; - case H_Reverb+22 : spu.rvb->IIR_DEST_A1=val*4; goto rvbd; - case H_Reverb+24 : spu.rvb->ACC_SRC_A0=val*4; goto rvbd; - case H_Reverb+26 : spu.rvb->ACC_SRC_A1=val*4; goto rvbd; - case H_Reverb+28 : spu.rvb->ACC_SRC_B0=val*4; goto rvbd; - case H_Reverb+30 : spu.rvb->ACC_SRC_B1=val*4; goto rvbd; - case H_Reverb+32 : spu.rvb->IIR_SRC_A0=val*4; goto rvbd; - case H_Reverb+34 : spu.rvb->IIR_SRC_A1=val*4; goto rvbd; - case H_Reverb+36 : spu.rvb->IIR_DEST_B0=val*4; goto rvbd; - case H_Reverb+38 : spu.rvb->IIR_DEST_B1=val*4; goto rvbd; - case H_Reverb+40 : spu.rvb->ACC_SRC_C0=val*4; goto rvbd; - case H_Reverb+42 : spu.rvb->ACC_SRC_C1=val*4; goto rvbd; - case H_Reverb+44 : spu.rvb->ACC_SRC_D0=val*4; goto rvbd; - case H_Reverb+46 : spu.rvb->ACC_SRC_D1=val*4; goto rvbd; - case H_Reverb+48 : spu.rvb->IIR_SRC_B1=val*4; goto rvbd; - case H_Reverb+50 : spu.rvb->IIR_SRC_B0=val*4; goto rvbd; - case H_Reverb+52 : spu.rvb->MIX_DEST_A0=val*4; goto rvbd; - case H_Reverb+54 : spu.rvb->MIX_DEST_A1=val*4; goto rvbd; - case H_Reverb+56 : spu.rvb->MIX_DEST_B0=val*4; goto rvbd; - case H_Reverb+58 : spu.rvb->MIX_DEST_B1=val*4; goto rvbd; - case H_Reverb+60 : spu.rvb->IN_COEF_L=(short)val; goto rvbd; - case H_Reverb+62 : spu.rvb->IN_COEF_R=(short)val; goto rvbd; + case H_Reverb+0 : goto rvbd; + case H_Reverb+2 : goto rvbd; + case H_Reverb+4 : spu.rvb->IIR_ALPHA=(short)val; break; + case H_Reverb+6 : spu.rvb->ACC_COEF_A=(short)val; break; + case H_Reverb+8 : spu.rvb->ACC_COEF_B=(short)val; break; + case H_Reverb+10 : spu.rvb->ACC_COEF_C=(short)val; break; + case H_Reverb+12 : spu.rvb->ACC_COEF_D=(short)val; break; + case H_Reverb+14 : spu.rvb->IIR_COEF=(short)val; break; + case H_Reverb+16 : spu.rvb->FB_ALPHA=(short)val; break; + case H_Reverb+18 : spu.rvb->FB_X=(short)val; break; + case H_Reverb+20 : goto rvbd; + case H_Reverb+22 : goto rvbd; + case H_Reverb+24 : goto rvbd; + case H_Reverb+26 : goto rvbd; + case H_Reverb+28 : goto rvbd; + case H_Reverb+30 : goto rvbd; + case H_Reverb+32 : goto rvbd; + case H_Reverb+34 : goto rvbd; + case H_Reverb+36 : goto rvbd; + case H_Reverb+38 : goto rvbd; + case H_Reverb+40 : goto rvbd; + case H_Reverb+42 : goto rvbd; + case H_Reverb+44 : goto rvbd; + case H_Reverb+46 : goto rvbd; + case H_Reverb+48 : goto rvbd; + case H_Reverb+50 : goto rvbd; + case H_Reverb+52 : goto rvbd; + case H_Reverb+54 : goto rvbd; + case H_Reverb+56 : goto rvbd; + case H_Reverb+58 : goto rvbd; + case H_Reverb+60 : spu.rvb->IN_COEF_L=(short)val; break; + case H_Reverb+62 : spu.rvb->IN_COEF_R=(short)val; break; } return; diff --git a/plugins/dfsound/reverb.c b/plugins/dfsound/reverb.c index 2ff6edc8..ec570fb3 100644 --- a/plugins/dfsound/reverb.c +++ b/plugins/dfsound/reverb.c @@ -50,16 +50,16 @@ INLINE int rvb2ram_offs(int curr, int space, int iOff) // get_buffer content helper: takes care about wraps #define g_buffer(var) \ - ((int)(signed short)spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->n##var)]) + ((int)(signed short)spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->var)]) // saturate iVal and store it as var #define s_buffer(var, iVal) \ ssat32_to_16(iVal); \ - spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->n##var)] = iVal + spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->var)] = iVal #define s_buffer1(var, iVal) \ ssat32_to_16(iVal); \ - spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->n##var + 1)] = iVal + spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->var + 1)] = iVal //////////////////////////////////////////////////////////////////////// @@ -174,43 +174,54 @@ static void MixREVERB_off(int *SSumLR, int ns_to, int curr_addr) static void REVERBPrep(void) { REVERBInfo *rvb = spu.rvb; - int space = 0x40000 - rvb->StartAddr; - int t; - #define prep_offs(v) \ - t = rvb->v; \ + int space, t; + + t = spu.regArea[(H_SPUReverbAddr - 0xc00) >> 1]; + if (t == 0xFFFF || t <= 0x200) + spu.rvb->StartAddr = spu.rvb->CurrAddr = 0; + else if (spu.rvb->StartAddr != (t << 2)) + spu.rvb->StartAddr = spu.rvb->CurrAddr = t << 2; + + space = 0x40000 - rvb->StartAddr; + + #define prep_offs(v, r) \ + t = spu.regArea[(0x1c0 + r) >> 1] * 4; \ while (t >= space) \ t -= space; \ - rvb->n##v = t - #define prep_offs2(d, v1, v2) \ - t = rvb->v1 - rvb->v2; \ + rvb->v = t + #define prep_offs2(d, r1, r2) \ + t = spu.regArea[(0x1c0 + r1) >> 1] * 4; \ + t -= spu.regArea[(0x1c0 + r2) >> 1] * 4; \ + while (t < 0) \ + t += space; \ while (t >= space) \ t -= space; \ - rvb->n##d = t - - prep_offs(IIR_SRC_A0); - prep_offs(IIR_SRC_A1); - prep_offs(IIR_SRC_B0); - prep_offs(IIR_SRC_B1); - prep_offs(IIR_DEST_A0); - prep_offs(IIR_DEST_A1); - prep_offs(IIR_DEST_B0); - prep_offs(IIR_DEST_B1); - prep_offs(ACC_SRC_A0); - prep_offs(ACC_SRC_A1); - prep_offs(ACC_SRC_B0); - prep_offs(ACC_SRC_B1); - prep_offs(ACC_SRC_C0); - prep_offs(ACC_SRC_C1); - prep_offs(ACC_SRC_D0); - prep_offs(ACC_SRC_D1); - prep_offs(MIX_DEST_A0); - prep_offs(MIX_DEST_A1); - prep_offs(MIX_DEST_B0); - prep_offs(MIX_DEST_B1); - prep_offs2(FB_SRC_A0, MIX_DEST_A0, FB_SRC_A); - prep_offs2(FB_SRC_A1, MIX_DEST_A1, FB_SRC_A); - prep_offs2(FB_SRC_B0, MIX_DEST_B0, FB_SRC_B); - prep_offs2(FB_SRC_B1, MIX_DEST_B1, FB_SRC_B); + rvb->d = t + + prep_offs(IIR_SRC_A0, 32); + prep_offs(IIR_SRC_A1, 34); + prep_offs(IIR_SRC_B0, 36); + prep_offs(IIR_SRC_B1, 38); + prep_offs(IIR_DEST_A0, 20); + prep_offs(IIR_DEST_A1, 22); + prep_offs(IIR_DEST_B0, 36); + prep_offs(IIR_DEST_B1, 38); + prep_offs(ACC_SRC_A0, 24); + prep_offs(ACC_SRC_A1, 26); + prep_offs(ACC_SRC_B0, 28); + prep_offs(ACC_SRC_B1, 30); + prep_offs(ACC_SRC_C0, 40); + prep_offs(ACC_SRC_C1, 42); + prep_offs(ACC_SRC_D0, 44); + prep_offs(ACC_SRC_D1, 46); + prep_offs(MIX_DEST_A0, 52); + prep_offs(MIX_DEST_A1, 54); + prep_offs(MIX_DEST_B0, 56); + prep_offs(MIX_DEST_B1, 58); + prep_offs2(FB_SRC_A0, 52, 0); + prep_offs2(FB_SRC_A1, 54, 0); + prep_offs2(FB_SRC_B0, 56, 2); + prep_offs2(FB_SRC_B1, 58, 2); #undef prep_offs #undef prep_offs2 diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c index 8681d354..c6a1bf5e 100644 --- a/plugins/dfsound/spu.c +++ b/plugins/dfsound/spu.c @@ -818,12 +818,8 @@ static void do_channels(int ns_to) } if (spu.rvb->StartAddr) { - if (do_rvb) { - if (unlikely(spu.rvb->dirty)) - REVERBPrep(); - + if (do_rvb) REVERBDo(spu.SSumLR, RVB, ns_to, spu.rvb->CurrAddr); - } spu.rvb->CurrAddr += ns_to / 2; while (spu.rvb->CurrAddr >= 0x40000) @@ -846,6 +842,7 @@ static struct spu_worker { unsigned int i_ready; unsigned int i_reaped; unsigned int last_boot_cnt; // dsp + unsigned int ram_dirty; }; // aligning for C64X_DSP unsigned int _pad0[128/4]; @@ -970,11 +967,8 @@ static void queue_channel_work(int ns_to, unsigned int silentch) work->rvb_addr = 0; if (spu.rvb->StartAddr) { - if (spu_config.iUseReverb) { - if (unlikely(spu.rvb->dirty)) - REVERBPrep(); + if (spu_config.iUseReverb) work->rvb_addr = spu.rvb->CurrAddr; - } spu.rvb->CurrAddr += ns_to / 2; while (spu.rvb->CurrAddr >= 0x40000) @@ -989,9 +983,9 @@ static void do_channel_work(struct work_item *work) { unsigned int mask; unsigned int decode_dirty_ch = 0; + const SPUCHAN *s_chan; int *SB, sinc, spos, sbpos; int d, ch, ns_to; - SPUCHAN *s_chan; ns_to = work->ns_to; @@ -1057,8 +1051,12 @@ static void sync_worker_thread(int force) struct work_item *work; int done, used_space; + // rvb offsets will change, thread may be using them + force |= spu.rvb->dirty && spu.rvb->StartAddr; + done = thread_get_i_done() - worker->i_reaped; used_space = worker->i_ready - worker->i_reaped; + //printf("done: %d use: %d dsp: %u/%u\n", done, used_space, // worker->boot_cnt, worker->i_done); @@ -1150,6 +1148,9 @@ void do_samples(unsigned int cycles_to, int do_direct) } } + if (unlikely(spu.rvb->dirty)) + REVERBPrep(); + if (do_direct || worker == NULL || !spu_config.iUseThread) { do_channels(ns_to); do_samples_finish(spu.SSumLR, ns_to, silentch, spu.decode_pos); @@ -1252,7 +1253,7 @@ void schedule_next_irq(void) void CALLBACK SPUasync(unsigned int cycle, unsigned int flags) { - do_samples(cycle, 0); + do_samples(cycle, spu_config.iUseFixedUpdates); if (spu.spuCtrl & CTRL_IRQ) schedule_next_irq(); diff --git a/plugins/dfsound/spu_c64x.c b/plugins/dfsound/spu_c64x.c index be10a6bb..e0aa0da2 100644 --- a/plugins/dfsound/spu_c64x.c +++ b/plugins/dfsound/spu_c64x.c @@ -47,6 +47,25 @@ static struct { unsigned int req_sent:1; } f; +static noinline void dsp_fault(void) +{ + dsp_msg_t msg; + + f.dsp_cache_inv_virt(worker, sizeof(*worker)); + printf("dsp crash/fault/corruption:\n"); + printf("state rdy/reap/done: %u %u %u\n", + worker->i_ready, worker->i_reaped, worker->i_done); + printf("active/boot: %u %u\n", + worker->active, worker->boot_cnt); + + if (f.req_sent) { + f.dsp_rpc_recv(&msg); + f.req_sent = 0; + } + f.dsp_logbuf_print(); + spu_config.iUseThread = 0; +} + static void thread_work_start(void) { struct region_mem *mem; @@ -84,9 +103,11 @@ static void thread_work_start(void) f.dsp_cache_inv_virt(&worker->i_done, 64); worker->last_boot_cnt = worker->boot_cnt; + worker->ram_dirty = spu.bMemDirty; + spu.bMemDirty = 0; mem = (void *)f.region.virt_addr; - memcpy(&mem->spu_config, &spu_config, sizeof(mem->spu_config)); + memcpy(&mem->in.spu_config, &spu_config, sizeof(mem->in.spu_config)); DSP_MSG_INIT(&msg, f.compid, CCMD_DOIT, f.region.phys_addr, 0); ret = f.dsp_rpc_send(&msg); @@ -97,6 +118,11 @@ static void thread_work_start(void) return; } f.req_sent = 1; + +#if 0 + f.dsp_rpc_recv(&msg); + f.req_sent = 0; +#endif } static int thread_get_i_done(void) @@ -110,6 +136,11 @@ static void thread_work_wait_sync(struct work_item *work, int force) int limit = 1000; int ns_to; + if ((unsigned int)(worker->i_done - worker->i_reaped) > WORK_MAXCNT) { + dsp_fault(); + return; + } + while (worker->i_done == worker->i_reaped && limit-- > 0) { if (!f.req_sent) { printf("dsp: req not sent?\n"); @@ -222,7 +253,7 @@ static void init_spu_thread(void) } mem = (void *)f.region.virt_addr; - memcpy(&mem->spu_config, &spu_config, sizeof(mem->spu_config)); + memcpy(&mem->in.spu_config, &spu_config, sizeof(mem->in.spu_config)); DSP_MSG_INIT(&init_msg, f.compid, CCMD_INIT, f.region.phys_addr, 0); ret = f.dsp_rpc(&init_msg, &msg_in); @@ -301,4 +332,23 @@ static void exit_spu_thread(void) worker = NULL; } +/* debug: "access" shared mem from gdb */ +#if 0 +struct region_mem *dbg_dsp_mem; + +void dbg_dsp_mem_update(void) +{ + struct region_mem *mem; + + if (dbg_dsp_mem == NULL) + dbg_dsp_mem = malloc(sizeof(*dbg_dsp_mem)); + if (dbg_dsp_mem == NULL) + return; + + mem = (void *)f.region.virt_addr; + f.dsp_cache_inv_virt(mem, sizeof(*mem)); + memcpy(dbg_dsp_mem, mem, sizeof(*dbg_dsp_mem)); +} +#endif + // vim:shiftwidth=1:expandtab diff --git a/plugins/dfsound/spu_c64x.h b/plugins/dfsound/spu_c64x.h index 8210e63a..7c4d5659 100644 --- a/plugins/dfsound/spu_c64x.h +++ b/plugins/dfsound/spu_c64x.h @@ -15,10 +15,10 @@ struct region_mem { // these are not to be modified by DSP SPUCHAN s_chan[24 + 1]; REVERBInfo rvb; + SPUConfig spu_config; } in; int _pad2[128/4 - ((sizeof(struct spu_in) / 4) & (128/4 - 1))]; struct spu_worker worker; - SPUConfig spu_config; // init/debug int sizeof_region_mem; int offsetof_s_chan1; diff --git a/plugins/dfsound/spu_c64x_dspcode.c b/plugins/dfsound/spu_c64x_dspcode.c index b0352a9f..570da5ed 100644 --- a/plugins/dfsound/spu_c64x_dspcode.c +++ b/plugins/dfsound/spu_c64x_dspcode.c @@ -37,13 +37,40 @@ struct out_driver *out_current; void SetupSound(void) {} +static void enable_l2_cache(void) +{ + volatile uint32_t *L2CFG = (volatile uint32_t *)0x01840000; + uint32_t *MARi = (void *)0x01848000; + int i; + + // program Memory Attribute Registers + // (old c64_tools has the defaults messed up) + // 00000000-0fffffff - not configurable + // 10000000-7fffffff - system + for (i = 0x10; i < 0x80; i++) + MARi[i] = 0; + // 80000000-9fffffff - RAM + for ( ; i < 0xa0; i++) + MARi[i] = 1; + // 0xa00000-ffffffff - reserved, etc + for ( ; i < 0x100; i++) + MARi[i] = 0; + + // enable L2 (1 for 32k, 2 for 64k) + if (!(*L2CFG & 2)) { + *L2CFG = 2; + // wait the for the write + *L2CFG; + } +} + static void invalidate_cache(struct work_item *work) { // see comment in writeout_cache() //syscalls.cache_inv(work, offsetof(typeof(*work), SSumLR), 1); - syscalls.cache_inv(spu.s_chan, sizeof(spu.s_chan[0]) * 24, 0); + syscalls.cache_inv(spu.s_chan, sizeof(spu.s_chan[0]) * 24, 1); syscalls.cache_inv(work->SSumLR, - sizeof(work->SSumLR[0]) * 2 * work->ns_to, 0); + sizeof(work->SSumLR[0]) * 2 * work->ns_to, 1); } static void writeout_cache(struct work_item *work) @@ -53,7 +80,7 @@ static void writeout_cache(struct work_item *work) syscalls.cache_wb(work->SSumLR, sizeof(work->SSumLR[0]) * 2 * ns_to, 1); // have to invalidate now, otherwise there is a race between // DSP evicting dirty lines and ARM writing new data to this area - syscalls.cache_inv(work, offsetof(typeof(*work), SSumLR), 0); + syscalls.cache_inv(work, offsetof(typeof(*work), SSumLR), 1); } static void do_processing(void) @@ -112,6 +139,7 @@ static unsigned int exec(dsp_component_cmd_t cmd, switch (cmd) { case CCMD_INIT: + enable_l2_cache(); InitADSR(); spu.spuMemC = mem->spu_ram; @@ -119,7 +147,7 @@ static unsigned int exec(dsp_component_cmd_t cmd, spu.s_chan = mem->in.s_chan; spu.rvb = &mem->in.rvb; worker = &mem->worker; - memcpy(&spu_config, &mem->spu_config, sizeof(spu_config)); + memcpy(&spu_config, &mem->in.spu_config, sizeof(spu_config)); mem->sizeof_region_mem = sizeof(*mem); mem->offsetof_s_chan1 = offsetof(typeof(*mem), in.s_chan[1]); @@ -131,16 +159,18 @@ static unsigned int exec(dsp_component_cmd_t cmd, case CCMD_DOIT: worker->active = ACTIVE_CNT; worker->boot_cnt++; - syscalls.cache_wb(&worker->i_done, 64, 1); - memcpy(&spu_config, &mem->spu_config, sizeof(spu_config)); + syscalls.cache_inv(worker, 128, 1); + syscalls.cache_wb(&worker->i_done, 128, 1); + memcpy(&spu_config, &mem->in.spu_config, sizeof(spu_config)); + + if (worker->ram_dirty) + // it's faster to do it all than just a 512k buffer + syscalls.cache_wbInvAll(); do_processing(); - // c64_tools lib does BCACHE_wbInvAll() when it receives mailbox irq, - // but invalidate anyway in case c64_tools is ever fixed.. - // XXX edit: don't bother as reverb is not handled, will fix if needed - //syscalls.cache_inv(mem, sizeof(mem->spu_ram) + sizeof(mem->SB), 0); - //syscalls.cache_inv(&mem->in, sizeof(mem->in), 0); + syscalls.cache_inv(&mem->SB, sizeof(mem->SB), 0); + syscalls.cache_inv(&mem->in, sizeof(mem->in), 0); break; default: diff --git a/plugins/dfsound/spu_config.h b/plugins/dfsound/spu_config.h index fce1cdaa..3e88a2c2 100644 --- a/plugins/dfsound/spu_config.h +++ b/plugins/dfsound/spu_config.h @@ -8,6 +8,7 @@ typedef struct int iUseInterpolation; int iTempo; int iUseThread; + int iUseFixedUpdates; // output fixed number of samples/frame // status int iThreadAvail; diff --git a/plugins/gpu_unai/gpu.cpp b/plugins/gpu_unai/gpu.cpp index d5096170..1552bed9 100644 --- a/plugins/gpu_unai/gpu.cpp +++ b/plugins/gpu_unai/gpu.cpp @@ -432,7 +432,7 @@ void GPU_readDataMem(u32* dmaAddress, s32 dmaCount) { if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024; // lower 16 bit - u32 data = (unsigned long)pvram[px]; + u32 data = pvram[px]; if (++px>=x_end) { @@ -442,7 +442,7 @@ void GPU_readDataMem(u32* dmaAddress, s32 dmaCount) if ((&pvram[px])>(VIDEO_END)) pvram-=512*1024; // higher 16 bit (always, even if it's an odd width) - data |= (unsigned long)(pvram[px])<<16; + data |= (u32)(pvram[px])<<16; *dmaAddress++ = data; diff --git a/plugins/gpu_unai/gpu_command.h b/plugins/gpu_unai/gpu_command.h index 049b1462..d6e7a742 100644 --- a/plugins/gpu_unai/gpu_command.h +++ b/plugins/gpu_unai/gpu_command.h @@ -21,9 +21,9 @@ /////////////////////////////////////////////////////////////////////////////// INLINE void gpuSetTexture(u16 tpage) { - long tp; - long tx, ty; - GPU_GP1 = (GPU_GP1 & ~0x7FF) | (tpage & 0x7FF); + u32 tp; + u32 tx, ty; + GPU_GP1 = (GPU_GP1 & ~0x1FF) | (tpage & 0x1FF); TextureWindow[0]&= ~TextureWindow[2]; TextureWindow[1]&= ~TextureWindow[3]; @@ -31,6 +31,7 @@ INLINE void gpuSetTexture(u16 tpage) tp = (tpage >> 7) & 3; tx = (tpage & 0x0F) << 6; ty = (tpage & 0x10) << 4; + if (tp == 3) tp = 2; tx += (TextureWindow[0] >> (2 - tp)); ty += TextureWindow[1]; @@ -437,8 +438,8 @@ void gpuSendPacketFunction(const int PRIM) case 0xE5: { const u32 temp = PacketBuffer.U4[0]; - DrawingOffset[0] = ((long)temp<<(32-11))>>(32-11); - DrawingOffset[1] = ((long)temp<<(32-22))>>(32-11); + DrawingOffset[0] = ((s32)temp<<(32-11))>>(32-11); + DrawingOffset[1] = ((s32)temp<<(32-22))>>(32-11); //isSkip = false; DO_LOG(("DrawingOffset(0x%x)\n",PRIM)); } diff --git a/plugins/gpu_unai/gpu_raster_line.h b/plugins/gpu_unai/gpu_raster_line.h index 4edfa06f..fc59b797 100644 --- a/plugins/gpu_unai/gpu_raster_line.h +++ b/plugins/gpu_unai/gpu_raster_line.h @@ -26,7 +26,7 @@ #define GPU_DIGITS 16 #define GPU_DIGITSC (GPU_DIGITS+3) -INLINE long GPU_DIV(long rs, long rt) +INLINE s32 GPU_DIV(s32 rs, s32 rt) { return rt ? (rs / rt) : (0); } diff --git a/plugins/gpu_unai/gpulib_if.cpp b/plugins/gpu_unai/gpulib_if.cpp index 0d506bc7..646b0f22 100644 --- a/plugins/gpu_unai/gpulib_if.cpp +++ b/plugins/gpu_unai/gpulib_if.cpp @@ -490,8 +490,8 @@ int do_cmd_list(unsigned int *list, int list_len, int *last_cmd) } case 0xE5: { const u32 temp = PacketBuffer.U4[0]; - DrawingOffset[0] = ((long)temp<<(32-11))>>(32-11); - DrawingOffset[1] = ((long)temp<<(32-22))>>(32-11); + DrawingOffset[0] = ((s32)temp<<(32-11))>>(32-11); + DrawingOffset[1] = ((s32)temp<<(32-22))>>(32-11); gpu.ex_regs[5] = temp; break; } diff --git a/plugins/gpulib/gpu.c b/plugins/gpulib/gpu.c index 0e6fe63d..125bd89b 100644 --- a/plugins/gpulib/gpu.c +++ b/plugins/gpulib/gpu.c @@ -21,7 +21,6 @@ #define unlikely(x) #define preload(...) #define noinline -#error huh #endif #define gpu_log(fmt, ...) \ @@ -522,7 +521,6 @@ void GPUwriteData(uint32_t data) long GPUdmaChain(uint32_t *rambase, uint32_t start_addr) { uint32_t addr, *list, ld_addr = 0; - uint32_t *llist_entry = NULL; int len, left, count; long cpu_cycles = 0; @@ -531,15 +529,6 @@ long GPUdmaChain(uint32_t *rambase, uint32_t start_addr) if (unlikely(gpu.cmd_len > 0)) flush_cmd_buffer(); - // ff7 sends it's main list twice, detect this - if (*gpu.state.frame_count == gpu.state.last_list.frame && - *gpu.state.hcnt - gpu.state.last_list.hcnt <= 1 && - gpu.state.last_list.cycles > 2048) - { - llist_entry = rambase + (gpu.state.last_list.addr & 0x1fffff) / 4; - *llist_entry |= 0x800000; - } - log_io("gpu_dma_chain\n"); addr = start_addr & 0xffffff; for (count = 0; (addr & 0x800000) == 0; count++) @@ -586,9 +575,6 @@ long GPUdmaChain(uint32_t *rambase, uint32_t start_addr) } } - if (llist_entry) - *llist_entry &= ~0x800000; - gpu.state.last_list.frame = *gpu.state.frame_count; gpu.state.last_list.hcnt = *gpu.state.hcnt; gpu.state.last_list.cycles = cpu_cycles; diff --git a/plugins/gpulib/vout_pl.c b/plugins/gpulib/vout_pl.c index 541b5e0b..a9437cb1 100644 --- a/plugins/gpulib/vout_pl.c +++ b/plugins/gpulib/vout_pl.c @@ -89,11 +89,12 @@ void vout_blank(void) { int w = gpu.screen.hres; int h = gpu.screen.h; + + check_mode_change(0); if (gpu.state.enhancement_active) { w *= 2; h *= 2; } - check_mode_change(0); cbs->pl_vout_flip(NULL, 1024, gpu.status.rgb24, w, h); } diff --git a/readme.txt b/readme.txt index 435a682d..55e1feb8 100644 --- a/readme.txt +++ b/readme.txt @@ -113,6 +113,14 @@ the main menu where it is possible to enable/disable individual cheats. Changelog --------- +r22 (2015-02-05) +* general: fixed a race condition/crash in threaded SPU mode +* pandora: C64x: fixed compatibility with newer c64_tools, enabled L2 cache +* frontend: fixed control config corruption on load for devices that are + disconnected on startup +* some dma accuracy improvements, might fix occasional glitches in ff7 +* ARMv6 build and the dynarec now make use of available instructions (gizmo98) + r21 (2015-01-12) + general: added ability to run SPU emulation on a separate thread, enabled it by default when multicore CPU is detected. Significant effort was made to