📄 timing.inc
字号:
popa
%else
RELATCH_HDMA
%endif
Update_FPS_Counter
pusha
call C_LABEL(update_sound_block)
popa
xor eax,eax
jmp CPU_START_IRQ ; Return to CPU
ALIGNC
EXPORT_C IRQFirstRender ; Check HDMA, IRQ, Render
section .data
.str:db " irqfirstrender ",0
section .text
report_event
mov dword [Last_Trip],0
;mov dword [C_LABEL(EventTrip)],CYCLES_DISPLAY_START
mov dword [FixedTrip],CYCLES_DISPLAY_START
;mov dword [Event_Handler],Render_Event
mov dword [Fixed_Event],Render_Event
mov dword [Render_Next_Event],HDMA_Event
mov dword [Render_Next_Trip],CYCLES_HDMA_START
mov dword [HDMA_Next_Event],C_LABEL(IRQRender)
Render_Start_Frame ; Reset framebuffer render address
Update_Cycles
mov eax,[C_LABEL(Current_Line_Timing)] ; Get current scanline
inc eax
mov [C_LABEL(Current_Line_Timing)],eax
jmp CPU_START_IRQ ; Return to CPU
ALIGNC
EXPORT_C IRQRender ; Check HDMA, IRQ, Render
section .data
.str:db " irqrender ",0
section .text
report_event
mov dword [Last_Trip],0
Update_Cycles
;mov dword [C_LABEL(EventTrip)],CYCLES_DISPLAY_START
mov dword [FixedTrip],CYCLES_DISPLAY_START
;mov dword [Event_Handler],Render_Event
mov dword [Fixed_Event],Render_Event
mov eax,[C_LABEL(Current_Line_Timing)] ; Get current scanline
inc eax
mov [C_LABEL(Current_Line_Timing)],eax
cmp [C_LABEL(LastRenderLine)],eax
jbe .end_of_display
jmp CPU_START_IRQ ; Return to CPU
ALIGNC
.end_of_display:
mov eax,[NMI_Event_Handler]
mov [Render_Next_Event],eax
mov dword [Render_Next_Trip],CYCLES_NEW_SCANLINE
jmp CPU_START_IRQ ; Return to CPU
ALIGNC
VBL_Update_Controllers:
section .data
.str:db " update controllers ",0
section .text
report_event
mov dword [Last_Trip],0
Update_Cycles
mov eax,[C_LABEL(Current_Line_Timing)]
inc eax
mov [C_LABEL(Current_Line_Timing)],eax
sub eax,[Vblank_Start]
cmp eax,byte 3
jb .no_controller_update
EXTERN_C update_controllers
call C_LABEL(update_controllers)
mov dword [Event_Handler],VBL
mov dword [Fixed_Event],VBL
and byte [HVBJOY],~HVBJOY_CONTROLLERS_BUSY ; Controllers ready
.no_controller_update:
mov eax,[C_LABEL(Current_Line_Timing)] ; Get current scanline
jmp CPU_START_IRQ ; Return to CPU
ALIGNC
VBL:
section .data
.str:db " vblank ",0
section .text
report_event
mov dword [Last_Trip],0
Update_Cycles
mov eax,[C_LABEL(Current_Line_Timing)] ; Get current scanline
inc eax
mov [C_LABEL(Current_Line_Timing)],eax
cmp [C_LABEL(LastVBLLine)],eax ; Needs adjustment for odd line?
ja .not_end_of_frame
mov dword [Event_Handler],IRQNewFrame
mov dword [Fixed_Event],IRQNewFrame
.not_end_of_frame:
jmp CPU_START_IRQ ; Return to CPU
ALIGNC
EXPORT_C IRQFirst ; Check HDMA, IRQ, Render
section .data
.str:db " irqfirst ",0
section .text
report_event
mov dword [Last_Trip],0
;mov dword [C_LABEL(EventTrip)],CYCLES_HDMA_START
mov dword [FixedTrip],CYCLES_HDMA_START
;mov dword [Event_Handler],HDMA_Event
mov dword [Fixed_Event],HDMA_Event
mov dword [HDMA_Next_Event],IRQNoRender
Render_Start_Frame_Skipped
Update_Cycles
mov eax,[C_LABEL(Current_Line_Timing)] ; Get current scanline
inc eax
mov [C_LABEL(Current_Line_Timing)],eax
jmp CPU_START_IRQ ; Return to CPU
ALIGNC
IRQNoRender: ; Check HDMA, IRQ
section .data
.str:db " irqnorender ",0
section .text
report_event
mov dword [Last_Trip],0
Update_Cycles
mov eax,[C_LABEL(Current_Line_Timing)] ; Get current scanline
inc eax
mov [C_LABEL(Current_Line_Timing)],eax
cmp [C_LABEL(LastRenderLine)],eax
jbe .end_of_display
;mov dword [C_LABEL(EventTrip)],CYCLES_HDMA_START
mov dword [FixedTrip],CYCLES_HDMA_START
;mov dword [Event_Handler],HDMA_Event
mov dword [Fixed_Event],HDMA_Event
jmp CPU_START_IRQ ; Return to CPU
ALIGNC
.end_of_display:
mov eax,[NMI_Event_Handler]
mov [Event_Handler],eax
mov [Fixed_Event],eax
jmp CPU_START_IRQ ; Return to CPU
ALIGNC
EXPORT_C NMI
UpdateDisplay ;*
mov ax,[C_LABEL(Real_SNES_Palette)]
push eax
mov al,[C_LABEL(fixedpalettecheck)]
test al,al
jz .Do_Copy
.Fixed_Back_Color_Add_Hack:
mov eax,[C_LABEL(COLDATA)]
%if 1
push ebx
mov bx,[C_LABEL(Real_SNES_Palette)]
push ecx
push edx
mov ecx,((1<<5)+(1<<10)+(1<<15))
mov edx,ebx
; get LSBs
and edx,ecx
and ebx,~((1<<5)+(1<<10)+(1<<15))
and ecx,eax
and eax,~((1<<5)+(1<<10)+(1<<15))
; add LSBs
add ecx,edx
mov edx,((2<<5)+(2<<10)+(2<<15))
; add colors
add eax,ebx
and edx,ecx
mov ebx,((1<<5)+(1<<10)+(1<<15))
add eax,edx
and ecx,ebx
and ebx,eax
add eax,ecx
; Perform saturation
; save carry bits
mov edx,ebx
; correct for carry/overflow into LSBs of adjacent color components
sub eax,ebx
shr edx,5 ; shift carry bits down to color LSBs
neg edx ; subtract from zero to get mask...
add edx,ebx ; add in carry bits to correct for borrows
or eax,edx ; apply saturation mask
.Add_Hack_End:
pop edx
pop ecx
pop ebx
%endif
mov [C_LABEL(Real_SNES_Palette)],ax
mov byte [C_LABEL(PaletteChanged)],1
.Do_Copy:
cmp byte [C_LABEL(FPS_ENABLED)],0
jz .no_fps_counter
%ifndef SNEeSe_No_GUI
call C_LABEL(ShowFPS)
%endif
.no_fps_counter:
cmp byte [C_LABEL(BREAKS_ENABLED)],0
jz .no_breaks_counter
%ifndef SNEeSe_No_GUI
call C_LABEL(ShowBreaks)
%endif
.no_breaks_counter:
mov dword [C_LABEL(BreaksLast)],0
%ifndef SINGLE_STEP
call C_LABEL(Copy_Screen)
mov eax,[C_LABEL(Current_Line_Render)]
mov [C_LABEL(Last_Frame_Line)],eax
%endif
;call C_LABEL(Display_Debug)
pop eax
mov [C_LABEL(Real_SNES_Palette)],ax
EXPORT_C NMI_NoRender
section .data
.str:db " nmi_norender ",0
section .text
report_event
mov dword [Last_Trip],0
mov dword [Event_Handler],VBL_Update_Controllers
mov dword [Fixed_Event],VBL_Update_Controllers
Update_Cycles
mov al,[HVBJOY]
; VBlank on, controllers being read
or al,HVBJOY_IN_VBLANK | HVBJOY_CONTROLLERS_BUSY
mov [HVBJOY],al
mov al,RDNMI_VBLANK_START | VERSION_NUMBER_5A22
and al,[RDNMI_mask] ; ensure only one vblank NMI per frame
mov [RDNMI],al ; Set NMI enabled bit in 0x4210
mov eax,[C_LABEL(Current_Line_Timing)]
inc eax
mov [C_LABEL(Current_Line_Timing)],eax
mov [Vblank_Start],eax
CheckNMI:
%ifdef DEBUG
mov al,[CPU_LABEL(PB)]
mov [C_LABEL(OLD_PB)],al ; Save program bank
mov eax,[CPU_LABEL(PC)]
mov [C_LABEL(OLD_PC)],eax ; Save program counter
%endif
cmp byte [NMI_pin],NMI_Raised ;NMI input raised previously?
je .setup_nmi
cmp byte [NMI_pin],NMI_Acknowledged
jz .CHECK_KEYS
test byte [RDNMI],RDNMI_VBLANK_START
jz .CHECK_KEYS
test byte [C_LABEL(NMITIMEN)],0x80
jz .CHECK_KEYS ; NMI off? (via hardware register)
cmp byte [CPU_Execution_Mode],CEM_In_DMA
je .CHECK_KEYS
mov byte [NMI_pin],NMI_Raised ;raise NMI input
.setup_nmi:
;setup chain to next timing event
mov eax,[Fixed_Event]
mov edx,[FixedTrip]
mov [NMI_Next_Event],eax
mov [NMI_Next_Trip],edx
;NMI executes after one opcode
mov eax,[C_LABEL(SNES_Cycles)]
inc eax
mov [FixedTrip],eax
mov [C_LABEL(EventTrip)],eax
mov eax,NMI_Event
mov [Fixed_Event],eax
mov [Event_Handler],eax
.CHECK_KEYS:
call C_LABEL(UPDATE_KEYS)
test eax,eax
jnz .break
; Return to emulation
mov eax,[C_LABEL(Current_Line_Timing)] ; Get current scanline
jmp CPU_START_IRQ ; Return to CPU
.break:
mov ebx,[CPU_LABEL(PB_Shifted)]
mov bx,[CPU_LABEL(PC)]
LOAD_CYCLES
GET_BYTE
mov [C_LABEL(Map_Byte)],al
mov eax,[C_LABEL(Current_Line_Timing)] ; Get current scanline
call IRQ_Check_Newline
.no_irq_check:
ret
ALIGNC
NMI_Setup_Event:
section .data
.str:db " nmi setup ",0
section .text
report_event
;NMI executes after one opcode
mov eax,[C_LABEL(SNES_Cycles)]
inc eax
mov [FixedTrip],eax
mov [C_LABEL(EventTrip)],eax
mov eax,NMI_Event
mov [Fixed_Event],eax
mov [Event_Handler],eax
jmp CPU_START.execute_opcode
ALIGNC
NMI_Event:
section .data
.str:db " nmi ",0
section .text
report_event
mov eax,[NMI_Next_Event]
mov [Fixed_Event],eax
mov eax,[NMI_Next_Trip]
mov [FixedTrip],eax
mov al,[CPU_Execution_Mode]
cmp al,CEM_In_DMA
je .no_nmi
cmp al,CEM_Clock_Stopped
je .no_nmi
cmp al,CEM_Waiting_For_Interrupt
jne .no_wai
%ifdef WAI_DELAY
; WAI delay after interrupt signal: 2 IO
add dword [C_LABEL(SNES_Cycles)],byte 12 ;*
%endif
inc word [CPU_LABEL(PC)]
mov byte [CPU_Execution_Mode],CEM_Normal_Execution
.no_wai:
mov byte [NMI_pin],NMI_Acknowledged ;acknowledge NMI input
push edi
LOAD_BASE
LOAD_CYCLES
add R_65c816_Cycles,byte 12 ; NMI processing: 2 IO
JUMP_NOT_FLAG SNES_FLAG_E,.E0_NMI ; Are we in emulation mode?
.E1_NMI:
; Emulation mode NMI
mov eax,[CPU_LABEL(PC)]
E1_PUSH_W
;CLR_FLAG SNES_FLAG_B ; Clear break bit on stack
E1_SETUPFLAGS 0 ; put flags into SNES packed flag format
;SET_FLAG SNES_FLAG_B
E1_PUSH_B
mov ebx,0xFFFA ; Get Emulation mode IRQ vector
jmp .NMI_completion
ALIGNC
.E0_NMI:
; Native mode NMI
mov al,[CPU_LABEL(PB)]
E0_PUSH_B
mov eax,[CPU_LABEL(PC)]
E0_PUSH_W
E0_SETUPFLAGS ; put flags into SNES packed flag format
E0_PUSH_B
mov ebx,0xFFEA ; Get Native mode IRQ vector
.NMI_completion:
xor eax,eax
GET_WORD
mov [CPU_LABEL(PC)],eax ; Setup PC vector
mov byte [CPU_LABEL(PB)],0 ; Setup bank
;SET_FLAG SNES_FLAG_I ; Disable IRQs
STORE_FLAGS_I 1
;CLR_FLAG SNES_FLAG_D ; Disable decimal mode
STORE_FLAGS_D 0
SAVE_CYCLES
pop edi
.no_nmi:
call IRQ_Check_Late ; chain
LOAD_CYCLES
test R_Cycles,R_Cycles
jl .no_chain
jmp dword [Event_Handler]
.no_chain:
jmp CPU_START ; Return to CPU
ALIGNC
IRQ_Event:
section .data
.str:db " irq ",0
section .text
report_event
mov eax,[C_LABEL(EventTrip)]
mov [Last_Trip],eax
mov dh,0x80 ; Internal IRQ
or [IRQ_pin],dh
mov al,[CPU_Execution_Mode]
cmp al,CEM_In_DMA
je .no_irq
cmp al,CEM_Clock_Stopped
je .no_irq
cmp al,CEM_Instruction_After_IRQ_Enable
je .no_irq
cmp al,CEM_Waiting_For_Interrupt
jne .no_wai
%ifdef WAI_DELAY
; WAI delay after interrupt signal: 2 IO
add dword [C_LABEL(SNES_Cycles)],byte 12 ;*
%endif
inc word [CPU_LABEL(PC)]
mov byte [CPU_Execution_Mode],CEM_Normal_Execution
.no_wai:
push edi
LOAD_BASE
JUMP_FLAG SNES_FLAG_I,.irq_disabled ; Interrupts disabled?
LOAD_CYCLES
add R_65c816_Cycles,byte 12 ; IRQ processing: 2 IO
JUMP_NOT_FLAG SNES_FLAG_E,.native_irq
call E1_IRQ
jmp .irq_return
ALIGNC
.native_irq:
call E0_IRQ
.irq_return:
SAVE_CYCLES
.irq_disabled:
pop edi
.no_irq:
mov edi,[FixedTrip]
mov ebx,[Fixed_Event]
mov [C_LABEL(EventTrip)],edi
mov [Event_Handler],ebx
jmp CPU_START ; Return to CPU
ALIGNC
IRQ_Check_Newline:
mov bl,[C_LABEL(NMITIMEN)]
mov edx,[FixedTrip]
cmp byte [NMI_pin],NMI_Raised
je .nmi_bypass
test bl,0x30 ; IRQ enabled?
jz .no_irq
test bl,0x20 ; V-IRQ enabled?
jz .no_virq
mov ebx,[C_LABEL(Current_Line_Timing)]
cmp [C_LABEL(VTIMEL)],ebx
jne .no_irq
.no_virq:
mov ebx,[HTimer]
cmp edx,ebx
jb .no_irq ; Next static event is before IRQ?
mov [C_LABEL(EventTrip)],ebx
mov dword [Event_Handler],IRQ_Event
ret
.nmi_bypass:
.no_irq:
mov ebx,[Fixed_Event]
mov [C_LABEL(EventTrip)],edx
mov [Event_Handler],ebx
ret
ALIGNC
; This can only trash ebx/edx!
IRQ_Check:
SAVE_CYCLES edx
cmp byte [NMI_pin],NMI_Raised
je .nmi_bypass
mov [Last_Trip],edx
push edx
mov bl,[C_LABEL(NMITIMEN)]
mov edx,[FixedTrip]
test bl,0x30 ; IRQ enabled?
jz .no_irq
test bl,0x20 ; V-IRQ enabled?
jz .no_virq
mov ebx,[C_LABEL(Current_Line_Timing)]
cmp [C_LABEL(VTIMEL)],ebx
jne .no_irq
.no_virq:
mov ebx,[HTimer]
cmp edx,ebx
jb .no_irq ; Next static event is before IRQ?
cmp [esp],ebx ; Check against current cycle
jae .no_irq ; Are we after the IRQ position?
mov [C_LABEL(EventTrip)],ebx
mov dword [Event_Handler],IRQ_Event
jmp .fixup_timing
.nmi_bypass:
mov edx,[FixedTrip]
.no_irq:
mov ebx,[Fixed_Event]
mov [C_LABEL(EventTrip)],edx
mov [Event_Handler],ebx
.fixup_timing:
LOAD_CYCLES edx
pop edx
ret
ALIGNC
; This can only trash ebx/edi!
IRQ_Check_Late:
mov bl,[C_LABEL(NMITIMEN)]
mov edi,[FixedTrip]
cmp byte [NMI_pin],NMI_Raised
je .nmi_bypass
test bl,0x30 ; IRQ enabled?
jz .no_irq
test bl,0x20 ; V-IRQ enabled?
jz .no_virq
mov ebx,[C_LABEL(Current_Line_Timing)]
cmp [C_LABEL(VTIMEL)],ebx
jne .no_irq
.no_virq:
mov ebx,[HTimer]
cmp edi,ebx
jb .no_irq ; Next static event is before IRQ?
cmp [Last_Trip],ebx ; Check against last event trip cycle
jae .no_irq ; Are we after the IRQ?
mov [C_LABEL(EventTrip)],ebx
mov dword [Event_Handler],IRQ_Event
ret
.nmi_bypass:
.no_irq:
mov ebx,[Fixed_Event]
mov [C_LABEL(EventTrip)],edi
mov [Event_Handler],ebx
ret
ALIGNC
EXPORT SNES_R2137 ; SLHV ; This latches the counter for horizontal/vertical data!
;counters cannot be latched if I/O port bit 7 held low
mov al,[C_LABEL(WRIO)]
and al,[C_LABEL(RDIO)]
jns .no_change
push ebx
GET_CYCLES ebx
xor edx,edx
; Set up H counters to cycles executed / 4, V counter to current scanline
; All this below ensures bits 9-15 to be same as bits 1-7
; (open bus kludge)
shr ebx,2
mov al,0xFE
cmp ebx,DOTS_BEFORE_REFRESH
jb .before_refresh
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -