Blaster Master + other fixes
[fceu.git] / ncpu.S
diff --git a/ncpu.S b/ncpu.S
index ea9cb61..6b68fe7 100644 (file)
--- a/ncpu.S
+++ b/ncpu.S
@@ -16,6 +16,7 @@
 #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_TIMESTAMP (timestamp        - cpu_exec_table)
 #define OTOFFS_X         (X_               - cpu_exec_table)
 
 @ fceu
        SECTION_TEXT
        ALIGN
 
+/*
 bbbb:
-.ascii "rebase: %04x"
+.ascii "lsr_a: %02x"
 .byte 0x0a,0
 .align 4
-
+stmfd sp!,{r0-r3,r12,lr}
+mov r1,r0
+ldr r0,=bbbb
+bl printf
+ldmfd sp!,{r0-r3,r12,lr}
+*/
 
 @@@
 @@@ r0 =  Address (unbased)
@@ -60,6 +67,16 @@ bbbb:
 .endm
 
 
+@ updates fceu "timestamp" variable
+@ loads cycles to reg, reg!=r1, trashes r1
+.macro FLUSH_TIMESTAMP reg
+       ldr     r1, [REG_OP_TABLE, #OTOFFS_TIMESTAMP]
+       and     \reg, REG_CYCLE, #0xff
+       add     r1, r1, \reg
+       bic     REG_CYCLE, REG_CYCLE, #0xff
+       str     r1, [REG_OP_TABLE, #OTOFFS_TIMESTAMP]
+.endm
+
 
 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ -71,14 +88,16 @@ bbbb:
 @@@
 @@@ ¤Ê¤ó¤«Ì¾Á°¤¬ÊѤÀ¤Ê(¤É¡¼¤Ç¤â¤¤¡¼¤±¤É¡¼
 @@@
-.macro CYCLE_NEXT      n
+.macro CYCLE_NEXT      n, hook_check=1
        @@DEBUG_INFO
 
-       subs    REG_CYCLE, REG_CYCLE, #\n*48
+       add     REG_CYCLE, REG_CYCLE, #\n
+       subs    REG_CYCLE, REG_CYCLE, #\n*48<<16
        ble     cpu_exec_end
+.if \hook_check
        tst     REG_P_REST, #1<<16
-       movne   r0, #\n
        blne    do_irq_hook
+.endif
        ldrb    r0, [REG_PC], #1
        tst     REG_P_REST, #0xff<<8
        ldreq   pc, [REG_OP_TABLE, r0, lsl #2]
@@ -104,11 +123,6 @@ bbbb:
 @@@ CLI¡¦PHP¤Ê¤É¥Õ¥é¥°¤òÊѹ¹¤·¤¿¾ì¹ç¤Ï¤³¤ì
 @@@
 .macro CYCLE_NEXT_INT  n
-@      @@DEBUG_INFO
-@
-@      subs    REG_CYCLE, REG_CYCLE, #\n*48
-@      bgt     cpu_exec_check_int
-@      RETURN_FROM_CPU_EXEC
        CYCLE_NEXT      \n
 .endm
 
@@ -261,18 +275,7 @@ bbbb:
        strb    r0, [REG_ADDR]
 .endm
 
-.macro READ_WRITE_3
-       .long   read_rom_byte
-       .long   read_rom_byte
-       .long   read_rom_byte
-       .long   read_rom_byte
-       .long   read_save_ram
-       .long   read_high_reg
-       .long   read_ppu_reg
-9999:
-.endm
-
-.macro READ_WRITE_4
+.macro READ_WRITE_W
        adr     lr, 1f
        ldr     pc, [pc, r3, lsl #2]
        nop
@@ -287,6 +290,22 @@ bbbb:
 1:
 .endm
 
+.macro READ_WRITE_3
+       .long   read_rom_byte
+       .long   read_rom_byte
+       .long   read_rom_byte
+       .long   read_rom_byte
+       .long   read_save_ram
+       .long   read_high_reg
+       .long   read_ppu_reg
+9999:
+       READ_WRITE_W            @ rmw first writes unmodified data
+.endm
+
+.macro READ_WRITE_4
+       READ_WRITE_W            @ and only then modified (Blaster Master)
+.endm
+
 @@@
 @@@ ½ñ¤­¹þ¤ß¤À¤±¤Î¾ì¹ç
 @@@
@@ -437,7 +456,8 @@ bbbb:
        bic     REG_ADDR, REG_ADDR, #0x10000
        and     r0,REG_ADDR,#0xff
        cmp     REG_Y,r0
-       subgt   REG_CYCLE,REG_CYCLE,#1*48
+       addgt   REG_CYCLE, REG_CYCLE, #1
+       subgt   REG_CYCLE, REG_CYCLE, #1*48<<16
 .endm
 
 @ Indirect Indexed (for writes and rmws)
@@ -474,7 +494,8 @@ bbbb:
        bic     REG_ADDR, REG_ADDR, #0x10000
        and     r0,REG_ADDR,#0xff
        cmp     REG_X,r0
-       subgt   REG_CYCLE,REG_CYCLE,#1*48
+       addgt   REG_CYCLE, REG_CYCLE, #1
+       subgt   REG_CYCLE, REG_CYCLE, #1*48<<16
 .endm
 
 @ Absolute Indexed (for writes and rmws)
@@ -492,7 +513,8 @@ bbbb:
        bic     REG_ADDR, REG_ADDR, #0x10000
        and     r0,REG_ADDR,#0xff
        cmp     REG_Y,r0
-       subgt   REG_CYCLE,REG_CYCLE,#1*48
+       addgt   REG_CYCLE, REG_CYCLE, #1
+       subgt   REG_CYCLE, REG_CYCLE, #1*48<<16
 .endm
 
 @ Absolute Indexed (for writes and rmws)
@@ -1898,14 +1920,16 @@ op7E:   @ ROR $nnnn, X
        and     r1,r1,#0xff
        add     r1,r3,r1
        tst     r1,#0x100
-       subne   REG_CYCLE,REG_CYCLE, #1*48
+       addne   REG_CYCLE, REG_CYCLE, #1
+       subne   REG_CYCLE, REG_CYCLE, #1*48<<16
 .endm
 
 .macro BRANCH_EQ
        ldreqsb r1, [REG_PC], #1
        movne   r1, #1
        add     REG_PC, REG_PC, r1
-       subeq   REG_CYCLE, REG_CYCLE, #1*48
+       addeq   REG_CYCLE, REG_CYCLE, #1
+       subeq   REG_CYCLE, REG_CYCLE, #1*48<<16
        bne     1f
        HAD_BRANCH
 1:
@@ -1915,7 +1939,8 @@ op7E:     @ ROR $nnnn, X
        ldrnesb r1, [REG_PC], #1
        moveq   r1, #1
        add     REG_PC, REG_PC, r1
-       subne   REG_CYCLE, REG_CYCLE, #1*48
+       addne   REG_CYCLE, REG_CYCLE, #1
+       subne   REG_CYCLE, REG_CYCLE, #1*48<<16
        beq     1f
        HAD_BRANCH
 1:
@@ -2761,7 +2786,19 @@ do_int:
        subne   REG_ADDR, REG_ADDR, #NMI_VECTOR
        READ_WORD
        REBASE_PC
-       CYCLE_NEXT      7
+@      CYCLE_NEXT      7
+
+       add     REG_CYCLE, REG_CYCLE, #7
+       subs    REG_CYCLE, REG_CYCLE, #7*48<<16
+       ble     cpu_exec_end
+       ldrb    r0, [REG_PC], #1
+       tst     REG_P_REST, #0xff<<8
+       ldreq   pc, [REG_OP_TABLE, r0, lsl #2]
+
+       tst     REG_P_REST, #P_REST_I_FLAG
+       ldrne   pc, [REG_OP_TABLE, r0, lsl #2]
+       b       do_int
+
 
 @@@
 @@@ ¥ê¥»¥Ã¥È¤Î½èÍý
@@ -2862,13 +2899,15 @@ write_ppu_reg:
 write_high_reg:
 write_save_ram:
 write_rom_byte:
+       FLUSH_TIMESTAMP r2                      @ Blaster Master, more...
 #ifndef DEBUG_ASM_6502
-       @ must preserve r3 for the callers too
+       @ must preserve r0 (data) and r3 for the callers
        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
        mov     REG_PC, lr                      @ r7
        mov     REG_P_REST, r3                  @ r8
+       mov     REG_CYCLE, r0                   @ r11
 
        ldr     r2, =BWrite
        mov     r1, r0
@@ -2879,6 +2918,7 @@ write_rom_byte:
        ldr     REG_OP_TABLE, =cpu_exec_table   @ got trashed because was in r12
        mov     lr, REG_PC
        mov     r3, REG_P_REST
+       mov     r0, REG_CYCLE
        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
@@ -2892,6 +2932,7 @@ write_rom_byte:
        ldr     r2, =dwrite_count_a
        add     r1, r1, #1
        str     r1, [r2]
+       and     r0, r0, #0xff
 #endif
        bx      lr
 
@@ -2916,9 +2957,14 @@ cpu_exec:
 
 @      ldr   REG_OP_TABLE, = cpu_exec_table @ set on init
 
-       CYCLE_NEXT      0
+       CYCLE_NEXT      0, 0
 
 cpu_exec_end:
+       FLUSH_TIMESTAMP r0
+
+       tst     REG_P_REST, #1<<16
+       blne    do_irq_hook_noflushts
+
        ldr     r0, =nes_registers
        stmia   r0, {r4-r12}
 
@@ -3002,6 +3048,7 @@ pc_base:
 MapIRQHook:
        .long   0
 timestamp:
+timestamp_a:
        .long   0
 #ifndef DEBUG_ASM_6502
 X:
@@ -3117,13 +3164,14 @@ op9E:   @ SHX $nnnn, Y
        ALIGN
        .globl  nes_registers @ TODO: hide?
        .globl  pc_base
+       .globl  MapIRQHook @ (int a)
 #ifndef DEBUG_ASM_6502
        .globl  X
        .globl  RAM
        .globl  timestamp
-       .globl  MapIRQHook @ (int a)
 #else
        .globl  nes_internal_ram
+       .globl  timestamp_a
 #endif
        .globl  X6502_Reset_a @ (void);
        .globl  X6502_Power_a @ (void);
@@ -3192,10 +3240,10 @@ TriggerNMINSF_a:
 
 X6502_AddCycles_a:
        ldr     r2, =nes_registers
-       ldr     r1, [r2, #0x1c]
+       ldrsh   r1, [r2, #0x1e]
        mvn     r3, #47                 @ r3=-48
        mla     r0, r3, r0, r1
-       str     r0, [r2, #0x1c]
+       strh    r0, [r2, #0x1e]
        bx      lr
 
 
@@ -3214,7 +3262,12 @@ X6502_Rebase_a:
 
 
 @ the nasty MapIRQHook thing from FCE..
+@ test Gradius 2 (J) if you change this
 do_irq_hook:
+       FLUSH_TIMESTAMP r0
+
+do_irq_hook_noflushts:
+#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
@@ -3226,6 +3279,11 @@ do_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
+#else
+       ldr     r1, =mapirq_cyc_a
+       str     r0, [r1]
+       mov     r1, r0
+#endif
        bx      lr