SekRunPS Cyclone integration

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@68 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
notaz 2007-03-14 17:59:53 +00:00
parent 8b71d0ebf9
commit 7336a99a49
12 changed files with 278 additions and 47 deletions

View file

@ -12,6 +12,7 @@
#include "../unzip/unzip.h"
#include "../unzip/unzip_stream.h"
static char *rom_exts[] = { "bin", "gen", "smd", "iso" };
@ -78,6 +79,9 @@ zip_failed:
f = fopen(path, "rb");
if (f == NULL) return NULL;
/* we use our own buffering */
setvbuf(f, NULL, _IONBF, 0);
file = malloc(sizeof(*file));
if (file == NULL) {
fclose(f);
@ -120,7 +124,8 @@ int pm_seek(pm_file *stream, long offset, int whence)
{
if (stream->type == PMT_UNCOMPRESSED)
{
return fseek(stream->file, offset, whence);
fseek(stream->file, offset, whence);
return ftell(stream->file);
}
else if (stream->type == PMT_ZIP)
{
@ -243,7 +248,10 @@ int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize)
// Allocate space for the rom plus padding
rom=PicoCartAlloc(size);
if (rom==NULL) return 1; // { fclose(f); return 1; }
if (rom==NULL) {
printf("out of memory (wanted %i)\n", size);
return 1;
}
pm_read(rom,size,f); // Load up the rom

View file

@ -24,8 +24,13 @@ extern "C" {
#ifdef EMU_C68K
#include "../cpu/Cyclone/Cyclone.h"
extern struct Cyclone PicoCpu, PicoCpuS68k;
#define SekCyclesLeft PicoCpu.cycles // cycles left for this run
#define SekSetCyclesLeft(c) PicoCpu.cycles=c
#define SekCyclesLeftNoMCD PicoCpu.cycles // cycles left for this run
#define SekCyclesLeft \
(((PicoMCD&1) && (PicoOpt & 0x2000)) ? (SekCycleAim-SekCycleCnt) : SekCyclesLeftNoMCD)
#define SekSetCyclesLeftNoMCD(c) PicoCpu.cycles=c
#define SekSetCyclesLeft(c) { \
if ((PicoMCD&1) && (PicoOpt & 0x2000)) SekCycleCnt=SekCycleAim-(c); else SekSetCyclesLeftNoMCD(c); \
}
#define SekPc (PicoCpu.pc-PicoCpu.membase)
#define SekPcS68k (PicoCpuS68k.pc-PicoCpuS68k.membase)
#endif
@ -55,8 +60,13 @@ extern int m68k_ICount;
extern m68ki_cpu_core PicoM68kCPU; // MD's CPU
extern m68ki_cpu_core PicoS68kCPU; // Mega CD's CPU
#ifndef SekCyclesLeft
#define SekCyclesLeft m68k_cycles_remaining()
#define SekSetCyclesLeft(c) SET_CYCLES(c)
#define SekCyclesLeftNoMCD m68k_cycles_remaining()
#define SekCyclesLeft \
(((PicoMCD&1) && (PicoOpt & 0x2000)) ? (SekCycleAim-SekCycleCnt) : SekCyclesLeftNoMCD)
#define SekSetCyclesLeftNoMCD(c) SET_CYCLES(c)
#define SekSetCyclesLeft(c) { \
if ((PicoMCD&1) && (PicoOpt & 0x2000)) SekCycleCnt=SekCycleAim-(c); else SET_CYCLES(c); \
}
#define SekPc m68k_get_reg(&PicoM68kCPU, M68K_REG_PC)
#define SekPcS68k m68k_get_reg(&PicoS68kCPU, M68K_REG_PC)
#endif

View file

@ -89,7 +89,8 @@ static void DmaSlow(int len)
if(Pico.m.scanline != -1) {
Pico.m.dma_bytes += len;
SekSetCyclesLeft(SekCyclesLeft - CheckDMA());
if ((PicoMCD&1) && (PicoOpt & 0x2000)) SekCycleCnt+=CheckDMA();
else SekSetCyclesLeftNoMCD(SekCyclesLeftNoMCD - CheckDMA());
} else {
// be approximate in non-accurate mode
SekSetCyclesLeft(SekCyclesLeft - (len*(((488<<8)/167))>>8));

View file

@ -421,7 +421,6 @@ u16 PicoReadM68k16(u32 a)
a = (a&2) | (cell_map(a >> 2) << 2); // cell arranged
else a &= 0x1fffe;
d = *(u16 *)(Pico_mcd->word_ram1M[bank]+a);
//d = 0xaaaa;
} else {
// allow access in any mode, like Gens does
d = *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
@ -936,9 +935,6 @@ static void decode_write8(u32 a, u8 d, int r3)
u8 *pd = Pico_mcd->word_ram1M[!(r3 & 1)] + (((a>>1)^1)&0x1ffff);
u8 oldmask = (a&1) ? 0xf0 : 0x0f;
//if ((a & 0x3ffff) < 0x28000) return;
//return;
r3 &= 0x18;
d &= 0x0f;
if (!(a&1)) d <<= 4;

View file

@ -83,45 +83,56 @@ static __inline void SekRunS68k(int cyc)
#endif
}
#define PS_STEP_M68K 8
#define PS_STEP_S68K 13
#define PS_STEP_M68K ((488<<16)/20) // ~24
//#define PS_STEP_S68K 13
#ifndef _ASM_CD_PICO_C
static __inline void SekRunPS(int cyc_m68k, int cyc_s68k)
{
int cyc_do_m68k, cyc_do_s68k, it=0;
int cyc_done_m68k=0, cyc_done_s68k=0;
int cycn, cycn_s68k, cyc_do;
int d_cm = 0, d_cs = 0, ex;
SekCycleAim+=cyc_m68k;
SekCycleAimS68k+=cyc_s68k;
cyc_do_m68k=SekCycleAim-SekCycleCnt;
cyc_do_s68k=SekCycleAimS68k-SekCycleCntS68k;
while (cyc_done_m68k < cyc_do_m68k || cyc_done_s68k < cyc_do_s68k) {
it++;
if (cyc_done_m68k < cyc_do_m68k && it*PS_STEP_M68K > cyc_done_m68k) {
// fprintf(stderr, "=== start %3i/%3i [%3i/%3i] {%05i.%i} ===\n", cyc_m68k, cyc_s68k,
// SekCycleAim-SekCycleCnt, SekCycleAimS68k-SekCycleCntS68k, Pico.m.frame_count, Pico.m.scanline);
/* loop 488 downto 0 in steps of PS_STEP */
for (cycn = (488<<16)-PS_STEP_M68K; cycn >= 0; cycn -= PS_STEP_M68K)
{
ex = 0;
cycn_s68k = (cycn + cycn/2 + cycn/8) >> 16;
//fprintf(stderr, "%3i/%3i: ", cycn>>16, cycn_s68k);
if ((cyc_do = SekCycleAim-SekCycleCnt-(cycn>>16)) > 0) {
#if defined(EMU_C68K)
PicoCpu.cycles = PS_STEP_M68K;
PicoCpu.cycles = cyc_do;
CycloneRun(&PicoCpu);
cyc_done_m68k += PS_STEP_M68K - PicoCpu.cycles;
SekCycleCnt += cyc_do - PicoCpu.cycles;
#elif defined(EMU_M68K)
m68k_set_context(&PicoM68kCPU);
cyc_done_m68k += m68k_execute(PS_STEP_M68K);
SekCycleCnt += (ex = m68k_execute(cyc_do));
#endif
} //else dprintf("m68k skipping it #%i", it);
if (cyc_done_s68k < cyc_do_s68k && it*PS_STEP_S68K > cyc_done_s68k) {
}
//fprintf(stderr, "%3i ", ex); d_cm += ex; ex = 0;
if ((cyc_do = SekCycleAimS68k-SekCycleCntS68k-cycn_s68k) > 0) {
#if defined(EMU_C68K)
PicoCpuS68k.cycles = PS_STEP_S68K;
PicoCpuS68k.cycles = cyc_do;
CycloneRun(&PicoCpuS68k);
cyc_done_s68k += PS_STEP_S68K - PicoCpuS68k.cycles;
SekCycleCntS68k += cyc_do - PicoCpuS68k.cycles;
#elif defined(EMU_M68K)
m68k_set_context(&PicoS68kCPU);
cyc_done_s68k += m68k_execute(PS_STEP_S68K);
SekCycleCntS68k += (ex = m68k_execute(cyc_do));
#endif
} //else dprintf("s68k skipping it #%i", it);
}
SekCycleCnt += cyc_done_m68k;
SekCycleCntS68k += cyc_done_s68k;
//dprintf("== end SekRunPS, it=%i ==", it);
//fprintf(stderr, "%3i\n", ex); d_cs += ex;
}
//fprintf(stderr, "== end %3i/%3i ==\n", d_cm, d_cs);
}
#else
void SekRunPS(int cyc_m68k, int cyc_s68k);
#endif
static __inline void check_cd_dma(void)
{
@ -271,7 +282,7 @@ static int PicoFrameHintsMCD(void)
//dprintf("m68k starting exec @ %06x", SekPc);
if(Pico.m.dma_bytes) SekCycleCnt+=CheckDMA();
if((PicoOpt & 0x2000) && (Pico_mcd->m.busreq&3) == 1) {
SekRunPS(cycles_68k, cycles_s68k); // "perfect sync"
SekRunPS(cycles_68k, cycles_s68k); // "better/perfect sync"
} else {
SekRun(cycles_68k);
if ((Pico_mcd->m.busreq&3) == 1) // no busreq/no reset

179
Pico/cd/Pico.s Normal file
View file

@ -0,0 +1,179 @@
@ vim:filetype=armasm
@ SekRunPS runs PicoCpu and PicoCpuS68k interleaved in steps of PS_STEP_M68K
@ cycles. This is done without calling CycloneRun and jumping directly to
@ Cyclone code to avoid pushing/popping all the registers every time.
@ (c) Copyright 2007, Grazvydas "notaz" Ignotas
@ All Rights Reserved
.equiv PS_STEP_M68K, ((488<<16)/20) @ ~24
@ .extern is ignored by gas, we add these here just to see what we depend on.
.extern CycloneJumpTab
.extern CycloneDoInterrupt
.extern PicoCpu
.extern PicoCpuS68k
.extern SekCycleAim
.extern SekCycleCnt
.extern SekCycleAimS68k
.extern SekCycleCntS68k
.text
.align 4
.global SekRunPS @ cyc_m68k, cyc_s68k
SekRunPS:
stmfd sp!, {r4-r11,lr}
sub sp, sp, #2*4 @ sp[0] = main_cycle_cnt, sp[4] = run_cycle_cnt
@ override CycloneEnd for both contexts
ldr r7, =PicoCpu
ldr lr, =PicoCpuS68k
ldr r2, =CycloneEnd_M68k
ldr r3, =CycloneEnd_S68k
str r2, [r7,#0x54]
str r3, [lr,#0x54]
@ update aims
ldr r8, =SekCycleAim
ldr r9, =SekCycleAimS68k
ldr r2, [r8]
ldr r3, [r9]
add r2, r2, r0
add r3, r3, r1
str r2, [r8]
str r3, [r9]
ldr r1, =SekCycleCnt
ldr r0, =((488<<16)-PS_STEP_M68K)
ldr r6, =CycloneJumpTab
@ schedule m68k for the first time..
ldr r1, [r1]
str r0, [sp] @ main target 'left cycle' counter
sub r1, r2, r1
subs r5, r1, r0, asr #16
ble schedule_s68k @ m68k has not enough cycles
str r5, [sp,#4] @ run_cycle_cnt
b CycloneRunLocal
CycloneEnd_M68k:
ldr r3, =SekCycleCnt
ldr r0, [sp,#4] @ run_cycle_cnt
ldr r1, [r3]
str r4, [r7,#0x40] ;@ Save Current PC + Memory Base
strb r9, [r7,#0x46] ;@ Save Flags (NZCV)
sub r0, r0, r5 @ subtract leftover cycles (which should be negative)
add r0, r0, r1
str r0, [r3]
schedule_s68k:
ldr r8, =SekCycleCntS68k
ldr r9, =SekCycleAimS68k
ldr r3, [sp]
ldr r8, [r8]
ldr r9, [r9]
sub r0, r9, r8
add r3, r3, r3, asr #1
add r3, r3, r3, asr #3 @ cycn_s68k = (cycn + cycn/2 + cycn/8)
subs r5, r0, r3, asr #16
ble schedule_m68k @ s68k has not enough cycles
ldr r7, =PicoCpuS68k
str r5, [sp,#4] @ run_cycle_cnt
b CycloneRunLocal
CycloneEnd_S68k:
ldr r3, =SekCycleCntS68k
ldr r0, [sp,#4] @ run_cycle_cnt
ldr r1, [r3]
str r4, [r7,#0x40] ;@ Save Current PC + Memory Base
strb r9, [r7,#0x46] ;@ Save Flags (NZCV)
sub r0, r0, r5 @ subtract leftover cycles (should be negative)
add r0, r0, r1
str r0, [r3]
schedule_m68k:
ldr r1, =PS_STEP_M68K
ldr r3, [sp] @ main_cycle_cnt
ldr r8, =SekCycleCnt
ldr r9, =SekCycleAim
subs r3, r3, r1
bmi SekRunPS_end
ldr r8, [r8]
ldr r9, [r9]
str r3, [sp] @ update main_cycle_cnt
sub r0, r9, r8
subs r5, r0, r3, asr #16
ble schedule_s68k @ m68k has not enough cycles
ldr r7, =PicoCpu
str r5, [sp,#4] @ run_cycle_cnt
b CycloneRunLocal
SekRunPS_end:
ldr r7, =PicoCpu
ldr lr, =PicoCpuS68k
mov r0, #0
str r0, [r7,#0x54] @ remove CycloneEnd handler
str r0, [lr,#0x54]
@ return
add sp, sp, #2*4
ldmfd sp!, {r4-r11,pc}
CycloneRunLocal:
;@ r0-3 = Temporary registers
ldr r4,[r7,#0x40] ;@ r4 = Current PC + Memory Base
;@ r5 = Cycles
;@ r6 = Opcode Jump table
;@ r7 = Pointer to Cpu Context
;@ r8 = Current Opcode
ldrb r9,[r7,#0x46] ;@ r9 = Flags (NZCV)
ldr r0,[r7,#0x44]
mov r9,r9,lsl #28 ;@ r9 = Flags 0xf0000000, cpsr format
;@ r10 = Source value / Memory Base
;@ CheckInterrupt:
movs r0,r0,lsr #24 ;@ Get IRQ level
beq NoIntsLocal
cmp r0,#6 ;@ irq>6 ?
ldrleb r1,[r7,#0x44] ;@ Get SR high: T_S__III
andle r1,r1,#7 ;@ Get interrupt mask
cmple r0,r1 ;@ irq<=6: Is irq<=mask ?
blgt CycloneDoInterrupt
;@ Check if interrupt used up all the cycles:
subs r5,r5,#0
ldrlt r1,[r7,#0x54]
bxlt r1 ;@ jump to alternative CycloneEnd
NoIntsLocal:
;@ Check if our processor is in stopped state and jump to opcode handler if not
ldr r0,[r7,#0x58]
ldrh r8,[r4],#2 ;@ Fetch first opcode
tst r0,r0 ;@ stopped?
ldreq pc,[r6,r8,asl #2] ;@ Jump to opcode handler
@ stopped
ldr r1,[r7,#0x54]
mov r5,#0
bx r1

View file

@ -93,7 +93,7 @@ void CheckInterrupt(int op)
ot(" ldrleb r1,[r7,#0x44] ;@ Get SR high: T_S__III\n");
ot(" andle r1,r1,#7 ;@ Get interrupt mask\n");
ot(" cmple r0,r1 ;@ irq<=6: Is irq<=mask ?\n");
ot(" blgt DoInterrupt\n");
ot(" blgt CycloneDoInterrupt\n");
ot("NoInts%x%s\n", op,ms?"":":");
ot("\n");
}
@ -109,7 +109,7 @@ static void PrintFramework()
ot(" mov r7,r0 ;@ r7 = Pointer to Cpu Context\n");
ot(" ;@ r0-3 = Temporary registers\n");
ot(" ldrb r9,[r7,#0x46] ;@ r9 = Flags (NZCV)\n");
ot(" ldr r6,=JumpTab ;@ r6 = Opcode Jump table\n");
ot(" ldr r6,=CycloneJumpTab ;@ r6 = Opcode Jump table\n");
ot(" ldr r5,[r7,#0x5c] ;@ r5 = Cycles\n");
ot(" ldr r4,[r7,#0x40] ;@ r4 = Current PC + Memory Base\n");
ot(" ;@ r8 = Current Opcode\n");
@ -124,7 +124,7 @@ static void PrintFramework()
ot(" ldrleb r1,[r7,#0x44] ;@ Get SR high: T_S__III\n");
ot(" andle r1,r1,#7 ;@ Get interrupt mask\n");
ot(" cmple r0,r1 ;@ irq<=6: Is irq<=mask ?\n");
ot(" blgt DoInterrupt\n");
ot(" blgt CycloneDoInterrupt\n");
ot(";@ Check if interrupt used up all the cycles:\n");
ot(" subs r5,r5,#0\n");
ot(" blt CycloneEndNoBack\n");
@ -143,7 +143,14 @@ static void PrintFramework()
ot("CycloneEnd%s\n", ms?"":":");
ot(" sub r4,r4,#2\n");
ot("CycloneEndNoBack%s\n", ms?"":":");
#ifdef CYCLONE_FOR_PICODRIVE
ot(" ldr r1,[r7,#0x54]\n");
ot(" mov r9,r9,lsr #28\n");
ot(" tst r1,r1\n");
ot(" bxne r1 ;@ jump to alternative CycloneEnd\n");
#else
ot(" mov r9,r9,lsr #28\n");
#endif
ot(" str r4,[r7,#0x40] ;@ Save Current PC + Memory Base\n");
ot(" str r5,[r7,#0x5c] ;@ Save Cycles\n");
ot(" strb r9,[r7,#0x46] ;@ Save Flags (NZCV)\n");
@ -161,7 +168,7 @@ static void PrintFramework()
ot(";@ uncompress jump table\n");
if (ms) ot("CycloneInit\n");
else ot("CycloneInit:\n");
ot(" ldr r12,=JumpTab\n");
ot(" ldr r12,=CycloneJumpTab\n");
ot(" add r0,r12,#0xe000*4 ;@ ctrl code pointer\n");
ot(" ldr r1,[r0,#-4]\n");
ot(" tst r1,r1\n");
@ -187,7 +194,7 @@ static void PrintFramework()
ot(" bgt unc_loop_in\n");
ot(" b unc_loop\n");
ot("unc_finish%s\n", ms?"":":");
ot(" ldr r12,=JumpTab\n");
ot(" ldr r12,=CycloneJumpTab\n");
ot(" ;@ set a-line and f-line handlers\n");
ot(" add r0,r12,#0xa000*4\n");
ot(" ldr r1,[r0,#4] ;@ a-line handler\n");
@ -255,7 +262,7 @@ static void PrintFramework()
ot("\n");
ot(";@ DoInterrupt - r0=IRQ number\n");
ot("DoInterrupt%s\n", ms?"":":");
ot("CycloneDoInterrupt%s\n", ms?"":":");
ot(" stmdb sp!,{lr} ;@ Push ARM return address\n");
ot(";@ Get IRQ Vector address:\n");
@ -475,7 +482,7 @@ static void PrintJumpTable()
// space for decompressed table
ot(ms?" area |.data|, data\n":" .data\n .align 4\n\n");
ot("JumpTab%s\n", ms?"":":");
ot("CycloneJumpTab%s\n", ms?"":":");
if(ms) {
for(i = 0; i < 0xa000/8; i++)
ot(" dcd 0,0,0,0,0,0,0,0\n");
@ -548,7 +555,7 @@ static void PrintJumpTable()
ot("\n");
free(indexes);
#else
ot("JumpTab%s\n", ms?"":":");
ot("CycloneJumpTab%s\n", ms?"":":");
len=0xfffe; // Hmmm, armasm 2.50.8684 messes up with a 0x10000 long jump table
// notaz: same thing with GNU as 2.9-psion-98r2 (reloc overflow)
// this is due to COFF objects using only 2 bytes for reloc count
@ -613,6 +620,10 @@ static int CycloneMake()
ot(" .global CycloneSetSr\n");
ot(" .global CycloneGetSr\n");
ot(" .global CycloneVer\n");
#ifdef CYCLONE_FOR_PICODRIVE
ot(" .global CycloneDoInterrupt\n");
ot(" .global CycloneJumpTab\n");
#endif
ot("CycloneVer: .long 0x%.4x\n",CycloneVer);
}
ot("\n");
@ -623,6 +634,8 @@ static int CycloneMake()
if (ms) ot(" END\n");
ot("\n\n;@ vim:filetype=armasm\n");
fclose(AsmFile); AsmFile=NULL;
#if 0

View file

@ -1,6 +1,6 @@
CFLAGS = -Wall
CFLAGS = -Wall -DCYCLONE_FOR_PICODRIVE
ALL : cyclone.s
all : cyclone.s
cyclone.s : Cyclone.exe
./Cyclone.exe

View file

@ -12,12 +12,13 @@ asm_memory = 0 # TODO
asm_render = 1
asm_ym2612 = 1
asm_misc = 1
asm_cdpico = 1
#profile = 1
#use_musashi = 1
#up = 1
DEFINC = -I../.. -I. -DARM -D__GP2X__ -D_UNZIP_SUPPORT # -DBENCHMARK
COPT_COMMON = -static -s -O3 -ftracer -fstrength-reduce -Wall -funroll-loops -fomit-frame-pointer -fstrict-aliasing -ffast-math
COPT_COMMON = -static -O3 -ftracer -fstrength-reduce -Wall -funroll-loops -fomit-frame-pointer -fstrict-aliasing -ffast-math # -s
ifeq "$(profile)" "1"
COPT_COMMON += -fprofile-generate
endif
@ -61,6 +62,10 @@ ifeq "$(asm_misc)" "1"
DEFINC += -D_ASM_MISC_C
OBJS += ../../Pico/misc_asm.o
endif
ifeq "$(asm_cdpico)" "1"
DEFINC += -D_ASM_CD_PICO_C
OBJS += ../../Pico/cd/pico_asm.o
endif
# Pico - sound
OBJS += ../../Pico/sound/mix_asm.o
OBJS += ../../Pico/sound/sound.o ../../Pico/sound/sn76496.o ../../Pico/sound/ym2612.o
@ -93,8 +98,10 @@ all: PicoDrive.gpe
PicoDrive.gpe : $(OBJS) helix/helix_mp3.a
@echo $@
@$(GCC) -o $@ $(COPT) $^ -lm
@$(GCC) -o $@ $(COPT) $^ -lm -Wl,-Map=PicoDrive.map
ifeq ($(DEBUG),)
@$(STRIP) $@
endif
# @$(GCC) $(COPT) $(OBJS) -lm -o PicoDrive_.gpe
# @gpecomp PicoDrive_.gpe $@
ifeq "$(up)" "1"
@ -137,6 +144,9 @@ testrefr.gpe : test.o gp2x.o asmutils.o
../../Pico/misc_asm.o : ../../Pico/misc.s
@echo $<
@$(AS) $(ASOPT) $< -o $@
../../Pico/cd/pico_asm.o : ../../Pico/cd/Pico.s
@echo $<
@$(AS) $(ASOPT) $< -o $@
# build Cyclone
../../cpu/Cyclone/proj/Cyclone.s :

View file

@ -547,7 +547,7 @@ int emu_WriteConfig(int game)
strncpy(cfg, PicoConfigFile, 511);
cfg[511] = 0;
} else {
romfname_ext(cfg, "cfg", ".pbcfg");
romfname_ext(cfg, "cfg/", ".pbcfg");
}
printf("emu_WriteConfig: %s ", cfg);

View file

@ -744,7 +744,7 @@ static void draw_cd_menu_options(int menu_sel, char *b_us, char *b_eu, char *b_j
gp2x_text_out8(tl_x, (y+=10), "CD LEDs %s", (currentConfig.EmuOpt &0x0400)?"ON":"OFF"); // 3
gp2x_text_out8(tl_x, (y+=10), "CDDA audio (using mp3s) %s", (currentConfig.PicoOpt&0x0800)?"ON":"OFF"); // 4
gp2x_text_out8(tl_x, (y+=10), "PCM audio %s", (currentConfig.PicoOpt&0x0400)?"ON":"OFF"); // 5
gp2x_text_out8(tl_x, (y+=10), "Better sync (very slow) %s", (currentConfig.PicoOpt&0x2000)?"ON":"OFF"); // 6
gp2x_text_out8(tl_x, (y+=10), "Better sync (slow) %s", (currentConfig.PicoOpt&0x2000)?"ON":"OFF"); // 6
gp2x_text_out8(tl_x, (y+=10), "ReadAhead buffer %s", ra_buff); // 7
gp2x_text_out8(tl_x, (y+=10), "Done");

View file

@ -216,6 +216,9 @@ Changelog
+ Added data pre-buffering support, this allows to reduce frequency of short pauses
in FMV games, but makes those pauses longer.
* Fixed PCM DMA transfers (intro FMV in Popful Mail).
+ Properly implemented "decode" data transformation (Jaguar XJ220).
* Integrated "better sync" code into cyclone code, what made this mode much faster.
* Fixed a bug related to game specific config saving.
1.201
+ Added basic cheat support (GameGenie and Genecyst patches).