Jump to content
IGNORED

Assembly Trick : Bit-delimited Strings


adamantyr

Recommended Posts

I was looking over an old game in a hex editor recently, and I noticed something interesting with the text data embedded in the program. All of the strings seemed fine until the end character, which was a byte value of 128 or greater.

 

I realized what the program was doing was using the top bit on ASCII characters to determine the string end. This lets you store strings at their exact size, rather than one byte more to store either a length byte or a null terminator byte. Very clever!

 

So I thought, how to leverage this on the TI, where I've spent a considerable amount of effort building menus and interfaces that consumed a lot of memory because of having to store strings and their addresses and lengths?

 

So I write a routine, VTEXT, and it's companion, VTEXTC. It's a subroutine that takes the address on screen into R0, and a pointer to the desired text in R1. No length needed! It writes to the screen until it encounters the eighth bit, and stops.

 

VTEXTC is the same, except it doesn't alter the VDP address. This will allow you to write concurrent strings to the screen one after the other.

 

Advantages are:

- Your text strings take up exactly their length in space

- Reduced operations for plotting text to screen

 

Disadvantages are:

- All static text in source files has to end with the top bit set, which can be aggravating to figure out the value of a given ASCII character

- Slower than a straight VMBW due to the need for a COC and copy operation on every character

- If you don't have the top bit set, it could overrun the screen buffer and the rest of VDP

 

Future expansion may include the idea of "values". Using characters 0-31 can be used as an indicator to, for example, switch to a stored numeric value in text form, so you can introduce string formatting. "%0 takes %1 damage!" for example, so it knows to plug in the 0 and 1 pre-calculated values into the string as it's writing to the screen.

TOPBIT DATA >8000                      * Top bit word
VDPWA  EQU  >8C02                      * VDP Write address port
VDPRD  EQU  >8800                      * VDP Read address port
VDPWD  EQU  >8C00                      * VDP access port (input/output)
SCRADR EQU  >0000                      * Screen address
TXTLN1 TEXT 'This is sample tex'
       BYTE 244
       TEXT 'More sample tex'
       BYTE 244
       TEXT 'Sample Tex'
       BYTE 244
       TEXT '-Sample Tex'
       BYTE 244
       
* Video Text writer, CPU to VDP
* Uses only R0 and R1 for location, length is determined by the top bit
* Sends R1 value back to calling rouine for continuous stream of text
* VTEXTC does not update position in VDP, so you can write multiple strings concurrently
VTEXT  ORI  R0,>4000                   * Set address for VDP write
       SWPB R0                         * Swap to low byte
       MOVB R0,@VDPWA                  * Move to VDP address
       SWPB R0                         * Swap
       MOVB R0,@VDPWA                  * Move to VDP address
       ANDI R0,>3FFF                   * remove extra bit so address is preserved for subsequent calls
VTEXTC MOVB *R1+,R2                    * Copy character to R2
       COC  @TOPBIT,R2                 * Check if top bit is set (end of line indicator)
       JEQ  VTEXT1                     * If so, skip to end
       MOVB R2,@VDPWD                  * Write character to screen
       JMP  VTEXTC                     * Loop
VTEXT1 ANDI R2,>7F00                   * Reset top bit on character
       MOVB R2,@VDPWD                  * Write to screen
       RT                              * return to calling program


* Example
       LI   R0,SCRADR+128              * Set R0 to SCRADR+128
       LI   R1,TXTLN1                  * Set R1 to start of text
       BL   @VTEXT                     * Write string to screen
       AI   R0,32                      * Add 32 to screen position
       BL   @VTEXT                     * Write a second line of the text
       LI   R0,SCRADR+256              * Change R0 to a different position
       BL   @VTEXT                     * Write next line to screen
       BL   @VTEXTC                    * Write the next text segment immediately after the prior
* Program continues...

Link to comment
Share on other sites

Nice! This is how many Apple2 programs handled their text strings (maybe the ROMs, I don't recall).

 

You can optimize your test a little bit:

 

 

COC  @TOPBIT,R2                 * Check if top bit is set (end of line indicator)
JEQ  VTEXT1                     * If so, skip to end

 

Can be replaced with "JLT VTEXT1"... since a byte with the MSB set is a negative value, and the MOVB will set the flags. Saves you the COC, which is one of the more expensive parts of that loop.

Link to comment
Share on other sites

Nice! This is how many Apple2 programs handled their text strings (maybe the ROMs, I don't recall).

 

You can optimize your test a little bit:

COC  @TOPBIT,R2                 * Check if top bit is set (end of line indicator)
JEQ  VTEXT1                     * If so, skip to end

Can be replaced with "JLT VTEXT1"... since a byte with the MSB set is a negative value, and the MOVB will set the flags. Saves you the COC, which is one of the more expensive parts of that loop.

 

Very nice optimization, that does save some bytes and a costly memory to register comparison!

Link to comment
Share on other sites

I think a big part of why I like this particular technique is that using a whole byte as a null terminator for text is SUCH a waste.

 

I'd written a lot of my CRPG interface code using the standard VMBW technique with three registers, but now I look at that and just think "That's FOUR BYTES i'm wasting every time I write a single line of text." Yes, I'm using AMS but I'm still trying to keep my modules to a fixed size. My Start module now has less than a kilobyte of space, and I still have to write up the opening introduction code. So optimization techniques like this are still useful.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...