Jump to content

TheBF

+AtariAge Subscriber
  • Content Count

    2,874
  • Joined

  • Last visited

Posts posted by TheBF


  1. I recently made changes to the kernel program but also have changed the way I access VDP RAM in both the GRAFIX and DIRSPRIT library files.

    They use the TABLEx:  concept posted earlier for faster indexing into VDP tables. 

     

    I saw the B52 demo in another post by @oddemann and thought that it would be a nice way to test my changes. 

     

    EDIT:  The B52 program was written by @SteveB to demonstrate his structured programming environment for BASIC programmers.

     

    To my chagrin, it took me way longer than I wanted to make a "proper" Forth version but once the foundation was laid it was easy to modify.

    I have to admit that getting started with a Forth program requires way more decisions if you want to do it the "Forth way".

    (I couldn't resist adding a few more features once it was running)

     

    I am fascinated by how different a Forth program is than a BASIC program.  All the Forth system creators have taken the time to make bridges between their Forth systems and TI-99 features but despite having those, the way you approach the task is very different.

     

    Some interesting differences from the BASIC version.

    • Forth can use automotion for the aircraft because it can scan for a collision more reliably than BASIC due to interpreter speed.
      This frees up the program to do other things as well. 
    • Even though the BASIC version is nicely factored into sub-routines the Forth version benefits from way more factoring. It can help sometimes with readability if the names are chosen well. 
    • There is no array used to draw the city. There is instead a Skyscraper function that takes random Y coordinate. Then you just put Skyscraper in a loop to make the city. 
    • The DropBomb word demonstrates the more functional nature of Forth. The task is to release a bomb from the aircraft. We can replace the x,y coordinates in SPRITE creation with a call to another sprite's POSITION. The numbers just drop onto the data stack ready for SPRITE to consume them. :) 
    : DropBomb
    \  char  colr     x   y        spr#
       bomb  11   #1 POSITION 12 +  #2 SPRITE  \ make sprite at bomber position
       24 0 #2 MOTION                          \ let it fall
    ;
    • This collision word lets us check if any SPRITE has moved over a non-space character. The coordinate conversion has been factored into PIX>CHAR 
    : COLLISION?  ( spr# -- ?) POSITION PIX>CHAR GCHAR  BL <>  ;
    
    • Sprite library has LOCATE and POSITION but also now has: SP.X  SP.Y 
      These words make some things simpler in Forth where you only want one item on the data stack and they allow faster manipulation of sprite coordinates when you only want to change one of the values.
    • You can see how factoring the sound control into  HZ  and DB  lets you add a descending tone to the bomb drop without needing to remember all the other parameters.

     

    And finally this little demo was a great way to show how to make a binary program from your Camel99 Forth program, shown at the end of the program.

    The video shows the build time at normal 99 speed.

    Zip file has the binary program and source if anyone wants to play. 

    (Known BUG: The airplane collisions need a correction in the vertical plane due to layout of the airplane sprite) 

     

    Spoiler
    \ translation of SteveB52 from Extended BASIC to Forth
    \ Original author unknown at this time
    
    \ INCLUDE DSK1.TOOLS
    INCLUDE DSK1.MARKER    \ need LOCK from this file
    INCLUDE DSK1.GRAFIX
    INCLUDE DSK1.DIRSPRIT
    INCLUDE DSK1.AUTOMOTION
    INCLUDE DSK1.RANDOM
    INCLUDE DSK1.SOUND
    
    \ ENDIF is easier to understand for Non-Forth speakers
    : ENDIF   POSTPONE THEN ; IMMEDIATE
    
    \ scoreboard manager
    VARIABLE HITS
    VARIABLE MISSES
    
    : .HITS      6 0 AT-XY  HITS @ U. ;  \ U. prints numbers unsigned
    : .MISSES   28 0 AT-XY  MISSES @ U. ;
    : .SCORE    .HITS  .MISSES ;
    
    \ numbered sprites like XB
    0 CONSTANT #1
    1 CONSTANT #2
    
    \ name the characters for clarity
    DECIMAL
    124 CONSTANT bomber
    128 CONSTANT bomb
    132 CONSTANT building
    133 CONSTANT ground
    134 CONSTANT crater
    
    : InitGraphics
    S" 2810383838100000000000000000000000000000000000000000000000000000"
    bomb CALLCHAR ( 80 char line limit in DV80 files)
    S" 00000080C0E070FFFF070F1C3800000000000000000000FEFFC0000000000000"
    bomber CALLCHAR
    S" FE929292FE929292" building CALLCHAR
    S" FFFFFFFF00000000" ground CALLCHAR
    S" 8183E7FF00000000" crater CALLCHAR
       2 MAGNIFY
       AUTOMOTION
       2 MOVING
    ;
    
    : ScrInit ( fg bg -- )
      DUP SCREEN         \ use bg color for screen
      DELALL
      1 19 2SWAP COLORS  \ does the range of color sets 1..19
      CLEAR
    ;
    
    : FlyPlane   ( -- ) bomber 13 1 12 #1 SPRITE  0 16 #1 MOTION  ;
    : DrawGround ( -- ) 0 20 ground 32 HCHAR ;
    : SkyScraper ( col row ) building  OVER 20 SWAP - 0 MAX VCHAR ;
    
    : RNDY       ( -- n) 7 RND 14 + ;
    : DrawCity   ( -- ) DrawGround  22 8 DO  I RNDY SkyScraper   LOOP ;
    
    : STARTUP
       16  2 ScrInit
       HITS OFF   MISSES OFF
       10 23 AT-XY ." Foxy's B52"
       0 0 AT-XY ." Hits:" .HITS    20 0 AT-XY ." Misses:"
       InitGraphics
       DrawCity
       FlyPlane
    ;
    
    : DropBomb
    \  char  colr     x   y        spr#
       bomb  11   #1 POSITION 12 +  #2 SPRITE  \ make sprite at bomber position
       24 0 #2 MOTION                          \ let it fall
    ;
    
    : VC+!  ( n Vaddr -- ) TUCK [email protected]  +  SWAP VC! ; \ add 'n' to VDP byte
    
    : Descend
          #1 SP.X [email protected]  250 >
          IF
             1 #1 SP.X VC!  \ reset sprite to left side
             4 #1 SP.Y VC+! \ plane falls down 4 pixels
          ENDIF ;
    
    : 8/  ( n -- n' ) 3 RSHIFT ;  \ divide by 8
    : PIX>CHAR  ( col row -- col' row')  8/ SWAP  8/ 1+ SWAP ;
    
    \ test if sprite is over a character that is not a blank (space)
    : COLLISION?  ( spr# -- ?) POSITION PIX>CHAR GCHAR  BL <>  ;
    
    : DELSPRITE ( spr# -- ) DUP>R  SP.Y 4 BL VFILL  0 0 R> MOTION ;
    
    \ volume fader
    : FADER   ( speed -- ) 16 0 DO  I DB  DUP MS  LOOP DROP  MUTE ;
    
    : Detonate
          0 0 #2 MOTION
          #2 POSITION PIX>CHAR 2DUP AT-XY
          GCHAR building =     \ test for building
          IF    BL   HITS 1+!      \ blank char
          ELSE crater  MISSES 1+!  \ we missed
          THEN (EMIT)          \ draw the character
          #2 DELSPRITE
         -2 NOISE 40 FADER     \ explosion with fade out
    ;
    
    : BombsAway
         GEN1                      \ select sound channel 1
         5000 DUP HZ               \ Set freq. Leave freq. copy on stack
         -8 DB                      \ volume
         BEGIN
            ( freq) 10 - DUP HZ    \ reduce freq in each loop.
            #2 COLLISION?
         UNTIL
         DROP MUTE                 \ remove freq. mute the sound channel
         Detonate ;
    
    : GameLoop
      DrawCity
      FlyPlane
      BEGIN
         Descend
         KEY? IF
           DropBomb  BombsAway
         ENDIF
         .SCORE
         #1 COLLISION? ?TERMINAL OR
      UNTIL
      0 0 #1 MOTION   #2 DELSPRITE
    ;
    
    : END    2 8 ScrInit ." ** DONE ** "  ;  \ imitate BASIC'S END  :)
    
    : RUN
       BEGIN
          STARTUP
          GameLoop
          8 10 AT-XY ." Game Over"
          12 8 AT-XY ." Play again? (Y/N)"
          KEY [CHAR] N =
       UNTIL
       END
    ;
    
    \ /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
    
    \ This is only needed if you want to make a binary program
    : B52   WARM         \ Boot Forth machine (40 column mode )
            GRAPHICS     \ switch VDP mode
            RUN          \ word to start the program
            BYE          \ exits Forth system to title screen
    ;
    
    
    LOCK  \ lock the dictionary to this point at boot time ...
    
    INCLUDE DSK1.SAVESYS  \ ... so this will not be retained when we boot the game
    
    ' B52 SAVESYS DSK2.B52EXE
    

     

     

    FORTHB52.ZIP

    • Like 6

  2. On 1/8/2022 at 12:50 PM, oddemann said:

    Recommendation... Start with the user manual for Basic that follows with the TI. Start at the beginning and get a overview of how the codes work. Then look at this game... "SteveB52" a short game where a bomb is dropped. Also if you find the TICodEd tread you will find a manual about TICodEd. You will find this game in it and it is broken up into parts to explain it. Also TICodEd in it self is a programming tool. Then go to the nest game you find and go over the code to understand what is dos. Don't remember any maze game. But maybe someone will give you a link or code to a maze game to look at.

    It is not that complicated, when you look at the code.

     

      Hide contents
    
    100 GOSUB 170
    110 GOSUB 220
    120 GOSUB 290
    130 GOSUB 380
    140 IF NOT (Answer=78 OR Answer=110) THEN 110
    150 CALL CLEAR
    160 END
    170 CALL CHAR(124,"00000080C0E070FFFF070F1C3800000000000000000000FEFFC0000000000000")
    180 CALL CHAR(128,"2810383838100000000000000000000000000000000000000000000000000000")
    190 CALL CHAR(132,"FE929292FE929292FFFFFFFF")
    200 CALL MAGNIFY(3) :: DIM A(26) :: RANDOMIZE
    210 RETURN
    220 CALL ScrInit(16,2) :: DISPLAY AT(23,10):"SteveB52"
    230 FOR I=1 to 26 :: A(I)=0 :: NEXT I
    240 FOR I=1 to 50 :: J=INT(RND*26)+1 :: A(J)=A(J)+1 :: NEXT I
    250 CALL HCHAR(21,1,133,32)
    260 FOR I=1 to 26 :: CALL VCHAR(21-A(I),I+3,132,A(I)):: NEXT I
    270 CALL SPRITE(#1,124,13,1,1,0,16) :: BOMB=0
    280 RETURN
    290 CALL POSITION(#1,Y1,X1) :: IF X1>240 THEN CALL LOCATE(#1,Y1+4,1)
    300 CALL KEY(3,K,S) :: IF K=32 AND BOMB=0 THEN CALL SPRITE(#2,128,11,Y1,X1,24,0) :: BOMB=1
    310 IF BOMB=0 THEN 350
    320 CALL POSITION(#2,Y2,X2) :: CALL GCHAR(Y2/8+1,X2/8+1,C2)
    330 IF C2=132 OR Y2>155 THEN CALL DELSPRITE(#2):: BOMB=0
    340 IF C2=132 THEN CALL HCHAR(Y2/8+1,X2/8+1,32,1) :: CALL SOUND(-250,-7,1)
    350 CALL GCHAR(INT((Y1-1)/8)+2,INT((X1-1)/8)+1,C1)
    360 IF NOT ((Y1>148 AND X1>200) OR C1<>32) THEN 290
    370 RETURN
    380 CALL MOTION(#1,0,0)::CALL DELSPRITE(#2)
    390 IF C1<>32 THEN DISPLAY AT(8,10):"Game Over" ELSE DISPLAY AT(8,10):"You landed"
    400 DISPLAY AT(12,8):"Play again? (Y/N)"
    410 CALL KEY(3,Answer,S)
    420 IF NOT (S<>0) THEN 410
    430 RETURN
    440 SUB ScrInit(fg,bg)
    450 CALL SCREEN(bg)
    460 CALL DELSPRITE(ALL)
    470 CALL CLEAR
    480 FOR I=0 to 14 :: CALL COLOR(I,fg,1) :: NEXT I
    490 SUBEND

     


     

    Hello @oddemann 

    Did you write this game? 

    I used the ideas in it to test the changes in my Forth system and would like to put the author in the comments.

    It's a good demo for a new Forth programmer.

     

     

    • Like 1

  3. 24 minutes ago, oddemann said:

    It is not that complicated, when you look at the code.
     

      Hide contents
    
    100 GOSUB 170
    110 GOSUB 220
    120 GOSUB 290
    130 GOSUB 380
    140 IF NOT (Answer=78 OR Answer=110) THEN 110
    150 CALL CLEAR
    160 END
    170 CALL CHAR(124,"00000080C0E070FFFF070F1C3800000000000000000000FEFFC0000000000000")
    180 CALL CHAR(128,"2810383838100000000000000000000000000000000000000000000000000000")
    190 CALL CHAR(132,"FE929292FE929292FFFFFFFF")
    200 CALL MAGNIFY(3) :: DIM A(26) :: RANDOMIZE
    210 RETURN
    220 CALL ScrInit(16,2) :: DISPLAY AT(23,10):"SteveB52"
    230 FOR I=1 to 26 :: A(I)=0 :: NEXT I
    240 FOR I=1 to 50 :: J=INT(RND*26)+1 :: A(J)=A(J)+1 :: NEXT I
    250 CALL HCHAR(21,1,133,32)
    260 FOR I=1 to 26 :: CALL VCHAR(21-A(I),I+3,132,A(I)):: NEXT I
    270 CALL SPRITE(#1,124,13,1,1,0,16) :: BOMB=0
    280 RETURN
    290 CALL POSITION(#1,Y1,X1) :: IF X1>240 THEN CALL LOCATE(#1,Y1+4,1)
    300 CALL KEY(3,K,S) :: IF K=32 AND BOMB=0 THEN CALL SPRITE(#2,128,11,Y1,X1,24,0) :: BOMB=1
    310 IF BOMB=0 THEN 350
    320 CALL POSITION(#2,Y2,X2) :: CALL GCHAR(Y2/8+1,X2/8+1,C2)
    330 IF C2=132 OR Y2>155 THEN CALL DELSPRITE(#2):: BOMB=0
    340 IF C2=132 THEN CALL HCHAR(Y2/8+1,X2/8+1,32,1) :: CALL SOUND(-250,-7,1)
    350 CALL GCHAR(INT((Y1-1)/8)+2,INT((X1-1)/8)+1,C1)
    360 IF NOT ((Y1>148 AND X1>200) OR C1<>32) THEN 290
    370 RETURN
    380 CALL MOTION(#1,0,0)::CALL DELSPRITE(#2)
    390 IF C1<>32 THEN DISPLAY AT(8,10):"Game Over" ELSE DISPLAY AT(8,10):"You landed"
    400 DISPLAY AT(12,8):"Play again? (Y/N)"
    410 CALL KEY(3,Answer,S)
    420 IF NOT (S<>0) THEN 410
    430 RETURN
    440 SUB ScrInit(fg,bg)
    450 CALL SCREEN(bg)
    460 CALL DELSPRITE(ALL)
    470 CALL CLEAR
    480 FOR I=0 to 14 :: CALL COLOR(I,fg,1) :: NEXT I
    490 SUBEND

     


     

    Is this for Extended BASIC?

    There are three errors just loading the lines into the editor on Classic99. :) 

    Very sorry.  I pressed 1 by mistake. 

    • Like 1

  4. Very good sleuthing by you.

     

    It took me a second to understand that this meant. Looks strange. :) 

     

    #include "DSK2.GRF1;H"

    I use a comma in these cases now. Semi-colon is burned too hard into my brain as the end of the something. :) 

     

    I remember Small C generating working code but tending to be not overly efficient. 

    Is C99 a "regular" Small implementation from what you see or is there some optimization going on?

     

    • Like 1

  5. In the very general sense it comes down to having some place in you program where your program "remembers" the location of the character.

    In BASIC this is done with numeric variables so two variables called ROW and COL might be all that you need.

     

    An important detail of this is that you must always move the character by changing the variables ROW and COL and place the character on the screen using ONLY those variables as well.

     

    Apologies if that is too simplistic for your needs. 

    So a simple exercise then is to make a program that moves a letter around the screen using this method.

     

    Example: 

    This line will put letter A  at position ROW,COL 

    CALL HCHAR( ROW,COL,65)  

     

    How you change ROW and COL is up to you.

    Have fun.

    • Like 2

  6. 19 hours ago, TheBF said:

    Truly nothing to do with TI-99 but I got a Rasberry Pi.

    Remember I have been away for a long time. Think Rip VanWinkle. :)

     

    Telnet to my windows machine and... I am amazed.

     

     

     

    This should have said Telnet FROM my Windows machine into the  PI. 

     


  7. "A funny thing happened on the way to the coliseum"

     

    Just in case anybody is asking "How the hell did the BF's Forth system even work if he had pointers where there shouldn't be any?

     

    The answer:

    I put bandaids in place in the kernel code to adjust pointers to make it compile correctly.

    The cross-compiler was being forced to generate the correct code structure so the system booted fine.

     

    However later, when you made your own variables, constants or user variables something really funny was happening.

    I saw it over and over but didn't understand why. After all my code was correct. :) 

     

    Example: The address of DOVAR  just happened to start its code at >A070

    >A070 contains A072,  as a CODE word should, pointing to the next address cell where some code begins. 

     

    When you made a VARIABLE  X  in your program, then you used X, it has to run DOVAR.

    DOVAR jumped to address >A070  and ran the code there!!! 

    It contained >A072...

    By sheer coincidence that is this instruction:  😆

    A *R2+,R1  

    Since both those registers are scratch in Camel99 Forth it didn't cause any trouble except running an extra useless instruction.

     

    The same thing was happening for CONSTANTS  BUT when I tried to move the code to different addresses those "pointers" changed into some different instruction and blew things up.

    So getting it all correct feels pretty good right now and pretty stupid at the same time. ;) 


     

    • Like 3

  8. 2 minutes ago, jrhodes said:

    Your post is nothing but a mess of characters, mixed up like a bowl of spaghetti.

    I assume it was code for a picture of sort?

    Ahh.. It is a picture.  I will try a different approach to putting it in the post.

    It looks ok here on my windows browser(Edge) and my mac laptop (Chrome)


  9. 3 hours ago, jrhodes said:

    This is all i see in that post:

    flying-spaghetti-monster.thumb.jpg.07ed8f05fc83f12a45f936c87d82bdbf.jpg

    I am not getting this reference.. :(  Can you help an old guy out?

     

    Cloudy with a chance of meatballs?

    All your noodles are belong to us?

    I'm a Pastafarian in New York?

    ???

     

    • Like 1
    • Haha 1

  10. 14 hours ago, pixelpedant said:

    I really like the contest idea.  Simple, but fun.  I'm in an "XB demo" state of mind, at the moment, after all :P

     

    As far as optimal code, though, it strikes me that's pretty hard to pin down in a generalised way.  Since even in BASIC, you can optimise for execution speed, use of stack space, use program space, readability, etc.  And oftentimes, these interests run straightforwardly contrary to one another.  Everything's a trade-off, depending on your goals and limitations. 

     

    Not too worried about all that from the standpoint of a "build the coolest New Years demo" contest goes, though.  That just sounds like straight-up fun regardless. 

    When I clicked on your link I got an ad for Speechelo.  https://speechelo.com

    OMG. 

    40 years after our favourite speech synthesizer we have this.

    • Like 2

  11. Sometimes I wish I was smart. :roll:

     

    What began as a maintenance exercise turned into a revelation about an fundamental mistake in my cross-compiler that I had fixed with chewing gum and toe-nail clippers. 

    The problem was in what I call the executors: DOVAR DOCON  DOUSER.  The hints had been shouting at me all this time.

    In trying to get a new Super Cart version running I had to dig in and really understand what was going on.

     

    Anyway its good now and the photo is the proof.

     

    The zip file has two new kernel programs. One for regular Editor/Assembler cartridges and one for SuperCart.

    (Note SuperCart version does not work properly with DSK1.SAVESYS.  I will need to make to some changes for that)

     

    Here is what changed.


    V2.68G
     

    #### JIFFS timer is Removed
    The JIFFS timer had more overhead than needed. It is replaced with TICKS.
    TICKS uses the 9901 timer as it's reference. TICKS is now used to create MS.
    MS resolution has been improved to ~10 milli-seconds. 

    Greatly reduces multi-tasking overhead with MS delay word. 

     

    #### VDP Driver changes
    - A return to a common address setting sub-routine to save space in the kernel.
    The performance difference was not worth worrying about.
    - Some VDP routines now exist in memory as "BL" sub-routines but are not in
    the dictionary.

     

    #### "EXECUTOR" word Changes
    - A fix was made to DOCON DOVAR DOUSER due my own misunderstanding. These words
    were compiled as CODE words with an ITC pointer in the CFA. WRONG!
    Each CFA of these words should have started with the actual code.

     

    #### SuperCart Forth
    With the Executor words fixed we could reliably create a SUPERCART version of
    Camel99 Forth that resides in lower RAM, cartridge space when an Editor
    Assembler cart has the 8K RAM chip installed.

     

    #### Changes to Code in Hi-Speed RAM
    Commonly used code snippets are copied to hi-speed RAM at boot-up. We removed
    DROP and added DUP and +  which are deemed to be more frequently used in the
    literature.

    Routines in 16bit RAM: EXIT NEXT ?BRANCH BRANCH ENTER LIT @ DUP +

     

    #### Source code Re-Org
    - FORTHITC.MAK file was created for easier understanding of the file
    compiling order and compiler switches.
    - Hi level Forth words and a few CODE words are now in HILEVEL.HSF.

      Other INCLUDE statements are still embedded in the HILEVEL.HSF file.
     

     

    IMG-1156.jpg

    CAMEL99-2.68G.ZIP

    • Like 3

  12. I think that horse still has weak pulse. :) 

     

    Something to watch out for when you run the FbForth multi-tasker.

     

    PAD becomes a shared resource.  I have the  "68" value in your FbForth kept in a user variable called TPAD (task pad)

    : PAD      HERE TPAD @ + ;  

    If a task needs it's own PAD you set its local TPAD variable to a higher value when the task starts or manually in the program's startup code. 

    You need enough space for the task's PAD and it's HOLD buffer as well. 

     

    • Like 2

  13. I finally got a bit more disciplined about how to build this system. I created a "make" file that is not a "make" file but just a little Forth file.

    This makes it easier to see the what's going on in terms of what is being built.  There are other include files inside the primary files but this seems a bit easier to manage when I want to make different flavours of this system.

     

    While doing this I was forced to fix a bug that had prevented me from build a SuperCart version on these sources.

    Got that one fixed but still not sure how it is happening inside the cross-compiler. 

    Here is FORTHITC.MAK.   As you can see there are some compiler switches. Hashing the dictionary is not yet implemented but its in the roadmap.

    I am just going to test these new kernels and will post them later tonight.

     

    For the curious writing a Forth system in Forth is pretty weird, probably because I was feeling my way along, but it's how I got it to work. 

    • First thing loaded is code to teach the compiler how to compiler Forth's simple data types (CONSTANT VARIABLE CREATE USER) and a primitive colon definer.
      I kept these are external because there are at four different ways to make a Forth system. 
    • Next come the parts of the language written in Forth Assembler
    • Once we have the primitives in memory, we use them to teach the compiler how to generated IF THEN ELSE, loop structures and Forth "colon" definitions. 
    • After we have almost everything compiled, only then do we compile the Forth code for the TI-99 "target" system to have IF THEN & loops and finally colon definitions.

    You can see the slightly updated code here: CAMEL99-V2/CC9900/SRC.ITC at master · bfox9900/CAMEL99-V2 · GitHub

    \ MAKE CAMEL99 indirect threaded Forth               Jan 2022 B Fox
    
    CROSS-COMPILING
    
    \ compiler switches
    TRUE  VALUE ITC          \ used to prevent directly compiling HILEVEL.HSF
    FALSE VALUE SLOWER       \ TRUE saves 22 bytes
    FALSE VALUE HASHING
    TRUE  VALUE SUPERCART
    
     INCLUDE CC9900\SRC.ITC\ITCTYPES.HSF   \ CROSS-Compiler Extensions
    
    \ compile the Forth kernel
     INCLUDE CC9900\SRC.ITC\9900CODE.HSF   \ ASM primitives for TMS9900
     INCLUDE CC9900\SRC.ITC\TI99IOX.HSF    \ VDP driver & KEY code
    
     INCLUDE CC9900\SRC.ITC\BOOTSTRP.HSF   \ cross-compiler looping & branching
    
     INCLUDE CC9900\SRC.ITC\HILEVEL.HSF   \ CORE Forth words
    

     

    • Like 1

  14. In Starting Forth there was a word called TEXT...  gotta get the book ...

    that did something similar although it was not used in compiling.

    It is defined as:

    : TEXT     PAD 72 32 FILL    WORD  COUNT PAD SWAP <CMOVE ; 

    But like the old version of WORD it doesn't return the address where the data is. :(

    The ANS gang factored out a lot of interpreter to make it more accessible.

    It still gives me grief but as you show with TOKEN you just make what you need. 

    It's mostly fun. I am trying to find a bug in my cross-compiler which is not fun right now.

    • Like 1

  15. After making the MASK: directive I wondered if there were other places where I could apply this ability to mix Forth data and Assembly language actions.

     

    I realized that all the tables in VDP RAM could be a good use since they are base address with offsets. 

    So I re-worked my sprite attribute table with with this:

    HEX
    : TABLE4: ( Vaddr -- )  \ create a table of 4 byte records
             CREATE    ,             \ compile base address into this word
            ;CODE ( n -- Vaddr')     \ RUN time
                 0A24 ,  \ TOS 2 SLA,  ( tos = n x 4 )
                 A118 ,  \ *W TOS ADD,
                 NEXT,
    ENDCODE
    300    CONSTANT SAT      \ sprite attribute table VDP RAM base address
    
    SAT     TABLE4: SP.Y
    SAT 1+  TABLE4: SP.X
    SAT 2+  TABLE4: SP.PAT
    SAT 3 + TABLE4: SP.COLR
    

    We can give each field in the table a different base address and it makes each sprite parameter look like a 1 dimensional array. :) 

     

    So the Motion table becomes:

    0780 TABLE4: ]SMT       \ SPRITE motion table as VDP array
    

    The neat thing about a TABLE4:  is you can use it on CPU RAM as well since it just computes offsets. It doesn't care where the base address is.

     

    For pattern tables I needed TABLE8:  for 8 byte records 

    and for colors I needed a TABLE of 1 byte records which I just call a TABLE: 

    It seems like a good solution to VDP memory access. 

     

    This making me wonder if the "name" table as TI calls is should also be accessed this way. 

    • Like 2
×
×
  • Create New...