Jump to content
TheBF

Camel99 Forth Information goes here

Recommended Posts

3 minutes ago, TheBF said:

I posted an expansion of the code in the Assembly forum since if I confused you then I was making trouble.

The PUSH, macro is for any register.  So in this case I did not PUSH R4 into memory stack. I only "pushed" R0 R1 & R2.

 

I see that, now—and, I am sure you explained it to me before. I just know that I will always need to relearn that fact any time I want to write or understand written Camel99 Forth Assembler code.

 

...lee

Share this post


Link to post
Share on other sites

Yes it took me time when I bought HsForth to remember that BX was used this way.

Now it's second nature.

 

BTW how do you get Camel99 

to print with the 99 sub-scripted?

 

It looks nice.

 

Share this post


Link to post
Share on other sites
1 hour ago, TheBF said:

BTW how do you get Camel99 

to print with the 99 sub-scripted?

 

It looks nice.

 

That is the font, Georgia, available on the edit menu above. 🙂

 

...lee

  • Like 2

Share this post


Link to post
Share on other sites

Can you smell the burnt brain cells out there in web space?  🤬

 

I have spent way to much time trying different things to marry Forth WORDLISTS to SAM memory in an elegant way.  I am sure it can be done but I struggle with keeping the mental map of all the pointers to pointers to pointer-pointers... :) 

One my challenges with Forth is that I not only want to write the program, I want to write the words that let somebody else write more programs simply. Double responsibility.

 

The context required to maintain the connections between the Forth Interpreter and compiler and arbitrary blocks of code out there in the SAMS card seem way to bulky the way I was doing it.

I made something that worked fine to load up and run the code.  But letting each code page be found in the wordlist search order exceeded my grasp this time. I am missing something and it doesn't seem very elegant.

 

Next Steps:

One of my specifications is I want to be able to load existing library files into SAMS without changes. 

I might have to make all the compiling words deferred and have a Forth version and a SAMS version and vector them all with a single command.

That would let : push the sams bank# onto the return stack and ; could compile code to revert back to the previous bank# before doing EXIT.

 

 

So I have lots things that work but not to my liking including this which I will call CODEX1.  It works like simplified Forth79 vocabularies where each CODEX only links back to Forth.

You can only compile code into the active CODEX using words in the CODEX and/or in Forth.  Not overly practical but you can load up lots of utilities.  You have to manually activate each CODEX by name.

Not very useful yet.

Spoiler
\ CODEX1: SAMS Memory Forth compiling         Jan 4, 2021 B Fox
\ A CODEX is named 4K page in SAMS memory that contains code.
\ Each code page holds its own DP and CONTEXT at the end of the SAMS page.
\ Each code page is like a small vocabulary that links back to Forth.

\ NEEDS DUMP FROM DSK1.TOOLS
NEEDS SAMSCARD FROM DSK1.SAMSFTH

HERE

HEX              E000 CONSTANT CSEG    \ "CODE SEG" window address
CSEG FFC +            CONSTANT PLINKS  \ local memory pointers, end of each bank
4000 CSEG 0B RSHIFT + CONSTANT CREG    \ compute CSEG SAMS register

VARIABLE  TOTAL-AMS
VARIABLE  BANK#
VARIABLE  PAGE#
CREATE HOME  0 , 0 ,         \ place holder for Forth DP & CONTEXT

: CODEX-RESET ( -- ) EF PAGE# !  TOTAL-AMS OFF ;

CODEX-RESET

: NEWPAGE ( - n) PAGE# 1+! PAGE# @  DUP FF > ABORT" No more CODE pages" ;

