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

📄 cpuexec.s

📁 SFC游戏模拟器 snes9x 1.43 的原代码
💻 S
字号:
/*******************************************************************************  Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.   (c) Copyright 1996 - 2003 Gary Henderson (gary.henderson@ntlworld.com) and                            Jerremy Koot (jkoot@snes9x.com)  (c) Copyright 2002 - 2003 Matthew Kendora and                            Brad Jorsch (anomie@users.sourceforge.net)                         C4 x86 assembler and some C emulation code  (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com),                            _Demo_ (_demo_@zsnes.com), and                            Nach (n-a-c-h@users.sourceforge.net)                                            C4 C++ code  (c) Copyright 2003 Brad Jorsch  DSP-1 emulator code  (c) Copyright 1998 - 2003 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson,                            John Weidman (jweidman@slip.net),                            neviksti (neviksti@hotmail.com), and                            Kris Bleakley (stinkfish@bigpond.com)   DSP-2 emulator code  (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and                     Lord Nightmare (lord_nightmare@users.sourceforge.net  OBC1 emulator code  (c) Copyright 2001 - 2003 zsKnight, pagefault (pagefault@zsnes.com)  Ported from x86 assembler to C by sanmaiwashi  SPC7110 and RTC C++ emulator code  (c) Copyright 2002 Matthew Kendora with research by                     zsKnight, John Weidman, and Dark Force  S-RTC C emulator code  (c) Copyright 2001 John Weidman    Super FX x86 assembler emulator code   (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault   Super FX C emulator code   (c) Copyright 1997 - 1999 Ivar and Gary Henderson.  S-DD1 decompression code  (c) Copyright 2003 Jose Luis Bravo   Specific ports contains the works of other authors. See headers in  individual files.   Snes9x homepage: http://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        jnz .DEC_IRQ_CYCLE_COUNT_DONE	testb $IRQ, FLAGS        jz .DEC_IRQ_CYCLE_COUNT_DONE        movb $1, IRQCycleCount.DEC_IRQ_CYCLE_COUNT_DONE:.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		movb (PC), %al	addl MemSpeed, CYCLES	movl CPUOpcodes, %ecx	incl PC	jmp *(%ecx,%eax,4)MainAsmLoop:	SAVE_CYCLES	ccall S9xUpdateAPUTimer	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:#ifdef DETECT_NASTY_FX_INTERLEAVE	movb BRKTriggered, %al	andb SuperFXEnabled, %al	jz .NoSuperFXBrkTest	andb TriedInterleavedMode2, %al	jnz .NoSuperFXBrkTest	movb $1, TriedInterleavedMode2	movb $0, BRKTriggered	call S9xDeinterleaveMode2.NoSuperFXBrkTest:#endif	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	imull $10000, %eax, %ecx	subl %ecx, NextAPUTimerPos	cmpb $0, APUExecuting	je .apunotrunning	subl %eax, APUCycles//	addl %eax, smpcyc	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	jb .L161	jmp .endofframe.ntsc_tv:	cmpl $262,%ecx	jb .L161.endofframe:	xorl %edx, %edx	movl Flags,%ecx	movb %dl,NMIActive	orl $16,%ecx	movl %edx,V_Counter	movb %dl,HVBeamCounterLatched	movl %ecx,Flags	movb %dl,RangeTimeOver	movl FillRAM, %ecx	xorb $0x80,0x213F(%ecx)	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	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 $0xff, ForcedBlanking	jnz .noOAMreset	movw SavedOAMAddr,%ax	movw %ax,OAMAddr	movb %ch,FirstSprite	testb $0xff, OAMPriorityRotation	jz .noOAMreset	shrw %ax	andb $0x7F,%al        testb $0x01,OAMFlip        jne .yesOAMReset        cmpb %al,FirstSprite        je .noOAMreset.yesOAMReset:	movb %al,FirstSprite        movb $0xff,OBJChanged.noOAMreset:	movb %ch,OAMFlip	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#if 0	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#endif	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 + -