My question is simple, although the answer may not be Smile

I want to know how to grab a single character out of a string of text that was declared in the following fashion:


Code:
txtSomeText:
    .db "Yo I'm some text!",0


My objective is to create a program that shows text progressively, letter by letter, as opposed to spewing it all out in an instant. Now, I realize I could just write the same code over and over and make a separate routine for EACH LETTER OF THE STRING, but that's insane and ridiculously tedious and messy. I think I can make a routine to do it slightly more autonomously if I can grab individual letters at specific locations in the string. Is this possible?

...also, on a side note if anyone knows, is there a version of the NewLine command that works with the smaller text? (vPutS)
I think that in Grammer there is a function that puts text out like a typewriter, but I haven't tested it myself.
If it wouldn't be a problem, I'd like the whole program to be native, as in I'm not using any libraries or anything like that.
Maybe have a routine to convert your ASCII chars to hex, then find some way to output each byte.
______EDIT________
something like this:
<convert to hex>
<break into bytes>
ld hl, <wherever you put the first byte>
BCall _PutS
<All the other bytes>

And possibly shorten it by using a djnz loop and starting w/ last byte, and hold index in b.
I will be rusty and don't know proper TIOS B_CALL names, but here it goes
Code:
main:
  ld hl,dbText
  ld b,dbText_end - dbText
main_loop1:
  ld a,(hl)
  inc hl
  B_CALL PutC
; Some delay
  djnz main_loop1
  ret
dbText:
  .text "Hello World"
dbText_end:
This looks to be what you need: http://wikiti.brandonw.net/index.php?title=83Plus:BCALLs:4504
Ghest, that's not really it, unfortunately.

Quargzon wrote:
If it wouldn't be a problem, I'd like the whole program to be native, as in I'm not using any libraries or anything like that.
An excellent question. In pseudocode, you'd want to do something like this:

Code:
   ld hl,txtSomeTest
DispLoop:
   ld a,(hl)
   or a
   jr z,DispLoopDone
   ;display character - PutC or VPutMap
   ;update coordinates if needed
   ;waste time / delay / pause if needed
   inc hl
   jr DispLoop
DispLoopDone:
   ...rest of program...
Oh.. >.< I meant putC, but the rest I had no idea. I thought there was some conversion required to get hex data. I'm sort of a noob at low-level languages.
ghest1138 wrote:
Oh.. >.< I meant putC, but the rest I had no idea. I thought there was some conversion required to get hex data. I'm sort of a noob at low-level languages.
Then keep your eyes open, and take a look at the code that the knowledgeable people post, and you'll get there. Smile
KermMartian wrote:
Ghest, that's not really it, unfortunately.

Quargzon wrote:
If it wouldn't be a problem, I'd like the whole program to be native, as in I'm not using any libraries or anything like that.
An excellent question. In pseudocode, you'd want to do something like this:

Code:
   ld hl,txtSomeTest
DispLoop:
   ld a,(hl)
   or a
   jr z,DispLoopDone
   ;display character - PutC or VPutMap
   ;update coordinates if needed
   ;waste time / delay / pause if needed
   inc hl
   jr DispLoop
DispLoopDone:
   ...rest of program...


Thanks for the detailed response, Kerm! So, does incrementing hl cause it to shift all its characters left or something?
Here, you're using hl as a point (do you write C?). When you're incrementing hl, you're moving the pointer down the string, one character at a time. When the pointer gets to the zero at the end of the string ('or a' is equivalent to 'cp 0'), it knows it should stop.
KermMartian wrote:
Here, you're using hl as a point (do you write C?). When you're incrementing hl, you're moving the pointer down the string, one character at a time. When the pointer gets to the zero at the end of the string ('or a' is equivalent to 'cp 0'), it knows it should stop.


AHA! That actually makes a lot more sense now. I didn't realize loading a string to hl filled hl with a pointer. I was wondering how it was fitting a whole string into 16 bits. Smile

Also, what can be done to create a delay/waste time? I expected the following to work but it seems to have no effect:


Code:
Delay:
    djnz Delay
    ret


I've set b to ridiculous values such as 10,000, but there is no perceivable delay... Do I need to put an actual command inside the loop to slow it down?

Edit: It just hit me that 10,000 will not fit into an 8-bit value *slaps forehead*

But still, how is this done?
Since it's an 8-bit register, b can only hold values between 0 and 255. Setting it to 10,000 is actually setting it to 10000%256 = 16. Try using a 16-bit register like bc:
Code:
ld bc,10000
DelayLoop:
   dec bc
   ld a,b
   or c
   jr nz,DelayLoop


By the way, care to Introduce Yourself when you get a chance?
KermMartian wrote:
Since it's an 8-bit register, b can only hold values between 0 and 255. Setting it to 10,000 is actually setting it to 10000%256 = 16. Try using a 16-bit register like bc:
Code:
ld bc,10000
DelayLoop:
   dec bc
   ld a,b
   or c
   jr nz,DelayLoop


By the way, care to Introduce Yourself when you get a chance?


Yes, I'm aware that values wrap around when they exceed their data type's max. BTW, what does that 'or' do in the loop? (I know what the OR command does Razz I just want to know what purpose it serves in the loop.)
Aye, you made your edit at the same time that I made my post. Smile Well, there's no 'cp' (compare) opcode for 16-bit registers, so I fudged it with an 8-bit compare. The bc register can only be zero when b=0 and c=0, and b|c (bitwise or) can only be zero if b=0 and c=0. Therefore, b|c==0 is equivalent to checking if bc=0.
KermMartian wrote:
Aye, you made your edit at the same time that I made my post. Smile Well, there's no 'cp' (compare) opcode for 16-bit registers, so I fudged it with an 8-bit compare. The bc register can only be zero when b=0 and c=0, and b|c (bitwise or) can only be zero if b=0 and c=0. Therefore, b|c==0 is equivalent to checking if bc=0.


OK, thanks! That looks like it will work! For the record, another option would be to nest two loops for 0 to 255 inside one another. That would be 255*255 iterations, which should be enough.
Quargzon wrote:
KermMartian wrote:
Aye, you made your edit at the same time that I made my post. Smile Well, there's no 'cp' (compare) opcode for 16-bit registers, so I fudged it with an 8-bit compare. The bc register can only be zero when b=0 and c=0, and b|c (bitwise or) can only be zero if b=0 and c=0. Therefore, b|c==0 is equivalent to checking if bc=0.


OK, thanks! That looks like it will work! For the record, another option would be to nest two loops for 0 to 255 inside one another. That would be 255*255 iterations, which should be enough.
Absolutely, but that would be functionally equivalent to a single loop with a 16-bit loop counter register. The method you propose would work well if you needed to do something every n cycles.
KermMartian wrote:
Quargzon wrote:
KermMartian wrote:
Aye, you made your edit at the same time that I made my post. Smile Well, there's no 'cp' (compare) opcode for 16-bit registers, so I fudged it with an 8-bit compare. The bc register can only be zero when b=0 and c=0, and b|c (bitwise or) can only be zero if b=0 and c=0. Therefore, b|c==0 is equivalent to checking if bc=0.


OK, thanks! That looks like it will work! For the record, another option would be to nest two loops for 0 to 255 inside one another. That would be 255*255 iterations, which should be enough.
Absolutely, but that would be functionally equivalent to a single loop with a 16-bit loop counter register. The method you propose would work well if you needed to do something every n cycles.


Hmm... It seems even the nested loop (65536 iterations) isn't enough to make the characters showing up one by one noticeable. Do I need to stick some pointless calculation inside the loop to make it slow enough? And, if so, what would that be? Or does the TI-84+ have an internal clock that I can reference?

EDIT: I take that back. My nested-delay-loop-thing-code was flawed in that at the end of the outer loop, it jumped to the inner loop instead of jumping back to the beginning of the outer loop. So it was effectively doing only 257 loops (256 from normal loop, plus the first loop from the outer loop). It works now, so thanks! Very Happy
Great, glad to hear it! If this is for a project you're working on, rather than random experimentation, you should think about a Your Projects subforum topic. Smile
FWIW, you could more efficiently delay using 'halt' (provided you haven't disabled interrupts). The timer interrupt fires somewhere around 120 Hz (IIRC), so if there's nothing else going on executing 'halt' will pause for about 8 milliseconds. Thus you can have a perceptible delay with only an 8-bit register:
Code:
    ld b,24
delay_200ms:
    halt
    djnz delay

Continuous link activity or the user mashing the ON key would muck up your timing a bit, but those are both edge cases that probably aren't worth worrying about.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 2
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement