Commit: cd619dc84cc9a455b20503506c10857bb1a1efba Author: Vi Grey Date: 2019-07-27 14:46 UTC Summary: Initial Commit .gitignore | 1 + DOCUMENTATION.txt | 63 +++++ Makefile | 36 +++ README.md | 58 ++++ src/smb2-discord-payload.asm | 1198 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1356 insertions(+) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba077a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bin diff --git a/DOCUMENTATION.txt b/DOCUMENTATION.txt new file mode 100644 index 0000000..dd3750b --- /dev/null +++ b/DOCUMENTATION.txt @@ -0,0 +1,63 @@ +Super Mario Bros 2 Discord Payload +By ViGreyTech (2019-07-25) + +Controller 1 will be polled 12 times per frame for input. +The new input data will print on the screen every 2nd frame. +That means 24 bytes will potentially be printed every 2nd frame. +You do not need to worry about if you are sending data on an even or +odd frame. If you do not have data to send at that moment, then send +a 0x00 byte. The data you send will be in ASCII format. + + +7 bit 0 +---- ---- +|||| |||| +|||| |||+- Right +|||| ||+-- Left +|||| |+--- Down +|||| +---- Up +|||+------ Start +||+------- Select +|+-------- B ++--------- A + +Example ASCII byte: + Uppercase Letter A: 01000001 + | | + | +- Right + +------- B + +The ASCII bytes this payload will accept are from Controller 1 are: + - Uppercase Letters + - Lowercase Letters + - Numbers + - Comma (,) + - Period (.) + - Question Mark (?) + - Exclamation Mark (!) + - At Symbol (@) + - Dollar Sign ($) + - Asterisk (*) + - Minus Sign (-) + - Newline Character (0x0A) + +At Sign (@) will convert to a copyright sign +Exclamation Mark (!) will convert to a period +Asterisk (*) will convert to a small star +Lowercase letters will convert to uppercase letters +Anything other than these characters will be treated as a 0x00 byte + +!!!!!!!!!!!!!!!!!!! +! ! +! ############# ! +! # IMPORTANT # ! +! ############# ! +! ! +!!!!!!!!!!!!!!!!!!! + +At the end of someone's message, send a Newline character. If you send +a newline character, the remaining characters of the 24 character print +buffer WILL be discarded by the payload. To prevent issues with this +functionality, send 23 0x00 bytes after sending a newline character. +This way, you do not need to keep track of frames or where in the frame +button inputs are happening. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b999a10 --- /dev/null +++ b/Makefile @@ -0,0 +1,36 @@ +# Copyright (C) 2019, Vi Grey +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +PKG_NAME := smb2-discord-payload +CURRENTDIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST)))) + +all: + mkdir -p $(CURRENTDIR)bin; \ + cd $(CURRENTDIR)src; \ + asm $(PKG_NAME).asm ../bin/$(PKG_NAME).bin; \ + cd ..; \ + +clean: + rm -rf $(CURRENTDIR)bin diff --git a/README.md b/README.md new file mode 100644 index 0000000..8aefe6d --- /dev/null +++ b/README.md @@ -0,0 +1,58 @@ +# TASBot SMB2 ACE Discord Payload + +Payload for turning Super Mario Bros 2 into a Discord chat client after achieving Arbitrary Code Execution on SMB2. + +**_TASBot SMB2 ACE Discord Payload was created by Vi Grey Vi Grey (https://vigrey.com) and is licensed under the BSD 2-Clause License._** + +### Description: +This is a payload that allows TASBot to turn Super Mario Bros 2 into a Discord chat client. This payload only uses assets from Super Mario Bros 2. Assets are not included in this repository. + +### Platforms: +- GNU/Linux + +### Build Dependencies: +- asm6 _(You'll probably have to build asm6 from source. Make sure the asm6 binary is named **asm** and that the binary is executable and accessible in your PATH. The source code can be found at **http://3dscapture.com/NES/asm6.zip**)_ + +### Build NES ROM: +From a terminal, go to the the main directory of this project (the directory this README.md file exists in), you can then build the NES ROM with the following command. + + $ make + +The resulting NES ROM will be located at **bin/smb2-discord-payload.bin** + +### Cleaning Build Environment: +If you used `make` to build the payload binary, you can run the following command to clean up the build environment. + + $ make clean + +### Injecting the Payload +Once you have Arbitary Code Execution, inject this payload into CPU memory starting at $6170 and then run JMP $6200 **_(4C 00 62)_** to begin executing the payload. This payload will be sitting inside of SRAM, so it is technically running from the cartridge itself and not just from CPU RAM. + +### Controller Input Documentation +Included in this repository is a file called DOCUMENTATION.txt, which will explain what is expected from a controller input system like TASBot for printing messages on the screen. + +### License: + Copyright (C) 2019, Vi Grey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS \`\`AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. diff --git a/src/smb2-discord-payload.asm b/src/smb2-discord-payload.asm new file mode 100644 index 0000000..e263d41 --- /dev/null +++ b/src/smb2-discord-payload.asm @@ -0,0 +1,1198 @@ +; Copyright (C) 2019, Vi Grey +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; +; 1. Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +; ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +; SUCH DAMAGE. + + +.enum $00BF + addr dsb 2 +.ende +.enum $7F00 + drawbufferoffset dsb 1 + drawbuffer dsb 100 + cursorframes dsb 1 + nametable dsb 1 + nmi dsb 1 + mergedvalue dsb 1 + yscroll dsb 1 + addrtmp dsb 2 + tmp dsb 2 + textrow dsb 1 + textaddr dsb 2 + tmpy dsb 1 + emphasis dsb 1 + theme dsb 1 + singlecharacter dsb 1 + characterascii dsb 1 + characters dsb 24 + screen dsb 1 + frames dsb 1 + seconds dsb 1 +.ende + +CHARACTER_TABLE_LENGTH = 44 +BUTTON_A = 1 << 7 +BUTTON_B = 1 << 6 +BUTTON_SELECT = 1 << 5 +BUTTON_START = 1 << 4 +BUTTON_UP = 1 << 3 +BUTTON_DOWN = 1 << 2 +BUTTON_LEFT = 1 << 1 +BUTTON_RIGHT = 1 << 0 + +PPU_CTRL = $2000 +PPU_MASK = $2001 +PPU_STATUS = $2002 +PPU_OAM_ADDR = $2003 +PPU_OAM_DATA = $2004 +PPU_SCROLL = $2005 +PPU_ADDRESS = $2006 +PPU_DATA = $2007 +OAM_DMA = $4014 +CONTROLLER1 = $4016 +CONTROLLER2 = $4017 +MMC3_COMMAND = $8000 +MMC3_BANK = $8001 +MMC3_MIRROR = $A000 +MMC3_WRAM_ENABLE = $A001 +MMC3_WRAM_RW = $80 +CALLBACK = $FFFA +LIGHT = $00 +DARK = $01 +SCREEN_LOADING = $00 +SCREEN_CHAT = $01 +SECONDS = 6 +FPS = 60 + + .base $6170 + +CharacterTable: + .db " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.?@$*-" + +CharacterTableConverted: + .byte $79, $5a, $5b, $5c, $5d, $5e, $5f, $60, $61, $62, $63, $64, $65, $66, $67, $68, $69, $6a, $6b, $6c, $6d, $6e, $6f, $70, $71, $72, $73, $50, $51, $52, $53, $54, $55, $56, $57, $58, $59, $77, $76, $75, $78, $16, $B1, $74 + +StartingText: + .byte $6c, $6d, $5a, $6b, $6d, $62, $67, $60 + +LoadingLineText: + .byte $5e, $71, $69, $5e, $6b, $62, $5e, $67, $5c, $62, $67, $60, $79, $6d, $6b, $5a, $67, $6a, $6e, $62, $65, $62, $6d, $72 + +ViGreyTechText: + .byte $69, $6b, $68, $60, $6b, $5a, $66, $66, $5e, $5d, $79, $5b, $72, $79, $6f, $62, $60, $6b, $5e, $72, $6d, $5e, $5c, $61 + +InitializeRAM: + ldx #$00 +InitializeRAMLoop: + lda #$00 + sta $7F00, x + lda #$FE + sta $0200, x + inx + bne InitializeRAMLoop + lda #DARK + sta theme + jsr ClearPPURAM + jsr SetMirroring + jsr Blank + jsr SetCHR + jsr SetPalette + jsr DrawDiscordLoadingScreen + lda #$FF + sta drawbuffer + lda #FPS + sta frames + lda #SECONDS + sta seconds + lda #$00 + sta nametable + sta PPU_CTRL + jsr ResetScroll + +Forever: + lda PPU_STATUS + and #%10000000 + beq Forever + +NMI: + lda #$00 + sta PPU_OAM_ADDR + lda #$02 + sta OAM_DMA + lda PPU_STATUS + jsr DrawLastFrame + jsr Draw + lda nametable + sta PPU_CTRL + jsr ResetScroll + lda nmi + eor #$01 + sta nmi + jmp NMIDone + +NMIDone: + jsr Update + jmp Forever + +DrawLastFrame: + ldx #$00 + stx drawbufferoffset + ldy #$02 + lda drawbuffer, x + bne DrawLastFrameDone + dec drawbuffer, x +DrawLastFrameSetAddrLoop: + inx + lda drawbuffer, x + cmp #$FF + bne DrawLastFrameSetAddrLoopContinue + jsr ResetScroll + jmp DrawLastFrameDone +DrawLastFrameSetAddrLoopContinue: + sta PPU_ADDRESS + dey + bne DrawLastFrameSetAddrLoop +DrawLastFrameLoop: + ldy #$02 + inx + lda drawbuffer, x + bne DrawLastFrameNotNewAddress + jmp DrawLastFrameSetAddrLoop +DrawLastFrameNotNewAddress: + cmp #$FF + bne DrawLastFrameLoopContinue: + jsr ResetScroll + jmp DrawLastFrameDone +DrawLastFrameLoopContinue: + sta PPU_DATA + jmp DrawLastFrameLoop +DrawLastFrameDone: + rts + + +Update: + lda screen + bne UpdateScreenChat + dec frames + beq UpdateTitleScreenContinue + jmp UpdateDone + UpdateTitleScreenContinue: + lda #FPS + sta frames + dec seconds + beq UpdateTitleScreenSecondsDone + jmp UpdateDone + UpdateTitleScreenSecondsDone: + lda #SCREEN_CHAT + sta nmi + sta screen + jsr Blank + jsr ClearScreen + jsr DrawChatScreen + jsr ResetScroll + jmp UpdateDone +UpdateScreenChat: + inc cursorframes + lda cursorframes + asl + cmp #FPS + bne CursorFramesNot60 + lda #$00 + sta cursorframes + jsr SwapCursor +CursorFramesNot60: + lda nmi + bne UpdateCheckText + ldx #$00 +UpdateScreenChatControllerLoop: + jsr LatchController + jsr PollController + inx + cpx #12 + bne UpdateScreenChatControllerLoop + jsr ClearInputLine + ldy drawbufferoffset + lda #$FF + sta (drawbuffer), y + jmp UpdateDone + UpdateCheckText: + ldx #12 + UpdateCheckTextControllerLoop: + jsr LatchController + jsr PollController + inx + cpx #24 + bne UpdateCheckTextControllerLoop + jsr TranslateCharacters + jsr DrawInputText + jsr DrawLineBackground + ldy drawbufferoffset + lda #$FF + sta (drawbuffer), y +UpdateDone: + rts + +LatchController: + ldy #$01 + sty CONTROLLER1 + dey + sty CONTROLLER1 + rts + +PollController: + ldy #$08 +PollControllerLoop: + lda CONTROLLER1 + lsr A + rol characters, x + dey + bne PollControllerLoop + rts + +SetCHR: + lda #$82 + sta MMC3_COMMAND + lda #$39 + sta MMC3_BANK + lda #$83 + sta MMC3_COMMAND + lda #$2F + sta MMC3_BANK + lda #$84 + sta MMC3_COMMAND + lda #$10 + sta MMC3_BANK + rts + +SetMirroring: + lda #$01 + sta MMC3_MIRROR + rts + +ResetScroll: + lda #$00 + sta PPU_SCROLL + lda yscroll + sta PPU_SCROLL + rts + +Draw: + lda emphasis + beq DrawContinue + lda #%11100000 +DrawContinue: + ora #%00011110 + sta PPU_MASK + rts + +DisableNMI: + lda #$00 + sta PPU_CTRL + rts + +Blank: + lda emphasis + beq BlankContinue + lda #%11100000 +BlankContinue: + ora #%00000110 + sta PPU_MASK + jsr DisableNMI + rts + +ClearPPURAM: + lda #$20 + sta PPU_ADDRESS + lda #$00 + sta PPU_ADDRESS + ldy #$0f + ldx #$ff +ClearPPURAMLoop: + sta PPU_DATA + dex + bne ClearPPURAMLoop + ldx #$ff + dey + bne ClearPPURAMLoop + rts + +ClearScreen: + ldx #$00 + ldy #$10 + lda #$20 + sta PPU_ADDRESS + lda #$00 + sta PPU_ADDRESS + lda #$79 +ClearScreenLoop: + sta PPU_DATA + inx + bne ClearScreenLoop + ldx #$00 + dey + bne ClearScreenLoop + rts + +SetPalette: + lda #$3F + sta PPU_ADDRESS + lda #$00 + sta PPU_ADDRESS + ldx #$08 +SetPaletteLoop: + ldy theme + bne SetPaletteDarkTheme + lda #$30 + sta PPU_DATA + lda #$0F + sta PPU_DATA + lda #$22 + sta PPU_DATA + lda #$30 + sta PPU_DATA + lda #LIGHT + sta emphasis + jmp SetPaletteContinue +SetPaletteDarkTheme: + lda #$2D + sta PPU_DATA + lda #$30 + sta PPU_DATA + lda #$22 + sta PPU_DATA + lda #$2D + sta PPU_DATA + lda #DARK + sta emphasis +SetPaletteContinue: + dex + bne SetPaletteLoop + rts + +TranslateCharacters: + ldx #$00 +TranslateCharactersLoop: + ldy #$00 + lda characters, x + beq TranslateCharactersLoopDone + cmp #10 + bne TranslateCharacterNotNewLine + tay + jmp TranslateCharactersLoopDone +TranslateCharacterNotNewLine: + cmp #$20 + bne TranslateCharacterNotSpace + ldy #$79 + jmp TranslateCharactersLoopDone +TranslateCharacterNotSpace: + cmp #$24 + bne TranslateCharacterNotDollar + ldy #$16 + jmp TranslateCharactersLoopDone +TranslateCharacterNotDollar: + cmp #$2C + bne TranslateCharacterNotComma + ldy #$77 + jmp TranslateCharactersLoopDone +TranslateCharacterNotComma: + cmp #$2D + bne TranslateCharacterNotDash + ldy #$74 + jmp TranslateCharactersLoopDone +TranslateCharacterNotDash: + cmp #$2E + bne TranslateCharacterNotPeriod + ldy #$76 + jmp TranslateCharactersLoopDone +TranslateCharacterNotPeriod: + cmp #$21 + bne TranslateCharacterNotExclamationMark + ldy #$76 + jmp TranslateCharactersLoopDone +TranslateCharacterNotExclamationMark: + cmp #$3F + bne TranslateCharacterNotQuestionMark + ldy #$75 + jmp TranslateCharactersLoopDone +TranslateCharacterNotQuestionMark: + cmp #$40 + bne TranslateCharacterNotAt + ldy #$78 + jmp TranslateCharactersLoopDone +TranslateCharacterNotAt: + cmp #$30 + bcc TranslateCharacterNotNumber + cmp #$3A + bcs TranslateCharacterNotNumber + clc + adc #$20 + tay + jmp TranslateCharactersLoopDone +TranslateCharacterNotNumber: + cmp #$41 + bcc TranslateCharactersLoopDone + cmp #$5B + bcs TranslateCharacterNotCapitalLetter + clc + adc #$19 + tay + jmp TranslateCharactersLoopDone +TranslateCharacterNotCapitalLetter: + cmp #$61 + bcc TranslateCharactersLoopDone + cmp #$7B + bcs TranslateCharactersLoopDone + sec + sbc #$07 + tay +TranslateCharactersLoopDone: + tya + sta characters, x + inx + cpx #24 + beq TranslateCharactersFinished + jmp TranslateCharactersLoop +TranslateCharactersFinished: + rts + +DrawDiscordLogo: + ldx #$7B + ; Layer 1 of 11 + lda #$20 + sta PPU_ADDRESS + lda #$E8 + sta PPU_ADDRESS + lda #$7D + stx PPU_DATA + stx PPU_DATA + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + stx PPU_DATA + stx PPU_DATA + stx PPU_DATA + stx PPU_DATA + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + stx PPU_DATA + stx PPU_DATA + ; Layer 2 or 11 + lda #$21 + sta PPU_ADDRESS + lda #$08 + sta PPU_ADDRESS + lda #$7D + stx PPU_DATA + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + stx PPU_DATA + ; Layer 3 or 11 + lda #$21 + sta PPU_ADDRESS + lda #$28 + sta PPU_ADDRESS + lda #$7D + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + ; Layer 4 or 11 + lda #$21 + sta PPU_ADDRESS + lda #$48 + sta PPU_ADDRESS + lda #$7D + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + ; Layer 5 or 11 + lda #$21 + sta PPU_ADDRESS + lda #$68 + sta PPU_ADDRESS + lda #$7D + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + ; Layer 6 or 11 + lda #$21 + sta PPU_ADDRESS + lda #$88 + sta PPU_ADDRESS + lda #$7D + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + ; Layer 7 or 11 + lda #$21 + sta PPU_ADDRESS + lda #$A8 + sta PPU_ADDRESS + lda #$7D + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + stx PPU_DATA + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + stx PPU_DATA + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + ; Layer 8 or 11 + lda #$21 + sta PPU_ADDRESS + lda #$C8 + sta PPU_ADDRESS + lda #$7D + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + ; Layer 9 or 11 + lda #$21 + sta PPU_ADDRESS + lda #$E8 + sta PPU_ADDRESS + lda #$7D + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + ; Layer 10 or 11 + lda #$22 + sta PPU_ADDRESS + lda #$08 + sta PPU_ADDRESS + lda #$7D + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + ; Layer 11 or 11 + lda #$22 + sta PPU_ADDRESS + lda #$28 + sta PPU_ADDRESS + lda #$7D + stx PPU_DATA + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + stx PPU_DATA + stx PPU_DATA + stx PPU_DATA + stx PPU_DATA + stx PPU_DATA + sta PPU_DATA + sta PPU_DATA + sta PPU_DATA + stx PPU_DATA + stx PPU_DATA + rts + +DrawLoadingLine: + lda #<(LoadingLineText) + sta addr + lda #>(LoadingLineText) + sta (addr + 1) + lda #$22 + sta PPU_ADDRESS + lda #$84 + sta PPU_ADDRESS + ldy #$00 +DrawLoadingLineLoop: + lda (addr), Y + sta PPU_DATA + iny + cpy #$18 + bne DrawLoadingLineLoop + rts + +DrawStartingText: + lda #<(StartingText) + sta addr + lda #>(StartingText) + sta (addr + 1) + lda #$22 + sta PPU_ADDRESS + lda #$CC + sta PPU_ADDRESS + ldy #$00 +DrawStartingTextLoop: + lda (addr), Y + sta PPU_DATA + iny + cpy #$08 + bne DrawStartingTextLoop + rts + +DrawViGreyTechText: + lda #<(ViGreyTechText) + sta addr + lda #>(ViGreyTechText) + sta (addr + 1) + lda #$23 + sta PPU_ADDRESS + lda #$62 + sta PPU_ADDRESS + ldy #$00 +DrawViGreyTechTextLoop: + lda (addr), Y + sta PPU_DATA + iny + cpy #24 + bne DrawViGreyTechTextLoop + rts + +DrawDiscordLoadingScreen: + jsr ClearScreen + jsr DrawDiscordLogo + jsr DrawLoadingLine + jsr DrawStartingText + jsr DrawViGreyTechText + rts + +DrawChatScreen: + jsr DrawLineSprites + jsr DrawCursorSprite + jsr DrawLineBackgroundTiles + lda #$20 + sta textaddr + lda #$62 + sta (textaddr + 1) + rts + +ClearInputLine: + lda textrow + cmp #21 + bcc ClearInputLineDone + ldy drawbufferoffset + lda (textaddr + 1) + and #%11100000 + clc + adc #$E2 + sta (addrtmp + 1) + lda textaddr + adc #$00 + sta addrtmp +ClearInputLineCheckEndNT0: + cmp #$23 + bcc ClearInputLineStart + cmp #$25 + bcs ClearInputLineCheckEndNT2 + cmp #$23 + bne ClearInputLineModifyAddr + lda (addrtmp + 1) + cmp #$C0 + bcc ClearInputLineStart +ClearInputLineModifyAddr: + lda (addrtmp + 1) + sec + sbc #$C0 + sta (addrtmp + 1) + lda addrtmp + adc #$04 + sta addrtmp + jmp ClearInputLineStart +ClearInputLineCheckEndNT2: + cmp #$2B + bcc ClearInputLineStart + bne ClearInputLineModifyAddrNT2 + lda (addrtmp + 1) + cmp #$C0 + bcc ClearInputLineStart +ClearInputLineModifyAddrNT2: + lda (addrtmp + 1) + sec + sbc #$C0 + sta (addrtmp + 1) + lda addrtmp + sbc #$0B + sta addrtmp +ClearInputLineStart: + lda #$00 + sta (drawbuffer), y + iny + lda addrtmp + sta (drawbuffer), y + iny + lda (addrtmp + 1) + sta (drawbuffer), y + iny + ldx #28 + lda #$79 +ClearInputLineLoop: + sta (drawbuffer), y + iny + dex + bne ClearInputLineLoop + sty drawbufferoffset +ClearInputLineDone: + rts + +ClearLineBackground: + lda textrow + cmp #21 + bcc ClearLinesBackgroundDone + lda (textaddr + 1) + and #%11100000 + clc + adc #$2A + sta (addrtmp + 1) + lda textaddr + adc #$00 + sta addrtmp +ClearLineBackgroundCheckNT0: + cmp #$23 + bcc ClearLineBackgroundStart + cmp #$25 + bcs ClearLineBackgroundCheckNT2 + cmp #$23 + bne ClearLineBackgroundModifyAddr + lda (addrtmp + 1) + cmp #$C0 + bcc ClearLineBackgroundStart +ClearLineBackgroundModifyAddr: + lda (addrtmp + 1) + sec + sbc #$C0 + sta (addrtmp + 1) + lda addrtmp + adc #$04 + sta addrtmp + jmp ClearLineBackgroundStart +ClearLineBackgroundCheckNT2: + cmp #$2B + bcc ClearLineBackgroundStart + bne ClearLineBackgroundModifyAddrNT2 + lda (addrtmp + 1) + cmp #$C0 + bcc ClearLineBackgroundStart +ClearLineBackgroundModifyAddrNT2: + lda (addrtmp + 1) + sec + sbc #$C0 + sta (addrtmp + 1) + lda addrtmp + sbc #$0B + sta addrtmp +ClearLineBackgroundStart: + ldy drawbufferoffset + lda #$00 + sta (drawbuffer), y + iny + lda addrtmp + sta (drawbuffer), y + iny + lda (addrtmp + 1) + sta (drawbuffer), y + iny + ldx #20 + lda #$79 + nop + nop +ClearLineBackgroundLoop: + sta (drawbuffer), y + iny + dex + bne ClearLineBackgroundLoop + sty drawbufferoffset +ClearLinesBackgroundDone: + rts + +DrawLineBackground: + jsr ClearLineBackground + lda textrow + cmp #21 + bcc DrawLineBackgroundDone + lda (textaddr + 1) + and #%11100000 + clc + adc #$4A + sta (addrtmp + 1) + lda textaddr + adc #$00 + sta addrtmp +DrawLineBackgroundCheckNT0: + cmp #$23 + bcc DrawLineBackgroundStart + cmp #$25 + bcs DrawLineBackgroundCheckNT2 + cmp #$23 + bne DrawLineBackgroundModifyAddr + lda (addrtmp + 1) + cmp #$C0 + bcc DrawLineBackgroundStart +DrawLineBackgroundModifyAddr: + lda (addrtmp + 1) + sec + sbc #$C0 + sta (addrtmp + 1) + lda addrtmp + adc #$04 + sta addrtmp + jmp DrawLineBackgroundStart +DrawLineBackgroundCheckNT2: + cmp #$2B + bcc DrawLineBackgroundStart + bne DrawLineBackgroundModifyAddrNT2 + lda (addrtmp + 1) + cmp #$C0 + bcc DrawLineBackgroundStart +DrawLineBackgroundModifyAddrNT2: + lda (addrtmp + 1) + sec + sbc #$C0 + sta (addrtmp + 1) + lda addrtmp + sbc #$0B + sta addrtmp +DrawLineBackgroundStart: + ldy drawbufferoffset + lda #$00 + sta (drawbuffer), y + iny + lda addrtmp + sta (drawbuffer), y + iny + lda (addrtmp + 1) + sta (drawbuffer), y + iny + ldx #20 + lda #$0D +DrawLineBackgroundLoop: + sta (drawbuffer), y + iny + dex + bne DrawLineBackgroundLoop + sty drawbufferoffset +DrawLineBackgroundDone: + rts + +DrawInputText: + ldy drawbufferoffset + lda #$00 + sta (drawbuffer), y + iny + lda textaddr + sta (drawbuffer), y + iny + lda (textaddr + 1) + sta (drawbuffer), y + iny + sty drawbufferoffset + ldx #$00 +DrawInputTextLoop: + lda characters, x + bne DrawInputTextLoopCharacterNot0 + jmp DrawInputTextLoopEnd +DrawInputTextLoopCharacterNot0: + cmp #10 + bne DrawInputTextNotNewLine + jmp DrawInputTextNewLine +DrawInputTextNotNewLine: + ldy drawbufferoffset + sta (drawbuffer), y + iny + sty drawbufferoffset + + inc (textaddr + 1) + lda (textaddr + 1) + and #%00011111 + cmp #%00011110 + bcs DrawInputTextNewLine + jmp DrawInputTextLoopEnd +DrawInputTextNewLine: + lda (textaddr + 1) + and #%11100000 + clc + adc #$22 + sta (textaddr + 1) + lda textaddr + adc #$00 + sta textaddr + inc textrow + lda textrow + cmp #22 + bne DrawInputTextNewLineNotScrollNT0 + dec textrow + lda yscroll + clc + adc #$08 + sta yscroll + cmp #240 + bne DrawInputTextNewLineNotScrollNT0 + lda #$00 + sta yscroll + lda nametable + eor #$02 + sta nametable + sta PPU_CTRL +DrawInputTextNewLineNotScrollNT0: + lda textaddr + cmp #$23 + bne DrawInputTextNewLineNotScrollNT1 + lda (textaddr + 1) + cmp #$C2 + bne DrawInputTextNewLineDone + lda #$28 + sta textaddr + lda #$02 + sta (textaddr + 1) + jmp DrawInputTextNewLineDone +DrawInputTextNewLineNotScrollNT1: + lda textaddr + cmp #$2B + bne DrawInputTextNewLineDone + lda (textaddr + 1) + cmp #$C2 + bne DrawInputTextNewLineDone + lda #$20 + sta textaddr + lda #$02 + sta (textaddr + 1) +DrawInputTextNewLineDone: + lda characters, x + cmp #10 + bne DrawInputTextNotNewLineCharacter + ldx #24 + jmp DrawInputTextEnd +DrawInputTextNotNewLineCharacter: + ldy drawbufferoffset + lda #$00 + sta (drawbuffer), y + iny + lda textaddr + sta (drawbuffer), y + iny + lda (textaddr + 1) + sta (drawbuffer), y + iny + sty drawbufferoffset +DrawInputTextLoopEnd: + inx + cpx #24 + beq DrawInputTextEnd + jmp DrawInputTextLoop +DrawInputTextEnd: + lda #$00 + dex +ClearCharacters: + sta characters, x + dex + bpl ClearCharacters + rts + +DrawLineBackgroundTiles: + lda #$23 + sta PPU_ADDRESS + lda #$4A + sta PPU_ADDRESS + lda #$0D + ldx #20 +DrawLineBackgroundTilesLoop: + sta PPU_DATA + dex + bne DrawLineBackgroundTilesLoop + rts + +DrawLineSprites: + lda #207 + sta $0204 + sta $0208 + sta $020C + sta $0210 + sta $0214 + sta $0218 + sta $021C + sta $0220 + lda #$0D + sta $0205 + sta $0209 + sta $020D + sta $0211 + sta $0215 + sta $0219 + sta $021D + sta $0221 + lda #$00 + sta $0206 + sta $020A + sta $020E + sta $0212 + sta $0216 + sta $021A + sta $021E + sta $0222 + lda #$10 + sta $0207 + lda #$18 + sta $020B + lda #$20 + sta $020F + lda #$28 + sta $0213 + lda #$30 + sta $0217 + lda #$38 + sta $021B + lda #$40 + sta $021F + lda #$48 + sta $0223 + rts + +DrawCursorSprite: + lda #223 + sta $0224 + lda #$0D + sta $0225 + lda #$00 + sta $0226 + lda #$10 + sta $0227 + rts + +SwapCursor: + lda $0225 + cmp #$0D + bne SwapCursorNotShowing + lda #$79 + sta $0225 + jmp SwapCursorDone +SwapCursorNotShowing: + lda #$0D + sta $0225 +SwapCursorDone: + rts