Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

1047520 Posts in 42463 Topics- by 34308 Members - Latest Member: NongBenz

September 30, 2014, 07:51:01 AM
TIGSource ForumsDeveloperTechnical (Moderators: Glaiel-Gamer, ThemsAllTook)Jes some Forth code
Pages: [1]
Print
Author Topic: Jes some Forth code  (Read 6540 times)
rogerlevy
Guest
« on: November 20, 2010, 11:37:22 PM »

Thought this was cool enough to post.  For my GUI in Tengoku, I added basic font-based text support (monospace) with a small bit of code.  And I decided to started a thread to showcase and explain it to the curious since I'm sure no one uses Forth for games due to its weirdness - but it's actually quite easy to understand once you learn it, which isn't hard either!  

So, this actually works by rerouting Forth's standard terminal commands ( TYPE CR EMIT SPACE . etc etc etc ) so the code within the callback you pass to GTEXT draws some OpenGL text.  You can also just print a string without any callback fussing with PRINT.

For a cheatsheet of the elementary stack operators, you can refer to this page.  Also, know these: @ is "fetch", ! is "store", and "+!" is plus-store (add value to value at address).

First, the original listing, then some play-by-play with added clarification.
Code:
\ =========================
\ -- Simple text support --
\ =========================
\ Predefined monospace font

6 10 tileset: dos.ts data\6x10.png

0 value lmargin
variable cnt
: _gemit    dos.ts { vtile } 6 0 +at 1 cnt +! ;
: _gtype    0 ?do c@+ _gemit loop drop ;
: _gcr      lmargin penxy nip 10 + at ;

CREATE graphics-text
   16 ,                 \ datasize
    7 ,                 \ #vectors
    0 ,                 \ phandle
    0 ,                 \ previous
   ' noop ,        \ INVOKE    ( -- )
   ' NOOP ,             \ REVOKE    ( -- )
   ' NOOP ,             \ /INPUT    ( -- )
   ' _gemit ,         \ EMIT      ( char -- )
   ' _gtype ,         \ TYPE      ( addr len -- )
   ' _gtype ,         \ ?TYPE     ( addr len -- )
   ' _gcr ,           \ CR        ( -- )

_dv 0 256 quadlist vprimseg: _chars

: gtext ( xt -- )
   dos.ts bind
   0 cnt !
   [[ penxy drop to lmargin graphics-text open-personality execute close-personality cnt @ _chars dim ]]
   _chars vdraw ;

: print ( addr c -- )
   [[ type cr ]] gtext ;

Code:
6 10 tileset: dos.ts data\6x10.png
This imports the font graphic and makes a tileset out of it where the tiles are 6x10.

Code:
0 value lmargin
variable cnt
: _gemit    ( char -- ) dos.ts { vtile } 6 0 +at 1 cnt +! ;
: _gtype    ( address count -- ) 0 ?do c@+ _gemit loop drop ;
: _gcr      ( -- ) lmargin penxy nip 10 + at ;
This implements the actual text drawing code, which actually builds a little vertex array.  LMARGIN stores the left margin to jump back to when we do a carriage return. CNT keeps track of the # of characters so we know how many quads to tell Tengoku to draw.

Code:
CREATE graphics-text
This part sets up a vector table that SwiftForth knows how to interpret to redirect terminal words, which I use mainly for debugging.  I won't go into detail about how this works but you can see where the functions I just defined are referenced.

Code:
_dv 0 256 quadlist vprimseg: _chars
Here we construct a "vprimseg", short for "vertex primitive buffer segment". It is actually a PRIMBUF (primitive buffer) object that is set up as region of an already-defined vertex buffer.  The point of all this is to be able to reuse a vertex buffer for different purposes, or partition it into predefined sections that we can update when needed.  _DV is an internal vertex buffer for drawing stuff, "0 256" defines a region from primitive #0 that is 256 primitives long, and the name we give it is _CHARS.

Code:
: gtext ( xt -- )
   dos.ts bind
   0 cnt !
   [[ penxy drop to lmargin graphics-text open-personality execute close-personality cnt @ _chars dim ]]
   _chars vdraw ;

: print ( addr c -- )
   [[ type cr ]] gtext ;
Here we implement the exposed functions for the font text feature.  GTEXT binds the DOS.TS tileset (setting up the texture matrix and binding the texture), and then sends a little callback to _CHARS:VDRAW, which finds LMARGIN using the current position of the  Pen (the means of specifying the position of drawing primitives in Tengoku), then opens our GRAPHICS-TEXT terminal-rerouting object (which is a "personality", in SwiftForth terms), and then execute the callback which would actually call the terminal words to print out the text.  at the end of the callback it takes CNT and changes the _CHARS array length using its DIM method.

Lastly, the minuscule function PRINT passes a simple callback to GTEXT that just types out the string passed to it and does a carriage return.

And here's our result!  Stars in eyes.

Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic