[Solved] Making "HandleTextBox.asm" work for both in game and cutscene text

tornotlukin

Member
Trying to get two types of textboxes, one for cutscenes and one for in game use. So, I thought I could duplicate the HandleTextBox.asm file, rename it, and go in and change some of the identifiers (is that what they are called?) so that they are different than the originals. On the surface it looks successful, nothing blew up, but it is not working. I would be using an AutoText tile to make text appear, it has this:

Code:
;; activate the text-box:
	LDA gameHandler
	ORA #%00100000
	STA gameHandler
	LDA #%10000000
	STA textboxHandler

I wanted to take advantage of the "HideSprites" and the "Warp" that are commented out in the original HandleTextBox but still keep the original functionality for the rest of the game. Here are the changes I made:

  1. Copied the original HandleTextBox.asm, renamed HandleTextBoxCutscene.asm
  2. Went into NESMaker, added the new ASM to PROJECT SETTINGS > SCRIPT SETTINGS. named the Define "SCR_HANDLE_TEXTBOX_CUTSCENE"
  3. Inside HandleTextBoxCutscene.asm I renamed all instances of "HandleTextBox:" to "HandleTextBoxCutscene:"
  4. Inside HandleTextBoxCutscene.asm I renamed all instances of "textboxHandler" to "textboxHandlerB"
  5. Inside the AutoText tile script I renamed "STA textboxHandler" to "STA textboxHandlerB"

I assume that by doing step 5, it would be looking at the new HandleTextBoxCutscene.asm file. It doesn't seem to work and I get this error message at compile:

"Routines\Basic_NoScroll\ModuleScripts\TileScripts\Adventure\AutoTextTileB.asm(25): Unknown label."
(Line 25 is the "STA textboxHandlerB")

My questions are:

Is this worth pursuing?
Or, is this approach fundamentally flawed and I should try something else?

My programming ability is basic (especially ASM6) so I am not catching the nuances of how things work, but I will scalpel at the code till something happens.
 

dale_coop

Moderator
Staff member
Why not keep using the original text box and just adding some custom lines of code with a test on variable (for example cutsceneTextBox) if not 0 then hide/show sprite and warp else skip that parts..?
 

Mugi

Member
STA is an opcode that stores whatever you have in accumulator into a variable called textboxHandler in this case.
if you rename this variable it will not work because the new variable does not exist. now you can go and make that new variable in user variables and then this script will work, but
you will also have to modfiy whatever it is that uses the value of "textboxhandler" to use "textboxhandlerB" instead.

the texts in the code that end with a : are called labels, and they are used as addresses of sorts when you branch code. the texts that appear in opcodes like STA or LDX or so are variables.
variable is just a defined address that holds a value and is given a name. you can then load the value from that variable by calling it by its' name.
 

tornotlukin

Member
dale_coop said:
Why not keep using the original text box and just adding some custom lines of code with a test on variable (for example cutsceneTextBox) if not 0 then hide/show sprite and warp else skip that parts..?
This is probably the best solution, I do not know how the syntax works exactly. I am going to follow what I see and put something together.


Mugi said:
STA is an opcode that stores whatever you have in accumulator into a variable called textboxHandler in this case...

Thank you for the clarification!
 

tornotlukin

Member
Code:
LDA tileCollisionFlag
	BEQ +
	JMP finishedWithAutoTextB
	+ 
	LDA #$01
	STA tileCollisionFlag

Is this an example of an If... Else ? I read BEQ as "branch on equal" and the "+" as the code to do if that is true. How do I get a value into a variable?

Code:
LDA #$01
STA tileCollisionFlag

Is this how you get a value into the variable?
 

Mugi

Member
yeah, this stores the value of A into "tileCollisionFlag"
and you just loaded 01 into A before storing it, so tileCollisionFlag is now 01

the above code is basically...

load tileCollisionFlag into A
if A = 0, goto +
jump to label finishedwithautotext
+
load 01 into A
store A into tilecollisionflag


