From e1591a12a775a600572ffccb2d6f8f4d6343b7dd Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 6 May 2007 19:14:50 +0000 Subject: [PATCH] FDS fixed for asm core git-svn-id: file:///home/notaz/opt/svn/fceu@126 be3aeb3a-fb24-0410-a615-afba39da0efa --- Makefile.base | 2 +- Makefile.gp2x | 7 +++-- fds.c | 43 ++++++++++++++++++++++++++++--- ncpu.S | 71 +++++++++++++++++++++++++++++++++++++++++---------- x6502.h | 6 +++-- 5 files changed, 107 insertions(+), 22 deletions(-) diff --git a/Makefile.base b/Makefile.base index 756e55c..bd411f2 100644 --- a/Makefile.base +++ b/Makefile.base @@ -9,7 +9,7 @@ include input/Makefile fceu2: ${OBJECTS} ${MOBJS} ${MUOBJS} ${MUSOBJS} ${INPOBJS} ${OBJDRIVER} ${CC} -o fceu ${OBJECTS} ${MOBJS} ${MUOBJS} ${MUSOBJS} ${INPOBJS} ${OBJDRIVER} ${LDRIVER} -ifndef DEBUG +ifndef NOSTRIP $(STRIP) fceu endif diff --git a/Makefile.gp2x b/Makefile.gp2x index af7d4ae..137b353 100644 --- a/Makefile.gp2x +++ b/Makefile.gp2x @@ -9,12 +9,15 @@ B = drivers/gp2x/ ifdef DEBUG TFLAGS += -ggdb LDRIVER += -ggdb +NOSTRIP = 1 else TFLAGS += -ftracer -fstrength-reduce -funroll-loops -fomit-frame-pointer -fstrict-aliasing -ffast-math -TFLAGS += -O3 # -pg -LDRIVER += -O3 # -pg +TFLAGS += -O3 #-pg -fno-omit-frame-pointer +LDRIVER += -O3 #-pg -fno-omit-frame-pointer endif +#NOSTRIP = 1 + asm_6502=1 #debug_asm_6502=1 diff --git a/fds.c b/fds.c index f0640a0..41b3a5d 100644 --- a/fds.c +++ b/fds.c @@ -144,6 +144,17 @@ static void FDSInit(void) FDSSoundReset(); InDisk=0; SelectDisk=0; + +#ifdef ASM_6502 + { + int page; + // asm code needs pages to be set again.. + for (page=12; page<28; page++) // 0x6000-0xdfff 32K RAM + Page[page]=FDSRAM - (page<<11) + ((page-12)<<11); + for (; page<32; page++) // 0xe000-0xffff 8K BIOS + Page[page]=FDSBIOS - (page<<11) + ((page-28)<<11); + } +#endif } void FCEU_FDSInsert(void) @@ -188,7 +199,7 @@ void FCEU_FDSSelect(void) static void FP_FASTAPASS(1) FDSFix(int a) { - if((IRQa&2) && IRQCount) + if(IRQCount && (IRQa&2)) { IRQCount-=a; if(IRQCount<=0) @@ -224,8 +235,13 @@ static DECLFR(FDSRead4030) uint8 ret=0; /* Cheap hack. */ +#ifndef ASM_6502 if(X.IRQlow&FCEU_IQEXT) ret|=1; if(X.IRQlow&FCEU_IQEXT2) ret|=2; +#else + if((nes_registers[4]>>8)&FCEU_IQEXT) ret|=1; + if((nes_registers[4]>>8)&FCEU_IQEXT2) ret|=2; +#endif if(!fceuindbg) { @@ -485,7 +501,7 @@ static INLINE void ClockFall(void) clockcount=(clockcount+1)&7; } -static INLINE int32 FDSDoSound(void) +static INLINE int32 FDSDoSound(int32 mul) { fdso.count+=fdso.cycles; if(fdso.count>=((int64)1<<40)) @@ -504,11 +520,14 @@ static INLINE int32 FDSDoSound(void) if(fdso.count>=32768) goto dogk; // Might need to emulate applying the amplitude to the waveform a bit better... +/* { int k=amplitude[0]; if(k>0x20) k=0x20; return (fdso.cwave[b24latch68>>19]*k)*4/((SPSG[0x9]&0x3)+2); } +*/ + return (fdso.cwave[b24latch68>>19]*mul)>>16; } static int32 FBC=0; @@ -517,6 +536,7 @@ static void RenderSound(void) { int32 end, start; int32 x; + int32 mul; start=FBC; end=(SOUNDTS<<16)/soundtsinc; @@ -524,10 +544,27 @@ static void RenderSound(void) return; FBC=end; + // hack for performance, might produce bad results.. + if (!amplitude[0]) + return; + + switch (SPSG[0x9]&0x3) + { + default:mul = (4<<16)/2; + case 1: mul = (4<<16)/3; + case 2: mul = (4<<16)/4; + case 3: mul = (4<<16)/5; + } + { + int k=amplitude[0]; + if(k>0x20) k=0x20; + mul *= k; + } + if(!(SPSG[0x9]&0x80)) for(x=start;x>1; t>>=4; Wave[x>>4]+=t; //(t>>2)-(t>>3); //>>3; diff --git a/ncpu.S b/ncpu.S index d26a9ca..96c867b 100644 --- a/ncpu.S +++ b/ncpu.S @@ -91,7 +91,7 @@ ldmfd sp!,{r0-r3,r12,lr} @@@ @@@ ¤Ê¤ó¤«Ì¾Á°¤¬ÊѤÀ¤Ê(¤É¡¼¤Ç¤â¤¤¡¼¤±¤É¡¼ @@@ -.macro CYCLE_NEXT n, hook_check=1, do_cyc_add=1 +.macro CYCLE_NEXT n, unused=0, do_cyc_add=1 @@DEBUG_INFO .if \do_cyc_add @@ -99,17 +99,17 @@ ldmfd sp!,{r0-r3,r12,lr} .endif subs REG_CYCLE, REG_CYCLE, #\n*48<<16 ble cpu_exec_end -.if \hook_check tst REG_P_REST, #1<<16 - blne do_irq_hook -.endif + bne do_irq_hook + ldrb r0, [REG_PC], #1 tst REG_P_REST, #0xff<<8 ldreq pc, [REG_OP_TABLE, r0, lsl #2] @ do some messing to find out which IRQ is pending.. - tst REG_P_REST, #FCEU_IQNMI<<8 - bne do_int + @ assumption: NMI can be set only on very first run, because it is only set once before vblank.. +@ tst REG_P_REST, #FCEU_IQNMI<<8 +@ bne do_int tst REG_P_REST, #P_REST_I_FLAG @@ if I_FLAG=1, continue execution, don't trigger IRQ bicne REG_P_REST, REG_P_REST, #FCEU_IQTEMP<<8 @@ -2826,13 +2826,26 @@ cpu_exec: @ ldr REG_OP_TABLE, = cpu_exec_table @ set on init - CYCLE_NEXT 0, 0 + ldrb r0, [REG_PC], #1 + tst REG_P_REST, #0xff<<8 + ldreq pc, [REG_OP_TABLE, r0, lsl #2] + + @ assumption: NMI can be set only on very first run, because it is only set once before vblank.. + tst REG_P_REST, #FCEU_IQNMI<<8 + bne do_int + tst REG_P_REST, #P_REST_I_FLAG + @@ if I_FLAG=1, continue execution, don't trigger IRQ + bicne REG_P_REST, REG_P_REST, #FCEU_IQTEMP<<8 + ldrne pc, [REG_OP_TABLE, r0, lsl #2] + @@ I_FLAG=0 and REST is checked, we have a IRQ + b do_int + cpu_exec_end: FLUSH_TIMESTAMP r0 tst REG_P_REST, #1<<16 - blne do_irq_hook_noflushts + bne do_irq_hook_final ldr r0, =nes_registers stmia r0, {r4-r12} @@ -2911,7 +2924,6 @@ nes_internal_ram: .fill 0x100, 1, 0 nes_stack: .fill 0x700, 1, 0 -@ TODO: write code which keeps it up-to-date pc_base: .long 0 MapIRQHook: @@ -3143,29 +3155,60 @@ X6502_Rebase_a: do_irq_hook: FLUSH_TIMESTAMP r0 -do_irq_hook_noflushts: @ get irqhook cycles and r0, REG_CYCLE, #0xff00 - bic REG_CYCLE, REG_CYCLE, #0xff00 mov r0, r0, lsr #8 #ifndef DEBUG_ASM_6502 @ I have reviewed all MapIRQHook functions, they only seem to cause IRQs, not messing cycles or something str REG_P_REST, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x10)] @ might set irq - mov REG_P_REST, lr @ r8 + mov REG_P_REST, REG_OP_TABLE @ r8 @ if somebody modifies MapIRQHook without calling reset, we are doomed mov lr, pc ldr pc, [REG_OP_TABLE, #OTOFFS_IRQ_HOOK] - ldr REG_OP_TABLE, =cpu_exec_table @ got trashed because was in r12 - mov lr, REG_P_REST + mov REG_OP_TABLE, REG_P_REST @ got trashed because was in r12 ldr REG_P_REST, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x10)] @ might set irq #else ldr r1, =mapirq_cyc_a str r0, [r1] mov r1, r0 #endif + + ldrb r0, [REG_PC], #1 + bic REG_CYCLE, REG_CYCLE, #0xff00 + tst REG_P_REST, #0xff<<8 + ldreq pc, [REG_OP_TABLE, r0, lsl #2] + + @ do some messing to find out which IRQ is pending.. + tst REG_P_REST, #P_REST_I_FLAG + @@ if I_FLAG=1, continue execution, don't trigger IRQ + bicne REG_P_REST, REG_P_REST, #FCEU_IQTEMP<<8 + ldrne pc, [REG_OP_TABLE, r0, lsl #2] + @@ I_FLAG=0 and REST is checked, we have a IRQ + b do_int + + +do_irq_hook_final: + ldr r1, =nes_registers + + @ get irqhook cycles + and r0, REG_CYCLE, #0xff00 + bic REG_CYCLE, REG_CYCLE, #0xff00 + mov r0, r0, lsr #8 + + stmia r1, {r4-r12} + + ldmfd r13!,{r4-r11,lr} + +#ifndef DEBUG_ASM_6502 + ldr pc, [REG_OP_TABLE, #OTOFFS_IRQ_HOOK] +#else + ldr r1, =mapirq_cyc_a + str r0, [r1] + mov r1, r0 bx lr +#endif @ vim:filetype=armasm diff --git a/x6502.h b/x6502.h index d6e8a05..83adca0 100644 --- a/x6502.h +++ b/x6502.h @@ -78,8 +78,10 @@ extern void FP_FASTAPASS(1) (*MapIRQHook)(int a); #define X6502_Reset X6502_Reset_a #define X6502_Power X6502_Power_a #define X6502_AddCycles X6502_AddCycles_a -#define X6502_IRQBegin X6502_IRQBegin_a -#define X6502_IRQEnd X6502_IRQEnd_a +//#define X6502_IRQBegin X6502_IRQBegin_a +//#define X6502_IRQEnd X6502_IRQEnd_a +#define X6502_IRQBegin(w) nes_registers[4]|=w<<8 +#define X6502_IRQEnd(w) nes_registers[4]&=~(w<<8) #define X6502_Rebase X6502_Rebase_a #define X6502_GetCycleCount() ((int32)nes_registers[7]>>16) #define X6502_A -- 2.39.2