%ifndef SNEeSe_SPC_i %define SNEeSe_SPC_i %define VAR_CYCLE_RATIO %define SPC2MHz %include "regs.ni" %include "cycles.ni" %ifndef SNEeSe_SPC700_asm %define _SPC_CTRL 0xF1 extern _SPCRAM extern _TotalCycles extern _SPC_T0_cycle_latch,_SPC_T0_target,_SPC_T0_position extern _SPC_T0_cycle_latch,_SPC_T0_counter extern _SPC_T1_cycle_latch,_SPC_T1_target,_SPC_T1_position extern _SPC_T1_cycle_latch,_SPC_T1_counter extern _SPC_T2_cycle_latch,_SPC_T2_target,_SPC_T2_position extern _SPC_T2_cycle_latch,_SPC_T2_counter %endif ;%1 = timer %macro Update_SPC_Timer 1 test byte [_SPCRAM+_SPC_CTRL],1 << %1 je %%done mov edx,[_SPC_T%1_cycle_latch] mov ecx,[_TotalCycles] sub ecx,edx mov eax,ecx %ifdef SPC2MHz %if %1 != 2 mov cl,0 shr eax,8 %else and ecx,byte ~31 shr eax,5 %endif %else %if %1 != 2 and ecx,byte ~127 shr eax,7 %else and ecx,byte ~15 shr eax,4 %endif %endif add edx,ecx add ax,[_SPC_T%1_position] mov [_SPC_T%1_cycle_latch],edx mov cx,[_SPC_T%1_target] mov [_SPC_T%1_position],ax cmp ax,cx jb %%done xor edx,edx div cx mov cl,[_SPC_T%1_counter] mov [_SPC_T%1_position],dx add al,cl and al,15 mov [_SPC_T%1_counter],al %%done: %endmacro ;%1 = SaveCycles %macro Execute_SPC 0-1 0 pusha %ifidni %1,SaveCycles cmp byte [In_CPU],0 jz %%not_in_cpu ;GET_CYCLES eax mov eax,[_EventTrip] add dword eax,R_65c816_Cycles jmp short %%got_cycles %%not_in_cpu: mov eax,[_SNES_Cycles] %%got_cycles: cmp eax,CYCLES_REFRESH_START jb %%before_refresh add eax,byte CYCLES_IN_REFRESH %%before_refresh: ; Update CPU and SPC cycles mov edi,[SPC_last_cycles] mov [SPC_last_cycles],eax sub eax,edi add eax,[SPC_CPU_cycles] %endif %if 0 SPC runs at 2048000 clock. NTSC 65c816 timing. Masterclock: 21.477272..MHz. (189e7 / 88 Hz) Dotclock: 5.36931818..MHz. Optimal conversion factors: 118125:11264 Line rate: 15.6997607655502~KHz. Frame rate: 59.92275~Hz. PAL 65c816 timing. Masterclock: 21.28137MHz. Dotclock: 5.3203425MHz. Optimal conversion factors: 2128137:204800 Line rate: 15.55655701~KHz. Frame rate: 49.86075967~Hz. %endif %ifdef SPC_CYCLES_DIV_BEFORE_MUL xor edx,edx div dword [_SPC_CPU_cycle_divisor] mov [SPC_CPU_cycles],edx ; Save remainder mul dword [_SPC_CPU_cycle_multiplicand] %else mul dword [_SPC_CPU_cycle_multiplicand] add eax,[SPC_CPU_cycles_mul] ;mov ecx,[_SPC_CPU_cycle_divisor] adc edx,byte 0 div dword [_SPC_CPU_cycle_divisor] xor edi,edi mov [SPC_CPU_cycles_mul],edx ; Save remainder mov [SPC_CPU_cycles],edi %endif add eax,[_SPC_Cycles] ; Add new balance of SPC cycles mov [_SPC_Cycles],eax cmp [_TotalCycles],eax jb %%need_execute ; Check for and handle 35-minute wrap test eax,eax js %%no_cycles cmp dword [_TotalCycles],byte 0 jns %%no_cycles call _Wrap_SPC_Cyclecounter %%need_execute: call _SPC_START %%no_cycles: popa %endmacro %endif ; SNEeSe_SPC_i