⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 65c816.asm

📁 NES game Emulator in Linux.c and asm codes.
💻 ASM
📖 第 1 页 / 共 5 页
字号:
 inc bx                 ; Preincrement S
%endif
%ifdef FAST_STACK_ACCESS_EMULATION_MODE
 FAST_GET_BYTE_STACK_EMULATION_MODE al
%else
 GET_BYTE
 mov ah,al
%endif
%ifnidni %1,New
 inc byte [CPU_LABEL(S)]    ; Preincrement SL
 mov ebx,[CPU_LABEL(S)] ; S only - bank always 0!
%else
 inc bx                 ; Preincrement S
 mov [CPU_LABEL(S)],bl  ; Update SL
%endif
%ifdef FAST_STACK_ACCESS_EMULATION_MODE
 FAST_GET_BYTE_STACK_EMULATION_MODE ah
%else
 GET_BYTE
 ror ax,8
%endif
%endmacro

%macro PULL_W 0-1 0
%if S_8bit
 E1_PULL_W %1
%else
 E0_PULL_W
%endif
%endmacro


; Native mode - push long (S--)
%macro E0_PUSH_L 0
 mov ebx,[CPU_LABEL(S)] ; S only - bank always 0!
 ror eax,16     ; bank byte
 SET_BYTE
 dec bx         ; Postdecrement S
 rol eax,8      ; high byte
 SET_BYTE
 dec bx         ; Postdecrement S
 rol eax,8      ; low byte
 SET_BYTE
 dec bx         ; Postdecrement S
 mov [CPU_LABEL(S)],ebx ; Set stack pointer
%endmacro

; Emulation mode - push long (SL--*)
%macro E1_PUSH_L_New 0
 mov ebx,[CPU_LABEL(S)] ; S only - bank always 0!
 ror eax,16     ; bank byte
 SET_BYTE
 dec bx         ; Postdecrement S
 rol eax,8      ; high byte
 SET_BYTE
 dec bx         ; Postdecrement S
 rol eax,8      ; low byte
 SET_BYTE
 dec bx         ; Postdecrement S
 mov [CPU_LABEL(S)],bl  ; Set stack pointer
%endmacro

%macro PUSH_L 0
%if S_8bit
 E1_PUSH_L_New
%else
 E0_PUSH_L
%endif
%endmacro


; Native mode - pull long (++S)
%macro E0_PULL_L 0
 mov ebx,[CPU_LABEL(S)] ; S only - bank always 0!
 inc bx         ; Preincrement S
 GET_BYTE
 inc bx         ; Preincrement S
 ror eax,8      ; low byte
 GET_BYTE
 inc bx         ; Preincrement S
 ror eax,8      ; high byte
 GET_BYTE
 ror eax,16     ; bank byte
 mov [CPU_LABEL(S)],ebx ; Set stack pointer
%endmacro

; Emulation mode - pull long (++SL*)
%macro E1_PULL_L_New 0
 mov ebx,[CPU_LABEL(S)] ; S only - bank always 0!
 inc bx         ; Preincrement S
 GET_BYTE
 inc bx         ; Preincrement S
 ror eax,8      ; low byte
 GET_BYTE
 inc bx         ; Preincrement S
 ror eax,8      ; high byte
 GET_BYTE
 ror eax,16     ; bank byte
 mov [CPU_LABEL(S)],bl  ; Set stack pointer
%endmacro

%macro PULL_L 0
%if S_8bit
 E1_PULL_L_New
%else
 E0_PULL_L
%endif
%endmacro


%macro Stack_Fixup 0
%if S_8bit
 mov byte B_SH,1
%endif
%endmacro


ALIGNC
EXPORT_C Reset_CPU
 pusha

 call Reset_DMA

 ; Reset timing registers
 xor eax,eax
 mov [Latched_H],eax
 mov [Latched_V],eax
 mov [OPHCT],al
 mov [OPVCT],al
 mov byte [RDNMI],VERSION_NUMBER_5A22
 mov [MEMSEL],al
 mov [HVBJOY],al
 mov [C_LABEL(NMITIMEN)],al
 mov [C_LABEL(HTIMEL)],eax
 mov [C_LABEL(VTIMEL)],eax
 mov [HTimer],eax
 mov [HTimer_Set],eax

 ; Reset other registers
 mov byte [C_LABEL(WRIO)],0xFF
 mov byte [C_LABEL(RDIO)],0xFF
 mov [WRMPYA],al
 mov [WRDIVL],al
 mov [WRDIVH],al
 mov [RDDIVL],al
 mov [RDDIVH],al
 mov [RDMPYL],al
 mov [RDMPYH],al

 mov [JOYC1],al
 mov byte [C_LABEL(Controller1_Pos)],16
 mov byte [C_LABEL(Controller23_Pos)],16
 mov byte [C_LABEL(Controller45_Pos)],16
 mov dword [C_LABEL(JOY1L)],(1<<31)
 mov dword [C_LABEL(JOY2L)],(1<<31)
 mov dword [C_LABEL(JOY3L)],(1<<31)
 mov dword [C_LABEL(JOY4L)],(1<<31)

 ; Reset hardware ports
 call Reset_Ports

 ; Reset SPC timing
 xor eax,eax
 mov [SPC_last_cycles],eax
 mov [SPC_CPU_cycles],eax
 mov [SPC_cycles_left],eax
 mov [SPC_CPU_cycles_mul],eax

 ; Clear interrupt inputs
 mov [IRQ_pin],al
 mov [NMI_pin],al

 ; Reset CPU

 mov [In_CPU],al
 mov [CPU_Execution_Mode],al ;CEM_Normal_Execution == 0
 mov dword [OpTable],OpTableE1  ; Set current opcode emulation table

 ; Clear cycle counts
 mov dword [C_LABEL(SNES_Cycles)],0x82  ;32.5 dots before reset (?)
 mov [C_LABEL(EventTrip)],eax

 LOAD_BASE
 LOAD_CYCLES edx

 mov dword [CPU_LABEL(S)],0x01FF
 mov [CPU_LABEL(A)],eax ; Clear A, D, X, Y
 mov [CPU_LABEL(D)],eax
 mov [CPU_LABEL(X)],eax
 mov [CPU_LABEL(Y)],eax

 call E1_RESET
 SAVE_CYCLES

 mov al,[CPU_LABEL(PB)]
 mov [C_LABEL(OLD_PB)],al

%ifdef DEBUG
 mov [C_LABEL(Frames)],eax
;mov [C_LABEL(Timer_Counter_FPS)],eax
%endif
 ; Initialize flags
;FLAGS_TO (SNES_FLAG_B1+SNES_FLAG_E+SNES_FLAG_I)
 STORE_FLAGS_E 1
 STORE_FLAGS_N 0
 STORE_FLAGS_V 0
 STORE_FLAGS_1 1
 STORE_FLAGS_B 1
 STORE_FLAGS_D 0
 STORE_FLAGS_I 1
 STORE_FLAGS_Z 1
 STORE_FLAGS_C 0

;%1 = vector; %2 = label prefix;
;%3 = register with relative address of ROM at 00:E000-FFFF
%macro cache_interrupt_vector 3
 movzx eax,word [%1+%3]     ; Get interrupt vector
 mov [C_LABEL(%2vector)],eax    ; Cache vector
%endmacro

 ; Get all interrupt vectors
 mov ebx,[C_LABEL(Read_Bank8Offset)+(0xE000 >> 13) * 4] ; Get address of ROM

 cache_interrupt_vector 0xFFFC,RES_E,ebx    ; Reset: Emulation mode
 cache_interrupt_vector 0xFFEA,NMI_N,ebx    ; NMI: Native mode
 cache_interrupt_vector 0xFFFA,NMI_E,ebx    ; NMI: Emulation mode
 cache_interrupt_vector 0xFFEE,IRQ_N,ebx    ; IRQ: Native mode
 cache_interrupt_vector 0xFFFE,IRQ_E,ebx    ; IRQ: Emulation mode
 cache_interrupt_vector 0xFFE6,BRK_N,ebx    ; BRK: Native mode
 cache_interrupt_vector 0xFFE4,COP_N,ebx    ; COP: Native mode
 cache_interrupt_vector 0xFFF4,COP_E,ebx    ; COP: Emulation mode

 mov eax,[C_LABEL(RES_Evector)] ; Get Reset vector
 mov [CPU_LABEL(PC)],eax    ; Setup PC
 mov [C_LABEL(OLD_PC)],eax

 call IRQNewFrameReset

 popa
 ret

ALIGNC
EXPORT do_DMA
 LOAD_CYCLES

 cmp byte [C_LABEL(MDMAEN)],0
 jz .dma_done

 cmp byte [DMA_Pending_B_Address],0
 jge .dma_started

 ;first bus cycle doesn't overlap
 add R_65c816_Cycles,_5A22_SLOW_CYCLE
.dma_started:

 DMAOPERATION 0,.early_out
 DMAOPERATION 1,.early_out
 DMAOPERATION 2,.early_out
 DMAOPERATION 3,.early_out
 DMAOPERATION 4,.early_out
 DMAOPERATION 5,.early_out
 DMAOPERATION 6,.early_out
 DMAOPERATION 7,.early_out

.dma_done:
 mov byte [CPU_Execution_Mode],CEM_Normal_Execution
 SAVE_CYCLES

 cmp byte [NMI_pin],NMI_Raised
 jne .no_nmi

 ;setup NMI to execute after one opcode

 mov edx,[FixedTrip]
 mov [NMI_Next_Trip],edx
 mov edx,[Fixed_Event]
 mov [NMI_Next_Event],edx

 mov edx,NMI_Event
 mov [Fixed_Event],edx
 mov [Event_Handler],edx
 mov eax,[C_LABEL(SNES_Cycles)]
 inc eax
 mov [FixedTrip],eax
 mov [C_LABEL(EventTrip)],eax

 jmp CPU_START

.no_nmi:
 mov byte [CPU_Execution_Mode],CEM_Instruction_After_IRQ_Enable
 jmp CPU_START

.early_out:
 SAVE_CYCLES
 jmp dword [Event_Handler]


ALIGNC
EXPORT_C Do_CPU
 pusha
 mov byte [C_LABEL(PaletteChanged)],1   ; Make sure we get our palette
 mov dword [C_LABEL(Last_Frame_Line)],239
%ifdef SINGLE_STEP
EXTERN_C set_gfx_mode
 push byte 0
 push byte 0
 push byte 0
 push byte 0
 push byte -1
 call _set_gfx_mode
 add esp,20
%endif

 call CPU_START
 popa
 ret

; Start of actual CPU execution core

; New for 0.25 - one CPU execution loop, also used for SPC
ALIGNC
EXPORT CPU_START_IRQ
 call IRQ_Check_Newline
CPU_START:
 LOAD_CYCLES
 test R_Cycles,R_Cycles
 jge .no_event_wait
.execute_opcode:
 mov al,[CPU_Execution_Mode]
 test al,al
 jz .normal_execution

 cmp al,CEM_In_DMA
 je do_DMA

 cmp al,CEM_Instruction_After_IRQ_Enable
 je .instruction_after_irq_enable
 xor R_Cycles,R_Cycles
;SAVE_CYCLES
 mov edx,[C_LABEL(EventTrip)]
 mov [C_LABEL(SNES_Cycles)],edx
.no_event_wait:
 jmp dword [Event_Handler]



ALIGNC
.instruction_after_irq_enable:
;set up an event for immediately the next instruction
 mov eax,IRQ_Enabled_Event
 xor edx,edx
 mov [Event_Handler],eax
 mov [C_LABEL(EventTrip)],edx
.normal_execution:
 LOAD_PC
 LOAD_CYCLES
 LOAD_BASE
 xor eax,eax        ; Zero for table offset
 mov byte [In_CPU],-1

 jmp C_LABEL(CPU_START_NEXT)

ALIGNC
EXPORT_C CPU_RETURN
%ifdef Abort_at_op_num
 dec dword [MaxOps]
 jz Op_0xDB     ;STP
%endif

 xor eax,eax        ; Zero for table offset
 test R_Cycles,R_Cycles

 jge HANDLE_EVENT

EXPORT_C CPU_START_NEXT
; This code is for a CPU-tracker dump... #define TRACKERS to make a dump
; of the CPU state before each instruction - uncomment the ret to
; force emulation core to break when buffer fills. TRACKERS must be
; defined to the size of the buffer to be used - which must be a power
; of two, and the variables required by this and the write in Wangle()
; (main.cc) exist only if DEBUG and TRACKERS are also defined in main.cc
; and romload.cc.
%ifdef TRACKERS
%if TRACKERS >= 16
 mov edx,[_LastIns]     ;
 add edx,[_InsAddress]  ;
 mov al,[CPU_LABEL(PB)] ;
 mov [edx],al           ;
 SAVE_CYCLES            ;
 SAVE_PC eax            ;
 mov [1+edx],ah         ;
 mov [2+edx],al         ;
 mov al,[CPU_LABEL(B)]  ;
 mov [3+edx],al         ;
 mov al,[CPU_LABEL(A)]  ;
 mov [4+edx],al         ;
 mov al,[CPU_LABEL(XH)] ;
 mov [5+edx],al         ;
 mov al,[CPU_LABEL(X)]  ;
 mov [6+edx],al         ;
 mov al,[CPU_LABEL(YH)] ;
 mov [7+edx],al         ;
 mov al,[CPU_LABEL(Y)]  ;
 mov [8+edx],al         ;
 mov al,[CPU_LABEL(SH)] ;
 mov [9+edx],al         ;
 mov al,[

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -