Shop OBEX P1 Docs P2 Docs Learn Events
TV_Text.Spin - User Defined Characters — Parallax Forums

TV_Text.Spin - User Defined Characters

hippyhippy Posts: 1,981
edited 2007-09-28 12:08 in Propeller 1
I'm trying to modify TV_Text.spin to display a user defined character but having little joy. The original character displaying' code is -

PRI print(c)
  screen[noparse][[/noparse]row * cols + col] := (color << 1 + c & 1) << 10 + $200 + c & $FE



Am I right, that to convert the character "X" to my single user defined character I need to use -

PRI print(c)
  if c == "X"
    screen[noparse][[/noparse]row * cols + col] := (color << 1 ) << 10 + ( @MyTileAddress >> 6 )
  else
    screen[noparse][[/noparse]row * cols + col] := (color << 1 + c & 1) << 10 + $200 + c & $FE



Also, how do I ensure that the tile definition I want to use is appropriately aligned in the DAT section ?

Comments

  • Ken PetersonKen Peterson Posts: 806
    edited 2007-09-26 16:07
    Hippy,

    If you are using the standard TV driver, you are probably aware of the need to align the data on a 16-long boundary. You can do the alignment at run time. One way to do this is to add a pad of 15 longs previous to your definition, create a pointer to your data and round it off (ptr & $FFC0), then move the data from the original location to the rounded location. Your copy will overlap the original, so make sure you copy starting at the lower address. You can also check to see if the rounded address == the original address to avoid copying unnecessarily if it's already aligned.

    BTW: Are you using 4-color mode?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    The more I know, the more I know I don't know.· Is this what they call Wisdom?

    Post Edited (Ken Peterson) : 9/26/2007 4:15:47 PM GMT
  • hippyhippy Posts: 1,981
    edited 2007-09-26 16:15
    @Ken : I'll give that a whirl. I take it I'm right that there's no "ALIGN LONG" type commands which allows alignment to be forced in the DAT area and haven't just missed it in the manual.

    As to 4 colour mode; I'm using as it comes, which allows a palette of 8 entries. In my own app I've modified it for 16 entries which seems to be working okay. I'm guessing there's some caveat I'm not aware of for four colour mode ?
  • Ken PetersonKen Peterson Posts: 806
    edited 2007-09-26 16:21
    You can align to a long, but the TV driver requires you to align your data to the nearest 16 longs. In other words, your pointer must be rounded off and the 6 LSB's are 0. SPIN does not have a function to do that, as it's a design decision that was made when the TV driver was written.

    Also, I noticed that you are leaving out the color calculations in your example. Since character definitions are "interlaced" in the ROM, the color palette determines which character of the pair is displayed. This is why the character is rounded off and the LSB of the character determines which color is used.

    Then again, if you are designing your own characters you probably wouldn't make them interlaced (interleaved?) like the ROM definitions. Then you can use all four colors per character using your code example (I think).

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    The more I know, the more I know I don't know.· Is this what they call Wisdom?

    Post Edited (Ken Peterson) : 9/26/2007 4:32:15 PM GMT
  • RaymanRayman Posts: 14,162
    edited 2007-09-26 16:29
    Do this:

    '64 byte align the user characters
    user_charbase := @uchar & $FFC0 'destination
    longmove(user_charbase,@uchar,16*nuchars)· 'nuchars=# of new characters

    padding LONG 7[noparse][[/noparse]16] 'alignment padding for the following user defined characters
    uchar
    LONG %%1100_1100_1100_1111 'new character 0
    LONG %%1100_1100_1100_1111
    LONG %%0011_0011_0011_0011
    LONG %%0011_0011_0011_0011
    LONG %%1100_1100_1100_1111
    LONG %%1100_1100_1100_1111
    LONG %%0011_0011_0011_0011
    LONG %%0011_0011_0011_0011
    LONG %%1100_1100_1100_1111
    LONG %%1100_1100_1100_1111
    LONG %%0011_0011_0011_0011
    LONG %%0011_0011_0011_0011
    LONG %%1100_1100_1100_1111
    LONG %%1100_1100_1100_1111
    LONG %%0011_0011_0011_0011
    LONG %%0011_0011_0011_0011
  • Ken PetersonKen Peterson Posts: 806
    edited 2007-09-26 16:34
    @Rayman: Exactly!

    I guess I wasn't sure whether LONGMOVE starts at the low end or high end. Sometimes code is better optimized by counting down. If it doesn't start at the low end, you'll have a problem.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    The more I know, the more I know I don't know.· Is this what they call Wisdom?
  • deSilvadeSilva Posts: 2,967
    edited 2007-09-26 22:06
    Is someone interested in an alternative TV driver which uses a modified tile concept?

    After this kind of dicussion has occurred three or four times now I changed it some weeks ago to allow LONG addressing, which leaves 2 bits for other purposes.. One is used to indicate the interleave variant, the other to allow non-interleaved bitpatterns (which is more comfortable).

    It still needs documentation ... the worst thing is, this SILVA_TV is not compatible to the standard TV.. So.it needs SILVA_TEXT ...
    And it is monochrome of course smile.gif

    Adding (256!!) colours is straightforward using a second BYTE vector corresponding to the LONGs, but not yet done
  • Ken PetersonKen Peterson Posts: 806
    edited 2007-09-27 01:16
    @deSilva: What is the interleave variant? Also, are you are saying that we'd have to define a text bitmap in RAM? That could take a lot of precious memory, more than the wasted 15 longs mentioned previously.

    As far as adding colors, it would also be possible to bank in different color vectors, as the color number is just an index. Each row of tiles could theoretically use a different color vector. I wouldn't be surprised if something like this has already been done.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    The more I know, the more I know I don't know.· Is this what they call Wisdom?
  • hippyhippy Posts: 1,981
    edited 2007-09-27 02:00
    @ Ken, Rayman : Thanks to your help I'm getting somewhere, but not completely there yet. I've modified the TV_Text of TV_Text_Demo.Spin and added the following character definition to replace "T" ...

    padding LONG 7[noparse][[/noparse] 16 ] 'alignment padding 
    uchar
    LONG %%3333_3333_3333_3333
    LONG %%3333_3333_3333_3333
    LONG %%3300_0000_0000_0033
    LONG %%3300_0000_0000_0033
    LONG %%3300_0000_0000_0033
    LONG %%3300_0000_0000_0033
    LONG %%3300_0000_0000_0033
    LONG %%3300_0000_0000_0033
    LONG %%3300_0000_0000_0033
    LONG %%3300_0000_0000_0033
    LONG %%3333_3333_3333_3333
    LONG %%3333_3333_3333_3333
    LONG %%0000_0000_0000_0000
    LONG %%0000_0000_0000_0000
    LONG %%0000_0000_0000_0000
    LONG %%0000_0000_0000_0000
    
    


    I do the longmove of 16 longs ( just the once ) and what I'm seeing is two square boxes stacked vertically, similar to an "8". What I was hoping to see was one box sitting just above the ground. I guess this is due to the interleaving, or I've misunderstood the pixel mapping ?

    The manual says "Each character definition is 16 pixels wide by 32 pixels tall", yet TV.spin says, "pixelgroups are <tileheight> longs which define (left-to-right, top-to-bottom) the 2-bit (four color) pixels that make up a 16x16 or a 32x32 pixel tile". For the life of me I cannot correlate those two statements together, nor understand what the manual means when it talks of merging and 'odd-even' pairs.

    More intriguing though; if I make the padding array longer, for example 64 longs, extra pixels are turned on beneath the two boxes. Even if I change the padding value from 7 to zero. That doesn't make sense to me. It's still moving 16 longs from '@uchar' to '@uchar & $FFC0', and the pointer put into the 'screen' array is '@uchar & $FFC0' in both cases. The addresses are further down memory, but still aligned on a 64 byte / 16 long boundary.

    Any ideas or pointers to clearer, more explanatory, information ?
  • deSilvadeSilva Posts: 2,967
    edited 2007-09-27 02:08
    @hippy: It is all terribly simple...But I do not want to copy three pages here explaining it in length. It will still take some days for the Video Tutorial...

    Just this: The Video Logic always outputs 16 2-bitPAIRS. You have to decide by the choice of an appropriate colour combination which bit of the pair is to be output... This is why TV_TEXT can only allow two colours (fg and bg ) per tile.
  • deSilvadeSilva Posts: 2,967
    edited 2007-09-27 02:14
    Ken Peterson said...
    @deSilva: What is the interleave variant?
    That's what hippy is just chewing on smile.gif You have to tell the driver which 16 bits of the 32 to take.
    said...
    Also, are you are saying that we'd have to define a text bitmap in RAM?
    No, you HAVE not - you CAN. Thats all the reason behind it!
    said...
    As far as adding colors, it would also be possible to bank in different color vectors, as the color number is just an index.
    There are many possibilities...
    The color number is not "just an index", but "just a number". I should prefer it to be a "color value" in SILVA_TV rather than an index as with TV. But I have not yet implemented anything...

    Post Edited (deSilva) : 9/27/2007 2:19:42 AM GMT
  • Ken PetersonKen Peterson Posts: 806
    edited 2007-09-27 02:19
    @Hippy:

    The characters in the ROM are interleaved in that each "character" in ROM is actually two characters. There is a pair of bits for each pixel, which represents one of four colors in your palette. If you choose 00, you get background. If you choose 01, you get one character. If you choose 10, you get the other character, and if you choose 11 (not usually used for text, only for box borders) you get BOTH characters.

    Look closely at how the TV_Text.spin calculates the value for the screen tile. It multiplies your color number by two and adds one if your character is ODD. This has the effect of choosing a color palette that will display the proper character in the interleave. Also notice that the offset in the Character ROM is rounded to the nearest even address (c & $FE). This is because there are TWO characters at each address, and the color palette, as mentioned above, makes the final determination as to which character you see.

    Also look closely at how the color palettes are defined in the TV_Text object. They work together in pairs - you have eight pairs of colors to work with for displaying text, and which one of the pair is chosen depends on whether you are displaying an even or odd character. For one character, values for 01 and 11 would be foreground, while 00 and 10 would be background. For the other character, values 10 and 11 would be foreground and 00 and 01 would be background.

    Hope this clears things up for you a little.

    Ken

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    The more I know, the more I know I don't know.· Is this what they call Wisdom?
  • hippyhippy Posts: 1,981
    edited 2007-09-27 02:24
    deSilva said...
    @hippy: It is all terribly simple...

    I hate to disagree, but I'm not finding it at all simple.

    Outside of TV_Spin_Demo, in my own application, I applied the same changes and I see one box at the top half of the character and garbage pixels below. There's obviously something missing which I haven't understood. It has all the hallmarks of the bottom half of the character being a (half?-) tile taken from some address I am not putting pixel data into, which indicates to me the tile definition I'm using is incomplete.
    deSilva said...
    ...But I do not want to copy three pages here explaining it in length. It will still take some days for the Video Tutorial

    I look forward to its arrival. It's got to be better than banging my head on my TV wink.gif
  • hippyhippy Posts: 1,981
    edited 2007-09-27 02:41
    @ Ken : I understand the gist of what you are saying. With only one user defined character it is always 'even' so that makes the pointer assignment to the 'screen' array quite simplistic, and there's only one pointer to set per character to be displayed. I've tried all values for the pixel bit-pairs within the tile from 0 to 3 and still do not see what I would expect to see; half the character seems to being loaded from somewhere other than my tile definition.
  • deSilvadeSilva Posts: 2,967
    edited 2007-09-27 02:45
    @hippy: When I understand it right, the LOWER part of your character is missing? But it seems you provide only 16 LONGs! TEXT_TV expects 32 (of course).
  • hippyhippy Posts: 1,981
    edited 2007-09-27 03:58
    @ deSilva : That would explain it. I was expecting the tile to need just 16 longs, and I guess Rayman was as well. I hadn't fully appreciated the comment about bit 4 in tv_mode which specifies the tileheight which in turn indicates how many longs per pixelgroup there must be.

    I'll try 32 longs later as it's definitely time for bed in my part of the world (5am).
  • hippyhippy Posts: 1,981
    edited 2007-09-28 01:30
    Finally, got there. Many thanks for everyone's help. This will hopefully save others the pain I went through ...

    Taking TV_Text_Demo.spin as delivered and modifying TV_Text.Spin as follows -

      ' ==== In PUB Start
    
      ' Make sure our four user defined characters are placed on a 128 byte, 
      ' 32 long boundary.  The longmove should only be executed once. A
      ' second execution will corrupt the pixel map unless lucky enough to
      ' have 'uchar' already aligned correctly.
      
      longmove( @uchar & $FF80, @uchar, 32*4 )
    
      '==== In PRI print(c)
    
      ' Convert characters 'A' through 'D' into our four user defined characters.
      ' All others remain as normal, mapped into Rom.
    
      if c => "A" and c =< "D"
        c -= "A"
        screen[noparse][[/noparse] row * cols + col ] := (color << 1 ) << 10 + ( ( @uchar & $FF80 ) >> 6 ) + ( c << 1 )
      else
        screen[noparse][[/noparse] row * cols + col ] := (color << 1 + c & 1) << 10 + $200 + c & $FE
    
    ' ==== At end of DAT
    
                  LONG 0[noparse][[/noparse] 31 ]                      ' Alignment padding
     
    uchar         LONG %%0000_0000_0000_0000[noparse][[/noparse] 5 ]   ' ***********
                  LONG %%0011_1111_1111_1111        '            *
                  LONG %%0111_1111_1111_1111        '            *
                  LONG %%0111_0000_0000_0000        '            *
                  LONG %%0110_0000_0000_0000[noparse][[/noparse] 16 ]  '            *
                  LONG %%1110_0000_0000_0000        '            *
                  LONG %%1110_0000_0000_0000        '            *
                  LONG %%1100_0000_0000_0000        '            *
                  LONG %%0000_0000_0000_0000[noparse][[/noparse] 5 ]   '             *
    
                  LONG %%0000_0000_0000_0000[noparse][[/noparse] 5 ]   '             *
                  LONG %%1100_0000_0000_0000        '            *
                  LONG %%1110_0000_0000_0000        '            *
                  LONG %%1110_0000_0000_0000        '            *
                  LONG %%0110_0000_0000_0000[noparse][[/noparse] 16 ]  '            *
                  LONG %%0111_0000_0000_0000        '            *
                  LONG %%0111_1111_1111_1111        '            *
                  LONG %%0011_1111_1111_1111        '            *
                  LONG %%0000_0000_0000_0000[noparse][[/noparse] 5 ]   ' ***********
    
                  LONG %%0000_0000_0000_0000[noparse][[/noparse] 5 ]   ' ****   ******
                  LONG %%1111_1111_0000_1111        '     * *
                  LONG %%1111_1111_1001_1111        '     * *
                  LONG %%0000_0011_1001_1100        '     * *
                  LONG %%0000_0001_1001_1000[noparse][[/noparse] 16 ]  '     * *
                  LONG %%0000_0001_1001_1000        '     * *
                  LONG %%0000_0001_1111_1000        '     * *
                  LONG %%0000_0000_1111_0000        '     * *
                  LONG %%0000_0000_0000_0000[noparse][[/noparse] 5 ]   '      *
    
                  LONG %%0000_0000_0000_0000[noparse][[/noparse] 5 ]   '      *
                  LONG %%0000_0000_1111_0000      '     * *
                  LONG %%0000_0001_1111_1000        '     * *
                  LONG %%0000_0001_1001_1000        '     * *
                  LONG %%0000_0001_1001_1000[noparse][[/noparse] 16 ]  '     * *
                  LONG %%0000_0011_1001_1100        '     * *
                  LONG %%1111_1111_1001_1111        '     * *
                  LONG %%1111_1111_0000_1111        '     * *
                  LONG %%0000_0000_0000_0000[noparse][[/noparse] 5 ]   ' ****   ******
    
    
    


    Optionally, modify TV_Text_Demo.spin as follows -

    
      ' ==== In PUB start
    
      ' Add just before the last 'repeat' ( which shows the incrementing count )
    
      text.str(String($1,"ABABAB",$D,"CCCCCC",$D,"DDDDDD",$D))
    
    
    


    The only unexpected thing is that the pixel maps are right to left, not left to right as TV.spin describes them.

    Post Edited (hippy) : 9/28/2007 1:35:33 AM GMT
  • RaymanRayman Posts: 14,162
    edited 2007-09-28 12:08
    Hippy,

    I have an applet here for generating characters:

    http://www.rayslogic.com/propeller/Programming/Characters.htm

    Note that it is for 16x16, 4-color characters right now.

    I think I'll only use 16x16 character mode so that I can draw buttons and borders using the built-in font.
Sign In or Register to comment.