CheckZSNES: SEP #$28 LDA.b #$FF CLC ADC.b #$FF CMP.b #$64 REP #$28 BEQ .zsnes LDA.w #$01FF : TCS ; thing we wrote over - initialize stack JML ReturnCheckZSNES .zsnes JML DontUseZSNES ;=================================================================================================== pushtable table "data/bsodencode.txt" ; Uncomment this to force a crash to test message ; pushpc : org $008132 : db 0 : pullpc ;=================================================================================================== DontUseZSNES: SEP #$35 ; sets carry and I flag too LDA.b #$00 STA.l NMITIMEN ; disable NMI and IRQ STA.l HDMAENABLE ; disable HDMA ROR ; A = 0x80 from carry STA.l INIDISP STA.l VMAIN ; Empty VRAM LDA.b #AllZeros>>16 : STA.l A1B0 REP #$20 LDA.w #AllZeros STA.l A1T0L LDA.w #$1809 STA.l DMAP0 LDA.w #$0000 STA.l DAS0L LDA.w #$0001 STA.l DMAENABLE JSR ConfigurePPUForFailureReport JSR ConfigureBSODVWF STZ.b VWFR LDA.w #ZSNESMessage JSR DrawVWFMessage LDA.w #$0F0F STA.w INIDISP -- BRA -- ZSNESMessage: db "It has been detected that you are attempting to load", $80 db "this ROM on a low-quality emulator.", $80 db "The randomizer is designed to work on real hardware,", $80 db "which this application cannot emulate properly;", $80 db "as such, this ROM file refuses to boot.", $80 db "Please upgrade to a more accurate emulator such as", $80 db "SNES9X or BSNES/higan.", $80 db $FF ;=================================================================================================== AllZeros: db $00 UselessStackTooFar: dw $137 Crashed: ;=================================================================================================== ;=================================================================================================== ;=================================================================================================== ; !!!DO NOT TRY TO OPTIMIZE THIS CODE!!! ; IT IS INTENTIONALLY AVOIDING CHANGING CERTAIN REGISTERS, ESPECIALLY THE STACK. ;=================================================================================================== ;=================================================================================================== ;=================================================================================================== SEP #$35 ; sets carry and I flag too LDA.b #$00 STA.l NMITIMEN ; disable NMI and IRQ STA.l HDMAENABLE ; disable HDMA ROR ; A = 0x80 from carry STA.l INIDISP STA.l VMAIN ; Empty VRAM LDA.b #AllZeros>>16 : STA.l A1B0 REP #$38 LDA.w #AllZeros STA.l A1T0L LDA.w #$1809 STA.l DMAP0 LDA.w #$0000 STA.l DAS0L LDA.w #$0001 STA.l DMAENABLE ;=================================================================================================== ; Create report LDA.w #$2100 TCD ;--------------------------------------------------------------------------------------------------- ; Report status ; stack pointer LDA.w #$0C38>>1 STA.b VMADDL TSC XBA AND.w #$00FF ORA.w #$0100 STA.b VMDATAL TSC AND.w #$00FF ORA.w #$0100 STA.l VMDATAL ; game module LDA.w #$0C78>>1 STA.b VMADDL LDA.l GameMode AND.w #$00FF ORA.w #$0100 STA.b VMDATAL LDA.l GameSubMode AND.w #$00FF ORA.w #$0100 STA.b VMDATAL ;--------------------------------------------------------------------------------------------------- ; Report stack TSC INC STA.l $7F0100 LDA.l UselessStackTooFar ; For now, we can report as much of the stack as possible ; If desired later on, uncomment the code below to keep the stack limited to ; where it was last doing stuff ; TSC ; ; ; keep stack in a useful range ; CMP.w #$01FF ; this means we pulled too much and the stack is useless ; BCC .stack_fine ; ; JMP .skip_stack ; ;.stack_fine ; CMP.l UselessStackTooFar ; BCS .stack_adjusted ; ; ; this means we went too far in, and the stack contains little useful info ; LDA.l UselessStackTooFar ; ;.stack_adjusted STA.l $7F0000 LDX.w #$01FF LDA.w #$0C04>>1 .next_row STA.l $7F0004 STA.b VMADDL LDY.w #20 TXA .next_char ; set carry to see if we should color this value as being in the stack CMP.l $7F0100 LDA.l $000000,X AND.w #$00FF ORA.w #$0500 BCS .in_stack AND.w #$01FF .in_stack STA.b VMDATAL DEX TXA CMP.l $7F0000 BEQ .skip_stack DEY BNE .next_char .done_row CLC LDA.l $7F0004 ADC.w #32 BRA .next_row ;=================================================================================================== ;=================================================================================================== ;=================================================================================================== ; once the stack is reported, we can start doing stuff that mucks with it .skip_stack LDA.w #$0000 TCD ; TSC ; STA.b $80 ; remember stack for later messages LDA.w #$01FF TCS JSR ConfigurePPUForFailureReport JSR ConfigureBSODVWF JSR LoadBSODHexFont STZ.b VWFR LDA.w #BSODMessage JSR DrawVWFMessage LDA.w #$0F0F STA.w INIDISP -- BRA -- BSODMessage: db "A fatal error has occurred and resulted in an", $80 db "unrecoverable crash. ?", $80 db "If you believe this was the result of a bug caused by", $80 db "the randomizer itself, please screenshot this message", $80 db "and share it in the #bug-reports channel of the official", $80 db "ALTTPR discord along with a detailed description of", $80 db "what you were doing, including video if available.", $80 db "Please also make a savestate now and include that in", $80 db "your report.", $80 db $FF ;=================================================================================================== DrawVWFMessage: STA.b Scrap06 .next LDA.b (Scrap06) INC.b Scrap06 AND.w #$00FF CMP.w #$0080 BEQ .done_row CMP.w #$00FF BEQ .done_message JSR DrawFailureVWFChar BRA .next .done_message RTS .done_row LDA.b VWFR ASL TAX LDA.w .row_offset,X STA.w VMADDL INC.b VWFR LDA.w #$1800 STA.w DMAP0 LDA.w #20*16 STA.w DAS0L LDA.w #$1000 STA.w A1T0L SEP #$20 STZ.w VMAIN STZ.w A1B0 LDA.b #$01 STA.w DMAENABLE REP #$20 JSR ResetVFW BRA .next .row_offset dw $10F8 dw $11E8 dw $12D8 dw $13C8 dw $14B8 dw $15A8 dw $1698 dw $1788 dw $1878 dw $1968 dw $1A58 ;=================================================================================================== VWFL = $40 VWFX = $44 VWFS = $46 VWFP = $48 VWFR = $4A ;=================================================================================================== DrawFailureVWFChar: AND.w #$00FF STA.b VWFL TAX ASL ASL ASL ADC.w #BSODFontGFX STA.b Scrap08 LDA.b VWFP AND.w #$FFF8 STA.w VWFX LDA.b VWFP AND.w #$0007 STA.w VWFS ; carry set on purpose to add letter spacing SEC LDA.w BSODCharWidths,X AND.w #$00FF ADC.b VWFP STA.b VWFP LDY.w #$0000 .next_row LDA.b (Scrap08),Y AND.w #$00FF XBA LDX.w VWFS BEQ ++ -- LSR DEX BNE -- ++ LDX.w VWFX SEP #$20 ORA.w $1008,X STA.w $1008,X XBA ORA.w $1000,X STA.w $1000,X REP #$20 INX STX.w VWFX INY CPY.w #$0008 BCC .next_row RTS ;=================================================================================================== LoadBSODHexFont: REP #$20 LDA.w #BSODHex STA.w A1T0L LDA.w #$1801 STA.w DMAP0 LDA.w #$1000 STA.w DAS0L LDA.w #$2800 STA.w VMADDL SEP #$20 LDA.b #BSODHex>>16 STA.w A1B0 LDA.b #$01 STA.w DMAENABLE REP #$30 RTS ;=================================================================================================== ConfigureBSODVWF: REP #$30 LDA.w #$2100 TCD SEP #$30 LDX.b #$FF LDY.b #$7F STZ.b CGADD STZ.b CGDATA : STZ.b CGDATA STX.b CGDATA : STY.b CGDATA LDA.b #$05 STA.b CGADD LDA.b #$11 : STA.b CGDATA : STY.b CGDATA LDA.b #$21 : STA.b CGADD STX.b CGDATA : STY.b CGDATA LDA.b #$25 : STA.b CGADD LDA.b #$11 : STA.b CGDATA : STY.b CGDATA REP #$30 PEA.w $0001 LDA.w #15 STA.w LinkRecoilX LDA.w #$0042>>1 BRA .start .next_row PHA LDA.w LinkPosY CLC LDA.w LinkPosY ADC.w #32 .start STA.w LinkPosY STA.b VMADDL PLA LDY.w #30 .next_char STA.b VMDATAL INC DEY BNE .next_char DEC.w LinkRecoilX BNE .next_row LDA.w #$0000 TCD ResetVFW: REP #$30 LDX.w #$0400 -- STZ.w $1000,X DEX DEX BPL -- STZ.b VWFL STZ.b VWFX STZ.b VWFS STZ.b VWFP RTS ;=================================================================================================== ConfigurePPUForFailureReport: SEP #$30 PHK PLB STZ.w BGMODE ; BG mode 0 STZ.w MOSAIC ; no mosaic STZ.w BG1SC ; BG1 tilemap to $0000 STZ.w TS STZ.w BG1HOFS : STZ.w BG1HOFS STZ.w BG1VOFS : STZ.w BG1VOFS STZ.w BG2HOFS : STZ.w BG2HOFS STZ.w BG2VOFS : STZ.w BG2VOFS STZ.w W12SEL STZ.w CGADSUB STZ.w SETINI LDA.b #$04 STA.w BG2SC ; BG1 tilemap to $0800 LDA.b #$21 STA.w BG12NBA LDA.b #$03 STA.w TM RTS ;=================================================================================================== BSODHex: incbin "data/bsodhex.2bpp" BSODFontGFX: incbin "data/bsodfont.1bpp" BSODCharWidths: ; [space] db 3 ; A B C D E F G H I J K L M N O P Q R S T U V W X Y Z db 4, 4, 3, 4, 3, 3, 4, 3, 1, 4, 3, 3, 5, 4, 4, 4, 5, 4, 4, 3, 4, 5, 5, 3, 3, 3 ; 0 1 2 3 4 5 6 7 8 9 . # ? - / , ' db 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 5, 8, 3, 3, 2, 1 ;=================================================================================================== pulltable