From 92e249b10ad9e479eddb18974555366dba725ef3 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 14 Apr 2007 20:52:13 +0000 Subject: [PATCH] asm cpu works, added sync()s git-svn-id: file:///home/notaz/opt/svn/fceu@103 be3aeb3a-fb24-0410-a615-afba39da0efa --- Makefile.gp2x | 4 +- drivers/common/config.c | 8 +- drivers/gp2x/gp2x-video.c | 9 ++- drivers/gp2x/minimal.c | 13 +++- fce.c | 101 +++++++++++++++++++++++-- fce.h | 8 +- ines.c | 42 ++++++----- ncpu.S | 154 +++++++++++++++++++++++++++----------- ncpu.h | 3 +- ncpu_debug.c | 47 ++++++++---- state.c | 15 +++- unif.c | 22 ++++-- video.c | 6 ++ x6502.c | 7 +- x6502.h | 23 +++++- 15 files changed, 352 insertions(+), 110 deletions(-) diff --git a/Makefile.gp2x b/Makefile.gp2x index bca522a..5071037 100644 --- a/Makefile.gp2x +++ b/Makefile.gp2x @@ -16,7 +16,7 @@ LDRIVER += -O3 # -pg endif asm_6502=1 -debug_asm_6502=1 +#debug_asm_6502=1 all: fceu @@ -43,7 +43,7 @@ endif x6502.o: x6502.c x6502.h ops.h fce.h sound.h ncpu.o: ncpu.S ncpu.h - $(CC) -c $< -o $@ + $(CC) $(TFLAGS) -c $< -o $@ include Makefile.base diff --git a/drivers/common/config.c b/drivers/common/config.c index 6f87f55..f82323d 100644 --- a/drivers/common/config.c +++ b/drivers/common/config.c @@ -29,6 +29,9 @@ #include #include #include +#ifdef GP2X +#include +#endif #include "../../types.h" #include "config.h" @@ -40,7 +43,7 @@ static int FReadString(FILE *fp, char *str, int n) { z=fgetc(fp); str[x]=z; - x++; + x++; if(z<=0) break; if(x>=n) return 0; } @@ -122,6 +125,9 @@ void SaveFCEUConfig(char *filename, CFGSTRUCT *cfgst) SaveParse(cfgst,fp); fclose(fp); +#ifdef GP2X + sync(); +#endif } static void LoadParse(CFGSTRUCT *cfgst, FILE *fp) diff --git a/drivers/gp2x/gp2x-video.c b/drivers/gp2x/gp2x-video.c index 8bd2be1..f7f09bd 100644 --- a/drivers/gp2x/gp2x-video.c +++ b/drivers/gp2x/gp2x-video.c @@ -214,9 +214,12 @@ static INLINE void printFps(uint8 *screen) } if (showfps) { - fps_str[2] = 0; - gp2x_text(screen, 0, 0, fps_str, FPS_COLOR, 0); - gp2x_text(screen, 0, 10, fps_str+3, FPS_COLOR, 0); + int sep; + for (sep=1; sep < 5; sep++) + if (fps_str[sep] == '/' || fps_str[sep] == 0) break; + fps_str[sep] = 0; + gp2x_text(screen, 0, 0, fps_str, FPS_COLOR, 0); + gp2x_text(screen, 0, 10, fps_str+sep+1, FPS_COLOR, 0); } needfpsflip--; } diff --git a/drivers/gp2x/minimal.c b/drivers/gp2x/minimal.c index facef9e..0250587 100644 --- a/drivers/gp2x/minimal.c +++ b/drivers/gp2x/minimal.c @@ -439,8 +439,17 @@ void gp2x_init(int ticks_per_second, int bpp, int rate, int bits, int stereo, in frag = 0x40000|13; ioctl(gp2x_dev[3], SNDCTL_DSP_SETFRAGMENT, &frag); - - printf("minimal() do sound, rate %d, bits %d, stereo %d, frag %d\n", rate, bits, stereo, frag); + { + // calculate buffer size + int frag = 0, bsize, buffers = 16; + bsize = rate / 32; + if (rate > 22050) { bsize*=4; buffers*=2; } // 44k mode seems to be very demanding + while ((bsize>>=1)) frag++; + frag |= buffers<<16; // 16 buffers + ioctl(gp2x_dev[3], SNDCTL_DSP_SETFRAGMENT, &frag); + printf("gp2x_set_sound: %i/%ibit/%s, %i buffers of %i bytes\n", + rate, bits, stereo?"stereo":"mono", frag>>16, 1<<(frag&0xffff)); + } if(first) { diff --git a/fce.c b/fce.c index 3e4dde5..64bb8dc 100644 --- a/fce.c +++ b/fce.c @@ -51,6 +51,11 @@ #define Pal (PALRAM) +#ifdef DEBUG_ASM_6502 +extern int cpu_repeat; +extern int cpu_lastval; +#endif + static void (*RefreshLine)(uint8 *P, uint32 vofs) = NULL; static void PRefreshLine(void); @@ -98,6 +103,71 @@ static readfunc *AReadG; static writefunc *BWriteG; static int RWWrap=0; +#ifdef ASM_6502 +static void asmcpu_update(int32 cycles) +{ + // timestamp.. + timestamp += ((cycles >> 4) * 43) >> 7; // aproximating /= 48 + + // some code from x6502.c + fhcnt-=cycles; + if(fhcnt<=0) + { + FrameSoundUpdate(); + fhcnt+=fhinc; + } + + if(PCMIRQCount>0) + { + PCMIRQCount-=cycles; + if(PCMIRQCount<=0) + { + vdis=1; + if((PSG[0x10]&0x80) && !(PSG[0x10]&0x40)) + { + extern uint8 SIRQStat; + SIRQStat|=0x80; + X6502_IRQBegin(FCEU_IQDPCM); + } + } + } +} + +void asmcpu_unpack(void) +{ + nes_registers[0] = X.A << 24; + nes_registers[1] = X.X; + nes_registers[2] = X.Y; + pc_base = 0; + nes_registers[3] = X.PC; + X6502_rebase_a(); + nes_registers[4] = X.S << 24; + nes_registers[4]|= X.IRQlow << 8; + nes_registers[7] = (uint32)X.count; + + // NVUB DIZC + nes_registers[4]|= X.P & 0x5d; + nes_registers[5] = X.P << 24; // N + if (!(X.P&0x02)) nes_registers[5] |= 1; // Z +} + +void asmcpu_pack(void) +{ + X.A = nes_registers[0] >> 24; + X.X = nes_registers[1]; + X.Y = nes_registers[2]; + X.PC= nes_registers[3] - pc_base; + X.S = nes_registers[4] >> 24; + X.IRQlow = nes_registers[4] >> 8; + X.count = (int32) nes_registers[7]; + + // NVUB DIZC + X.P = nes_registers[4] & 0x5d; + if ( nes_registers[5]&0x80000000) X.P |= 0x80; // N + if (!(nes_registers[5]&0x000000ff)) X.P |= 0x02; // Z +} +#endif + DECLFW(BNull) { @@ -203,12 +273,11 @@ uint32 TempAddr,RefreshAddr; /* scanline is equal to the current visible scanline we're on. */ int scanline; -static uint32 scanlines_per_frame; uint8 GameMemBlock[131072] __attribute__ ((aligned (4))); uint8 NTARAM[0x800] __attribute__ ((aligned (4))); uint8 PALRAM[0x20] __attribute__ ((aligned (4))); -#ifndef ASM_6502 +#if !defined(ASM_6502) || defined(DEBUG_ASM_6502) uint8 RAM[0x800] __attribute__ ((aligned (4))); #endif @@ -245,9 +314,15 @@ static DECLFR(ARAMH) static DECLFR(A2002) { uint8 ret; +#ifdef DEBUG_ASM_6502 + if (cpu_repeat) return cpu_lastval; +#endif ret = PPU_status; vtoggle=0; PPU_status&=0x7F; +#ifdef DEBUG_ASM_6502 + cpu_lastval=ret|(PPUGenLatch&0x1F); +#endif return ret|(PPUGenLatch&0x1F); } @@ -260,6 +335,9 @@ static DECLFR(A2007) { uint8 ret; uint32 tmp=RefreshAddr&0x3FFF; +#ifdef DEBUG_ASM_6502 + if (cpu_repeat) return cpu_lastval; +#endif PPUGenLatch=ret=VRAMBuffer; if(PPU_hook) PPU_hook(tmp); @@ -275,6 +353,9 @@ static DECLFR(A2007) if (INC32) RefreshAddr+=32; else RefreshAddr++; if(PPU_hook) PPU_hook(RefreshAddr&0x3fff); +#ifdef DEBUG_ASM_6502 + cpu_lastval=ret; +#endif return ret; } @@ -400,9 +481,16 @@ static DECLFW(B4014) { uint32 t=V<<8; int x; +#ifdef DEBUG_ASM_6502 + if (cpu_repeat) { X6502_AddCycles_a(512); return; } + for(x=0;x<256;x++) + B2004(0x2004,X.DB=ARead[t+x](t+x)); + X6502_AddCycles_c(512); +#else for(x=0;x<256;x++) B2004(0x2004,X.DB=ARead[t+x](t+x)); X6502_AddCycles(512); +#endif } void BGRender(uint8 *target) @@ -1006,14 +1094,12 @@ void FCEU_ResetVidSys(void) if(w) { PAL=1; - scanlines_per_frame=312; FSettings.FirstSLine=FSettings.UsrFirstSLine[1]; FSettings.LastSLine=FSettings.UsrLastSLine[1]; } else { PAL=0; - scanlines_per_frame=262; FSettings.FirstSLine=FSettings.UsrFirstSLine[0]; FSettings.LastSLine=FSettings.UsrLastSLine[0]; } @@ -1076,6 +1162,7 @@ void EmLoop(void) { for(;;) { + uint32 scanlines_per_frame = PAL ? 312 : 262; //extern int asdc; //printf("asdc: %i\n", asdc); //asdc=0; @@ -1096,7 +1183,9 @@ void EmLoop(void) else if(VBlankON) TriggerNMI(); - X6502_Run((scanlines_per_frame-242)*(256+85)-12); + X6502_Run(256+85-12); + for(scanline=242+1;scanline #include #include +#ifdef GP2X +#include +#endif #include "types.h" #include "x6502.h" @@ -58,7 +61,7 @@ static int SaveGame=0; static iNES_HEADER head; -/* MapperReset() is called when the NES is reset(with the reset button). +/* MapperReset() is called when the NES is reset(with the reset button). Mapperxxx_init is called when the NES has been powered on. */ @@ -77,7 +80,7 @@ static void iNESGI(int h) case GI_CLOSE: { FILE *sp; - + if(ROM) {free(ROM);ROM=0;} if(VROM) {free(VROM);VROM=0;} @@ -110,6 +113,9 @@ static void iNESGI(int h) fwrite(ptr,1,amount,sp); fclose(sp); +#ifdef GP2X + sync(); +#endif } } if(MapClose) MapClose(); @@ -236,7 +242,7 @@ static void CheckHInfo(void) {0x932ff06e,34,1}, /* Classic Concentration */ {0x4c7c1af3,34,1}, /* Caesar's Palace */ {0x9ea1dc76,2,0}, /* Rainbow Islands */ - + {0x9eefb4b4,4,8}, /* Pachi Slot Adventure 2 */ {0x5337f73c,4,8}, /* Niji no Silk Road */ {0x7474ac92,4,8}, /* Kabuki: Quantum Fighter */ @@ -411,7 +417,7 @@ static void CheckHInfo(void) sprintf(gigastr+strlen(gigastr),"Mirroring should be set to \"%s\". ",mstr[Mirroring&3]); } if(tofix&4) - strcat(gigastr,"The battery-backed bit should be set. "); + strcat(gigastr,"The battery-backed bit should be set. "); if(tofix&8) strcat(gigastr,"This game should not have any CHR ROM. "); strcat(gigastr,"\n"); @@ -465,8 +471,8 @@ int iNESLoad(char *name, int fp) if(!(ROM=(uint8 *)FCEU_malloc(ROM_size<<14))) return 0; - - if (VROM_size) + + if (VROM_size) if(!(VROM=(uint8 *)FCEU_malloc(VROM_size<<13))) { free(ROM); @@ -523,7 +529,7 @@ int iNESLoad(char *name, int fp) else if(MapperNo==1) DetectMMC1WRAMSize(); if(head.ROM_type&2) - { + { char *soot; SaveGame=1; @@ -589,7 +595,7 @@ static void NONE_init(void) ROM_BANK16(0x8000,0); ROM_BANK16(0xC000,~0); - if(VROM_size) + if(VROM_size) VROM_BANK8(0); else setvram8(CHRRAM); @@ -616,7 +622,7 @@ static uint8 *secptr; static void CheckVSUni(void) { FCEUGameInfo.type=GIT_VSUNI; - + /* FCE Ultra doesn't complain when headers for these games are bad. */ secptr=0; switch(iNESGameCRC32) @@ -625,9 +631,9 @@ static void CheckVSUni(void) case 0xffbef374: pale=1;break; /* Castlevania */ - case 0x98e3c75a: + case 0x98e3c75a: case 0x7cff0f84: pale=2;break; /* SMB */ - + case 0xef7af338: pale=2;break; /* Ice Climber */ case 0xabe1a0c2: FCEUGameInfo.input[0]=SI_ZAPPER;break; /*Duck hunt */ case 0x16aa4e2d: pale=7;FCEUGameInfo.input[0]=SI_ZAPPER;break; /* hoganal ^_^ */ @@ -653,7 +659,7 @@ static void CheckVSUni(void) case 0x159ef3c1:break; /* Star Luster */ case 0x9768e5e0:break; /* Stroke and Match Golf */ - + /* FCE Ultra doesn't have correct palettes for the following games. */ case 0x0fa322c2:pale=2;break; /* Clu Clu Land */ @@ -664,7 +670,7 @@ static void CheckVSUni(void) case 0x832cf592:FCEUGameInfo.input[0]=SI_ZAPPER;break; /* Freedom Force */ case 0x63abf889:break; /* Ladies Golf */ case 0x8c0c2df5:pale=2;MapperNo=1;Mirroring=1;break; /* Top Gun */ - case 0x52c501d0:vsdip=0x80;MapperNo=4;secptr=secdata[0];break; + case 0x52c501d0:vsdip=0x80;MapperNo=4;secptr=secdata[0];break; /* TKO Boxing */ } @@ -753,14 +759,14 @@ void (*MapStateRestore)(int version); void iNESStateRestore(int version) { int x; - + if(!MapperNo) return; for(x=0;x<4;x++) setprg8(0x8000+x*8192,PRGBankList[x]); if(VROM_size) - for(x=0;x<8;x++) + for(x=0;x<8;x++) setchr1(0x400*x,CHRBankList[x]); switch(Mirroring) @@ -833,7 +839,7 @@ static int MMC_init(int type) if(head.ROM_type&8) AddExState(ExtraNTARAM, 2048, 0, "EXNR"); - /* Exclude some mappers whose emulation code handle save state stuff + /* Exclude some mappers whose emulation code handle save state stuff themselves. */ if(type && type!=13 && type!=96) { @@ -846,7 +852,7 @@ static int MMC_init(int type) for(x=0;x<8;x++) { char tak[8]; - sprintf(tak,"CBL%d",x); + sprintf(tak,"CBL%d",x); AddExState(&CHRBankList[x], 2, 1,tak); } } diff --git a/ncpu.S b/ncpu.S index 381437f..2a7fafe 100644 --- a/ncpu.S +++ b/ncpu.S @@ -15,6 +15,8 @@ #define OTOFFS_NES_STACK (nes_stack - cpu_exec_table) #define OTOFFS_NES_REGS (nes_registers - cpu_exec_table) #define OTOFFS_PC_BASE (pc_base - cpu_exec_table) +#define OTOFFS_IRQ_HOOK (MapIRQHook - cpu_exec_table) +#define OTOFFS_X (X - cpu_exec_table) @ fceu #define FCEU_IQNMI 0x08 @@ -48,10 +50,6 @@ .endm -.macro RETURN_FROM_CPU_EXEC - b cpu_exec_end -.endm - @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ -68,6 +66,9 @@ subs REG_CYCLE, REG_CYCLE, #\n*48 ble cpu_exec_end + tst REG_P_REST, #1<<16 + movne r0, #\n + blne do_irq_hook ldrb r0, [REG_PC], #1 tst REG_P_REST, #0xff<<8 ldreq pc, [REG_OP_TABLE, r0, lsl #2] @@ -429,6 +430,14 @@ subgt REG_CYCLE,REG_CYCLE,#1*48 .endm +@ Indirect Indexed (for writes and rmws) +.macro INDY_ADDR_W + ZERO_ADDR + ZP_READ_ADDR + add REG_ADDR, REG_ADDR, REG_Y + bic REG_ADDR, REG_ADDR, #0x10000 +.endm + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ -458,6 +467,13 @@ subgt REG_CYCLE,REG_CYCLE,#1*48 .endm +@ Absolute Indexed (for writes and rmws) +.macro ABSX_ADDR_W + ABS_ADDR + add REG_ADDR, REG_ADDR, REG_X + bic REG_ADDR, REG_ADDR, #0x10000 +.endm + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@ $nnnn, Y .macro ABSY_ADDR @@ -469,6 +485,15 @@ subgt REG_CYCLE,REG_CYCLE,#1*48 .endm +@ Absolute Indexed (for writes and rmws) +.macro ABSY_ADDR_W + ABS_ADDR + add REG_ADDR, REG_ADDR, REG_Y + bic REG_ADDR, REG_ADDR, #0x10000 +.endm + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @@@ P ¤òÉü¸µ¤¹¤ë @@@ r0 => 6502 ¤Î P ¥ì¥¸¥¹¥¿ @@@ REG_NZ <= Éü¸µ¤µ¤ì¤¿ REG_NZ @@ -843,7 +868,7 @@ op8D: @ STA $nnnn CYCLE_NEXT 4 op9D: @ STA $nnnn, X - ABSX_ADDR + ABSX_ADDR_W OP_STA WRITE_1 CYCLE_NEXT 5 @@ -851,7 +876,7 @@ op9D: @ STA $nnnn, X CYCLE_NEXT 5 op99: @ STA $nnnn, Y - ABSY_ADDR + ABSY_ADDR_W OP_STA WRITE_1 CYCLE_NEXT 5 @@ -867,7 +892,7 @@ op81: @ STA ($nn, X) CYCLE_NEXT 6 op91: @ STA ($nn), Y - INDY_ADDR + INDY_ADDR_W OP_STA WRITE_1 CYCLE_NEXT 6 @@ -974,7 +999,7 @@ opEE: @ INC $nnnn CYCLE_NEXT 6 opFE: @ INC $nnnn, X - ABSX_ADDR + ABSX_ADDR_W READ_WRITE_1 OP_INC READ_WRITE_2 @@ -1020,7 +1045,7 @@ opCE: @ DEC $nnnn CYCLE_NEXT 6 opDE: @ DEC $nnnn, X - ABSX_ADDR + ABSX_ADDR_W READ_WRITE_1 OP_DEC READ_WRITE_2 @@ -1660,7 +1685,7 @@ op0E: @ ASL $nnnn CYCLE_NEXT 6 op1E: @ ASL $nnnn, X - ABSX_ADDR + ABSX_ADDR_W READ_WRITE_1 OP_ASL READ_WRITE_2 @@ -1702,7 +1727,7 @@ op4E: @ LSR $nnnn CYCLE_NEXT 6 op5E: @ LSR $nnnn, X - ABSX_ADDR + ABSX_ADDR_W READ_WRITE_1 OP_LSR READ_WRITE_2 @@ -1790,7 +1815,7 @@ op2E: @ ROL $nnnn op3E: @ ROL $nnnn, X - ABSX_ADDR + ABSX_ADDR_W READ_WRITE_1 OP_ROL READ_WRITE_2 @@ -1832,7 +1857,7 @@ op6E: @ ROR $nnnn CYCLE_NEXT 6 op7E: @ ROR $nnnn, X - ABSX_ADDR + ABSX_ADDR_W READ_WRITE_1 OP_ROR READ_WRITE_2 @@ -2078,7 +2103,7 @@ op43: @ SRE ($nn, X) CYCLE_NEXT 8 op53: @ SRE ($nn), Y - INDY_ADDR + INDY_ADDR_W READ_WRITE_1 OP_SRE READ_WRITE_2 @@ -2090,7 +2115,7 @@ op53: @ SRE ($nn), Y op9C: @ SHY $nnnn, X - ABSX_ADDR + ABSX_ADDR_W OP_SHY WRITE_1 CYCLE_NEXT 5 @@ -2264,7 +2289,7 @@ op1F: @ SLO $nnnn, X CYCLE_NEXT 7 op1B: @ SLO $nnnn, Y - ABSY_ADDR + ABSY_ADDR_W READ_WRITE_1 OP_SLO READ_WRITE_2 @@ -2286,7 +2311,7 @@ op03: @ SLO ($nn, X) CYCLE_NEXT 8 op13: @ SLO ($nn), Y - INDY_ADDR + INDY_ADDR_W READ_WRITE_1 OP_SLO READ_WRITE_2 @@ -2409,7 +2434,7 @@ op2F: @ RLA $nnnn CYCLE_NEXT 6 op3F: @ RLA $nnnn, X - ABSX_ADDR + ABSX_ADDR_W READ_WRITE_1 OP_RLA READ_WRITE_2 @@ -2420,11 +2445,11 @@ op3F: @ RLA $nnnn, X CYCLE_NEXT 7 op3B: @ RLA $nnnn, Y - ABSY_ADDR + ABSY_ADDR_W READ_WRITE_1 OP_RLA - READ_WRITE_2 - CYCLE_NEXT 7 + READ_WRITE_2 + CYCLE_NEXT 7 READ_WRITE_3 OP_RLA READ_WRITE_4 @@ -2442,7 +2467,7 @@ op23: @ RLA ($nn, X) CYCLE_NEXT 8 op33: @ RLA ($nn), Y - INDY_ADDR + INDY_ADDR_W READ_WRITE_1 OP_RLA READ_WRITE_2 @@ -2482,7 +2507,7 @@ op6F: @ RRA $nnnn CYCLE_NEXT 6 op7F: @ RRA $nnnn, X - ABSX_ADDR + ABSX_ADDR_W READ_WRITE_1 OP_RRA READ_WRITE_2 @@ -2495,7 +2520,7 @@ op7F: @ RRA $nnnn, X CYCLE_NEXT 7 op7B: @ RRA $nnnn, Y - ABSY_ADDR + ABSY_ADDR_W READ_WRITE_1 OP_RRA READ_WRITE_2 @@ -2521,7 +2546,7 @@ op63: @ RRA ($nn, X) CYCLE_NEXT 8 op73: @ RRA ($nn), Y - INDY_ADDR + INDY_ADDR_W READ_WRITE_1 OP_RRA READ_WRITE_2 @@ -2708,9 +2733,11 @@ op60: @@@ @@@ ³ä¤ê¹þ¤ß¤Î½èÍý +@@@ WARNING: decrements REG_PC @@@ do_int: ldr r0, [REG_OP_TABLE, #OTOFFS_PC_BASE] + sub REG_PC, REG_PC, #1 sub r0, REG_PC, r0 PUSH_WORD bic REG_P_REST, REG_P_REST, #P_REST_B_FLAG @@ -2742,6 +2769,12 @@ reset_cpu: @@REG_P_REST = 0, don't touch REG_S bic REG_P_REST, REG_P_REST, #0xff + @ fceu: set MapIRQHook present flag + ldr r0, [REG_OP_TABLE, #OTOFFS_IRQ_HOOK] + tst r0, r0 + orrne REG_P_REST, REG_P_REST, #1<<16 + biceq REG_P_REST, REG_P_REST, #1<<16 + @@ R bit is always 1 orr REG_NZ, REG_NZ, #P_R_FLAG @@ -2763,12 +2796,26 @@ reset_cpu: @@@ low-level memhandlers @@@ +read_rom_byte: + ldr r0, =CartBR + ldr r2, =ARead + mov r1, #0xff00 + orr r1, r1, r1, lsr #4 + ldr r1, [r2, r1, lsl #2] @ if (ARead[0xfff0] == CartBR) + cmp r0, r1 + bne read_ppu_reg + ldr r2, =Page + mov r1, REG_ADDR, lsr #11 + ldr r2, [r2, r1, lsl #2] + ldrb r0, [r2, REG_ADDR] + bx lr + + read_ppu_reg: read_high_reg: read_save_ram: -read_rom_byte: @ must preserve r3 for the callers too - @ TODO: check if all of saves are needed, optimize read_rom_byte, _DB + @ TODO: check if all of saves are needed, _DB (is full needed?) str REG_PC, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x0c)] @ might get rebased str REG_P_REST, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x10)] @ might set irq str REG_CYCLE, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x1c)] @ might get used @@ -2786,6 +2833,7 @@ read_rom_byte: ldr REG_PC, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x0c)] @ might get rebased ldr REG_P_REST, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x10)] @ might set irq ldr REG_CYCLE, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x1c)] @ might get used + strb r0, [REG_OP_TABLE, #(OTOFFS_X + 0x10)] @ X.DB bx lr @@ -2910,7 +2958,9 @@ cpu_exec_table: @@@ nes_registers: .fill 0x40, 1, 0 +#ifndef DEBUG_ASM_6502 RAM: +#endif nes_internal_ram: .fill 0x100, 1, 0 nes_stack: @@ -2918,6 +2968,13 @@ nes_stack: @ TODO: write code which keeps it up-to-date pc_base: .long 0 +#ifndef DEBUG_ASM_6502 +MapIRQHook: + .long 0 +timestamp: + .long 0 +X: .fill 0x20, 1, 0 +#endif .pool @@ -2982,16 +3039,12 @@ opAB: @ LXA #$nn @op37: @ RLA $nn, X @op2F: @ RLA $nnnn @op3F: @ RLA $nnnn, X -@op3B: @ RLA $nnnn, Y @op23: @ RLA ($nn, X) -@op33: @ RLA ($nn), Y @op67: @ RRA $nn @op77: @ RRA $nn, X @op6F: @ RRA $nnnn @op7F: @ RRA $nnnn, X -@op7B: @ RRA $nnnn, Y @op63: @ RRA ($nn, X) -@op73: @ RRA ($nn), Y op87: @ SAX $nn op97: @ SAX $nn, Y op8F: @ SAX $nnnn @@ -3001,21 +3054,17 @@ op9F: @ SHA $nnnn, Y op93: @ SHA ($nn), Y op9B: @ SHS $nnnn, Y op9E: @ SHX $nnnn, Y -@op9C: @ SHY $nnnn, X @op03: @ SLO ($nn, X) @op07: @ SLO $nn @op17: @ SLO $nn, X @op0F: @ SLO $nnnn @op1F: @ SLO $nnnn, X -@op1B: @ SLO $nnnn, Y -@op13: @ SLO ($nn), Y @op47: @ SRE $nn @op57: @ SRE $nn, X @op4F: @ SRE $nnnn @op5F: @ SRE $nnnn, X @op5B: @ SRE $nnnn, Y @op43: @ SRE ($nn, X) -@op53: @ SRE ($nn), Y CYCLE_NEXT 1 @ emu_panic? @@ -3029,20 +3078,19 @@ op9E: @ SHX $nnnn, Y .extern Page .extern ARead .extern BWrite +.extern MapIRQHook SECTION_DATA ALIGN -@ .globl X - .globl RAM .globl nes_registers @ TODO: hide? .globl pc_base -@ .globl timestamp -@ .globl MapIRQHook @ (int a) -@ TODO... .. conversion X <-> nes_registers for savestates -@timestamp: .long 0 -@MapIRQHook: .long 0 -@X: .fill 0x20, 1, 0 +#ifndef DEBUG_ASM_6502 + .globl X + .globl RAM + .globl timestamp + .globl MapIRQHook @ (int a) +#endif .globl X6502_Reset_a @ (void); .globl X6502_Power_a @ (void); .globl X6502_Run_a @ (int32 cycles); @@ -3099,7 +3147,7 @@ X6502_IRQEnd_a: TriggerNMI_a: - mov r0, #FCEU_IQTEMP + mov r0, #FCEU_IQNMI b X6502_IRQBegin_a @@ -3111,7 +3159,7 @@ TriggerNMINSF_a: X6502_AddCycles_a: ldr r2, =nes_registers ldr r1, [r2, #0x1c] - mvn r3, #49 + mvn r3, #47 @ r3=-48 mla r0, r3, r0, r1 str r0, [r2, #0x1c] bx lr @@ -3131,5 +3179,21 @@ X6502_rebase_a: .pool +@ the nasty MapIRQHook thing from FCE.. +do_irq_hook: + @ 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 + + @ 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 + ldr REG_P_REST, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x10)] @ might set irq + bx lr + + @ vim:filetype=armasm diff --git a/ncpu.h b/ncpu.h index 015320a..c123dc7 100644 --- a/ncpu.h +++ b/ncpu.h @@ -78,7 +78,8 @@ * note: fceu uses this differently * [7:0] - interrupt flags (same as above) * [15:8] - FCEU IRQ pending sources - * [23:16] - unused + * [16] - a flag which indicates that MapIRQHook is not null + * [23:17] - unused * [31:24] - stack pointer */ diff --git a/ncpu_debug.c b/ncpu_debug.c index 864cae3..ebb32fa 100644 --- a/ncpu_debug.c +++ b/ncpu_debug.c @@ -8,12 +8,14 @@ // asm core state extern uint32 nes_registers[0x10]; extern uint32 pc_base; -uint32 PC_prev = 0; +uint32 PC_prev = 0, g_cnt = 0; +int cpu_repeat; +int cpu_lastval; static void leave(void) { - printf("A: %02x, X: %02x, Y: %02x, S: %02x\n", X.A, X.X, X.Y, X.S); + printf("\nA: %02x, X: %02x, Y: %02x, S: %02x\n", X.A, X.X, X.Y, X.S); printf("PC = %04lx, OP=%02X\n", PC_prev, (PC_prev < 0x2000) ? RAM[PC_prev&0x7ff] : ARead[PC_prev](PC_prev)); exit(1); } @@ -21,35 +23,36 @@ static void leave(void) static void compare_state(void) { uint8 nes_flags; + int fail = 0; if ((nes_registers[0] >> 24) != X.A) { printf("A: %02lx vs %02x\n", nes_registers[0] >> 24, X.A); - leave(); + fail = 1; } if ((nes_registers[1] & 0xff) != X.X) { printf("X: %02lx vs %02x\n", nes_registers[1] & 0xff, X.X); - leave(); + fail = 1; } if ((nes_registers[2] & 0xff) != X.Y) { printf("Y: %02lx vs %02x\n", nes_registers[2] & 0xff, X.Y); - leave(); + fail = 1; } if (nes_registers[3] - pc_base != X.PC) { printf("PC: %04lx vs %04x\n", nes_registers[3] - pc_base, X.PC); - leave(); + fail = 1; } if ((nes_registers[4] >> 24) != X.S) { printf("S: %02lx vs %02x\n", nes_registers[4] >> 24, X.S); - leave(); + fail = 1; } if (((nes_registers[4]>>8)&0xff) != X.IRQlow) { printf("IRQlow: %02lx vs %02x\n", ((nes_registers[4]>>8)&0xff), X.IRQlow); - leave(); + fail = 1; } // NVUB DIZC @@ -58,15 +61,17 @@ static void compare_state(void) if (!(nes_registers[5]&0x000000ff)) nes_flags |= 0x02; // Z // nes_flags |= 0x20; // U, not set in C core (set only when pushing) - if (nes_flags != X.P) { - printf("flags: %02x vs %02x\n", nes_flags, X.P); - leave(); + if (nes_flags != (X.P&~0x20)) { + printf("flags: %02x vs %02x\n", nes_flags, (X.P&~0x20)); + fail = 1; } if ((int32)nes_registers[7] != X.count) { printf("cycles: %li vs %li\n", (int32)nes_registers[7], X.count); - leave(); + fail = 1; } + + if (fail) leave(); } @@ -95,18 +100,26 @@ void X6502_Run_d(int32 c) int32 cycles = c << 4; /* *16 */ \ if (PAL) cycles -= c; /* *15 */ \ - printf("-- run(%i)\n", (int)c); + //printf("-- %06i: run(%i)\n", (int)g_cnt, (int)c); + g_cnt += c; while (cycles > 0) { PC_prev = X.PC; nes_registers[7]=1; X.count=1; + + cpu_repeat = 0; X6502_Run_c(); + + cpu_repeat = 1; X6502_Run_a(); + compare_state(); cycles -= 1 - X.count; } + + //printf("-- run_end\n"); } void X6502_Reset_d(void) @@ -129,10 +142,12 @@ void X6502_Power_d(void) void X6502_AddCycles_d(int x) { - printf("-- AddCycles(%i)\n", x); + printf("-- AddCycles(%i|%i)\n", x, x*48); - X6502_AddCycles_c(x); - X6502_AddCycles_a(x); + printf("can't use this in debug\n"); + exit(1); + //X6502_AddCycles_c(x); + //X6502_AddCycles_a(x); //compare_state(); } diff --git a/state.c b/state.c index 871ef80..5e4308d 100644 --- a/state.c +++ b/state.c @@ -24,6 +24,9 @@ #include #include #include +#ifdef GP2X +#include +#endif #include "types.h" #include "x6502.h" @@ -255,7 +258,11 @@ for(;;) if(!read32(&size,st)) break; switch(t) { - case 1:if(!ReadStateChunk(st,SFCPU,SFCPUELEMENTS,size)) ret=0;break; + case 1:if(!ReadStateChunk(st,SFCPU,SFCPUELEMENTS,size)) ret=0; +#ifdef ASM_6502 + asmcpu_unpack(); +#endif + break; case 2:if(!ReadStateChunk(st,SFCPUC,SFCPUCELEMENTS,size)) ret=0; else { @@ -299,6 +306,9 @@ void SaveState(void) header[3]=VERSION_NUMERIC; fwrite(header,1,16,st); +#ifdef ASM_6502 + asmcpu_pack(); +#endif totalsize=WriteStateChunk(st,1,SFCPU,SFCPUELEMENTS); totalsize+=WriteStateChunk(st,2,SFCPUC,SFCPUCELEMENTS); totalsize+=WriteStateChunk(st,3,SFPPU,SFPPUELEMENTS); @@ -310,6 +320,9 @@ void SaveState(void) write32(totalsize,st); SaveStateStatus[CurrentState]=1; fclose(st); +#ifdef GP2X + sync(); +#endif FCEU_DispMessage("State %d saved.",CurrentState); } else diff --git a/unif.c b/unif.c index 07ec184..bcd2d3d 100644 --- a/unif.c +++ b/unif.c @@ -27,6 +27,9 @@ #include #include #include +#ifdef GP2X +#include +#endif #include "types.h" @@ -132,7 +135,7 @@ static int DoMirroring(int fp) { uint8 t; t=FCEU_fgetc(fp); - mirrortodo=t; + mirrortodo=t; { static char *stuffo[6]={"Horizontal","Vertical","$2000","$2400","\"Four-screen\"","Controlled by Mapper Hardware"}; @@ -209,7 +212,7 @@ static int LoadPRG(int fp) else puts(""); - SetupCartPRGMapping(z,malloced[z],t,0); + SetupCartPRGMapping(z,malloced[z],t,0); return(1); } @@ -340,13 +343,13 @@ int LoadUNIFChunks(int fp) for(;;) { t=FCEU_fread(&uchead,1,4,fp); - if(t<4) + if(t<4) { if(t>0) - return 0; + return 0; return 1; } - if(!(FCEU_read32(&uchead.info,fp))) + if(!(FCEU_read32(&uchead.info,fp))) return 0; t=0; for(x=0;x #include #include +#ifdef GP2X +#include +#endif #include "types.h" #include "video.h" @@ -249,6 +252,9 @@ int SaveSnapshot(void) free(compmem); fclose(pp); +#ifdef GP2X + sync(); +#endif return u+1; diff --git a/x6502.c b/x6502.c index 87ba0f5..cb0d761 100644 --- a/x6502.c +++ b/x6502.c @@ -37,7 +37,7 @@ void FP_FASTAPASS(1) (*MapIRQHook)(int a); #define _S X.S #define _P X.P #define _PI X.mooPI -#define _PZ X.PZ // unused? +//#define _PZ X.PZ // unused? #define _DB X.DB #define _count X.count #define _tcount X.tcount @@ -475,7 +475,7 @@ void X6502_Run_c(void/*int32 cycles*/) ADDCYC(temp); //temp=_tcount; //_tcount=0; -/* + if(MapIRQHook) MapIRQHook(temp); temp*=48; @@ -487,7 +487,6 @@ void X6502_Run_c(void/*int32 cycles*/) fhcnt+=fhinc; } - if(PCMIRQCount>0) { PCMIRQCount-=temp; @@ -502,7 +501,7 @@ void X6502_Run_c(void/*int32 cycles*/) } } } -*/ + //printf("$%04x:$%02x\n",_PC,b1); //_PC++; //printf("$%02x\n",b1); diff --git a/x6502.h b/x6502.h index 48843fc..9411108 100644 --- a/x6502.h +++ b/x6502.h @@ -24,7 +24,7 @@ typedef struct { uint16 PC; /* I'll change this to uint32 later... */ /* I'll need to AND PC after increments to 0xFFFF */ /* when I do, though. Perhaps an IPC() macro? */ - uint8 A,X,Y,S,P,mooPI,PZ; + uint8 A,X,Y,S,P,mooPI; uint8 DB; /* Data bus "cache" for reads from certain areas */ uint8 IRQlow; /* Simulated IRQ pin held low(or is it high?). */ uint8 jammed; @@ -78,16 +78,30 @@ extern void FP_FASTAPASS(1) (*MapIRQHook)(int a); #define X6502_IRQEnd X6502_IRQEnd_a #define X6502_A -extern uint32 nes_registers[0x10]; #define X6502_Run(c) \ { \ int32 cycles = (c) << 4; /* *16 */ \ if (PAL) cycles -= (c); /* *15 */ \ nes_registers[7]+=cycles; \ - if (nes_registers[7] > 0) X6502_Run_a(); \ + if (nes_registers[7] > 0) { \ + cycles = (int32)nes_registers[7]; \ + X6502_Run_a(); \ + cycles -= (int32)nes_registers[7]; \ + asmcpu_update(cycles); \ + } \ } #else +#define TriggerIRQ TriggerIRQ_c +#define TriggerNMI TriggerNMI_c +#define TriggerNMINSF TriggerNMINSF_c +#define X6502_Reset X6502_Reset_c +#define X6502_Power X6502_Power_c +#define X6502_AddCycles X6502_AddCycles_c +#define X6502_IRQBegin X6502_IRQBegin_c +#define X6502_IRQEnd X6502_IRQEnd_c +#define X6502_C + #define X6502_Run(c) \ { \ int32 cycles = (c) << 4; /* *16 */ \ @@ -113,6 +127,8 @@ void FASTAPASS(1) X6502_IRQEnd_c(int w); // asm #ifdef X6502_A +extern uint32 nes_registers[0x10]; +extern uint32 pc_base; void TriggerIRQ_a(void); void TriggerNMI_a(void); void TriggerNMINSF_a(void); @@ -122,6 +138,7 @@ void X6502_Power_a(void); void X6502_AddCycles_a(int x); void X6502_IRQBegin_a(int w); void X6502_IRQEnd_a(int w); +void X6502_rebase_a(void); #endif // debug -- 2.39.5