/* tiny text output system for snes by d4s in 2006 call every frame in nmi, should be executed before global palette upload: DMATileMapToVramBG3 call every time a textstring should be loaded: LoadTextString text byte commands: #$00 - terminate string #$01 - set new offset, only executed if not first byte in string(has 2 additional bytes) #$02 - set font #$03 - draw string from special adress, but with fixed length(has 4 additional bytes, first byte length, last 3 bytes string vector, maximum string length: 32 letters) #$04 - draw string from special adress(has 3 additional bytes for string vector) #$05 - draw byte in hexadecimal(has 3 additional bytes for string vector) #$06 - draw byte in binary(has 3 additional bytes for string vector) #$07 - change palette number(AND'ed with 0x7) #$08 - draw byte in decimal variables needed: Bg3Status bit 0=font and palette uploaded PrintStringThreeBytePointerLo PrintStringThreeBytePointerHi PrintStringThreeBytePointerBank CurrentStringTarget CurrentStringTargetHi FontSelector FrameCounterLo FixedStringLength PrintStringBuffer0 PrintStringBuffer1 PrintStringBuffer2 PrintStringBuffer3 PrintStringBuffer4 PrintStringBuffer5 PrintStringBuffer6 PrintStringBuffer7 PrintStringBuffer8 PrintStringBuffer9 PrintStringPalette ;real number of palette ram areas needed: Bg3Buffer PaletteBuffer data needed: BG38x8FontTiles BG38x8FontPalette TextStrings TextStringPTable ASCIITable static vars needed: FontTileConfig */ DMATilesToVramBG3: php rep #$30 ; sep #$20 ; lda.b #$03 ;set vram adress of bg3/4 tiles $6000 ; lda.b BGTilesVram34 ; and.w ; sta.l $210c ; lda.b #$30 ;bg3 tilemap @ vram $7000, 32x32 tiles ; sta $2109 ; stz $2112 ;set bg3 v-offset to $0000 ; stz $2112 lda #0 jsr UploadFontBG3 jsr ClearBg3TilemapBuffer plp rts DMATileMapToVramBG3: php rep #$30 sep #$20 lda.b NMIBg3UploadFlag beq DontDMATileMapToVramBG3 stz.b NMIBg3UploadFlag ;clear upload flag ldx.b DmaFifoPointer lda #1 ;transfer type sta.l DmaFifoEntryType,x ;DMATileMapToVramBG3DontUploadFont: lda.b #$7e ;get source bank of tilemap buffer ; sta.w $4304 ;Store the data bank of the source data sta.l DmaFifoEntrySrcBank,x ;source 4304 rep #$30 ;accu 16bit lda.w #Bg3MapBuffer&$ffff ;get source offset ; sta.w $4302 sta.l DmaFifoEntrySrcLo,x ;source 4302 lda.w #$0800 ; sta.w $4305 ;Store the size of the data block sta.l DmaFifoEntryCount,x ;length 4305 ; ldx.w #$3000 ; stx.w $2116 ;vram adress $7000 lda.b BG3TilemapVram and.w #%11111100 ;mask off bg size bits xba ; sta.w $2116 sta.l DmaFifoEntryTarget,x ;vram target 2116 txa ;update fifo entry pointer clc adc.w #DmaFifoEntryLength sta.b DmaFifoPointer /* sep #$20 lda #$80 sta $2115 ;set VRAM transfer mode to word-access, increment by 1 lda #$01 ;Set the DMA mode (word, normal increment) sta $4300 lda #$18 ;Set the destination register (VRAM gate) sta $4301 lda #$01 ;Initiate the DMA transfer sta $420B */ DontDMATileMapToVramBG3: plp rts ;in: a,8bit: number of font to upload UploadFontBG3: php rep #$31 ; sep #$20 and.w #$ff asl a asl a tax lda.l (Bg38x8FontLUT+BaseAdress+2),x ;get font length pha lda.l (Bg38x8FontLUT+BaseAdress),x ;get font pointer pha ldx.b DmaFifoPointer sep #$20 lda #1 ;transfer type sta.l DmaFifoEntryType,x lda.b #(:Bg38x8FontLUT+BaseAdress>>16) ;get source bank ; sta $4304 ;Store the data bank of the source data sta.l DmaFifoEntrySrcBank,x rep #$30 ; lda.w #BG38x8FontTiles ; sta $4302 ;Store the data offset into DMA source offset pla sta.l DmaFifoEntrySrcLo,x ;source 4302 ; lda.w #(BG38x8FontTilesEnd-BG38x8FontTiles) ;get size of font ; sta $4305 ;Store the size of the data block pla sta.l DmaFifoEntryCount,x ;length 4305 lda.b BGTilesVram34 and.w #$0f clc ror ror ror ror ror ;put into highest nibble clc adc.w #$400 ;add $800 for tilemap ; sta $2116 ;vram destination adress $1000(bg1 tilespace) sta.l DmaFifoEntryTarget,x ;vram target 2116 /* sep #$20 lda #$80 sta $2115 ;set VRAM transfer mode to word-access, increment by 1 lda #$01 ;Set the DMA mode (word, normal increment) sta $4300 lda #$18 ;Set the destination register (VRAM gate) sta $4301 lda #$01 ;Initiate the DMA transfer sta $420B */ txa ;update fifo entry pointer clc adc.w #DmaFifoEntryLength sta.b DmaFifoPointer DMAUploadPaletteBG3: lda #(:BG38x8FontPalette+BaseAdress>>16) ;get source bank of tilemaps sta PrintStringThreeBytePointerBank ; rep #$30 ;accu 16bit lda.w #BG38x8FontPalette ;get source offset of tilemap sta PrintStringThreeBytePointerLo lda.w #(BG38x8FontPaletteEnd-BG38x8FontPalette) sta.b TempBuffer ; ldx.w #$0008 ;get length lda.w #FontTileConfig ;get palette number and.w #%00011100 lsr a lsr a asl a asl a asl a tax ;calculate starting offset in palette buffer and put in x ldy.w #$0000 ;clear target/source counter DMAUploadPaletteBG3Loop: lda [PrintStringThreeBytePointerLo],y ;load word from PrintStringThreeBytePointer sta.w PaletteBuffer&$ffff,x ;store in bg3 pal buffer, palette 1 iny ;word-inc copy counter iny inx ;word-dec length counter inx dec TempBuffer dec TempBuffer bne DMAUploadPaletteBG3Loop ;done if length counter = 0 sep #$20 inc.b NMIPaletteUploadFlag plp rts LoadTextString: pha php sep #$20 phb ;set data bank = wram lda.b #$7e pha plb lda.b #FontTileConfig and.b #%00011100 sta.b PrintStringPalette lda #(:TextStrings+BaseAdress>>16) ;get source bank of strings sta PrintStringThreeBytePointerBank ; rep #$30 ;accu 16bit txa ;get number of string asl ;multiply by 2 to get pointertable entry tax lda.l (TextStringPTable+BaseAdress),x ;get source offset of string sta PrintStringThreeBytePointerLo ldy.w #$0000 lda [PrintStringThreeBytePointerLo],y ;get target buffer in wram and.w #$fffe ;mask off bit 0 to ensure text is word-formatted properly sta.w CurrentStringTarget iny ;increment source position, word iny ;process all script commands with jump table. ;if processing a fixed length string, dont execute any script codes at all LoadTextStringFetchLetter: rep #$30 tya cmp.w #$01ff ;maximum string length: 256 bytes bcs ScriptCommandExit sep #$20 lda #$00 ;set upper byte of a to zero xba lda.b FixedStringLength beq NoFixedLengthDynaString lda.b FixedStringLength dec a sta.b FixedStringLength cmp.b #$01 bne NoScriptCommand jmp ScriptCommandExit NoFixedLengthDynaString: rep #$30 lda [PrintStringThreeBytePointerLo],y ;check if we are processing a script command and.w #$00f0 bne NoScriptCommand lda [PrintStringThreeBytePointerLo],y ;get script command and.w #$000f clc asl a tax jmp (ScriptCommandPointerTable,x) NoScriptCommand: sep #$20 TextStringNotTerminated: lda [PrintStringThreeBytePointerLo],y tax lda.w FontSelector beq TextStringNormalFont ;special 8x16 font lda.l (ASCIITable8x16+BaseAdress),x ;get tile value for current letter ; clc xba lda.b #FontTileConfig ;palette and mirroring config for font tiles and.b #%11100011 ;clear old palette number ora.b PrintStringPalette ;set palette number xba rep #$30 ;now we have the full tileinfo for the letter ldx.w CurrentStringTarget ;get current position in tilemap sta.l Bg3MapBuffer,x ;store upper tile clc adc.w #$0010 ;add 16 to get tile number of lower tile sta.l (Bg3MapBuffer+$40),x ;store lower tile sep #$20 iny ;advance to next letter inx inx ;increment pointer in bg1 tilemap stx.w CurrentStringTarget jmp LoadTextStringFetchLetter ScriptCommandExit: sep #$20 stz.b FixedStringLength stz.w FontSelector ;reset font inc.b NMIBg3UploadFlag plb plp pla rts ;normal 8x8 font TextStringNormalFont: lda.l (ASCIITable+BaseAdress),x ;get tile value for current letter ; sec ; sbc.b #$50 clc adc.b #$30 xba lda.b #FontTileConfig ;palette and mirroring config for font tiles bcc TextStringNormalFontNoWrap ora.b #1 ;set tile number msb TextStringNormalFontNoWrap: and.b #%11100011 ;clear old palette number ora.b PrintStringPalette ;set palette number xba rep #$30 ;now we have the full tileinfo for the letter ldx.w CurrentStringTarget ;get current position in tilemap sta.l Bg3MapBuffer,x sep #$20 iny ;advance to next letter inx inx ;increment pointer in bg1 tilemap stx.w CurrentStringTarget jmp LoadTextStringFetchLetter ScriptCommandPrintByte: rep #$30 iny lda [PrintStringThreeBytePointerLo],y ;get ThreeByte adress of byte pha iny lda [PrintStringThreeBytePointerLo],y sta.w PrintStringThreeBytePointerHi ;and store in ThreeByte pointer pla sta.w PrintStringThreeBytePointerLo ldy.w #$0000 ;reset source pointer sep #$20 lda.b #$04 ;print 2 letters + overhang sta.b FixedStringLength lda [PrintStringThreeBytePointerLo],y pha lsr a ;get upper nibble lsr a lsr a lsr a and.b #$0f clc adc.b #$30 ;add ASCII "0" to every letter cmp.b #$3a ;check if bigger than ASCII "9" bcc PrintByteNotA1 adc.b #$06 ;add until ASCII "A" if bigger than 9(carry always set, so -1) PrintByteNotA1: sta.w PrintStringBuffer0&$ffff ;store in first letter pla and.b #$0f clc adc.b #$30 ;add ASCII "0" to every letter cmp.b #$3a ;check if bigger than ASCII "9" bcc PrintByteNotA2 adc.b #06 ;add until ASCII "A" if bigger than 9(carry always set, so -1) PrintByteNotA2: sta.w PrintStringBuffer0&$ffff+1 ;store in second letter lda.b #$7e ; sta.b PrintStringThreeBytePointerBank rep #$30 lda.w #PrintStringBuffer0&$ffff sta.b PrintStringThreeBytePointerLo jmp LoadTextStringFetchLetter ScriptCommandPrintByteBinary: rep #$30 iny lda [PrintStringThreeBytePointerLo],y ;get ThreeByte adress of byte pha iny lda [PrintStringThreeBytePointerLo],y sta.b PrintStringThreeBytePointerHi ;and store in ThreeByte pointer pla sta.b PrintStringThreeBytePointerLo ldy.w #$0000 ;reset source pointer tyx sep #$20 lda.b #10 ;print 8 letters + overhang sta.b FixedStringLength ScriptCommandBinaryConvLoop: rep #$30 txa asl a tax sep #$20 lda [PrintStringThreeBytePointerLo],y jmp (ScriptCommandBinaryConvJtbl,x) ScriptCommandBinaryConvJtbl: .dw ScriptCommandBinaryConv+0 .dw ScriptCommandBinaryConv+1 .dw ScriptCommandBinaryConv+2 .dw ScriptCommandBinaryConv+3 .dw ScriptCommandBinaryConv+4 .dw ScriptCommandBinaryConv+5 .dw ScriptCommandBinaryConv+6 .dw ScriptCommandBinaryConv+7 ScriptCommandBinaryConv: lsr a lsr a lsr a lsr a lsr a lsr a lsr a clc and.b #01 adc.b #$30 ;add until ASCII "0" or "1", depending on bit0 pha rep #$30 txa lsr a tax sep #$20 pla sta.w PrintStringBuffer0&$ffff,x inx cpx.w #$0008 bne ScriptCommandBinaryConvLoop lda.b #$7e ; sta.b PrintStringThreeBytePointerBank rep #$30 lda.w #PrintStringBuffer0&$ffff sta.b PrintStringThreeBytePointerLo jmp LoadTextStringFetchLetter ScriptCommandGetDynaStringFixLength: sep #$20 iny lda [PrintStringThreeBytePointerLo],y ;get string length inc a inc a and.b #$1f ;maximum string length: 32 letters sta.b FixedStringLength ScriptCommandGetDynaString: rep #$30 iny lda [PrintStringThreeBytePointerLo],y ;get ThreeByte adress of dynamic string pha iny lda [PrintStringThreeBytePointerLo],y sta.w PrintStringThreeBytePointerHi ;and store in ThreeByte pointer pla sta.w PrintStringThreeBytePointerLo ldy.w #$0000 ;reset source pointer jmp LoadTextStringFetchLetter ScriptCommandNewPosition: rep #$30 iny lda [PrintStringThreeBytePointerLo],y ;get new offset in bg3 buffer and.w #$fffe sta.w CurrentStringTarget iny iny lda.w #$0000 sep #$20 stz.w FontSelector ;reset font jmp LoadTextStringFetchLetter ScriptCommandNewFont: sep #$20 lda.w FontSelector eor.b #$01 ;xor bit 0 sta.w FontSelector ;save to font selection var iny ;increment string pointer jmp LoadTextStringFetchLetter ScriptCommandChangePalette: sep #$20 iny lda [PrintStringThreeBytePointerLo],y ;get new palette number asl a asl a and.b #%00011100 ;maximum number of palettes:8, move to correct location in tile config sta.b PrintStringPalette iny ;increment string pointer jmp LoadTextStringFetchLetter ScriptCommandVoid: jmp ScriptCommandExit ;exit if an unimplemented script code is executed StringSpace: ldx.w CurrentStringTarget inx inx ;increment target buffer pointer by 2 stx.w CurrentStringTarget iny ;increment string pointer rts HdmaFontPaletteGradient: rts ;alternates every 64 frames between 2 consecutive textstrings ;in: x,16bit: number of first textstring FlashTextString: php rep #$30 sep #$20 lda.w FrameCounterLo bit #$20 beq FlashTextStringShowFirstString inx ;get next textstring FlashTextStringShowFirstString: jsr LoadTextString plp rts ScriptCommandPointerTable: .dw ScriptCommandExit ;0 .dw ScriptCommandNewPosition .dw ScriptCommandNewFont .dw ScriptCommandGetDynaStringFixLength .dw ScriptCommandGetDynaString .dw ScriptCommandPrintByte ;5 .dw ScriptCommandPrintByteBinary .dw ScriptCommandChangePalette .dw ScriptCommandPrintByteDecimal .dw ScriptCommandVoid .dw ScriptCommandVoid ;10 .dw ScriptCommandVoid .dw ScriptCommandVoid .dw ScriptCommandVoid .dw ScriptCommandVoid .dw ScriptCommandVoid ScriptCommandPrintByteDecimal: rep #$30 iny lda [PrintStringThreeBytePointerLo],y ;get ThreeByte adress of byte pha iny lda [PrintStringThreeBytePointerLo],y sta.b PrintStringThreeBytePointerHi ;and store in ThreeByte pointer pla sta.b PrintStringThreeBytePointerLo ldy.w #$0000 ;reset source pointer tyx sep #$20 lda.b #5 ;print 8 letters + overhang sta.b FixedStringLength ;have 3 variables, hexa value, a hexa counter and decimal(word). ;increment decimal word and hexa counter until hexa value is reached. ;if hexa counter=a: add 7 to go to 10 rep #$31 stz.b TempBuffer+2 ;hex counter stz.b TempBuffer+4 ;decimal counter lda [PrintStringThreeBytePointerLo],y and.w #$ff sta.b TempBuffer ;target hex value beq DeciConvPrint ;skip counting if zero ScriptCommandDecimalConvLoop: inc.b TempBuffer+4 ;inc decimal lda.b TempBuffer lda.b TempBuffer+4 and.w #$f cmp.w #$a bne DeciConvNoOverf1 lda.b TempBuffer+4 clc adc.w #6 sta.b TempBuffer+4 DeciConvNoOverf1: lda.b TempBuffer+4 and.w #$f0 cmp.w #$a0 bne DeciConvNoOverf2 lda.b TempBuffer+4 clc adc.w #$60 sta.b TempBuffer+4 DeciConvNoOverf2: dec.b TempBuffer bne ScriptCommandDecimalConvLoop DeciConvPrint: ;print to buffer sep #$20 lda.b TempBuffer+5 and.b #$f sta.b TempBuffer+6 bne DeciConvPrint1 ;dont print leading zero lda.b #$f0 DeciConvPrint1: clc adc.b #$30 ;add until ASCII "0" or "1", depending on bit0 sta.w PrintStringBuffer0&$ffff lda.b TempBuffer+4 lsr a lsr a lsr a lsr a and.b #$f bne DeciConvPrint2 ;dont print leading zero cmp.b TempBuffer+6 bne DeciConvPrint2 lda.b #$f0 DeciConvPrint2: clc adc.b #$30 ;add until ASCII "0" or "1", depending on bit0 sta.w PrintStringBuffer0&$ffff+1 lda.b TempBuffer+4 and.b #$f clc adc.b #$30 ;add until ASCII "0" or "1", depending on bit0 sta.w PrintStringBuffer0&$ffff+2 ; sep #$20 lda.b #$7e ; sta.b PrintStringThreeBytePointerBank rep #$30 lda.w #PrintStringBuffer0&$ffff sta.b PrintStringThreeBytePointerLo jmp LoadTextStringFetchLetter MessagePendingDelete: php rep #$31 ; sep #$20 lda.w MessageDeleteCounter beq MessagePendingDeleteInactive cmp.w #1 bne MessagePendingDec ldx.w #52 jsr LoadTextString ;delete message if counter is 1 MessagePendingDec: dec.w MessageDeleteCounter MessagePendingDeleteInactive: plp rts