|
| 1 | +.include "libSFX.i" |
| 2 | + |
| 3 | + |
| 4 | +;Very hacky, really not proud of this code. Written in ~30 minutes |
| 5 | + |
| 6 | +;Offsets of several registers and strings present in the SPC header. |
| 7 | +;See http://vspcplay.raphnet.net/spc_file_format.txt for format specifications |
| 8 | + |
| 9 | +SPCHEADER = $81FF25 ;CPU Registers |
| 10 | +SPCTITLE = $81FF2E |
| 11 | +SPCGAME = $81FF4E |
| 12 | +SPCDUMPER = $81FF6E |
| 13 | +SPCARTIST = $81FFB1 |
| 14 | +SPCLENGTH = $81FFA9 |
| 15 | + |
| 16 | + |
| 17 | +Main: |
| 18 | + |
| 19 | +;VRAM destination addresses |
| 20 | +VRAM_MAP_LOC = $0000 |
| 21 | +VRAM_TILES_LOC = $8000 |
| 22 | + |
| 23 | +;Just uploading the tileset, palette and tilemap (logo.bin) to VRAM |
| 24 | +VRAM_memcpy VRAM_TILES_LOC, Tiles, sizeof_Tiles |
| 25 | +VRAM_memcpy VRAM_MAP_LOC, logomap, sizeof_logomap |
| 26 | +CGRAM_memcpy $0, Palette, sizeof_Palette |
| 27 | + |
| 28 | + |
| 29 | +;This copies the first 32kb, second 32kb, DSP Registers and CPU Registers from the ROM to WRAM. |
| 30 | +;Normally this could be handled by the SPC_Play macro included in libSFX, |
| 31 | +;But that routine expects DSP and CPU registers to be right after eachother which is not the case for SPC files |
| 32 | +;Since i wanted to make it so you can drop in the SPC file unmodified without reassembling, i had to do some manual work. |
| 33 | +;This very closely mimics the libSFX macro though. |
| 34 | +WRAM_memcpy SFX_SPC_IMAGE, LOWB, $8000 ;Low 32k |
| 35 | +WRAM_memcpy SFX_SPC_IMAGE + $8000, HIGHB, $8000 ;High 32k |
| 36 | +WRAM_memcpy SFX_DSP_STATE, DSPSTATE, $80 ;DSP Registers |
| 37 | +WRAM_memcpy SFX_DSP_STATE+$80, SPCHEADER, $7 ;CPU Registers |
| 38 | + |
| 39 | +;This calls the libSFX copy and exec routine |
| 40 | +RW_push set:a8i16 |
| 41 | +jsl SFX_SMP_execspc |
| 42 | +RW_pull |
| 43 | + |
| 44 | + |
| 45 | +;The next few lines each read a string of metadata from rom, prepares it for VRAM and then copies it to VRAM. |
| 46 | +;Horribly inefficient, but it only does this once when starting so whatever. |
| 47 | +WRAM_memcpy $00, SPCTITLE, $20 |
| 48 | +jsl preparetext |
| 49 | +VRAM_memcpy $150, $100, $30 |
| 50 | + |
| 51 | +WRAM_memcpy $00, SPCGAME, $20 |
| 52 | +jsl preparetext |
| 53 | +VRAM_memcpy $1D0, $100, $30 |
| 54 | + |
| 55 | +WRAM_memcpy $00, SPCARTIST, $20 |
| 56 | +jsl preparetext |
| 57 | +VRAM_memcpy $250, $100, $30 |
| 58 | + |
| 59 | +WRAM_memcpy $00, SPCDUMPER, $20 |
| 60 | +jsl preparetext |
| 61 | +VRAM_memcpy $2D0, $100, $20 |
| 62 | + |
| 63 | +WRAM_memcpy $00, SPCLENGTH, $20 |
| 64 | +jsl preparetext |
| 65 | +VRAM_memcpy $350, $100, $6 |
| 66 | + |
| 67 | +;The screen setup is straight up copied from the Hello example of libSFX. Couldn't be bothered tbh. |
| 68 | +;Set up screen mode |
| 69 | +lda #bgmode(BG_MODE_1, BG3_PRIO_NORMAL, BG_SIZE_8X8, BG_SIZE_8X8, BG_SIZE_8X8, BG_SIZE_8X8) |
| 70 | +sta BGMODE |
| 71 | +lda #bgsc(VRAM_MAP_LOC, SC_SIZE_32X32) |
| 72 | +sta BG1SC |
| 73 | +ldx #bgnba(VRAM_TILES_LOC, 0, 0, 0) |
| 74 | +stx BG12NBA |
| 75 | +lda #tm(ON, OFF, OFF, OFF, OFF) |
| 76 | +sta TM |
| 77 | + |
| 78 | +;Turn on screen |
| 79 | +lda #inidisp(ON, DISP_BRIGHTNESS_MAX) |
| 80 | +sta SFX_inidisp |
| 81 | + VBL_on |
| 82 | + |
| 83 | + |
| 84 | +VBL_set handler ;Sets up the VBlank interrupt handler that copies the SPC port values to VRAM every frame. |
| 85 | + |
| 86 | +: wai |
| 87 | + bra :- |
| 88 | + |
| 89 | + |
| 90 | +handler: |
| 91 | + |
| 92 | +;In desperate need for a loop. Basically does the same exact thing 4 times. Once for each byte |
| 93 | +;Basically it explodes a byte into 2 nibbles which then corospond to the tiles $0-F. Also every second VRAM byte is 0 to not mess with palette and stuff. |
| 94 | +lda $2140 ;Port 0 |
| 95 | +and #$F0 ;Only the high nibble |
| 96 | +lsr a ;shift right 4 times to put high nibble in low nibble |
| 97 | +lsr a |
| 98 | +lsr a |
| 99 | +lsr a |
| 100 | +sta $100 ;store to RAM to get copied to VRAM later |
| 101 | + |
| 102 | +lda $2140;Still port 0 |
| 103 | +and #$0F ;Only the low nibble |
| 104 | +sta $102 ;No need to shift it since it's already in the low nibble. Also stored in WRAM for upload |
| 105 | + |
| 106 | + |
| 107 | +lda #$20 ;Tile for a blank space |
| 108 | +sta $104 ;Space inbetween 2 shown bytes |
| 109 | + |
| 110 | +;And now basically the whole thing 3 more times. Did i mention i could've looped this. oh well. |
| 111 | + |
| 112 | +lda $2141 |
| 113 | +and #$F0 |
| 114 | +lsr a |
| 115 | +lsr a |
| 116 | +lsr a |
| 117 | +lsr a |
| 118 | +sta $106 |
| 119 | + |
| 120 | +lda $2141 |
| 121 | +and #$0F |
| 122 | +sta $108 |
| 123 | + |
| 124 | + |
| 125 | +lda #$20 |
| 126 | +sta $10a |
| 127 | + |
| 128 | +lda $2142 |
| 129 | +and #$F0 |
| 130 | +lsr a |
| 131 | +lsr a |
| 132 | +lsr a |
| 133 | +lsr a |
| 134 | +sta $10c |
| 135 | + |
| 136 | +lda $2142 |
| 137 | +and #$0F |
| 138 | +sta $10e |
| 139 | + |
| 140 | + |
| 141 | +lda #$20 |
| 142 | +sta $110 |
| 143 | + |
| 144 | +lda $2143 |
| 145 | +and #$F0 |
| 146 | +lsr a |
| 147 | +lsr a |
| 148 | +lsr a |
| 149 | +lsr a |
| 150 | +sta $112 |
| 151 | + |
| 152 | +lda $2143 |
| 153 | +and #$0F |
| 154 | +sta $114 |
| 155 | + |
| 156 | +VRAM_memcpy $4D5, $100, $16 ;Aaaaaaaaaand ship it off to VRAM and return. |
| 157 | +rtl |
| 158 | + |
| 159 | + |
| 160 | +;oof where do i even start on this one... |
| 161 | +;This is the routine that prepares the text for VRAM |
| 162 | +;VRAM doesn't accept straight up bytes for the tilemap. The tilemap data is interleaved with palette, priority and flip data for each tile. |
| 163 | +; Some of the bits in the second byte are also used to select tiles higher than $FF. Just read up in fullsnes, not that difficult. |
| 164 | +; For this it basically means i have to add a $00 byte after each character byte. I probably massively overcomplicated this. |
| 165 | + |
| 166 | +preparetext: |
| 167 | +ldx #$00 ;Sets the X index to 0 |
| 168 | +phx ;Pushes the X index to the stack. The index will later be used both for source and destination with some switcharoo trickery. |
| 169 | + |
| 170 | +ptloop: ;Processing loop starts here |
| 171 | +LDA $00, X ;Loads the current byte at index $00+X |
| 172 | +cmp #$00 ;Compares it with $00. $00 is used in SPC files as a placeholder if the string is shorter than the full 32b. |
| 173 | + ;In my tileset that's not a blank time (0 tile from the hex font) |
| 174 | +bne skip0 ;So if it detects that it's a $00 character... |
| 175 | +LDA #$20 ;It replaces it with a blank $20 tile. |
| 176 | +skip0: ;Otherwise it just skips this. |
| 177 | +inx ;Alright loading the byte into A complete, source X index gets incremented. |
| 178 | +txy ;Temporarily puts X into Y, for safe keeping. |
| 179 | +plx ;Pulls X from the stack (this is where the destination X index was, or $00 in the first iteration) |
| 180 | +phy ;Puts Y on the stack (This gets pulled as X from the stack later) We basically do a switcharoo. Pull one x from the stack and push the other onto it. |
| 181 | +STA $100, X ;Store byte in A into the destination address |
| 182 | +STZ $101, X ;Store zero into the byte right after it, for obvious reasons. |
| 183 | +inx ;Increment X twice because we just wrote 2 bytes. |
| 184 | +inx |
| 185 | +txy ;Puts X into Y, same as before |
| 186 | +plx ;Pulls source X from the stack |
| 187 | +phy ;Pushes Y (destination X) to the stack. same thing as above. |
| 188 | +cpx #$20 ;Check if we copied 32bytes |
| 189 | +bne ptloop ;If no, go back to the beginning of the loop |
| 190 | +plx ;Otherwise, pull the leftover X from the Stack to make room for the return address that's still on the stack |
| 191 | +rtl ;Return |
| 192 | + |
| 193 | + |
| 194 | + |
| 195 | +;Import graphics stuff. |
| 196 | +incbin logomap, "Data/logo.bin" |
| 197 | +incbin Palette, "Data/font.png.palette" |
| 198 | +incbin Tiles, "Data/font.png.tiles" |
| 199 | + |
| 200 | +;Import placeholder music |
| 201 | +.segment "SPCHeader" |
| 202 | + .incbin "Data/placeholder.spc", $0, $100 |
| 203 | +.SEGMENT "ROM2" |
| 204 | +LOWB: .incbin "Data/placeholder.spc", $100, $8000 |
| 205 | +.SEGMENT "ROM3" |
| 206 | +HIGHB: .incbin "Data/placeholder.spc", $8100, $8000 |
| 207 | +.SEGMENT "ROM4" |
| 208 | +DSPSTATE: .incbin "Data/placeholder.spc", $10100 |
| 209 | + |
| 210 | + |
0 commit comments