endif
asm_6502=1
-debug_asm_6502=1
+#debug_asm_6502=1
all: fceu
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifdef GP2X
+#include <unistd.h>
+#endif
#include "../../types.h"
#include "config.h"
{
z=fgetc(fp);
str[x]=z;
- x++;
+ x++;
if(z<=0) break;
if(x>=n) return 0;
}
SaveParse(cfgst,fp);
fclose(fp);
+#ifdef GP2X
+ sync();
+#endif
}
static void LoadParse(CFGSTRUCT *cfgst, FILE *fp)
}
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--;
}
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)
{
#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);
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)
{
/* 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
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);
}
{
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);
if (INC32) RefreshAddr+=32;
else RefreshAddr++;
if(PPU_hook) PPU_hook(RefreshAddr&0x3fff);
+#ifdef DEBUG_ASM_6502
+ cpu_lastval=ret;
+#endif
return ret;
}
{
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)
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];
}
{
for(;;)
{
+ uint32 scanlines_per_frame = PAL ? 312 : 262;
//extern int asdc;
//printf("asdc: %i\n", asdc);
//asdc=0;
else if(VBlankON)
TriggerNMI();
- X6502_Run((scanlines_per_frame-242)*(256+85)-12);
+ X6502_Run(256+85-12);
+ for(scanline=242+1;scanline<scanlines_per_frame;scanline++)
+ X6502_Run(256+85);
PPU_status&=0x1f;
GeniePower();
+printf("X.DB offs: %02x\n", (int)&X.DB - (int)&X);
+
memset(RAM,0x00,0x800);
ResetMapping();
GameInterface(GI_POWER);
#ifndef _FCEH
+
+#ifdef ASM_6502
+void asmcpu_unpack(void);
+void asmcpu_pack(void);
+#endif
+
extern int GameLoaded;
void ResetGameLoaded(void);
extern writefunc BWrite[0x10000];
#define VBlankON (PPU[0]&0x80) /* Generate VBlank NMI */
-#define SpHitON (PPU[0]&0x40)
+#define SpHitON (PPU[0]&0x40)
#define Sprite16 (PPU[0]&0x20) /* Sprites 8x16/8x8 */
#define BGAdrHI (PPU[0]&0x10) /* BG pattern adr $0000/$1000 */
#define SpAdrHI (PPU[0]&0x08) /* Sprite pattern adr $0000/$1000 */
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
- * Copyright (C) 1998 BERO
+ * Copyright (C) 1998 BERO
* Copyright (C) 2002 Ben Parnell
*
* This program is free software; you can redistribute it and/or modify
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifdef GP2X
+#include <unistd.h>
+#endif
#include "types.h"
#include "x6502.h"
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.
*/
case GI_CLOSE:
{
FILE *sp;
-
+
if(ROM) {free(ROM);ROM=0;}
if(VROM) {free(VROM);VROM=0;}
fwrite(ptr,1,amount,sp);
fclose(sp);
+#ifdef GP2X
+ sync();
+#endif
}
}
if(MapClose) MapClose();
{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 */
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");
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);
else if(MapperNo==1) DetectMMC1WRAMSize();
if(head.ROM_type&2)
- {
+ {
char *soot;
SaveGame=1;
ROM_BANK16(0x8000,0);
ROM_BANK16(0xC000,~0);
- if(VROM_size)
+ if(VROM_size)
VROM_BANK8(0);
else
setvram8(CHRRAM);
static void CheckVSUni(void)
{
FCEUGameInfo.type=GIT_VSUNI;
-
+
/* FCE Ultra doesn't complain when headers for these games are bad. */
secptr=0;
switch(iNESGameCRC32)
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 ^_^ */
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 */
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 */
}
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)
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)
{
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);
}
}
#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
.endm
-.macro RETURN_FROM_CPU_EXEC
- b cpu_exec_end
-.endm
-
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
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]
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
+
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
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
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
CYCLE_NEXT 4
op9D: @ STA $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
OP_STA
WRITE_1
CYCLE_NEXT 5
CYCLE_NEXT 5
op99: @ STA $nnnn, Y
- ABSY_ADDR
+ ABSY_ADDR_W
OP_STA
WRITE_1
CYCLE_NEXT 5
CYCLE_NEXT 6
op91: @ STA ($nn), Y
- INDY_ADDR
+ INDY_ADDR_W
OP_STA
WRITE_1
CYCLE_NEXT 6
CYCLE_NEXT 6
opFE: @ INC $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_INC
READ_WRITE_2
CYCLE_NEXT 6
opDE: @ DEC $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_DEC
READ_WRITE_2
CYCLE_NEXT 6
op1E: @ ASL $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_ASL
READ_WRITE_2
CYCLE_NEXT 6
op5E: @ LSR $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_LSR
READ_WRITE_2
op3E: @ ROL $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_ROL
READ_WRITE_2
CYCLE_NEXT 6
op7E: @ ROR $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_ROR
READ_WRITE_2
CYCLE_NEXT 8
op53: @ SRE ($nn), Y
- INDY_ADDR
+ INDY_ADDR_W
READ_WRITE_1
OP_SRE
READ_WRITE_2
op9C: @ SHY $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
OP_SHY
WRITE_1
CYCLE_NEXT 5
CYCLE_NEXT 7
op1B: @ SLO $nnnn, Y
- ABSY_ADDR
+ ABSY_ADDR_W
READ_WRITE_1
OP_SLO
READ_WRITE_2
CYCLE_NEXT 8
op13: @ SLO ($nn), Y
- INDY_ADDR
+ INDY_ADDR_W
READ_WRITE_1
OP_SLO
READ_WRITE_2
CYCLE_NEXT 6
op3F: @ RLA $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_RLA
READ_WRITE_2
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
CYCLE_NEXT 8
op33: @ RLA ($nn), Y
- INDY_ADDR
+ INDY_ADDR_W
READ_WRITE_1
OP_RLA
READ_WRITE_2
CYCLE_NEXT 6
op7F: @ RRA $nnnn, X
- ABSX_ADDR
+ ABSX_ADDR_W
READ_WRITE_1
OP_RRA
READ_WRITE_2
CYCLE_NEXT 7
op7B: @ RRA $nnnn, Y
- ABSY_ADDR
+ ABSY_ADDR_W
READ_WRITE_1
OP_RRA
READ_WRITE_2
CYCLE_NEXT 8
op73: @ RRA ($nn), Y
- INDY_ADDR
+ INDY_ADDR_W
READ_WRITE_1
OP_RRA
READ_WRITE_2
@@@
@@@ ³ä¤ê¹þ¤ß¤Î½èÍý
+@@@ 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
@@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
@@@ 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
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
@@@
nes_registers:
.fill 0x40, 1, 0
+#ifndef DEBUG_ASM_6502
RAM:
+#endif
nes_internal_ram:
.fill 0x100, 1, 0
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
@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
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?
.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);
TriggerNMI_a:
- mov r0, #FCEU_IQTEMP
+ mov r0, #FCEU_IQNMI
b X6502_IRQBegin_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
.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
* 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
*/
// 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);
}
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
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();
}
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)
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();
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifdef GP2X
+#include <unistd.h>
+#endif
#include "types.h"
#include "x6502.h"
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
{
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);
write32(totalsize,st);
SaveStateStatus[CurrentState]=1;
fclose(st);
+#ifdef GP2X
+ sync();
+#endif
FCEU_DispMessage("State %d saved.",CurrentState);
}
else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifdef GP2X
+#include <unistd.h>
+#endif
#include "types.h"
{
uint8 t;
t=FCEU_fgetc(fp);
- mirrortodo=t;
+ mirrortodo=t;
{
static char *stuffo[6]={"Horizontal","Vertical","$2000","$2400","\"Four-screen\"","Controlled by Mapper Hardware"};
else
puts("");
- SetupCartPRGMapping(z,malloced[z],t,0);
+ SetupCartPRGMapping(z,malloced[z],t,0);
return(1);
}
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<BMF;x++)
if(!bfunc[x].init(fp))
return 0;
t=1;
- break;
+ break;
}
if(!t)
if(FCEU_fseek(fp,uchead.info,SEEK_CUR))
FCEU_fseek(fp,0,SEEK_SET);
FCEU_fread(&unhead,1,4,fp);
if(memcmp(&unhead,"UNIF",4))
- return 0;
+ return 0;
ResetCartMapping();
GameInterface=UNIFGI;
return 1;
-
+
aborto:
FreeUNIF();
if(fssp)
fclose(fssp);
fssp=0;
+#ifdef GP2X
+ sync();
+#endif
}
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#ifdef GP2X
+#include <unistd.h>
+#endif
#include "types.h"
#include "video.h"
free(compmem);
fclose(pp);
+#ifdef GP2X
+ sync();
+#endif
return u+1;
#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
ADDCYC(temp);
//temp=_tcount;
//_tcount=0;
-/*
+
if(MapIRQHook) MapIRQHook(temp);
temp*=48;
fhcnt+=fhinc;
}
-
if(PCMIRQCount>0)
{
PCMIRQCount-=temp;
}
}
}
-*/
+
//printf("$%04x:$%02x\n",_PC,b1);
//_PC++;
//printf("$%02x\n",b1);
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;
#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 */ \
// 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);
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