294 lines
8.7 KiB
NASM
294 lines
8.7 KiB
NASM
SECTION "ram_textwriter", WRAM0
|
|
textwriter_curtext: ds 2
|
|
textwriter_posx: ds 1
|
|
textwriter_posy: ds 1
|
|
textwriter_curdelay: ds 1
|
|
textwriter_active: ds 1
|
|
textwriter_starting: ds 1
|
|
textwriter_ending: ds 1
|
|
textwriter_pausing: ds 1
|
|
|
|
SECTION "rom_textmap", ROM0,ALIGN[8]
|
|
textwriter_map:
|
|
; 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
|
|
db $44,$50,$50,$50,$50,$50,$50,$50,$50,$50,$50,$50,$50,$50,$50,$50 ; 0
|
|
; 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
|
|
db $50,$50,$50,$50,$50,$50,$50,$50,$50,$50,$50,$50,$50,$50,$50,$50 ; 16
|
|
; 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
|
|
db $50,$41,$50,$45,$50,$50,$50,$43,$50,$50,$50,$50,$42,$50,$3F,$50 ; 32
|
|
; 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
|
|
db $35,$36,$37,$38,$39,$3A,$3B,$3C,$3D,$3E,$50,$50,$50,$50,$50,$40 ; 48
|
|
; 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
|
|
db $50,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,$0B,$0C,$0D,$0E,$0F ; 64
|
|
; 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
|
|
db $10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$1A,$50,$50,$50,$50,$50 ; 80
|
|
; 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
|
|
db $50,$1B,$1C,$1D,$1E,$1F,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29 ; 96
|
|
; 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
|
|
db $2A,$2B,$2C,$2D,$2E,$2F,$30,$31,$32,$33,$34,$50,$50,$50,$50,$50 ; 112
|
|
|
|
SECTION "TextWriter", ROM0
|
|
|
|
InitWindow:
|
|
; Fill first line in window with straight line
|
|
ld hl, (_SCRN1 + 1)
|
|
ld b, 19
|
|
ld a, $52
|
|
call Memfill
|
|
; Fill rest of the area with dark bg
|
|
call ClearWindow
|
|
; Fill last line in window with straight line
|
|
ld hl, (_SCRN1 + $61)
|
|
ld b, 19
|
|
ld a, $57
|
|
call Memfill
|
|
; Top left corner
|
|
ld hl, _SCRN1
|
|
ld [hl], $51
|
|
; Top right corner
|
|
ld hl, _SCRN1 + 19
|
|
ld [hl], $53
|
|
; Bottom Left corner
|
|
ld hl, _SCRN1 + $60
|
|
ld [hl], $56
|
|
; Bottom Right corner
|
|
ld hl, _SCRN1 + $60 + 19
|
|
ld [hl], $58
|
|
; Left line
|
|
ld hl, _SCRN1 + $20
|
|
ld [hl], $54
|
|
ld hl, _SCRN1 + $40
|
|
ld [hl], $54
|
|
; Right line
|
|
ld hl, _SCRN1 + $20 + 19
|
|
ld [hl], $55
|
|
ld hl, _SCRN1 + $40 + 19
|
|
ld [hl], $55
|
|
; Some other common memory addresses that should be filled
|
|
ld a, 0
|
|
ld [textwriter_posx], a
|
|
ld [textwriter_posy], a
|
|
ld [textwriter_ending], a
|
|
ld [textwriter_pausing], a
|
|
ld [textwriter_active], a
|
|
ld [textwriter_curdelay], a
|
|
ld [textwriter_starting], a
|
|
ret ; Return
|
|
|
|
ClearWindow:
|
|
ld hl, (_SCRN1 + $21)
|
|
ld a, $50
|
|
ld b, 18
|
|
call Memfill
|
|
ld hl, (_SCRN1 + $41)
|
|
ld b, 18
|
|
call Memfill
|
|
ret
|
|
|
|
; Start to print a string on screen
|
|
; @param de - Address source string
|
|
; @return a - garbage
|
|
; @return b - PosX on where to draw text
|
|
; @return c - PosY on where to draw text
|
|
; @return hl - Workram position for text pointer
|
|
; @return de - Memory address to source string
|
|
StartText:
|
|
ld a, 10
|
|
ld [textwriter_curdelay], a
|
|
ld a, 0
|
|
ld [textwriter_posx], a
|
|
ld [textwriter_posy], a
|
|
ld [textwriter_ending], a
|
|
ld [textwriter_pausing], a
|
|
ld a, 1
|
|
ld [textwriter_active], a
|
|
ld hl, textwriter_curtext
|
|
ld a, d
|
|
ld [hli], a
|
|
ld a, e
|
|
ld [hl], a
|
|
dec hl
|
|
ld a, 16
|
|
ld [textwriter_starting], a
|
|
call ClearWindow ; Clear it just in case
|
|
ret
|
|
|
|
; Draw text if one is currently active
|
|
DrawActiveText:
|
|
ld a, [textwriter_active] ; Check if text is currently active
|
|
and a
|
|
ret z ; If no text is active, just exit immediately
|
|
|
|
ld a, [textwriter_starting] ; Check if we're booting up the window
|
|
and a
|
|
jr z, .afterLoading ; Jump to after loading if we're not loading
|
|
|
|
; We are loading the window
|
|
ld a, [rWY] ; Get current window position
|
|
dec a ; Decrement twice (moves it slowly up)
|
|
dec a
|
|
ld [rWY], a ; Set the position back into window
|
|
ld a, [textwriter_starting]
|
|
dec a
|
|
ld [textwriter_starting], a
|
|
jr z, .afterLoading
|
|
ret
|
|
|
|
.afterLoading
|
|
ld a, [textwriter_ending] ; Check if we are ending
|
|
and a
|
|
jr z, .checkPausing ; If we are not ending, jump to check pause
|
|
|
|
; We are ending, animate the window back down
|
|
ld a, [rWY] ; Get current window position
|
|
inc a ; Increment twice
|
|
inc a
|
|
ld [rWY], a ; Set the position back into window
|
|
ld a, [textwriter_ending] ; Grab the ending guy
|
|
dec a ; Decrement it
|
|
ld [textwriter_ending], a ; Set it back
|
|
jr z, .closingAll ; If we reach zero, we can disable text renderer
|
|
ret
|
|
|
|
.closingAll
|
|
ld [textwriter_active], a
|
|
ret
|
|
|
|
.checkPausing
|
|
ld a, [textwriter_pausing] ; Check if we're in a paused state
|
|
and a
|
|
jr z, .checkDelay ; Jump to Delayer if we're not in paused state
|
|
|
|
ld b, a ; We are in pause state so store pause state in register b
|
|
ld a, [controller_newkeys] ; Check our controller
|
|
and a, PAD_A|PAD_B ; Check if we pressed either A or B
|
|
ret z ; Exit if he didn't
|
|
|
|
dec b ; Decrement B, our paused state
|
|
jr z, .continuingNextLine ; If paused state was 1 then we continue
|
|
;to render next line
|
|
|
|
; If we reach here, paused state was 2 which means we should
|
|
; end text reader
|
|
ld a, 16 ; Set a to 1
|
|
ld [textwriter_ending], a ; Mark it as we are ending
|
|
ret
|
|
|
|
.continuingNextLine
|
|
call ClearWindow
|
|
ld a, 0
|
|
ld [textwriter_pausing], a
|
|
ld [textwriter_posx], a
|
|
ld [textwriter_posy], a
|
|
jr .delayFinished
|
|
|
|
.checkDelay
|
|
; Delay writing a letter by 10 frames if no button is down
|
|
ld a, [textwriter_curdelay]
|
|
dec a
|
|
ld [textwriter_curdelay], a
|
|
jr z, .delayFinished
|
|
|
|
ld a, [controller_curkeys] ; Check our controller
|
|
and a, PAD_B
|
|
ret z ; If B button is being held, we skip any delay
|
|
|
|
.delayFinished
|
|
; Reset the curdelay
|
|
ld a, 10
|
|
ld [textwriter_curdelay], a
|
|
|
|
.startdrawtext
|
|
; Get the memory address pointing to the text currently being
|
|
; displayed. This is stored in textwriter_curtext
|
|
ld hl, textwriter_curtext ; Get the memory address of the pointer
|
|
ld d, [hl] ; Store the first byte address to d
|
|
inc hl ; Move to next byte
|
|
ld e, [hl] ; Store the next byte address to e
|
|
; We now have the current letter being drawn at [de]
|
|
|
|
; Get the current X position for the text on screen
|
|
ld hl, (_SCRN1 + $21) ; Load the top-left window position for our text
|
|
; Load the x position for current text position and
|
|
ld a, [textwriter_posx]
|
|
ld b, a
|
|
ld a, l
|
|
add b ; Add the x position
|
|
ld l, a
|
|
|
|
; Get the current Y position for the text on screen
|
|
ld a, [textwriter_posy]
|
|
and a ; Check if it's zero
|
|
jr z, .drawletter
|
|
; If not, jump forward by a whole line.
|
|
ld a, l
|
|
add a, $20
|
|
ld l, a
|
|
.drawletter
|
|
ld a, [de] ; Load the first byte in the string
|
|
ld bc, textwriter_map ; Get the map for the ASCII->Tile map
|
|
ld c, a ; Set the position of C to the ASCII byte of current character
|
|
ld a, [bc] ; Get the tile byte for the ASCII from the map
|
|
ld [hl], a ; Print the byte to the map
|
|
|
|
.checkIsEnding
|
|
ld a, [de]
|
|
and a ; Check if we reached the end
|
|
jr nz, .checkContinuing
|
|
|
|
; We have reached the end of the string, mark it
|
|
ld a, 2
|
|
ld [textwriter_pausing], a
|
|
jr .continue ; Jump straight to continue. No need to check anything
|
|
|
|
.checkContinuing
|
|
ld a, [de] ; Regrab the ascii byte we printed
|
|
cp a, $23 ; Check if it's '#'
|
|
jr nz, .checkNewline ; Jump to next check if it wasn't
|
|
|
|
ld a, 1
|
|
ld [textwriter_pausing], a
|
|
jr .continue
|
|
|
|
.checkNewline
|
|
ld a, [de] ; Regrab the ascii byte we printed
|
|
cp a, $0A ; Check if it was a new line '\n'
|
|
jr nz, .checkRepeatOnce ; Jump to checkRepeatOnce if it wasn't a new line
|
|
|
|
; The byte we printed was a new line so we increment Y position
|
|
; and reset our X position.
|
|
ld a, -1 ; Usually we'd print into first position but since we're jumping
|
|
; into continue, continue will automatically increment x for us.
|
|
ld [textwriter_posx], a
|
|
ld a, 1
|
|
ld [textwriter_posy], a ; Set our Y position to 1
|
|
ld [textwriter_curdelay], a ; Also set curdelay to 1 as well
|
|
jr .continue
|
|
|
|
.checkRepeatOnce
|
|
ld a, [bc] ; Regrab the tile we printer
|
|
|
|
; Check if we printed an empty letter
|
|
cp a, $50
|
|
jr nz, .continue
|
|
ld a, 1
|
|
ld [textwriter_curdelay], a ; Set curdelay to 1 so it immediately prints next character
|
|
|
|
.continue
|
|
; Time to update our work ram
|
|
inc de ; Increment de to next letter
|
|
; Load the position pointer of current text and update it to the next letter
|
|
ld hl, textwriter_curtext
|
|
ld a, d
|
|
ld [hli], a
|
|
ld a, e
|
|
ld [hl], a
|
|
; Update the x position in ram
|
|
ld a, [textwriter_posx]
|
|
inc a
|
|
ld [textwriter_posx], a
|
|
|
|
.exit
|
|
ld a, [textwriter_active]
|
|
ret
|