.syntax unified .cpu cortex-m4 .fpu softvfp .thumb .include "6502mac_gcc.S" .extern NES_RAM .extern NES_SRAM .extern spr_ram .extern debug_6502 // 无效操作码时调用这个函数 .global cpunmi // cpu中断标志 .global cpuirq // cpu中断标志 .global clocks // apu要的cpu时钟 .global cpu_data // 地址 cart.s .global NMI6502 .global CPU_reset .global run6502 .global op_table .equ IRQ_VECTOR, 0xfffe // IRQ / BRK中断向量地址 .equ RES_VECTOR, 0xfffc // 复位中断向量地址 .equ NMI_VECTOR, 0xfffa // NMI中断向量地址 .section .text._6502_cpu .type _00, %function _00: ldr r0,[globalptr,#lastbank] sub r1,m6502_pc,r0 add r0,r1,#1 push16 encodeP (B+R) ldr r12,=IRQ_VECTOR bl VecCont fetch 7 // 把常量放在这里 .ltorg .type _01, %function _01:// ORA ($nn,X) doIIX opORA fetch 6 .type _05, %function _05:// ORA $nn doZ opORA fetch 3 .type _06, %function _06:// ASL $nn doZ opASL fetch_c 5 .type _08, %function _08:// PHP encodeP (B+R) push8 r0 fetch 3 .type _09, %function _09:// ORA #$nn doIMM opORA fetch 2 .type _0A, %function _0A:// ASL adds m6502_a,m6502_a,m6502_a mov m6502_nz,m6502_a,asr#24 // NZ orr cycles,cycles,#CYC_C // Prepare C fetch_c 2 // also subs carry .type _0D, %function _0D:// ORA $nnnn doABS opORA fetch 4 .type _0E, %function _0E:// ASL $nnnn doABS opASL fetch_c 6 .type _10, %function _10:// BPL * tst m6502_nz,#0x80000000 ldrsb r0,[m6502_pc],#1 ITT EQ addeq m6502_pc,m6502_pc,r0 subeq cycles,cycles,#256 fetch 2 .type _11, %function _11:// ORA ($nn),Y doIIY opORA fetch 5 .type _15, %function _15:// ORA $nn,X doZIXf opORA fetch 4 .type _16, %function _16:// ASL $nn,X doZIXf opASL fetch_c 6 .type _18, %function _18:// CLC bic cycles,cycles,#CYC_C fetch 2 .type _19, %function _19:// ORA $nnnn,Y doAIY opORA fetch 4 .type _1D, %function _1D:// ORA $nnnn,X doAIX opORA fetch 4 .type _1E, %function _1E:// ASL $nnnn,X doAIX opASL fetch_c 7 .type _20, %function _20:// JSR $nnnn ldrb r2,[m6502_pc],#1 ldr r1,[globalptr,#lastbank] sub r0,m6502_pc,r1 ldrb r1,[m6502_pc] orr m6502_pc,r2,r1,lsl#8 push16 encodePC fetch 6 .type _21, %function _21:// AND ($nn,X) doIIX opAND fetch 6 .type _24, %function _24:// BIT $nn doZ opBIT fetch 3 .type _25, %function _25:// AND $nn doZ opAND fetch 3 .type _26, %function _26:// ROL $nn doZ opROL fetch 5 .type _28, %function _28:// PLP pop8 r0 decodeP fetch 4 .type _29, %function _29:// AND #$nn doIMM opAND fetch 2 .type _2A, %function _2A:// ROL movs cycles,cycles,lsr#1 // get C IT CS orrcs m6502_a,m6502_a,#0x00800000 adds m6502_a,m6502_a,m6502_a mov m6502_nz,m6502_a,asr#24 // NZ adc cycles,cycles,cycles // Set C fetch 2 .type _2C, %function _2C:// BIT $nnnn doABS opBIT fetch 4 .type _2D, %function _2D:// AND $nnnn doABS opAND fetch 4 .type _2E, %function _2E:// ROL $nnnn doABS opROL fetch 6 .type _30, %function _30:// BMI * tst m6502_nz,#0x80000000 ldrsb r0,[m6502_pc],#1 ITT NE addne m6502_pc,m6502_pc,r0 subne cycles,cycles,#256 fetch 2 .type _31, %function _31:// AND ($nn),Y doIIY opAND fetch 5 .type _35, %function _35:// AND $nn,X doZIXf opAND fetch 4 .type _36, %function _36:// ROL $nn,X doZIXf opROL fetch 6 .type _38, %function _38:// SEC orr cycles,cycles,#CYC_C fetch 2 .type _39, %function _39:// AND $nnnn,Y doAIY opAND fetch 4 .type _3D, %function _3D:// AND $nnnn,X doAIX opAND fetch 4 .type _3E, %function _3E:// ROL $nnnn,X doAIX opROL fetch 7 .type _40, %function _40:// RTI pop8 r0 // pop 6502 flags and decode decodeP pop16 // pop the return address encodePC fetch 6 .type _41, %function _41:// EOR ($nn,X) doIIX opEOR fetch 6 .type _45, %function _45:// EOR $nn doZ opEOR fetch 3 .type _46, %function _46:// LSR $nn doZ opLSR fetch_c 5 .type _48, %function _48:// PHA mov r0,m6502_a,lsr#24 push8 r0 fetch 3 .type _49, %function _49:// EOR #$nn doIMM opEOR fetch 2 .type _4A, %function _4A:// LSR movs m6502_nz,m6502_a,lsr#25 // Z, N=0 mov m6502_a,m6502_nz,lsl#24 // result without garbage orr cycles,cycles,#CYC_C // Prepare C fetch_c 2 .type _4C, %function _4C:// JMP $nnnn ldrb r0,[m6502_pc],#1 ldrb r1,[m6502_pc] orr m6502_pc,r0,r1,lsl#8 encodePC fetch 3 .type _4D, %function _4D:// EOR $nnnn doABS opEOR fetch 4 .type _4E, %function _4E:// LSR $nnnn doABS opLSR fetch_c 6 .type _50, %function _50:// BVC * tst cycles,#CYC_V ldrsb r0,[m6502_pc],#1 ITT EQ addeq m6502_pc,m6502_pc,r0 subeq cycles,cycles,#256 fetch 2 .type _51, %function _51:// EOR ($nn),Y doIIY opEOR fetch 5 .type _55, %function _55:// EOR $nn,X doZIXf opEOR fetch 4 .type _56, %function _56:// LSR $nn,X doZIXf opLSR fetch_c 6 .type _58, %function _58:// CLI bic cycles,cycles,#CYC_I fetch 2 .type _59, %function _59:// EOR $nnnn,Y doAIY opEOR fetch 4 .type _5D, %function _5D:// EOR $nnnn,X doAIX opEOR fetch 4 .type _5E, %function _5E:// LSR $nnnn,X doAIX opLSR fetch_c 7 .type _60, %function _60:// RTS pop16 add m6502_pc,m6502_pc,#1 encodePC fetch 6 .type _61, %function _61:// ADC ($nn,X) doIIX opADC fetch_c 6 .type _65, %function _65:// ADC $nn doZ opADC fetch_c 3 .type _66, %function _66:// ROR $nn doZ opROR fetch 5 .type _68, %function _68:// PLA pop8 m6502_nz mov m6502_a,m6502_nz,lsl#24 fetch 4 .type _69, %function _69:// ADC #$nn doIMM opADC fetch_c 2 .type _6A, %function _6A:// ROR movs cycles,cycles,lsr#1 // get C mov m6502_a,m6502_a,rrx movs m6502_nz,m6502_a,asr#24 // NZ and m6502_a,m6502_a,#0xff000000 adc cycles,cycles,cycles // Set C fetch 2 .type _6C, %function _6C:// JMP ($nnnn) JMP ($data16) 间接寻址 ********************************* doABS add r1, globalptr,#memmap_tbl and r2,addy,#0xE000 // lsr r0,r2,#11 ldr r1,[r1,r0] // 在数据传送之前,将偏移量加到Rn 中,其结果作为传送数据的存储地址 ldrb m6502_pc,[r1,addy] // //若使用后缀"!",则结果写回到Rn中 add r1,r1,addy ldrb r0,[r1,#1] orr m6502_pc,m6502_pc,r0,lsl#8 // m6502_pc=r9使用ORR 指令将近R9的高8 位数据移入到R0低8位 encodePC fetch 5 .type _6D, %function _6D:// ADC $nnnn doABS opADC fetch_c 4 .type _6E, %function _6E:// ROR $nnnn doABS opROR fetch 6 .type _70, %function _70:// BVS * tst cycles,#CYC_V ldrsb r0,[m6502_pc],#1 ITT NE addne m6502_pc,m6502_pc,r0 subne cycles,cycles,#256 fetch 2 .type _71, %function _71:// ADC ($nn),Y doIIY opADC fetch_c 5 .type _75, %function _75:// ADC $nn,X doZIXf opADC fetch_c 4 .type _76, %function _76:// ROR $nn,X doZIXf opROR fetch 6 .type _78, %function _78:// SEI orr cycles,cycles,#CYC_I fetch 2 .type _79, %function _79:// ADC $nnnn,Y doAIY opADC fetch_c 4 .type _7D, %function _7D:// ADC $nnnn,X doAIX opADC fetch_c 4 .type _7E, %function _7E:// ROR $nnnn,X doAIX opROR fetch 7 .type _81, %function _81:// STA ($nn,X) doIIX opSTORE m6502_a fetch 6 .type _84, %function _84:// STY $nn doZ opSTORE m6502_y fetch 3 .type _85, %function _85:// STA $nn doZ opSTORE m6502_a fetch 3 .type _86, %function _86:// STX $nn doZ opSTORE m6502_x fetch 3 .type _88, %function _88:// DEY sub m6502_y,m6502_y,#0x01000000 mov m6502_nz,m6502_y,asr#24 fetch 2 .type _8A, %function _8A:// TXA mov m6502_a,m6502_x mov m6502_nz,m6502_x,asr#24 fetch 2 .type _8C, %function _8C:// STY $nnnn doABS opSTORE m6502_y fetch 4 .type _8D, %function _8D:// STA $nnnn doABS opSTORE m6502_a fetch 4 .type _8E, %function _8E:// STX $nnnn doABS opSTORE m6502_x fetch 4 .type _90, %function _90:// BCC * tst cycles,#CYC_C // Test Carry ldrsb r0,[m6502_pc],#1 ITT EQ addeq m6502_pc,m6502_pc,r0 subeq cycles,cycles,#256 fetch 2 .type _91, %function _91:// STA ($nn),Y doIIY opSTORE m6502_a fetch 6 .type _94, %function _94:// STY $nn,X doZIXf opSTORE m6502_y fetch 4 .type _95, %function _95:// STA $nn,X doZIXf opSTORE m6502_a fetch 4 .type _96, %function _96:// STX $nn,Y doZIYf opSTORE m6502_x fetch 4 .type _98, %function _98:// TYA mov m6502_a,m6502_y mov m6502_nz,m6502_y,asr#24 fetch 2 .type _99, %function _99:// STA $nnnn,Y doAIY opSTORE m6502_a fetch 5 .type _9A, %function _9A:// TXS mov r0,m6502_x,lsr#24 strb r0,[globalptr,#m6502_s] fetch 2 .type _9D, %function _9D:// STA $nnnn,X doAIX opSTORE m6502_a fetch 5 .type _A0, %function _A0:// LDY #$nn doIMM opLOAD m6502_y fetch 2 .type _A1, %function _A1:// LDA ($nn,X) doIIX opLOAD m6502_a fetch 6 .type _A2, %function _A2:// LDX #$nn doIMM opLOAD m6502_x fetch 2 .type _A4, %function _A4:// LDY $nn doZ opLOAD m6502_y fetch 3 .type _A5, %function _A5:// LDA $nn doZ opLOAD m6502_a fetch 3 .type _A6, %function _A6:// LDX $nn doZ opLOAD m6502_x fetch 3 .type _A8, %function _A8:// TAY mov m6502_y,m6502_a mov m6502_nz,m6502_y,asr#24 fetch 2 .type _A9, %function _A9:// LDA #$nn doIMM opLOAD m6502_a fetch 2 .type _AA, %function _AA:// TAX mov m6502_x,m6502_a mov m6502_nz,m6502_x,asr#24 fetch 2 .type _AC, %function _AC:// LDY $nnnn doABS opLOAD m6502_y fetch 4 .type _AD, %function _AD:// LDA $nnnn doABS opLOAD m6502_a fetch 4 .type _AE, %function _AE:// LDX $nnnn doABS opLOAD m6502_x fetch 4 .type _B0, %function _B0:// BCS * tst cycles,#CYC_C // Test Carry ldrsb r0,[m6502_pc],#1 ITT NE addne m6502_pc,m6502_pc,r0 subne cycles,cycles,#256 fetch 2 .type _B1, %function _B1:// LDA ($nn),Y doIIY opLOAD m6502_a fetch 5 .type _B4, %function _B4:// LDY $nn,X doZIX opLOAD m6502_y fetch 4 .type _B5, %function _B5:// LDA $nn,X doZIX opLOAD m6502_a fetch 4 .type _B6, %function _B6:// LDX $nn,Y doZIY opLOAD m6502_x fetch 4 .type _B8, %function _B8:// CLV bic cycles,cycles,#CYC_V fetch 2 .type _B9, %function _B9:// LDA $nnnn,Y doAIY opLOAD m6502_a fetch 4 .type _BA, %function _BA:// TSX ldrb m6502_x,[globalptr,#m6502_s] mov m6502_x,m6502_x,lsl#24 mov m6502_nz,m6502_x,asr#24 fetch 2 .type _BC, %function _BC:// LDY $nnnn,X doAIX opLOAD m6502_y fetch 4 .type _BD, %function _BD:// LDA $nnnn,X doAIX opLOAD m6502_a fetch 4 .type _BE, %function _BE:// LDX $nnnn,Y doAIY opLOAD m6502_x fetch 4 .type _C0, %function _C0:// CPY #$nn doIMM opCOMP m6502_y fetch_c 2 .type _C1, %function _C1:// CMP ($nn,X) doIIX opCOMP m6502_a fetch_c 6 .type _C4, %function _C4:// CPY $nn doZ opCOMP m6502_y fetch_c 3 .type _C5, %function _C5:// CMP $nn doZ opCOMP m6502_a fetch_c 3 .type _C6, %function _C6:// DEC $nn doZ opDEC fetch 5 .type _C8, %function _C8:// INY add m6502_y,m6502_y,#0x01000000 mov m6502_nz,m6502_y,asr#24 fetch 2 .type _C9, %function _C9:// CMP #$nn doIMM opCOMP m6502_a fetch_c 2 .type _CA, %function _CA:// DEX sub m6502_x,m6502_x,#0x01000000 mov m6502_nz,m6502_x,asr#24 fetch 2 .type _CC, %function _CC:// CPY $nnnn doABS opCOMP m6502_y fetch_c 4 .type _CD, %function _CD:// CMP $nnnn doABS opCOMP m6502_a fetch_c 4 .type _CE, %function _CE:// DEC $nnnn doABS opDEC fetch 6 .type _D0, %function _D0:// BNE * tst m6502_nz,#0xff ldrsb r0,[m6502_pc],#1 ITT NE addne m6502_pc,m6502_pc,r0 subne cycles,cycles,#256 fetch 2 .type _D1, %function _D1:// CMP ($nn),Y doIIY opCOMP m6502_a fetch_c 5 .type _D5, %function _D5:// CMP $nn,X doZIXf opCOMP m6502_a fetch_c 4 .type _D6, %function _D6:// DEC $nn,X doZIXf opDEC fetch 6 .type _D8, %function _D8:// CLD bic cycles,cycles,#CYC_D fetch 2 .type _D9, %function _D9:// CMP $nnnn,Y doAIY opCOMP m6502_a fetch_c 4 .type _DD, %function _DD:// CMP $nnnn,X doAIX opCOMP m6502_a fetch_c 4 .type _DE, %function _DE:// DEC $nnnn,X doAIX opDEC fetch 7 .type _E0, %function _E0:// CPX #$nn doIMM opCOMP m6502_x fetch_c 2 .type _E1, %function _E1:// SBC ($nn,X) doIIX opSBC fetch_c 6 .type _E4, %function _E4:// CPX $nn doZ opCOMP m6502_x fetch_c 3 .type _E5, %function _E5:// SBC $nn doZ opSBC fetch_c 3 .type _E6, %function _E6:// INC $nn doZ opINC fetch 5 .type _E8, %function _E8:// INX add m6502_x,m6502_x,#0x01000000 mov m6502_nz,m6502_x,asr#24 fetch 2 .type _E9, %function _E9:// SBC #$nn doIMM opSBC fetch_c 2 .type _EA, %function _EA:// NOP fetch 2 .type _EC, %function _EC:// CPX $nnnn doABS opCOMP m6502_x fetch_c 4 .type _ED, %function _ED:// SBC $nnnn doABS opSBC fetch_c 4 .type _EE, %function _EE:// INC $nnnn doABS opINC fetch 6 .type _F0, %function _F0:// BEQ * tst m6502_nz,#0xff ldrsb r0,[m6502_pc],#1 ITT EQ addeq m6502_pc,m6502_pc,r0 subeq cycles,cycles,#256 fetch 2 .type _F1, %function _F1:// SBC ($nn),Y doIIY opSBC fetch_c 5 .type _F5, %function _F5:// SBC $nn,X doZIXf opSBC fetch_c 4 .type _F6, %function _F6:// INC $nn,X doZIXf opINC fetch 6 .type _F8, %function _F8:// SED orr cycles,cycles,#CYC_D fetch 2 .type _F9, %function _F9:// SBC $nnnn,Y doAIY opSBC fetch_c 4 .type _FD, %function _FD:// SBC $nnnn,X doAIX opSBC fetch_c 4 .type _FE, %function _FE:// INC $nnnn,X doAIX opINC fetch 7 // ***********************************************************以下指令是一些HACK游戏需要****************** .type _FF, %function _FF:// ISB $????,X 加的,不确定正确 激龟忍者传2无敌HACK需要 doAIX opSBC fetch 5 .type _FB, %function _FB:// ISB $????,X 加的,不确定正确 激龟忍者传2无敌HACK需要 doAIY opSBC fetch 5 .type _14, %function _14:// 加的,不确定正确 激龟忍者传2无敌HACK需要 add m6502_pc,m6502_pc,#1 fetch 4 .type _67, %function _67:// 帝国战机无敌HACK需要 doZ opADC fetch 5 .type _03, %function _03:// 帝国战机无敌HACK需要 doIIX fetch 8 .type _07, %function _07: doZ fetch 5 .type _xx, %function _xx: // invalid opcode 无效的操作码 mov r1,#1 // 不用debug可以直接注译这两行 bl debug_6502 fetch 2 .type run6502, %function run6502: stmfd sp!,{r4-r11,lr} // 将这几个寄存器中的值保存到堆栈中 ldr globalptr,=cpu_data // r10 wram_globals: 读取地址 ldr cpu_zpage,=NES_RAM // r11 ldr cpu_zpage,[cpu_zpage] // NES_RAM用了指针 add r1, globalptr,#cpuregs ldmia r1,{m6502_nz-m6502_pc} // restore 6502 state恢复6502状态 r3-r9 add cycles,cycles,r0 ldrb r0,[globalptr,#cpuirqf] // cpu中断标志 cmp r0,#0x01 beq CheckI // EQ 相等(EQual) irq6502; fetch 0 // 提取操作码并运行 .type exit_run, %function exit_run: ldrb r0,[globalptr,#cpunmif] // cpu中断标志 cmp r0,#0x01; beq NMI6502 // EQ 相等(EQual) exit_nmi: add r0, globalptr,#cpuregs stmia r0,{m6502_nz-m6502_pc} // 保存6502状态 r3-r9 ldmfd sp!,{r4-r11,pc} // exit NMI6502: mov r0,#0 str r0,[globalptr,#cpunmif] // 清除cpu中断标志 ldr r12,=NMI_VECTOR // NMI? addy bl Vec6502 sub cycles,cycles,#7*256 // CYCLE=256 6502的中断潜伏期为七 (7) 个周 // 期; 这也就是说需要需要七 (7) 个周期来移入和移出一个中断 b exit_nmi // return default_scanlinehook: fetch 0 CheckI: // Check Interrupt Disable 检查中断禁用 tst cycles,#CYC_I bne default_scanlinehook // we dont want no stinkin irqs 我们不需要没有讨厌的IRQ irq6502: mov r0,#0 str r0,[globalptr,#cpuirqf] // 清除cpu中断标志 ldr r12,=IRQ_VECTOR bl Vec6502 fetch 7 Vec6502: ldr r0,[globalptr,lastbank] sub r0,m6502_pc,r0 push16 // save PC encodeP (R) // save P VecCont: push8 r0 orr cycles,cycles,#CYC_I // disable IRQ 禁用IRQ ldr r0,[globalptr,#memmap_tbl+28] // 7*4 // ldrb m6502_pc,[r0,r12]! ldrb m6502_pc,[r0,r12] // 在数据传送之前,将偏移量加到Rn 中,其结果作为传送数据的存储地址 // 若使用后缀"!",则结果写回到Rn中 add r0,r0,r12 // R12=0xfffc 复位中断向量地址 ldrb r2,[r0,#1] orr m6502_pc,m6502_pc,r2,lsl#8 encodePC // get IRQ vector得到6502 PC ROM的偏移量 bx lr .type CPU_reset, %function CPU_reset: // called by loadcart (r0-r9 are free to use) str lr,[sp,#-4]! mov m6502_a,#0 mov m6502_x,#0 mov m6502_y,#0 mov m6502_nz,#0 add m6502_rmem, globalptr,#readmem_tbl // 把readmem_tbl的地址加载到m6502_rmem ldr r0,=NES_RAM // NES_RAM用了指针 ldr r0,[r0] add r0,#0x100 str r0,[globalptr,#m6502_s] // S=0xFD (0x100-3) 把一个寄存器按字存储到存储器中 mov r0,#0 str r0,[globalptr,#cpunmif] // 清除cpu中断标志 str r0,[globalptr,#cpuirqf] // 清除cpu中断标志 mov cycles,#0 // D=0, C=0, V=0, I=1 disable IRQ. ldr r12,=RES_VECTOR // 复位中断向量地址 bl Vec6502 add r0, globalptr,#cpuregs // 读取地址 stmia r0,{m6502_nz-m6502_pc} // 保存6502状态 ldr r1,=exit_run str r1,[globalptr,#nexttimeout] // 保存指令执行完后下一步的PC地址 ldr pc,[sp],#4 .type empty_R, %function empty_R: // 读地址不正确read bad address (error) mov r0,r12 mov r1,#2 bl debug_6502 mov r0,#0 orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .type void, %function void: // - - - - - - - - -空函数 mov r0,#0 orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .type ram_R, %function ram_R: // ram read ($0000-$1FFF) bic addy,addy,#0x1f800 // only 0x07FF is RAM ldrb r0,[cpu_zpage,addy] orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .type ram_W, %function ram_W: // ram write ($0000-$1FFF) bic addy,addy,#0x1f800 // only 0x07FF is RAM strb r0,[cpu_zpage,addy] // cpu_zpage RN r11 ;=CPU_RAM orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .type sram_R, %function sram_R: // sram read ($6000-$7FFF) sub r1,addy,#0x6000 ldr r2,[globalptr,#memmap_tbl+12] ldrb r0,[r2,r1] orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .type sram_W, %function sram_W: // sram write ($6000-$7FFF) sub addy,addy,#0x6000 ldr r1,[globalptr,#memmap_tbl+12] strb r0,[r1,addy] orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .type rom_R60, %function rom_R60: // rom read ($6000-$7FFF) ldr r1,[globalptr,#memmap_tbl+12] ldrb r0,[r1,addy] orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .type rom_R80, %function rom_R80: // rom read ($8000-$9FFF) ldr r1,[globalptr,#memmap_tbl+16] ldrb r0,[r1,addy] orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .type rom_RA0, %function rom_RA0: // rom read ($A000-$BFFF) ldr r1,[globalptr,#memmap_tbl+20] ldrb r0,[r1,addy] orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .type rom_RC0, %function rom_RC0: // rom read ($C000-$DFFF) ldr r1,[globalptr,#memmap_tbl+24] ldrb r0,[r1,addy] orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .type rom_RE0, %function rom_RE0: // ;rom read ($E000-$FFFF) ldr r1,[globalptr,#memmap_tbl+28] ldrb r0,[r1,addy] orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .type IO_R, %function IO_R: // I/O read mov r2,#0x4018 // $4018-$6000 cmp r12,r2 bhi Read_Low // HI 无符号数大于 C==1 && Z==0 sub r1,r12,#0x4000 // addy=r12 subs r1,r1,#0x15 bmi empty_R // 读地址不正确 MI 负数(MInus) N==1 cmp r1,#3 ldr r2,=io_read_tbl // 改过,加3行 add r2,r2,r1,lsl#2 // <<2 IT MI ldrmi pc,[r2] b empty_R // 读地址不正确 .type io_read_tbl, %object io_read_tbl: .word apu_4015R // void_4015r ;4015 (sound) .word joy0_R // 4016: controller 1 .word joy1_R // 4017: controller 2 .type IO_W, %function IO_W: // I/O write mov r2,#0x4018 // $4018-$6000 cmp r12,r2 bhi Write_Low // HI 无符号数大于 C==1 && Z==0 sub r1,r12,#0x4000 // addy=r12 cmp r1,#0x18 ldr r2,=io_write_tbl // 改过,加3行 add r2,r2,r1,lsl#2 // <<2 IT MI ldrmi pc,[r2] // 直接操作pc太他妈危险了 b empty_R // 读地址不正确 .type io_write_tbl, %object io_write_tbl: .word apu_w // void_4000w .word apu_w // _4001w .word apu_w // _4002w .word apu_w // _4003w .word apu_w // _4004w .word apu_w // _4005w .word apu_w // _4006w .word apu_w // _4007w .word apu_w // _4008w .word apu_w // void .word apu_w // _400aw .word apu_w // void_400bw .word apu_w // void_400cw .word apu_w // void .word apu_w // void_400ew .word apu_w // void_400fw .word apu_w // void_4010w .word apu_w // void_4011w .word apu_w // void_4012w .word apu_w // void_4013w .word dma_W // $4014: Sprite DMA transfer .word apu_4015w // void_4015w 声音通道切换 .word joy0_W // $4016: Joypad 0 write joypad_write_ptr .word void // joy1_W $4017: .extern asm_Mapper_ReadLow .type Read_Low, %function Read_Low: // $5000-$6000 mapper->MemoryReadLow(addr); stmfd sp!,{r3,lr} // LR 寄存器放栈 mov r0,r12 bl asm_Mapper_ReadLow ldmfd sp!,{r3,lr} orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .extern asm_Mapper_WriteLow .type Write_Low, %function Write_Low: // $5000-$6000 mapper->MemoryWriteLow( data, addr); stmfd sp!,{r3,lr} // LR 寄存器放栈 mov r1,r12 bl asm_Mapper_WriteLow ldmfd sp!,{r3,lr} orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .extern Apu_Write .extern Apu_Write4015 .type apu_w, %function apu_w: // 0x4000--0x4013 stmfd sp!,{r3,lr} // LR 寄存器放栈 bl Apu_Write ldmfd sp!,{r3,lr} orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .type apu_4015w, %function apu_4015w: stmfd sp!,{r3,lr} bl Apu_Write4015 ldmfd sp!,{r3,lr} orr lr,#0x01 bx lr .extern Apu_Read4015 .type apu_4015R, %function apu_4015R: stmfd sp!,{r3,lr} add r0,r1,#0x15 bl Apu_Read4015 ldmfd sp!,{r3,lr} orr lr,#0x01 bx lr .type dma_W, %function dma_W: // (4014) sprite DMA transfer 精灵DMA传输 DMA访问精灵RAM: // 通过写一个值xx到这个端口,引起CPU内存地址为$xx00-$xxFF的区域传送到精灵内存 sub cycles,cycles,#512*256 stmfd sp!,{r3,lr} and r1,r0,#0xe0 add r2, globalptr,#memmap_tbl lsr r1,r1,#3 ldr r2,[r2,r1] and r0,r0,#0xff add r2,r2,r0,lsl#8 // addy r2=DMA source 源 ldr r1,=spr_ram // r1 DMA的 目的地 ppu.c ldr r1,[r1] // spr_ram用了指针 mov r0,#64 // 256/4/8 copy_: subs r0,r0,#1 // -1 ldr r3,[r2,r0,lsl#2] str r3,[r1,r0,lsl#2] // <<2 *4 bne copy_ ldmfd sp!,{r3,lr} orr lr,#0x01 bx lr .extern PADdata .extern PADdata1 .type joy0_W, %function joy0_W: // 4016 手柄1键值 [7:0]右7 左6 下5 上4 Start3 Select2 B1 A0 ) tst r0,#1 // 0=写,1=读 orr lr,#0x01 // lr最低位置1防止进入arm状态 IT NE bxne lr // NE 不等(NotEqual) ldr r1,=PADdata; // 手柄1键值 ldr r1,[r1] str r1,[globalptr,#joy0data] ldr r1,=PADdata1; // 手柄1键值 ldr r1,[r1] str r1,[globalptr,#joy1data] bx lr // 在手柄0里面把手柄1的数据一起读取了,所以这个函数不需要了 joy1_W: // 4017 手柄1键值 [7:0]右7 左6 下5 上4 Start3 Select2 B1 A0 ) // tst r0,#1 ; 0=??,1=读 // orr lr,#0x01 ;lr最低位置1防止进入arm状态 // bxne lr ;NE 不等(NotEqual) bx lr .type joy0_R, %function joy0_R: ldr r0,[globalptr,#joy0data] // 串行数据 当前读取位;joy0data是键值 mov r1,r0,lsr#1 // >>1 str r1,[globalptr,#joy0data] and r0,r0,#1 // &1 orr r0,r0,#0x40 // |0x40 orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .type joy1_R, %function joy1_R: ldr r0,[globalptr,#joy1data] // 串行数据 当前读取位;joy0data是键值 mov r1,r0,lsr#1 // >>1 str r1,[globalptr,#joy1data] and r0,r0,#1 // &1 orr r0,r0,#0x40 // |0x80? 0xf8? orr lr,#0x01 // lr最低位置1防止进入arm状态 bx lr .global K6502_Read .type K6502_Read, %function K6502_Read: // apu Rendering DPCM channel #5 r0=APU->ApuC5Address不确定正确* stmfd sp!,{lr} mov r1,r0,lsr#13 // >>13= & 0xe000 ldr r2,=CPU_RAM // 存储器映象 ram+rom ldr r1,[r2,r1,lsl#2] // lookup rom ptr..查找ptr bic r0,r0,#0xe000 // and r0,#0x1fff &0x1fff ldrb r0,[r1,r0] ldmfd sp!,{lr} bx lr .extern PPU_WriteToPort .extern PPU_ReadFromPort .type PPU_W, %function PPU_W: stmfd sp!,{r3,lr} mov r1,r12 bl PPU_WriteToPort ldmfd sp!,{r3,lr} orr lr,#0x01 bx lr .type PPU_R, %function PPU_R: stmfd sp!,{r3,lr} mov r0,r12 bl PPU_ReadFromPort ldmfd sp!,{r3,lr} orr lr,#0x01 bx lr .type op_table, %object op_table: .word _00,_01,_xx,_03,_xx,_05,_06,_07,_08,_09,_0A,_xx,_xx,_0D,_0E,_xx .word _10,_11,_xx,_xx,_14,_15,_16,_xx,_18,_19,_xx,_xx,_xx,_1D,_1E,_xx .word _20,_21,_xx,_xx,_24,_25,_26,_xx,_28,_29,_2A,_xx,_2C,_2D,_2E,_xx .word _30,_31,_xx,_xx,_xx,_35,_36,_xx,_38,_39,_xx,_xx,_xx,_3D,_3E,_xx .word _40,_41,_xx,_xx,_xx,_45,_46,_xx,_48,_49,_4A,_xx,_4C,_4D,_4E,_xx .word _50,_51,_xx,_xx,_xx,_55,_56,_xx,_58,_59,_xx,_xx,_xx,_5D,_5E,_xx .word _60,_61,_xx,_xx,_xx,_65,_66,_67,_68,_69,_6A,_xx,_6C,_6D,_6E,_xx .word _70,_71,_xx,_xx,_xx,_75,_76,_xx,_78,_79,_xx,_xx,_xx,_7D,_7E,_xx .word _xx,_81,_xx,_xx,_84,_85,_86,_xx,_88,_xx,_8A,_xx,_8C,_8D,_8E,_xx .word _90,_91,_xx,_xx,_94,_95,_96,_xx,_98,_99,_9A,_xx,_xx,_9D,_xx,_xx .word _A0,_A1,_A2,_xx,_A4,_A5,_A6,_xx,_A8,_A9,_AA,_xx,_AC,_AD,_AE,_xx .word _B0,_B1,_xx,_xx,_B4,_B5,_B6,_xx,_B8,_B9,_BA,_xx,_BC,_BD,_BE,_xx .word _C0,_C1,_xx,_xx,_C4,_C5,_C6,_xx,_C8,_C9,_CA,_xx,_CC,_CD,_CE,_xx .word _D0,_D1,_xx,_xx,_xx,_D5,_D6,_xx,_D8,_D9,_xx,_xx,_xx,_DD,_DE,_xx .word _E0,_E1,_xx,_xx,_E4,_E5,_E6,_xx,_E8,_E9,_EA,_xx,_EC,_ED,_EE,_xx .word _F0,_F1,_xx,_xx,_xx,_F5,_F6,_xx,_F8,_F9,_xx,_FB,_xx,_FD,_FE,_FF .section .data._6502_cpu_data .type cpu_data, %object cpu_data: .word 0 // opz # 4 代码表地址 // readmem_tbl .word ram_R // $0000 .word PPU_R // $2000 .word IO_R // $4000 .word sram_R // $6000 .word rom_R80 // $8000 .word rom_RA0 // $A000 .word rom_RC0 // $C000 .word rom_RE0 // $E000 // writemem_tbl .word ram_W // $0000 .word PPU_W // $2000 r0传参数 .word IO_W // $4000 .word sram_W // $6000 .word void // $8000 .word void // $A000 .word void // $C000 .word void // $E000 CPU_RAM: // memmap_tbl 存储器映象 .word NES_RAM // $0000 0000-7fff keep $400 byte aligned for 6502 stack shit .word NES_RAM // $2000 should 保持1024字节对齐 .word NES_RAM // $4000 never .word NES_SRAM // NES_RAM-0x5800 ;$6000 change改变 rommap: .space 4*4 // $8000-FFFF memmap_tbl+16 cpustate: // group these together for save/loadstate .space 7*4 // cpuregs (nz,c,a,x,y,cycles,pc) .word 0 // m6502_s: .word 0 // lastbank: 最后MEMMAP添加到PC (用于计算当前的PC ) .word 0 // nexttimeout: jump here when cycles runs out 跳到下一个时钟周期运行 .word 0 // rombase # 4 ;//ROM开始地址 .word 0 // romnumber # 4 ;// .word 0 // rommask # 4 ;//ROM掩膜 rommask=romsize-1 .word 0 // joy0data # 4 ;//手柄1串行数据 .word 0 // joy1data # 4 ;//手柄2串行数据 clocks: .word 0 // clocksh # 4 ;//执行的时钟数 apu用 cpunmi: .word 0 // cpunmif # 4 ;cpu中断标志 cpuirq: .word 0 // cpuirqf # 4 ;cpu中断标志