im not sure that works actually, because there's no value to compare with A, but then again, my assembly skills are terrible, so maybe it does.

the issue i see here is that you load tilecollision flag to A and then you try to branch if equal but you have no value to compare against if it's equal or not.
 

tornotlukin

Member
Mugi said:
im not sure that works actually, because there's no value to compare with A, but then again, my assembly skills are terrible, so maybe it does.

the issue i see here is that you load tilecollision flag to A and then you try to branch if equal but you have no value to compare against if it's equal or not.

This was just a snippet I copied just to understand the syntax. What you wrote makes it clearer for me:

first you put a number into accumulator, then you take that number and put it into a variable.

So I have two things at play, based on Dale_Coop's suggestion to test on a variable. The tile autoText code and the textboxHandler code.

Do I create the variable and if/else in the textBoxHandler.asm file and set a value for it in the tile autoText code? Or, do I create the variable and give it a value in the tile autoText and then do the if/else in textBoxHandler.asm?
 

dale_coop

Moderator
Staff member
For a good practice, you should create the variable in the "Project settings > user variables" and make a duplicate of "HandleTextBox.asm" as "HandleTextBox_withCutscene.asm" (or anything) and assign that script to the "Handle Text Box" element in your "Project Settings > Script settings".
 

tornotlukin

Member
dale_coop said:
For a good practice, you should create the variable in the "Project settings > user variables" and make a duplicate of "HandleTextBox.asm" as "HandleTextBox_withCutscene.asm" (or anything) and assign that script to the "Handle Text Box" element in your "Project Settings > Script settings".

Oh good, this makes it easier. Thank you.
 

tornotlukin

Member
Snippet from "AutoTextTileB.asm"
Code:
; this makes it so the HandleTextBoxCutsceneCheck.asm knows that it is a cutscene. cutsceneCheck == 1
LDA #$01
STA cutsceneCheck

Snippet from "HandleTextBoxCutsceneCheck.asm"
Code:
; check to see that we are in a cutscene. cutsceneCheck == 1. Hide sprites for cutscene.
LDA cutsceneCheck
BNE +
JMP letsContinue
+
HideSprites
	
letsContinue:

Code:
; check to see that we are in a cutscene. cutsceneCheck == 1. Show the sprites and warp to next scene
	LDA cutsceneCheck
	BNE +
	JMP dontReturnToGame
	+
	ShowSprites

	LDA #$00
	STA cutsceneCheck

	 LDA warpMap
	 sta currentMap
 	clc
 	ADC #$01
	 STA temp
 	GoToScreen warpToScreen, temp, #$02
 	LDA #$00
 	STA playerToSpawn
 	LDX player1_object
 	DeactivateCurrentObject
 	LDA #$01
 	STA loadObjectFlag
 
	LDA mapPosX
	STA newX
	LDA mapPosY
	STA newY

This includes some code from Dale's new warp block (if I am incorrect please let me know)
Ok, so everything worked. I just want to type it out loud so I get what is going on here.

  • cutsceneCheck is the USER VARIABLE I made in the NESMaker Project Settings. It was set to 0 (#$00, right?)
  • In the autoTextTileB.asm I set the cutsceneCheck variable == 1, by putting a number into the accumulator then moving that number into the variable. (side question, does that number get cleared from accumulator after STA?)
  • It then goes through the HandleTextBoxCutsceneCheck.asm, BNE means that if it 'doesn't equal zero' then do stuff
  • Finally, before it shows the sprite and goes into warp, it sets the cutsceneCheck variable back to zero, to be used again

Does everything seem good form?
 

dale_coop

Moderator
Staff member
Yep everything looks good, congrats!

And for your question, after STA, the Accumulator keeps its value.
So it's possible to do, for example:
Code:
	LDA #$01
	STA temp1  ;; store the value of the accumulator (01) to temp1
	STA temp2  ;; store the value of the accumulator (01) to temp2
	ADC #$01   ;; add 01 to the value of the accumulator
	STA temp3  ;; store the value of the accumulator (02) to temp3
 

tornotlukin

Member
dale_coop said:
Yep everything looks good, congrats!

And for your question, after STA, the Accumulator keeps its value.
So it's possible to do, for example:
Code:
	LDA $01
	STA temp1  ;; store the value of the accumulator (01) to temp1
	STA temp2  ;; store the value of the accumulator (01) to temp2
	ADC #$01   ;; add 01 to the value of the accumulator
	STA temp3  ;; store the value of the accumulator (02) to temp3

Why is there a # symbol for ADC's value?
 

Kasumi

New member
ADC $01 adds the number stored in RAM Location $0001 to the accumulator.
ADC #$01 adds 1 to the accumulator.

So with a '#', it will add the given value. Without a '#', it will add the value stored at the given RAM location.

Edit: This is true for other instructions.
LDA $01 loads the number stored in RAM Location $0001 to the accumulator.
LDA #$01 loads the number 1 to the accumulator.

Edit2: Further, I guess I should say ADC adds the given value (either from the RAM location or the number) plus the carry.
So:
Code:
sec
lda #$00
adc #$00;This adds 1, not 0 because the carry was set.
;A = #$01
clc
lda #$00
adc #$00;This adds 0, because the carry is clear
This is why you clear the carry before additions, usually. If you don't already know the carry is clear, the addition could be one off from what you expect.
 

dale_coop

Moderator
Staff member
Yep sorry I missed a # in my LDA (ahhh typing on a smartphone). I updated my previous post.
But this demonstrates how easy typo mistakes can happen.
Writing $01 instead of #$01 and you load a completely different value from a memory address instead of the constant value 01.
(Or a #$00000100 instead of #%00000100, or a #10 instead of #$10 and your object is not at created the correct position >_<)
I found in NESMaker scripts some typos of that kind. And the compilation is ok because there is no error.
 

Bucket Mouse

Active member
Let me know if this works for you because I handled things a bit differently back on version 4.0.6.

I was the first to get a cutscene out there, thanks to a custom flag called "Cutscene Screen" that would turn the HUD off and disable user input with the exception of button A. The player sprite loaded directly onto the Autotext tile, which triggered the dialogue, and at the end of the text was a trigger to warp to the next screen, at which point the dialogue would continue.

Just about all my ideas have special screens that need this trick again to display correctly. But if yours works better....
 

tornotlukin

Member
Bucket Mouse said:
Let me know if this works for you because I handled things a bit differently back on version 4.0.6.

I was the first to get a cutscene out there, thanks to a custom flag called "Cutscene Screen" that would turn the HUD off and disable user input with the exception of button A. The player sprite loaded directly onto the Autotext tile, which triggered the dialogue, and at the end of the text was a trigger to warp to the next screen, at which point the dialogue would continue.

Just about all my ideas have special screens that need this trick again to display correctly. But if yours works better....

That is how I have been implementing it. Player1 on a autotext tile with warp functionality, but I use the hud for story text. The disabling user input except "button" would be useful though.
 

tornotlukin

Member
Th HandleTextBox.asm I am noticing some comments on MORE text. does this mean that this can check for the "more (>)" symbol in the text and shows the next text box?
 

dale_coop

Moderator
Staff member
Exactly, if you write a > at then end of a line of text, the rest will be on a next page.
Try that, it’s very useful!!!
 

tornotlukin

Member
dale_coop said:
Exactly, if you write a > at then end of a line of text, the rest will be on a next page.
Try that, it’s very useful!!!
It froze the text, that's why I was confused. Should more text appear after the button press? Does all the text have to live in one text box? Or does it take it from the other text boxes? What is the usage?
 

dale_coop

Moderator
Staff member
Yes all the texts need to be in the same « Text » element.
For example:
Code:
Some lines of text here
Appearing on page one>
This on page 2 and...>
This last words on the last page
All that in my « Text 1 », assigned to my « Text group1 » assigned to my screen.
 
Top Bottom