Bucket Mouse
Active member
Joe said something about "eventually" making it possible to string together text boxes. As it is text boxes are limited to 256 characters, which makes 11 to 12 lines of text per box -- enough in most cases, but sometimes you need more.
I didn't think I'd be tinkering with this so soon, but it turns out a scene fairly early on in my game needs a lot more text. So I'm attempting to patch together an Extended Text Mode on my own.
At first I thought I'd need to write a separate sequence for it, but I think it should be possible to get what I want by slightly modifying the value of one variable in DrawNPCText.asm. In order to figure that out, I had to understand exactly what's going on in DrawNPCText itself. I've studied it hard, but there's something crucial I can't seem to find. Here's the whole thing dissected:
If the conditions are right, draw a text box. Unless there's already a text box onscreen, in which case skip the next part of the code.
A box is drawn to the specifications set in NESMaker. Then a little math is calculated to set the dimensions of the text itself as slightly smaller.
"HideSprites" appears to be dummied out with a semicolon, yet it works. I don't understand that part.
This next part must be important for a border to be marked around it. The text is loaded into A while something called "stringTemp" is loaded into Y, then they're combined. The text is drawn at the dimensions calculated by DrawBox, then the game reads the controller again (I think....I'm not quite sure what "gameHandler" does exactly).
A routine runs that prevents you from skipping the text or closing the box prematurely. If you wanted skippable text, here's where you'd modify it.
The program reads the gamepad inputs. If the binary for the B button is coming through, the program branches to "Turn Off Text Box."
Otherwise it jumps to "dontTurnOffTextBox" -- a routine that simply leads to an RTS.
"turnOffTextBox" is a misleading name because it doesn't exactly turn off the box. Instead it loads a value called "stringEnd" and determines if it matches the correct value. If it doesn't yet, the program moves on to the next part, which "erases" the onscreen text by drawing a new box over it. There's some dummied-out code here; not sure what it's for. Pre-release, a video came out on Facebook that showed colored text screens, but that feature had to be drawn in like everything else and the box took far longer...so it was cut. It doesn't look like this dummied code is what that does, though.
This is mostly the same as before except "DrawText" is now "ContinueText." The code then RTSes itself away, where I assume, it continues to loop back here until stringEnd equals...I have no idea what it's supposed to equal because nothing tells me. More on this in a bit.
dontLoadANewTextString launches HideBox, the routine that undraws the text box and restores all that was there before.
From everything I've gathered here, Extended Text Mode should be rather simple. The variable that appears to control the time at which the game stops loading text is STRINGEND.....but I can't find anyplace in the code where the value of it is defined. You'd think it would be here somewhere, but it isn't. Extended Text Mode would temporarily load a new value into STRINGEND that would push things past the current text entry into the next one on the list. The number you establish on that particular screen determines the amount of text you can get in one window.
I feel like I'm really close. Where is STRINGEND?
I didn't think I'd be tinkering with this so soon, but it turns out a scene fairly early on in my game needs a lot more text. So I'm attempting to patch together an Extended Text Mode on my own.
At first I thought I'd need to write a separate sequence for it, but I think it should be possible to get what I want by slightly modifying the value of one variable in DrawNPCText.asm. In order to figure that out, I had to understand exactly what's going on in DrawNPCText itself. I've studied it hard, but there's something crucial I can't seem to find. Here's the whole thing dissected:
Code:
DrawTextBox:
LDA gameHandler
AND #%00100000
BEQ dodrawTextBox
JMP dontDrawTextBox
Code:
dodrawTextBox:
; HideSprites
;;; this means that npc text is off right now
;;; so create the box and disable object updates.
DrawBox #BOX_1_ORIGIN_X,#BOX_1_ORIGIN_Y,#BOX_1_WIDTH, #BOX_1_HEIGHT, #BOX_1_ATT_WIDTH, #BOX_1_ATT_HEIGHT, #$00, #$00, #$00
LDA #BOX_1_ORIGIN_X
ASL
CLC
ADC #$01
STA temp
LDA #BOX_1_ORIGIN_Y
ASL
CLC
ADC #$01
STA temp1
"HideSprites" appears to be dummied out with a semicolon, yet it works. I don't understand that part.
Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LDY stringTemp
LDA screenText,y
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
STA stringGroupOffset
DrawText temp, temp1
LDA gameHandler
ORA #%00100000
STA gameHandler
Code:
dontDrawTextBox:
LDA writingText
BEQ canPressBeBecauseNotWritingText
JMP dontTurnOffTextBox ;; can't press b to advance or close because still writing text
canPressBeBecauseNotWritingText:
LDA gamepad
AND #%00000010 ;; is b button pressed when there is a textbox on the screen?
BNE turnOffTextBox
JMP dontTurnOffTextBox
The program reads the gamepad inputs. If the binary for the B button is coming through, the program branches to "Turn Off Text Box."
Otherwise it jumps to "dontTurnOffTextBox" -- a routine that simply leads to an RTS.
Code:
turnOffTextBox:
LDA stringEnd
BEQ dontLoadANewTextString
DrawBox #BOX_1_ORIGIN_X,#BOX_1_ORIGIN_Y,#BOX_1_WIDTH, #BOX_1_HEIGHT, #BOX_1_ATT_WIDTH, #BOX_1_ATT_HEIGHT, #$00, #$01, #$00
;LDA stringGroupPointer
;ASL
;ASL
;CLC
;ADC stringTemp
;STA stringGroupOffset
LDY stringTemp
LDA screenText,y
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
STA stringGroupOffset
LDA #BOX_1_ORIGIN_X
ASL
CLC
ADC #$01
STA temp
LDA #BOX_1_ORIGIN_Y
ASL
CLC
ADC #$01
STA temp1
ContinueText temp, temp1
RTS
This is mostly the same as before except "DrawText" is now "ContinueText." The code then RTSes itself away, where I assume, it continues to loop back here until stringEnd equals...I have no idea what it's supposed to equal because nothing tells me. More on this in a bit.
Code:
dontLoadANewTextString:
HideBox #BOX_1_ORIGIN_X,#BOX_1_ORIGIN_Y,#BOX_1_WIDTH, #BOX_1_HEIGHT, #BOX_1_ATT_WIDTH, #BOX_1_ATT_HEIGHT
LDA gameHandler
AND #%11011111
STA gameHandler
ShowSprites
LDA #$00
STA textBoxFlag
STA updateHUD_offset
dontTurnOffTextBox:
rts
From everything I've gathered here, Extended Text Mode should be rather simple. The variable that appears to control the time at which the game stops loading text is STRINGEND.....but I can't find anyplace in the code where the value of it is defined. You'd think it would be here somewhere, but it isn't. Extended Text Mode would temporarily load a new value into STRINGEND that would push things past the current text entry into the next one on the list. The number you establish on that particular screen determines the amount of text you can get in one window.
I feel like I'm really close. Where is STRINGEND?