The loop that writes the tile/pattern data for the graphic is in 6502 but most of the rest is in the VM bytecode using the standard sysops for nametable printing + palette change.
First I used the bootstrap to write the data below & a pointer to the image data destination to $50 and then overwrote the jump address to go to the bottom function.
$6000 = destination of tile table
$6340 = destination of pattern table
Function $667E -> Uses PAD1 to print the above data. $667E-667F are overwritten with the last 2 bytes, then $6680 is overwritten with 0x60 to exit.
My issue w/ continually polling PAD1 to print data was that when the interrupt happened in the middle of the input getting polled, the results got screwed up. My workaround involves having input on PAD2 the entire time this loop runs. This loop never polls PAD2 input, so if $6F ever becomes nonzero this is a "flag" that the interrupt happened and that the value in $6E can't be trusted, in which case the game takes the input again.
667E LDY #$00
6680 TYA
6681 JSR $F9B9 ; Poll PAD1 input (updates in $6E)
6684 LDA $6F ; Check PAD2 input (should be zero)
6686 BEQ $668E
6688 STY $6F ; If PAD2 was updated, reset to zero and retake PAD1 input
668A BNE $6680 ; (Functional JMP)
668C LDA $6E
668E STA ($50),Y
6690 INC $50 ; Increment pointer
6692 BNE $66A0
6694 INC $51
6696 BNE $6680 ; (Functional JMP)
Palette Set @ 6698
I don't think the BG color I choose here matters since I have to run another function to actually get it to change.
30 10 00 0F 30 10 0F 00 30 00 10 0F 30 00 0F 10
Function $66A8 -> Sets palette BG to white
I don't 100% understand this but w/ trial & error I got it to work this way.
66A8 LDA PPU_STATUS
66AB LDA #$3F
66AD STA PPU_ADDR
66B0 LDA #$00
66B2 STA PPU_ADDR
66B5 LDA #$30
66B7 STA PPU_DATA
66BA JMP $F3AC
(66BD-66C6) [obsoleted code I didn't remove yet]
Function $66C7 (Written in VM bytecode)
66C7 AC 0B FA / Call $FA0B (Clear sprites)
66CA AC 7E 66 / Call $667E (Print image data)
66CD AC A8 66 / Call $66A8 (Set nametable BG to white)
66D0 8E 98 66 / Push #$6698
66D3 8D 10 / Push #$10
66D5 60 / Push #$00
66D6 E9 81 D6 06 / Call $D681 (Update nametable palettes)
66DA 8E 40 63 / Push #$6340 (pattern table)
66DD 8E 00 60 / Push #$6000 (tile table)
66E0 8D 1A / Push #$1A (height of 27 tiles)
66E2 8D 20 / Push #$20 (width of 32 tiles)
66E4 62 / Push #$02 (y-pos 2)
66E5 60 / Push #$00 (x-pos 0)
66E6 68
66E7 E9 E6 EE 10 / Call $EEE6 -> Sysop 0x08 (Print graphic to nametable)
66EB D6 EB 88 / Jump $66EB (Loop)