: CMAP    ( bank# -- )     \ ** bank# must be in low byte**
         DUP BANK# !       \ last used SAMS bank
         SAMSCARD 0SBO     \ turn on the card
        ( bank#) CREG !    \ store bank# in SAMS register
         0SBZ ;            \ turn off card

: AMS-HERE   ( -- addr) PLINKS @ ;
: DICTIONARY ( -- dp context)  DP @ CONTEXT @ @  ;
: RELINK     ( dp context -- ) CONTEXT @ !  DP ! ;
: ACTIVATE   ( bank# -- ) CMAP  PLINKS [email protected] RELINK ;
: FAR:       ( -- ) BANK# @ ACTIVATE ;
: LOCAL:     ( -- ) HOME [email protected] RELINK ;
: END-LOCAL  ( -- ) DICTIONARY HOME 2!  ;
: BANK-MEM   ( -- n ) PLINKS [email protected] DROP  CSEG - ;
: END-SAMS   ( -- )
            DICTIONARY PLINKS 2!  LOCAL:
            AMS-HERE EFFF > ABORT" SAMS page size exceeds 4K"
            BANK-MEM TOTAL-AMS +!
;

: .SAMSCODE   CR ." SAMS CODE: "  TOTAL-AMS @ U. ;

: CODEX: ( -- )
     CREATE
         NEWPAGE >< DUP , CMAP
         CSEG  CONTEXT @ @ PLINKS 2!  \ init local memory pointers in SAMS
     DOES> @ ACTIVATE ; IMMEDIATE

HERE SWAP - DECIMAL .  .( bytes used)

 

 

Demo code

Spoiler
\ CODEX1 tests

CODEX-RESET

\ define some named code pages
CODEX: MISC
CODEX: ASSEMBLER
CODEX: FILES
CODEX: GRAPHICS
CODEX: TOOLS
CODEX: SOUND

\ END-LOCAL remembers where the Forth dictionary ends
\ You must use it you add more code to Forth
END-LOCAL

MISC
DECIMAL
   : STAR    42 EMIT ;
   : STARS   0 ?DO  STAR LOOP ;
   : HI      CR ." Hello world from SAMS memory!" ;
   INCLUDE DSK1.SOUND

END-SAMS

ASSEMBLER
    INCLUDE DSK1.ASM9900
END-SAMS

GRAPHICS
    INCLUDE DSK1.GRAFIX
    INCLUDE DSK1.COLORS
    INCLUDE DSK1.DIRSPRIT
    INCLUDE DSK1.AUTOMOTION
END-SAMS

FILES
    INCLUDE DSK1.DIR
    INCLUDE DSK1.CATALOG
    INCLUDE DSK1.BLOCKS
END-SAMS

TOOLS
    INCLUDE DSK1.TOOLS
    INCLUDE DSK1.ELAPSE
END-SAMS

TEXT 17 7 VWTR

DECIMAL
.SAMSCODE

 

 

  • Thanks 1

Share this post


Link to post
Share on other sites

Catching up with TI-BASIC

 

I am reviewing everything for release V2.66 and I have never been happy with how I handled character definitions.

I was also envious of BASIC's ability to handle character definition strings of arbitrary length.  :) 

The secret to that feature is using a text string as the input parameter.

 

It occurred to me that now I have all the pieces needed to make a "CALLCHAR"  that works like TI-BASIC.

I just had to put the pieces together.

 

The pieces used are

  1. VDP memory manager in Forth style that lets you compile numbers into VDP memory sequentially as done in the Forth dictionary
  2. Forth's DIGIT? that converts an ascii char to a number with a conversion success flag (re-written in Assembler in V2.0)
  3. S"  Forth word to define a string literal
     
NEEDS VC, FROM DSK1.VDPMEM

: >NIB  ( char -- n) DIGIT? 0= ABORT" Bad char" ;

: CALLCHAR ( addr len char --)
        BASE @ VP @ 2>R                \ save radix & VDP mem pointer
        HEX
        8* 800 +                       \ compute VDP address of char
        VP !                           \ set VP pointer
        BOUNDS                         \ convert addr,len to addresses
        DO
           I [email protected] >NIB  4 LSHIFT         \ convert left nibble & shift
           I 1+ [email protected] >NIB                \ convert right nibble
           OR VC,                      \ OR them, compile into VDP RAM
        2 +LOOP
        2R> VP ! BASE !                \ restore VP and BASE
;

EDIT:  I forgot that I had to convert chars to nibbles and put them together. :) 

  • Like 2

Share this post


Link to post
Share on other sites

I was working on refining the operation of the ED99 editor. 

I never liked the fact that if you are copying records in SAMS memory and you only have one 4K window in memory, as I did, you have to copy the record out to RAM and then write the copy back to the new record.

All this to avoid the the boundary where you want to move the last record of a page to the first record of a new page or vice versa.

 

I recently read a presentation by Chuck Moore and he spoke about using the word BLOCK to deal with memory even when there are no disks on the system.

For those who don't speak FORTH, BLOCK takes an integer argument and returns the address where you can get a "block" of disk space. This is traditionally 1K.

There are typically a number of buffers and BLOCK has a enough smarts to manage the disk and memory like a virtual memory system.

 

Wouldn't it be nice if SAMS memory could be accessed so simply?  Well I took today to figure out a way.

I decided to keep two 4K windows in LOW RAM.  A BLOCK is  4K in size for simplicity.  The code toggles back and forth between the two buffers as you request a SAMS "BLOCK".

If the SAMS page is mapped into a buffer already, it just returns the buffer address.

 

I also provide BUFF0 and BUFF1 to map in pass-thru memory for those cases where you just need regular memory for other stuff.

 

This is not optimal code by any means but it seems to work. I will know for sure when I weave it into a new version of ED99. 

 

Spoiler
\ BLOCK  as a method to manage SAMS pages    Jan 14 2021 Brian Fox

\ NEEDS .S FROM DSK1.TOOLS

HERE

DECIMAL
 24 USER 'R12  \ address of R12 in any Forth workspace

HEX
: SAMSCARD  ( -- ) 1E00 'R12 ! ;   \ select sams card
\ using machine code so we don't need the CRU library
HEX
\ *set the CRU address in 'R12 before using these words*
  CODE 0SBO  ( -- ) 1D00 ,  NEXT, ENDCODE
  CODE 0SBZ  ( -- ) 1E00 ,  NEXT, ENDCODE
  CODE 1SBO  ( -- ) 1D01 ,  NEXT, ENDCODE
  CODE 1SBZ  ( -- ) 1E01 ,  NEXT, ENDCODE

: SAMS-ON   ( -- ) SAMSCARD 1SBO ;  \ enable mapper
: SAMS-OFF  ( -- ) SAMSCARD 1SBZ ;  \ disable mapper

\ * SAMSINI sets card to "pass-through" condition
: SAMSINI
       SAMSCARD          \ select SAMS card
       0SBO              \ turn card on
       0                 \ register value stays on stack
       4000 20           \ register address, # SAMS regs
       BOUNDS ( -- 4100 4000)
       DO
           DUP I !       \ I is reg. address
           I @ OVER <> ABORT" SAMSINI err"
           0100 +        \ next value 0101 for 1MB card, 0100 Classic99
       2 +LOOP
       0SBZ              \ turn off card
       DROP
;

: MAP  ( block# buffer -- )  
         SWAP >< SWAP                \ (fix this with code word)
         0B RSHIFT                   \ divide by 2048
         4000 +                      \ convert to SAMS register address
         SAMSCARD 0SBO               \ enable SAMS card
         !                           \ write block# to SAMS register
         0SBZ ;                      \ turn off SAMS card

\ ==========================================
\ block manager uses handles 0 & 1
DECIMAL
 256 CONSTANT HIGHBLK    \ assumes 1Mb card (256*4K = 1Mb)

VARIABLE USE

\ BUFFER management arrays
HEX
CREATE BLK#S       0 ,    0 ,      \ SAMS page in the buffer
CREATE WINDOWS  2000 , 3000 ,      \ windows in Low CPU RAM

: ]BLK#   ( handle -- addr)   CELLS BLK#S +  ;
: ]BUFFER ( handle -- buffer) CELLS WINDOWS + @ ;

HEX
: BUFF0  ( -- addr) 2000 02 OVER MAP ; \ map in pass-thru memory
: BUFF1  ( -- addr) 3000 03 OVER MAP ;

: BLOCK   ( block# --- addr )
\           HIGHBLK OVER U> ABORT" SAMS page error"    \ optional range test
           0 ]BLK# @ OVER = IF DROP  2000   EXIT THEN  \ mapped in 0?  return buffer
           1 ]BLK# @ OVER = IF DROP  3000   EXIT THEN  \ mapped in 1?  return buffer
         \ page is not already mapped...
           USE @ 1 XOR USE !           \ toggle to USE other buffer
           DUP USE @ ]BLK# !           \ record block# for this handle
               USE @ ]BUFFER TUCK MAP  \ get the buffer address & map in SAMS page
