; similar to ProcessText except it calls InitTextPrinting first ; with the first two bytes of hl being used to set hTextBGMap0Address. ; (the caller to ProcessText usually calls InitTextPrinting first) InitTextPrinting_ProcessText: push de push bc ld d, [hl] inc hl ld e, [hl] inc hl call InitTextPrinting jr ProcessText.next_char ; reads the characters from the text at hl processes them. loops until ; TX_END is found. ignores TX_RAM1, TX_RAM2, and TX_RAM3 characters. ProcessText: push de push bc call InitTextFormat jr .next_char .char_loop cp TX_CTRL_START jr c, .character_pair cp TX_CTRL_END jr nc, .character_pair call ProcessSpecialTextCharacter jr .next_char .character_pair ld e, a ; first char ld d, [hl] ; second char call ClassifyTextCharacterPair jr nc, .not_tx_fullwidth inc hl .not_tx_fullwidth call Func_22ca xor a call ProcessSpecialTextCharacter .next_char ld a, [hli] or a jr nz, .char_loop ; TX_END call TerminateHalfWidthText pop bc pop de ret ; processes the text character provided in a checking for specific control characters. ; hl points to the text character coming right after the one loaded into a. ; returns carry if the character was not processed by this function. ProcessSpecialTextCharacter: or a ; TX_END jr z, .tx_end cp TX_HIRAGANA jr z, .set_syllabary cp TX_KATAKANA jr z, .set_syllabary cp "\n" jr z, .end_of_line cp TX_SYMBOL jr z, .tx_symbol cp TX_HALFWIDTH jr z, .tx_halfwidth cp TX_HALF2FULL jr z, .tx_half2full scf ret .tx_halfwidth ld a, HALF_WIDTH ld [wFontWidth], a ret .tx_half2full call TerminateHalfWidthText xor a ; FULL_WIDTH ld [wFontWidth], a ld a, TX_KATAKANA ldh [hJapaneseSyllabary], a ret .set_syllabary ldh [hJapaneseSyllabary], a xor a ret .tx_symbol ld a, [wFontWidth] push af ld a, HALF_WIDTH ld [wFontWidth], a call TerminateHalfWidthText pop af ld [wFontWidth], a ldh a, [hffb0] or a jr nz, .skip_placing_tile ld a, [hl] push hl call PlaceNextTextTile pop hl .skip_placing_tile inc hl .tx_end ldh a, [hTextLineLength] or a ret z ld b, a ldh a, [hTextLineCurPos] cp b jr z, .end_of_line xor a ret .end_of_line call TerminateHalfWidthText ld a, [wLineSeparation] or a call z, .next_line .next_line xor a ldh [hTextLineCurPos], a ldh a, [hTextHorizontalAlign] add BG_MAP_WIDTH ld b, a ; get current line's starting BGMap0 address ldh a, [hTextBGMap0Address] and $e0 ; advance to next line add b ; apply background scroll correction ldh [hTextBGMap0Address], a ldh a, [hTextBGMap0Address + 1] adc $0 ldh [hTextBGMap0Address + 1], a ld a, [wCurTextLine] inc a ld [wCurTextLine], a xor a ret ; calls InitTextFormat, selects tiles at $8800-$97FF for text, and clears the wc600. ; selects the first and last tile to be reserved for constructing text tiles in VRAM ; based on the values given in d and e respectively. SetupText: ld a, d dec a ld [wcd04], a ld a, e ldh [hffa8], a call InitTextFormat xor a ldh [hffb0], a ldh [hffa9], a ld a, $88 ld [wTilePatternSelector], a ld a, $80 ld [wTilePatternSelectorCorrection], a ld hl, wc600 .clear_loop xor a ld [hl], a inc l jr nz, .clear_loop ret ; wFontWidth <- FULL_WIDTH ; hTextLineCurPos <- 0 ; wHalfWidthPrintState <- 0 ; hJapaneseSyllabary <- TX_KATAKANA InitTextFormat: xor a ; FULL_WIDTH ld [wFontWidth], a ldh [hTextLineCurPos], a ld [wHalfWidthPrintState], a ld a, TX_KATAKANA ldh [hJapaneseSyllabary], a ret ; call InitTextPrinting ; hTextLineLength <- a InitTextPrintingInTextbox: push af call InitTextPrinting pop af ldh [hTextLineLength], a ret ; hTextHorizontalAlign <- d ; hTextLineLength <- 0 ; wCurTextLine <- 0 ; write BGMap0-translated DE to hTextBGMap0Address ; call InitTextFormat InitTextPrinting: push hl ld a, d ldh [hTextHorizontalAlign], a xor a ldh [hTextLineLength], a ld [wCurTextLine], a call DECoordToBGMap0Address ld a, l ldh [hTextBGMap0Address], a ld a, h ldh [hTextBGMap0Address + 1], a call InitTextFormat xor a ld [wHalfWidthPrintState], a pop hl ret ; requests a text tile to be generated and prints it in the screen ; different modes depending on hffb0: ; hffb0 == $0: generate and place text tile ; hffb0 == $2 (bit 1 set): only generate text tile? ; hffb0 == $1 (bit 0 set): not even generate it, but just update text buffers? Func_22ca: push hl push de push bc ldh a, [hffb0] and $1 jr nz, .asm_22ed call Func_2325 jr c, .tile_already_exists or a jr nz, .done call GenerateTextTile .tile_already_exists ldh a, [hffb0] and $2 jr nz, .done ldh a, [hffa9] call PlaceNextTextTile .done pop bc pop de pop hl ret .asm_22ed call Func_235e jr .done ; writes a to wCurTextTile and to the tile pointed to by hTextBGMap0Address, ; then increments hTextBGMap0Address and hTextLineCurPos PlaceNextTextTile: ld [wCurTextTile], a ld hl, hTextBGMap0Address ld e, [hl] inc hl ld d, [hl] inc de ld [hl], d dec hl ld [hl], e dec de ld l, e ld h, d ld de, wCurTextTile ld c, 1 call SafeCopyDataDEtoHL ld hl, hTextLineCurPos inc [hl] ret ; when terminating half-width text with "\n" or TX_END, or switching to full-width ; with TX_HALF2FULL or to symbols with TX_SYMBOL, check if it's necessary to append ; a half-width space to finish an incomplete character pair. TerminateHalfWidthText: ld a, [wFontWidth] or a ; FULL_WIDTH ret z ld a, [wHalfWidthPrintState] or a ret z ; return if the last printed character was the second of a pair push hl push de push bc ld e, " " call Func_22ca pop bc pop de pop hl ret Func_2325: call Func_235e ret c or a ret nz ldh a, [hffa8] ld hl, wcd04 cp [hl] jr nz, .asm_2345 ldh a, [hffa9] ld h, $c8 .asm_2337 ld l, a ld a, [hl] or a jr nz, .asm_2337 ld h, $c9 ld c, [hl] ld b, $c8 xor a ld [bc], a jr .asm_234a .asm_2345 inc [hl] jr nz, .asm_2349 inc [hl] .asm_2349 ld l, [hl] .asm_234a ldh a, [hffa9] ld c, a ld b, $c9 ld a, l ldh [hffa9], a ld [bc], a ld h, $c8 ld [hl], c ld h, $c6 ld [hl], e inc h ; $c7 ld [hl], d ld b, l xor a ret ; search linked-list for text characters e/d (registers), if found hoist ; the result to head of list and return it. carry flag denotes success. Func_235e: ld a, [wFontWidth] or a jr z, .print call CaseHalfWidthLetter ; if [wHalfWidthPrintState] != 0, load it to d and print the pair of chars ; zero wHalfWidthPrintState for next iteration ld a, [wHalfWidthPrintState] ld d, a or a jr nz, .print ; if [wHalfWidthPrintState] == 0, don't print text in this iteration ; load the next value of register d into wHalfWidthPrintState ld a, e ld [wHalfWidthPrintState], a ld a, $1 or a ret ; nz .print xor a ld [wHalfWidthPrintState], a ldh a, [hffa9] ld l, a ; l ← [hffa9]; index to to linked-list head .asm_237d ld h, $c6 ; ld a, [hl] ; a ← key1[l] ; or a ; ret z ; if NULL, return a = 0 ; cp e ; loop for e/d key in jr nz, .asm_238a ; ; linked list inc h ; $c7 ; ; ld a, [hl] ; if key1[l] == e and ; cp d ; key2[l] == d: ; jr z, .asm_238f ; break ; .asm_238a ld h, $c8 ; ; ld l, [hl] ; l ← next[l] ; jr .asm_237d .asm_238f ldh a, [hffa9] cp l jr z, .asm_23af ; assert at least one iteration ld c, a ld b, $c9 ld a, l ld [bc], a ; prev[i0] ← i ldh [hffa9], a ; [hffa9] ← i (update linked-list head) ld h, $c9 ld b, [hl] ld [hl], $0 ; prev[i] ← 0 ld h, $c8 ld a, c ld c, [hl] ld [hl], a ; next[i] ← i0 ld l, b ld [hl], c ; next[prev[i]] ← next[i] ld h, $c9 inc c dec c jr z, .asm_23af ; if next[i] != NULL: ld l, c ; l ← next[i] ld [hl], b ; prev[next[i]] ← prev[i] .asm_23af scf ; set carry to indicate success ret ; (return new linked-list head in a) ; uppercases e if [wUppercaseHalfWidthLetters] is nonzero CaseHalfWidthLetter: ld a, [wUppercaseHalfWidthLetters] or a ret z ld a, e cp $60 ret c cp $7b ret nc sub "a" - "A" ld e, a ret ; iterates over text at hl until TX_END is found, and sets wFontWidth to ; FULL_WIDTH if the first character is TX_HALFWIDTH ; returns: ; b = length of text in tiles ; c = length of text in bytes ; a = -b GetTextLengthInTiles: ld a, [hl] cp TX_HALFWIDTH jr nz, .full_width call GetTextLengthInHalfTiles ; return a = - ceil(b/2) inc b srl b xor a sub b ret .full_width xor a ; FULL_WIDTH ld [wFontWidth], a ; fallthrough ; iterates over text at hl until TX_END is found ; returns: ; b = length of text in half-tiles ; c = length of text in bytes ; a = -b GetTextLengthInHalfTiles: push hl push de lb bc, $00, $00 .char_loop ld a, [hli] or a ; TX_END jr z, .tx_end inc c ; any char except TX_END: c ++ ; TX_FULLWIDTH, TX_SYMBOL, or > TX_CTRL_END : b ++ cp TX_CTRL_START jr c, .character_pair cp TX_CTRL_END jr nc, .character_pair cp TX_SYMBOL jr nz, .char_loop inc b jr .next .character_pair ld e, a ; first char ld d, [hl] ; second char inc b call ClassifyTextCharacterPair jr nc, .char_loop ; TX_FULLWIDTH .next inc c ; TX_FULLWIDTH or TX_SYMBOL: c ++ inc hl jr .char_loop .tx_end ; return a = -b xor a sub b pop de pop hl ret ; copy text of maximum length a (in tiles) from hl to de, then terminate ; the text with TX_END if it doesn't contain it already. ; fill any remaining bytes with spaces plus TX_END to match the length specified in a. ; return the text's actual length in characters (i.e. before the first TX_END) in e. CopyTextData: ld [wTextMaxLength], a ld a, [hl] cp TX_HALFWIDTH jr z, .half_width_text ld a, [wTextMaxLength] call .copyTextData jr c, .fw_text_done push hl .fill_fw_loop ld a, FW_SPACE ld [hli], a dec d jr nz, .fill_fw_loop ld [hl], TX_END pop hl .fw_text_done ld a, e ret .half_width_text ld a, [wTextMaxLength] add a call .copyTextData jr c, .hw_text_done push hl .fill_hw_loop ld a, " " ld [hli], a dec d jr nz, .fill_hw_loop ld [hl], TX_END pop hl .hw_text_done ld a, e ret .copyTextData push bc ld c, l ld b, h ld l, e ld h, d ld d, a ld e, 0 .loop ld a, [bc] or a ; TX_END jr z, .done inc bc ld [hli], a cp TX_CTRL_START jr c, .character_pair cp TX_CTRL_END jr c, .loop .character_pair push de ld e, a ; first char ld a, [bc] ld d, a ; second char call ClassifyTextCharacterPair jr nc, .not_tx_fullwidth ld a, [bc] inc bc ld [hli], a .not_tx_fullwidth pop de inc e ; return in e the amount of characters actually copied dec d ; return in d the difference between the maximum length and e jr nz, .loop ld [hl], TX_END pop bc scf ; return carry if the text did not already end with TX_END ret .done pop bc or a ret ; convert the number at hl to TX_SYMBOL text format and write it to wStringBuffer ; replace leading zeros with SYM_SPACE TwoByteNumberToTxSymbol_TrimLeadingZeros: push de push bc ld de, wStringBuffer push de ld bc, -10000 call .get_digit ld bc, -1000 call .get_digit ld bc, -100 call .get_digit ld bc, -10 call .get_digit ld bc, -1 call .get_digit xor a ; TX_END ld [de], a pop hl ld e, 5 .digit_loop inc hl ld a, [hl] cp SYM_0 jr nz, .done ; jump if not zero ld [hl], SYM_SPACE ; trim leading zero inc hl dec e jr nz, .digit_loop dec hl ld [hl], SYM_0 .done dec hl pop bc pop de ret .get_digit ld a, TX_SYMBOL ld [de], a inc de ld a, SYM_0 - 1 .subtract_loop inc a add hl, bc jr c, .subtract_loop ld [de], a inc de ld a, l sub c ld l, a ld a, h sbc b ld h, a ret ; generates a text tile and copies it to VRAM ; if wFontWidth == FULL_WIDTH ; de = full-width font tile number ; if wFontWidth == HALF_WIDTH ; d = half-width character 1 (left) ; e = half-width character 2 (right) ; b = destination VRAM tile number GenerateTextTile: push hl push de push bc ld a, [wFontWidth] or a jr nz, .half_width ;.full_width call CreateFullWidthFontTile_ConvertToTileDataAddress call SafeCopyDataDEtoHL .done pop bc pop de pop hl ret .half_width call CreateHalfWidthFontTile call ConvertTileNumberToTileDataAddress call SafeCopyDataDEtoHL jr .done ; create, at wTextTileBuffer, a half-width font tile ; made from the ascii characters given in d and e CreateHalfWidthFontTile: push bc ldh a, [hBankROM] push af ld a, BANK(HalfWidthFont) call BankswitchROM ; write the right half of the tile (first character) to wTextTileBuffer + 2n push de ld a, e ld de, wTextTileBuffer call CopyHalfWidthCharacterToDE pop de ; write the left half of the tile (second character) to wTextTileBuffer + 2n+1 ld a, d ld de, wTextTileBuffer + 1 call CopyHalfWidthCharacterToDE ; construct the 2bpp-converted half-width font tile ld hl, wTextTileBuffer ld b, TILE_SIZE_1BPP .loop ld a, [hli] swap a or [hl] dec hl ld [hli], a ld [hli], a dec b jr nz, .loop call BankpopROM pop bc ld de, wTextTileBuffer ret ; copies a 1bpp tile corresponding to a half-width font character to de. ; the ascii value of the character to copy is provided in a. ; assumes BANK(HalfWidthFont) is already loaded. CopyHalfWidthCharacterToDE: sub $20 ; HalfWidthFont begins at ascii $20 ld l, a ld h, $0 add hl, hl add hl, hl add hl, hl ld bc, HalfWidthFont add hl, bc ld b, TILE_SIZE_1BPP .loop ld a, [hli] ld [de], a inc de inc de dec b jr nz, .loop ret ; create, at wTextTileBuffer, a full-width font tile given its tile ; number within the full-width font graphics (FullWidthFonts) in de. ; return its v*Tiles address in hl, and return c = TILE_SIZE. CreateFullWidthFontTile_ConvertToTileDataAddress: push bc call GetFullWidthFontTileOffset call CreateFullWidthFontTile pop bc ; fallthrough ; given a tile number in b, return its v*Tiles address in hl, and return c = TILE_SIZE ; wTilePatternSelector and wTilePatternSelectorCorrection are used to select the source: ; - if wTilePatternSelector == $80 and wTilePatternSelectorCorrection == $00 -> $8000-$8FFF ; - if wTilePatternSelector == $88 and wTilePatternSelectorCorrection == $80 -> $8800-$97FF ConvertTileNumberToTileDataAddress: ld hl, wTilePatternSelectorCorrection ld a, b xor [hl] ld h, $0 ld l, a add hl, hl add hl, hl add hl, hl add hl, hl ld a, [wTilePatternSelector] ld b, a ld c, $0 add hl, bc ld c, TILE_SIZE ret ; create, at wTextTileBuffer, a full-width font tile given its ; within the full-width font graphics (FullWidthFonts) in hl CreateFullWidthFontTile: ld a, BANK(Fonts) ; BANK(DuelGraphics) call BankpushROM ld de, wTextTileBuffer push de ld c, TILE_SIZE_1BPP .loop ld a, [hli] ld [de], a inc de ld [de], a inc de dec c jr nz, .loop pop de call BankpopROM ret ; given two text characters at de, use the char at e (first one) ; to determine which type of text this pair of characters belongs to. ; return carry if TX_FULLWIDTH1 to TX_FULLWIDTH4. ClassifyTextCharacterPair: ld a, [wFontWidth] or a ; FULL_WIDTH jr nz, .half_width ld a, e cp TX_CTRL_END jr c, .continue_check cp $60 jr nc, .not_katakana ldh a, [hJapaneseSyllabary] cp TX_KATAKANA jr nz, .not_katakana ld d, TX_KATAKANA or a ret .half_width ; in half width mode, the first character goes in e, so leave them like that or a ret .continue_check cp TX_CTRL_START jr c, .ath_font .not_katakana ; 0_1_hiragana.1bpp (e < $60) or 0_2_digits_kanji1.1bpp (e >= $60) ld d, $0 or a ret .ath_font ; TX_FULLWIDTH1 to TX_FULLWIDTH4 ; swap d and e to put the TX_FULLWIDTH* character first ld e, d ld d, a scf ret ; convert the full-width font tile number at de to the ; equivalent offset within the full-width font tile graphics. ; if d == TX_KATAKANA: get tile from the 0_0_katakana.1bpp font. ; if d == TX_HIRAGANA or d == $0: get tile from the 0_1_hiragana.1bpp or 0_2_digits_kanji1.1bpp font. ; if d >= TX_FULLWIDTH1 and d <= TX_FULLWIDTH4: get tile from one of the other full-width fonts. GetFullWidthFontTileOffset: ld bc, $50 tiles_1bpp ld a, d cp TX_HIRAGANA jr z, .hiragana cp TX_KATAKANA jr nz, .get_address ld bc, $0 tiles ld a, e sub $10 ; the first $10 are control characters, but this font's graphics start at $0 ld e, a .hiragana ld d, $0 .get_address ld l, e ld h, d add hl, hl add hl, hl add hl, hl add hl, bc ret ; pointers to VRAM? ; unreferenced Unknown_2589: db $18 dw $8140 dw $817e dw $8180 dw $81ac dw $81b8 dw $81bf dw $81c8 dw $81ce dw $81da dw $81e8 dw $81f0 dw $81f7 dw $81fc dw $81fc dw $824f dw $8258 dw $8260 dw $8279 dw $8281 dw $829a dw $829f dw $82f1 dw $8340 dw $837e dw $8380 dw $8396 dw $839f dw $83b6 dw $83bf dw $83d6 dw $8440 dw $8460 dw $8470 dw $847e dw $8480 dw $8491 dw $849f dw $84be dw $889f dw $88fc dw $8940 dw $9443 dw $9840 dw $9872 dw $989f dw $98fc dw $9940 dw $ffff