merged ppu code, added input+zapper, FDS/VS insert in menu
[fceu.git] / ncpu.S
diff --git a/ncpu.S b/ncpu.S
index d26a9ca..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
@@ -405,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
@@ -435,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
@@ -2826,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}
@@ -2911,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:
@@ -3039,6 +3058,7 @@ op9E:     @ SHX $nnnn, Y
        .globl  RAM
        .globl  timestamp
 #else
+       .globl  X_
        .globl  nes_internal_ram
        .globl  timestamp_a
 #endif
@@ -3143,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