merged ppu code, added input+zapper, FDS/VS insert in menu
[fceu.git] / ncpu.S
diff --git a/ncpu.S b/ncpu.S
index 0b000ec..dcade08 100644 (file)
--- 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
@@ -205,20 +205,13 @@ ldmfd sp!,{r0-r3,r12,lr}
 @@@ Read byte
 @@@
 
-.macro READ rom_optimize=1
-       adr     lr, 1f
-.if \rom_optimize
-       tst     REG_ADDR, #0x8000
-       bne     read_rom_byte
-.endif
+.macro READ unused_param
        tst     REG_ADDR, #0xe000
-       bne     read_byte
        @ RAM
-       bic     r0, REG_ADDR, #0x1800
-       add     r0, r0, #OTOFFS_NES_RAM
-       ldrb    r0, [r0, REG_OP_TABLE]
-       @@ ¤È¤¤¤¦¤ï¤±¤Ç¥¸¥ã¥ó¥×¤¹¤ëɬÍפϤʤ¤
-1:
+       biceq   r0, REG_ADDR, #0x1800
+       addeq   r0, r0, #OTOFFS_NES_RAM
+       ldreqb  r0, [r0, REG_OP_TABLE]
+       blne    read_byte
 .endm
 
 @@@
@@ -235,10 +228,8 @@ ldmfd sp!,{r0-r3,r12,lr}
 @@@ OP¤Ç¤Ïr3¤òÊݸ¤·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤
 
 .macro READ_WRITE_1
-       adr     lr, 9999f
-       tst     REG_ADDR, #0x8000
-       bne     read_rom_byte
        tst     REG_ADDR, #0xe000
+       adrne   lr, 9999f
        bne     read_byte
        @ RAM
        bic     REG_ADDR, REG_ADDR, #0x1800
@@ -282,7 +273,6 @@ ldmfd sp!,{r0-r3,r12,lr}
 @@@ REG_ADDR¤òÊѹ¹¤¹¤ë¤¬µ¤¤Ë¤¹¤ë¤Ê
 @@@
 .macro READ_WORD
-       @ don't do ROM check, because we might be fetching important stuff like vectors
        READ    0
        mov     REG_PC, r0
        add     REG_ADDR, REG_ADDR, #1
@@ -415,18 +405,25 @@ ldmfd sp!,{r0-r3,r12,lr}
 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 @@@ $nnnn
 
-.macro ABS_ADDR
+.macro ABS_ADDR update_db=0
+.if \update_db
+       ldrb    r0, [REG_PC, #1]
+       ldrb    REG_ADDR, [REG_PC], #2
+       strb    r0, [REG_OP_TABLE, #(OTOFFS_X + 0x10)]          @ X.DB
+       orr     REG_ADDR, REG_ADDR, r0, lsl #8
+.else
        tst     REG_PC, #1
        ldrneb  REG_ADDR, [REG_PC], #1
        ldrneb  r0, [REG_PC], #1
        ldreqh  REG_ADDR, [REG_PC], #2
        orrne   REG_ADDR, REG_ADDR, r0, lsl #8
+.endif
 .endm
 
 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 @@@ $nnnn, X
 .macro ABSX_ADDR
-       ABS_ADDR
+       ABS_ADDR 1
        add     REG_ADDR, REG_ADDR, REG_X
        bic     REG_ADDR, REG_ADDR, #0x10000
        and     r0,REG_ADDR,#0xff
@@ -445,7 +442,7 @@ ldmfd sp!,{r0-r3,r12,lr}
 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 @@@ $nnnn, Y
 .macro ABSY_ADDR
-       ABS_ADDR
+       ABS_ADDR 1                                      @ a hack needed for Paperboy, Dirty Harry controls to work
        add     REG_ADDR, REG_ADDR, REG_Y
        bic     REG_ADDR, REG_ADDR, #0x10000
        and     r0,REG_ADDR,#0xff
@@ -2723,10 +2720,11 @@ reset_cpu:
 @@@ low-level memhandlers
 @@@
 
+/*
+@ disabled because no improvements noticed, only causes trouble (with gg for example)
 read_rom_byte:
 @ try to avoid lookup of every address at least for ROM and RAM areas
 @ I've verified that if ARead[0xfff0] points to CartBR, it is always normal ROM read.
-#ifndef DEBUG_ASM_6502
        ldr     r0, =CartBR
        ldr     r2, =ARead
        mov     r1, #0xff00
@@ -2739,7 +2737,7 @@ read_rom_byte:
        ldr     r2, [r2, r1, lsl #2]
        ldrb    r0, [r2, REG_ADDR]
        bx      lr
-#endif
+*/
 
 
 read_byte:
@@ -2835,13 +2833,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}
@@ -2920,7 +2931,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:
@@ -3048,6 +3058,7 @@ op9E:     @ SHX $nnnn, Y
        .globl  RAM
        .globl  timestamp
 #else
+       .globl  X_
        .globl  nes_internal_ram
        .globl  timestamp_a
 #endif
@@ -3152,29 +3163,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