quickdev16/snes/loader/routines/printstring.asm
David Voswinkel 7f84c8d97a add loader
2009-07-28 08:37:40 +02:00

756 lines
16 KiB
NASM

/*
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