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

📄 cpuexec.s

📁 著名SFC模拟器Snes9x的源代码。
💻 S
字号:
/* * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. * * (c) Copyright 1996 - 2001 Gary Henderson (gary@daniver.demon.co.uk) and *                           Jerremy Koot (jkoot@snes9x.com) * * Super FX C emulator code  * (c) Copyright 1997 - 1999 Ivar (Ivar@snes9x.com) and *                           Gary Henderson. * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. * * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. * C4 C code (c) Copyright 2001 Gary Henderson (gary@daniver.demon.co.uk). * * DOS port code contains the works of other authors. See headers in * individual files. * * Snes9x homepage: www.snes9x.com * * Permission to use, copy, modify and distribute Snes9x in both binary and * source form, for non-commercial purposes, is hereby granted without fee, * providing that this license information and copyright notice appear with * all copies and any derived work. * * This software is provided 'as-is', without any express or implied * warranty. In no event shall the authors be held liable for any damages * arising from the use of this software. * * Snes9x is freeware for PERSONAL USE only. Commercial users should * seek permission of the copyright holders first. Commercial use includes * charging money for Snes9x or software derived from Snes9x. * * The copyright holders request that bug fixes and improvements to the code * should be forwarded to them so everyone can benefit from the modifications * in future versions. * * Super NES and Super Nintendo Entertainment System are trademarks of * Nintendo Co., Limited and its subsidiary companies. */#include "asmstruc.h"#include "asmops.h"#include "spcops.h".globl MainAsmLoop.text	.align 4.globl S9xMainLoopS9xMainLoop:	pushl %ebp	pushl %edi	pushl %esi	pushl %ebx	LOAD_REGISTERS.L9:	cmpb $0,APUExecuting	je .L12.apuloop:	cmpl CYCLES, APUCycles	jg .L12#ifdef DEBUGGER	testb $2,APUFlags	je .L14	STORE_REGISTERS	ccall S9xTraceAPU	LOAD_REGISTERS.L14:#endif	xorl %eax,%eax#ifdef SPC700_C	movl APUPC, %edx	SAVE_CYCLES	movb (%edx),%al#else	movb (APUPC),%al#endif	movl S9xAPUCycles(,%eax,4), %edx	movl S9xApuOpcodes(,%eax,4),%eax	addl %edx, APUCycles	call *%eax#ifdef SPC700_C	LOAD_CYCLES#endif	jmp .apuloop.L12:	cmpl $0, Flags	je .L15	movl Flags, %eax	testb %al, %al	jge .NO_NMI	decl NMICycleCount	jnz .NO_NMI	andb $~NMI_FLAG, %al	movl %eax, Flags	cmpb $0, WaitingForInterrupt	je .L17	movb $0, WaitingForInterrupt	incl PC.L17:	call S9xOpcode_NMI.NO_NMI:#ifdef DEBUGGER	testb $BREAK_FLAG, Flags	jz .NO_BREAK_POINTS	pushl %esi	pushl %ebx	movl $S9xBreakpoint, %esi	movb PB, %bl	xorl %edx, %edx	movl PC, %ecx	subl PCBase, %ecx.BREAK_CHECK_LOOP:	movzwl %dx, %eax	sall $2, %eax	cmpb $0, S9xBreakpoint(%eax)	je .BREAK_MATCH_FAILED	cmpb %bl, 1(%esi, %eax)	jne .BREAK_MATCH_FAILED	movzwl 2(%esi, %eax), %eax	cmpl %ecx, %eax	jne .BREAK_MATCH_FAILED	orb $DEBUG_MODE_FLAG, Flags.BREAK_MATCH_FAILED:	incw %dx	cmpw $6, %dx	jne .BREAK_CHECK_LOOP	popl %ebx	popl %esi.NO_BREAK_POINTS:#endif	testl $IRQ_PENDING_FLAG, Flags	jz .NO_PENDING_IRQ	cmpl $0, IRQCycleCount	jne .DEC_IRQ_CYCLE_COUNT	testb $0xff, WaitingForInterrupt	jz .NOT_WAITING	movb $0, WaitingForInterrupt	incl PC.NOT_WAITING:	testb $0xff, IRQActive	jz .CLEAR_PENDING_IRQ_FLAG	testb $0xff, DisableIRQ	jnz .CLEAR_PENDING_IRQ_FLAG	testb $IRQ, FLAGS	jnz .NO_PENDING_IRQ	call S9xOpcode_IRQ	jmp .NO_PENDING_IRQ.CLEAR_PENDING_IRQ_FLAG:	andl $~IRQ_PENDING_FLAG, Flags	jmp .NO_PENDING_IRQ.DEC_IRQ_CYCLE_COUNT:	decl IRQCycleCount.NO_PENDING_IRQ:#ifdef DEBUGGER	movl Flags, %eax	testb $DEBUG_MODE_FLAG,%al	jnz .L31#else	movl Flags, %eax#endif	testb $SCAN_KEYS_FLAG, %al	jnz .L31.L28:#ifdef DEBUGGER	testb $TRACE_FLAG, %al	jz .NO_TRACE	STORE_REGISTERS	ccall S9xTrace	LOAD_REGISTERS.NO_TRACE:	movl Flags, %eax	testb $SINGLE_STEP_FLAG, %al	jz .L15	andb $~SINGLE_STEP_FLAG, %al	orb $DEBUG_MODE_FLAG, %al	movl %eax, Flags#endif.L15:	xorl %eax,%eax#ifdef CPU_SHUTDOWN	movl PC, PCAtOpcodeStart#endif	#ifdef VAR_CYCLES	movb (PC), %al	addl MemSpeed, CYCLES#else	xorl %ecx, %ecx	movl CPUSpeed, %edx	movb (PC), %al	movb (%edx,%eax), %cl	addl %ecx, CYCLES#endif	movl CPUOpcodes, %ecx	incl PC	jmp *(%ecx,%eax,4)MainAsmLoop:	cmpb $0, SA1Executing	je .nosa1	STORE_REGISTERS	call S9xSA1MainLoop	LOAD_REGISTERS.nosa1:	cmpl NextEvent, CYCLES	jl .L9	STORE_REGISTERS	call S9xDoHBlankProcessing	LOAD_REGISTERS	jmp .L9.L31:	S9xPackStatus S9xMainLoop	STORE_REGISTERS	subl PCBase, PC	movw %di, PCR#ifdef SPC700_C	movl APUPC, %edx	movl APURAM, %eax	subl %eax, %edx	movw %dx, APUPCR#else	subl APURAM, APUPC	movw %bp, APUPCR#endif	APUS9xPackStatus S9xMainLoop	movl Flags, %eax	testb $SCAN_KEYS_FLAG, %al	jz .NoScanKeys	andb $~SCAN_KEYS_FLAG, %al	movl %eax, Flags#ifdef DEBUGGER	testl $FRAME_ADVANCE_FLAG, %eax	jnz .NoScanKeys#endif	ccall S9xSyncSpeed.NoScanKeys:	movb BRKTriggered, %al	andb SuperFXEnabled, %al	jz .NoSuperFXBrkTest	andb TriedInterleavedMode2, %al	jnz .NoSuperFXBrkTest	movb $1, TriedInterleavedMode2	movb $0, BRKTriggered	call S9xDeinterleaveMode2.NoSuperFXBrkTest:	popl %ebx	popl %esi	popl %edi	popl %ebp	ret.globl S9xDoHBlankProcessingS9xDoHBlankProcessing:	pushl %edi	pushl %esi	pushl %ebx#ifdef CPU_SHUTDOWN	incl WaitCounter#endif	movb WhichEvent,%bl	cmpb $1,%bl	je .hblank_end	jg .L196	testb %bl,%bl	jz .hblank_start	jmp .reschedule.L196:	cmpb $3,%bl	jle .htimer_trigger	jmp .reschedule.hblank_start:	movb HDMA,%dl	testb %dl,%dl	je .reschedule	movl V_Counter, %eax	cmpw ScreenHeight, %ax	ja .reschedule 	xorl %eax,%eax	movb %dl,%al	pushl %eax	ccall S9xDoHDMA	movb %al,HDMA	addl $4,%esp	jmp .reschedule.hblank_end:	ccall S9xSuperFXExec	testb $0xff, SoundSync	jz .nosoundsync	ccall S9xGenerateSound.nosoundsync:	movl H_Max,%eax	subl %eax, Cycles	cmpb $0, APUExecuting	je .apunotrunning	subl %eax, APUCycles	jmp .apucycleskip.apunotrunning:	movl $0, APUCycles.apucycleskip:		movl V_Counter,%ecx	incl %ecx	incl Scanline	movl $-1,NextEvent	movl %ecx,V_Counter	testb $0xff, PAL	jz .ntsc_tv	cmpl $312,%ecx	jbe .L161	jmp .endofframe.ntsc_tv:	cmpl $262,%ecx	jbe .L161.endofframe:	movw SavedOAMAddr,%ax	xorl %edx,%edx	movl Flags,%ecx	movw %ax,OAMAddr	movb %dl,OAMFlip	movb %dl,NMIActive	orl $16,%ecx	movl %edx,V_Counter	movb %dl,HVBeamCounterLatched	movl %ecx,Flags	ccall S9xStartHDMA.L161:	movb VTimerEnabled,%al	testb %al,%al	je .L162	movb HTimerEnabled,%dl	testb %dl,%dl	jne .L162	xorl %eax,%eax	movw IRQVBeamPos,%ax	movl V_Counter,%ecx	cmpl %eax,%ecx	jne .L162		pushl $2	call S9xSetIRQ	addl $4, %esp.L162:	xorl %eax,%eax	movl V_Counter,%edx	movw ScreenHeight,%ax	incl %eax	cmpl %eax,%edx	jne .L165	ccall S9xEndScreenRefresh	movb Brightness,%al	xorl %ecx,%ecx	movb %al,MaxBrightness	movb %cl,FirstSprite	movl FillRAM,%eax	movb %cl,HDMA	movb 0x2100(%eax),%cl	movb 0x4200(%eax),%dl	shrb $7,%cl	movb %cl,ForcedBlanking	movb $0x80, 0x4210(%eax)	testb %dl,%dl	jge .L165	orl $NMI_FLAG, Flags	movb $1, NMIActive	movl NMITriggerPoint, %eax	movl %eax, NMICycleCount.L165:	xorl %eax, %eax	movw ScreenHeight,%ax	addl $3,%eax	cmpl V_Counter,%eax	jne .NoJoypadUpdate	ccall S9xUpdateJoypads.NoJoypadUpdate:	movl V_Counter,%eax	cmpl $1,%eax	jne .L177	movl FillRAM,%eax	andl $~NMI_FLAG,Flags	movb $0,0x4210(%eax)	ccall S9xStartScreenRefresh.L177:	movl V_Counter,%edx	testl %edx,%edx	je .L178	xorl %eax,%eax	movw ScreenHeight,%ax	incl %eax	cmpl %eax,%edx	jae .L178	movb V_Counter,%al	decb %al	andl $255,%eax	pushl %eax	ccall RenderLine	addl $4,%esp.L178:#if 0	movl APUTimerErrorCounter,%eax	incl %eax	movl %eax,APUTimerErrorCounter	andl $31,%eax	jz .reschedule#endif	movb APUTimerEnabled + 2,%cl	testb %cl,%cl	je .L179	movw APUTimer + 4,%ax	addl $4,%eax	movw %ax,APUTimer + 4	cmpw %ax,APUTimerTarget + 4	ja .L179.L182:	movl APURAM,%edx	movb 255(%edx),%al	incb %al	andb $15,%al	movb %al,255(%edx)	movw APUTimerTarget + 4,%dx	movw APUTimer + 4,%ax	movl APUWaitCounter,%ecx	subl %edx,%eax	incl %ecx	movb $1,APUExecuting	movw %ax,APUTimer + 4	movl %ecx,APUWaitCounter	cmpw %dx,%ax	jae .L182.L179:	testb $1,V_Counter	je .reschedule	movb APUTimerEnabled,%al	testb %al,%al	je .L185	incw APUTimer	movw APUTimerTarget,%ax	cmpw %ax,APUTimer	jb .L185	movl APURAM,%edx	movb 253(%edx),%al	incb %al	andb $15,%al	movb %al,253(%edx)	movl APUWaitCounter,%edx	incl %edx	movw $0,APUTimer	movb $1,APUExecuting	movl %edx,APUWaitCounter.L185:	movb APUTimerEnabled + 1,%al	testb %al,%al	je .reschedule	incw APUTimer + 2	movw APUTimerTarget + 2,%ax	cmpw %ax,APUTimer + 2	jb .reschedule	movl APURAM,%edx	movb 254(%edx),%al	incb %al	andb $15,%al	movb %al,254(%edx)	movl APUWaitCounter,%edx	incl %edx	movw $0,APUTimer + 2	movb $1,APUExecuting	movl %edx,APUWaitCounter	jmp .reschedule.htimer_trigger:	cmpb $0, HTimerEnabled	je .reschedule	cmpb $0, VTimerEnabled	je .L191	xorl %eax,%eax	movw IRQVBeamPos,%ax	movl V_Counter,%edx	cmpl %eax,%edx	jne .reschedule.L191:	// CHANGED: 20/11/00	pushl $1	call S9xSetIRQ	addl $4, %esp.reschedule:	cmpb $0, WhichEvent	je .next_is_hblank_end	cmpb $3, WhichEvent	jne .next_is_hblank_start.next_is_hblank_end:	movb $1,%bl	movl H_Max,%edx	jmp .skip.next_is_hblank_start:	xorl %ebx,%ebx	movl HBlankStart,%edx.skip:	cmpb $0, HTimerEnabled	je .not_enabled	movswl HTimerPosition,%esi	cmpl %edx,%esi	jge .not_enabled	movl NextEvent,%eax	cmpl %eax,%esi	jle .not_enabled	cmpb $0, VTimerEnabled	je .enabled	xorl %eax,%eax	movw IRQVBeamPos,%ax	movl V_Counter,%ecx	cmpl %eax,%ecx	jne .not_enabled.enabled:	movb $2,%bl	cmpl %esi, HBlankStart	jg .before	movb $3,%bl.before:	movl %esi,%edx.not_enabled:	movb %bl,WhichEvent	popl %ebx	popl %esi	movl %edx,NextEvent	popl %edi	ret.text	.align 4.globl S9xSetIRQS9xSetIRQ:	movl 4(%esp), %eax	orb %al,IRQActive	// CHANGED: 20/11/00	movl $3, IRQCycleCount	orl $IRQ_PENDING_FLAG, Flags	cmpb $0, WaitingForInterrupt	je .NoIncPC	movb $0, WaitingForInterrupt	// IRQ must trigger immediately after a WAI instruction - 	// Final Fantasy Mystic Quest requires this.	movl $0, IRQCycleCount	incl PCS.NoIncPC:	ret.globl S9xClearIRQS9xClearIRQ:	movl 4(%esp), %eax	xorl $~0, %eax	andb IRQActive, %al	movb %al, IRQActive	jnz .irqsstillpending	andl $~IRQ_PENDING_FLAG, Flags	.irqsstillpending:	ret

⌨️ 快捷键说明

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