;

HERE SWAP - DECIMAL  CR .  .( bytes)

 

 

  • Like 3

Share this post


Link to post
Share on other sites

SAMS BLOCK is even better in CODE :) 

 

I am always impressed with how Forth code maps so well onto 9900 Forth Assembler .

(Gives me more ideas about a Machine Forth system that maps closer to 9900 than Chuck's ideas which were based on his F21 CPU.)

 

Just did a timing test and it looks like this code is 9X faster than the Forth code version. :-o

\ block as SAMS manager
HEX
VARIABLE USE
CREATE BLK#S       0 ,    0 ,      \ SAMS page in the buffer
CREATE WINDOWS  2000 , 3000 ,      \ windows in Low CPU RAM

CODE BLOCK ( bank -- buffer)
          R0 BLK#S LI,     \ handle 0 search
         R0 ** TOS CMP,
          EQ IF,
                TOS 2000 LI,
                NEXT,
          ENDIF,
                R0 INCT,   \ handle 1 search
         R0 ** TOS CMP,
          EQ IF,
                TOS 3000 LI,
                NEXT,
          ENDIF,

           W  0001 LI,
         USE @@  W XOR,
         W  USE @@ MOV,
         W       W ADD,   \ W holds offset
     TOS BLK#S (W) MOV,   \ store the bank#
    WINDOWS (W) R1 MOV,   \ get the window to use
          R1    0B SRL,   \ divide by 2048
          R1  4000 AI,    \ convert to SAMS register address
          R12 1E00 LI,    \ cru address of SAMS
                 0 SBO,   \ SAMS card on
              TOS  SWPB,  \ swap bytes on bank value
         TOS R1 ** MOV,   \ load bank into register
                 0 SBZ,   \ SAMS card off
   WINDOWS (W) TOS MOV,   \ return buffer on TOS
                   NEXT,
ENDCODE

Edit: Did the SWPB too early in 1st version

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites

I am really enjoying using the BLOCK code for SAMS management.  I am making some major changes to ED99 and IT really has simplified everything.

 

Here is my new definition for a temporary buffer: :) 

: HEAP  ( -- addr)  2 BLOCK ;

It's so seamless. It just swaps out the SAMS page that was last used and gives me a 4K block of pass thru memory.

 

I have to use some 32bit intermediate math to compute a record but it's in the kernel so no worries.

VARIABLE BLK
: ]RECORD ( n -- addr)  RECSIZE UM* 4K UM/MOD 1STBLK + DUP BLK ! BLOCK + ;

1STBLK is just an offset into the 255 available blocks computed from a variable that is the file# we are editing.

I record the block in use in case I might need it but so far I have not, since the editor works mostly at the line level.

 

I built a clipboard by doing the same thing but using a "1stblock" that is above the last block used for text.

DECIMAL
\ clipline returns the string at top of clipstack
\ clip board uses blocks 161..193
: ]CLIP    ( rec# -- addr) RECSIZE UM* 4K UM/MOD 161 + BLOCK + ;

Since there are two 4K buffers copying a line of text to the clipboard is just:

: LINE2CLIP ( line# -- )
      ]RECORD CLIPLINE COPY-REC 
      #CLIPS 1+!
;

It seems to be coming together much easier now.

 

I hope to have new version out this week. 

Working on adding the ability to mark text lines (with highlighting) and cutting them out to clipboard and pasting them back in.

Old version can copy one line at a time or copy the entire file.

 

 

  • Like 3

Share this post


Link to post
Share on other sites

I am working hard on getting a new release of ED99.

It will have some new features like hi-lighting lines for copy/delete, 1000 lines per file and paste now can insert lines anywhere in a file.

I have limited it to 5 files open at once to save some room in SAMS memory for future development. It is still record based and very wasteful of the memory.

 

Wouldn't it be nice to be able to delete files that you no longer need? :)

Tested it here on my TI-99.

(It doesn't work on Classic99 of course but will be great for working on real iron)

 

 

  • Like 2

Share this post


Link to post
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.

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...