Jump to content

Photo

Camel99 Forth Information goes here

Camel99 Forth Concatentive Programming ANS Forth

60 replies to this topic

#26 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Thu Feb 15, 2018 2:22 PM

After playing with this code I realized that MAP was a general purpose routine.

\ Forth translation of same word in TurboForth
: MAP  ( bank addr -- ) \ ASM converted to Forth
         F000 AND  0B RSHIFT 4000 +
         SWAP 00FF AND  DUP >< OR   \ Hi & lo bytes are now identical
         SWAP ( -- bank address)
         1E00 CRU! SBO              \ enable SAMS card
         !                          \ store bank in SAMS register
         SBZ ;                      \ disable SAMS card

I didn't need general purpose for the following reasons:

  1. I didn't need to protect from mapping to a non-4k boundary. I use a constant (MBLOCK)
  2. I don't need to re-calculate the SAMS register every time cuz I always use >2000
  3. The bank# is computed will not exceed >FF 
  4. I could remove ' >< OR'   because CAMEL99 has 'FUSE' which "fuses" 2 bytes into an integer

 

So with all that considered I could remove MAP entirely and just put the remaining code in >BANK.

 

One very Forthy thing I did was moving the calculation of the correct SAMS register to compile time.

This register is calculated based on the constant MBLOCK at compile time but kept in the code as one literal number.

 

So >BANK now becomes this and saves about 36 bytes!

HEX
: >BANK  ( 32bit -- addr)           \ must have 32bit address!!
         B/BANK UM/MOD  1STBANK +   ( -- offset bank#+1STBANK)
         BANK# @ OVER <>            \ do we need to change banks?
         IF   DUP BANK# !           \ update bank#
              DUP FUSE              \ Hi & lo bytes are now identical

         \ compute SAMS register for address=MBLOCK at compile time
            [ MBLOCK 0B RSHIFT 4000 + ] LITERAL

              1E00 CRU! SBO        \ enable SAMS card
            ( bank# register) !    \ store bank in SAMS register
              SBZ                  \ disable SAMS card

         ELSE DROP                 \ not needed. Drop the bank#

         THEN MBLOCK OR            \ return the address in mapped block
;


#27 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Mon Feb 26, 2018 10:39 PM

Super Simple ENUMERATORs in Forth

 

​Many high level languages have a way to create a set of named values that are sequential.

​Forth does not have such a thing out of the box but  it is a one-liner to add 'ENUM' to the language

​thanks to the mind of the late Neil Baud, an innovative Forth developer.

\ ENUM  made with CONSTANT  from Neil Baud's Toolbox

: ENUM  ( 0 <text> -- n) DUP CONSTANT  1+ ;

Now to make a set of enumerated values in our program we simply do:

0 ENUM Q
  ENUM R
  ENUM S
  ENUM T
  ENUM U
  ENUM V
  ENUM W
  ENUM X
  ENUM Y
  ENUM Z
  DROP

We now have a set of named numbers from 0 to 9.  


Edited by TheBF, Mon Feb 26, 2018 10:41 PM.


#28 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Wed Feb 28, 2018 3:54 PM

Creating a Fast Text Driver that Supports Multi-tasking

 

I had been spinning for some time on creating a small but fast set of words to emit text to the screen.

I have played with a number of ways to do it which all work but also were not optimal for speed.

 

I found the screen display of Turbo Forth to be quite enviable. :-)

 

My problem was that I wanted my scroll routine to be in Forth for instructional purposes and it's painful to call Forth from an Assembler word. (not impossible but just kind of silly)  I also needed to interact with the Forth word PAUSE which switches tasks.  So the final routines had to be Forth.  But writing it all in Forth was 25% ..30% slower than the benchmark.

 

I think I have finally realized how to do it.   I created two primitives in Assembler. One that does a newline (carriage return in Forth parlance) and one to "emit" a character to the screen.

 

The difference was to have both primitives return a true/false flag.  With that all the hard stuff is in Assembler and the flag lets me know if I have to SCROLL or CR.

 

The whole thing got so simple by adding the output flag and it's now about as FAST as TF.  (about 90% for text, number conversion is still in Forth...)

: CR          ( -- )                        \ Forth's "newline"
              (CR) ( -- ?)                  \ (CR) returns TRUE if we have to scroll
              IF  SCROLL  THEN ;

: EMIT        ( char -- )
             (EMIT)  ( -- ?)                \ write char, return true if we need to CR
              IF  CR THEN PAUSE ;

Here are the ASM words.

CODE: (CR)    ( -- ? )  \ return true if we need to SCROLL
              TOS PUSH,
              TOS CLR,
             _OUT  @@ CLR,
             _VCOL @@ CLR,
             _VROW @@ INC,
              W  _L/SCR LI,
             _VROW @@ W CMP,
              EQ IF,
                  TOS SETO,
              ENDIF,
              NEXT,
              END-CODE

 CODE: (EMIT) ( char -- ?)  \ (emit) returns true if we need to CR
             _VROW @@ R1 MOV,
             _C/L  @@ R1 MPY,
             _VCOL @@ R2 ADD,           \ fetch _VCOL and add to R0
              R2 R0 MOV,
              WMODE @@ BL,              \ call: setup VDP address in "write mode"
              TOS SWPB,
              TOS VDPWD @@ MOVB,        \ write char to vdp data port
             _OUT  @@ INC,              \ count chars since last Carriage return
             _VCOL @@ INC,              \ advance the column variable

              TOS CLR,                  \ clear TOS. It' the output flag
             _C/L  @@ _VCOL @@ CMP,     \ compare column variable to chars per line var
              EQ IF,
                  TOS SETO,             \ set TOS to true, we need a new line
              ENDIF,
              NEXT,
              END-CODE

Edited by TheBF, Wed Feb 28, 2018 4:09 PM.


#29 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,637 posts
  • Location:Silver Run, Maryland

Posted Thu Mar 1, 2018 3:51 PM

I am sure I asked Willsy this same question about TurboForth years ago:  What about BEL, BS, CR and LF as characters for EMIT ?  On the face of it, it is not particularly important except that I pretty much have no choice in fbForth but to process them as inherited from TI Forth, which is to say, BEL (ASCII 7) does nothing but ring the bell (TI GPL “beep”), BS (ASCII 8 ) must backspace over (thus erasing) the last-typed character, LF (ASCII 10) goes to the same position in the next line, scrolling if it is past the end of the screen, and CR (ASCII 13) goes back to the beginning of the current line.  Any other ASCII characters are assumed to be printable.  I did think seriously about doing it the way it seems you and Willsy are doing it, but decided it might break TI Forth code it did not need to break.

 

In fbForthEMIT calls a low-level ALC routine that includes scrolling.  There is also EMIT8 to allow printing/displaying of 8-bit codes (ASCII 128 – 255).

 

Anyway, thought I would put it out there.  :)

 

...lee



#30 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Thu Mar 1, 2018 6:33 PM

I am sure I asked Willsy this same question about TurboForth years ago:  What about BEL, BS, CR and LF as characters for EMIT ?  On the face of it, it is not particularly important except that I pretty much have no choice in fbForth but to process them as inherited from TI Forth, which is to say, BEL (ASCII 7) does nothing but ring the bell (TI GPL “beep”), BS (ASCII 8 ) must backspace over (thus erasing) the last-typed character, LF (ASCII 10) goes to the same position in the next line, scrolling if it is past the end of the screen, and CR (ASCII 13) goes back to the beginning of the current line.  Any other ASCII characters are assumed to be printable.  I did think seriously about doing it the way it seems you and Willsy are doing it, but decided it might break TI Forth code it did not need to break.

 

In fbForthEMIT calls a low-level ALC routine that includes scrolling.  There is also EMIT8 to allow printing/displaying of 8-bit codes (ASCII 128 – 255).

 

Anyway, thought I would put it out there.  :)

 

...lee

 

Yes I studied TI-Forth Emit code and saw that.  I handle the backspace char in ACCEPT but that's the only control character that I handle.

It seemed a little pointless on the VDP to deal with these where we are talking to a memory mapped device.

I suppose I could deal with ^G to beep and ^J and ^M to CR/LF.

 

Does the TI file system have a EOL delimiter? I have not seen one. In the 1970's this may not have been very normal.

 

If I ever wake up the real iron here then I would have to write a different version to talk over RS232. I would probably use vector I/O for that. That's what I have done in the past.

So just vector in a 232-EMIT and 232-KEY and call it a day.

 

In Forth 2012 EMIT gives you quite a bit of freedom. TI-Forth's interpretation is valid ... as is TF and CAMEL99.   :) 

EMIT
( x -- ) 
If x is a graphic character in the implementation-defined character set, display x. The effect of EMIT for all other values of x is implementation-defined. 
When passed a character whose character-defining bits have a value between hex 20 and 7E inclusive, the corresponding standard character, 
specified by 3.1.2.1 Graphic characters, is displayed. Because different output devices can respond differently to control characters, 
programs that use control characters to perform specific functions have an environmental dependency. 
Each EMIT deals with only one character. 

Thanks for keeping me honest.



#31 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,637 posts
  • Location:Silver Run, Maryland

Posted Thu Mar 1, 2018 9:16 PM

...

Does the TI file system have a EOL delimiter? I have not seen one. In the 1970's this may not have been very normal.

...

 

Usually, DV files store packed (or counted) strings, i.e., a string-length byte followed by the string.  Specific programs might do their own thing.  TI Writer comes to mind.

 

...lee



#32 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Sat Mar 3, 2018 7:28 PM

Version 1.99 Update.

 

I found some ways to save 100 bytes in the final binary which let me compile GRAFIX and CRU word sets.

 

A lot of things were changed as I continue to beat up this little system.

 

 

=============================================================
Feb 3 2018   Version 1.99
Looking for space savings and efficiency:
KEY operation
Replaced (KEY?) CODE word with a smaller version called KEY?
Now WARM sets the correct value for KUNIT# on startup.  (I read the fine print on the matter)
Default value is now 2 (BASIC keyboard)
You can change the keyboard by setting byte variable KUNIT# TO 0,1 OR 2
\ example:  1 KUNIT# C!
 
Change to screen driver
------------------------
Kernel Changes:
Removed VEMIT and <CR>
Replaced with (EMIT) and (CR)
Both of these words return a flag if we need to CR  or SCROLL respectively.
Forth words CR and EMIT are greatly simplified now.
NEW word:   WARM
COLD does a cold boot and CALLs WARM.
- WARM keeps the dictionary intact.

Simplified ." (dot-quote) using ideas from Neil Baud.  Allowed the removal of ,"
Comma-quote has been moved to the \lib folder if you need it.
Dot quote now works in IMMEDIATE mode as well as compiling.
It is an evil state smart word now.
Per above change I removed  the talking comment .( from the kernel and put it in \lib folder.
This is allowed under Forth 2012 but not allowed under Forth 94.
Changed machine code in DOES> to BRANCH to DODOES rather than BRANCH&LINK.
This was an error that didn't seem to create a bug for me but it would use R11 needlessly 
and is a hair slower.
----------------------------
GRAFIX2.HSF
Added 1+ to COLORS word so that the colorset range you select works as expected.
----------------------------
CRU.HSF
I now include a CRU wordset in the kernel.
This allows implementation of SAMS 1Mbyte memory card words.
See \CCLIB\CRU.HSF
------------------
SAMS card support
See \DEMO\BANK.FTH  for examples of how to use SAMS card to create large arrays.
-----------------
SPRITES.FTH
Removed motion table support. I tend to use direct control of sprites and I needed I would use
the multi-tasker.  Added new words that directly control SPRITES in the VDP memory space.
But retained the first system of keeping a mirror in CRU RAM that is updated all at once.
SP.WRITE now replaces SP.SHOW to write the CPU ram table into VDP ram for all created sprites.
See the source file for the new words.
-----------------
XFC99 CROSS-COMPILER CHANGES:
Fixed problem with HEADLESS word so it works now.
Used HEADLESS to remove ADR>IN word from searchable dictionary.
It is used by PARSE AND PARSE-NAME but is not useful by itself.

Edited by TheBF, Wed Mar 7, 2018 6:22 AM.


#33 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Sun Mar 18, 2018 8:50 PM

CAMEL99 Version 2 Update         Mar 18 2012

 

I made a focused effort over the past week to get a functioning device service routine working. 

 

I chose to write it in Forth with only a few lines of Assembler to call the system. 

I plan to document what I learned in the DSR Tutorial thread for any others that might want to write one in some other language.

 

With Version 2 CAMEL99 Forth leaves childhood behind and becomes an adult.

By stripping back a few thing in the KERNEL and creating the file access words CAMEL99 can now extend itself with ordinary TI-99 DV80 files.

 

The magic ANS Forth word is called   'INCLUDED' and it is built into the V2 kernel.

INCLUDED takes a "stack string" as an input parameter which is the address of the text and the length on the Forth data stack.

 

I have settled on using DISPLAY VARIABLE 80 files for the source code with the file extension  '.F'

 

When the Version 2 kernel starts it runs:  

 

S" DSK1.INI.F"  INCLUDED

 

which adds 2 new words to the system.

Its a pretty fast startup because this is all it contains at the moment:

: INCLUDE    BL PARSE-NAME INCLUDED ;

: .FREE      CR ." Free Mem"
             3F20 H @  - CR ." Low Heap : " U.
             FF00 HERE - CR ." Upper mem: " U.  ;
DECIMAL
CR .FREE
HEX

After INI.F compiles you can say: 

 

 INCLUDE DSK2.TOOLS.F 

 INCLUDE DSK1.GRAFIX.F

 

At this time INCLUDEs cannot be nested inside other includes because I have only 1 peripheral access block.

 

I will be moving to a "handle" based file system which is a better fit to ANS/ISO Forth and then files will be able to INCLUDE other files to a depth set by the "FILES" word.

 

Currently using the E/A Editor I can make programs as text files, save them by name, and compile them into CAMEL99 Forth. 

So it is actually a development system now like the EDITOR/Assembler combination.

 

Using variable files means no space is wasted at the end of lines in the text so this should make it pretty efficient.

The compiler looks like it compiles about 20 lines per second in preliminary testing, but I will compile something big as see how that goes.

​Edit: Looks like it's more like 14 lines/sec or 840 lines/minute. Not too shabby for a TI-99. 

 

I have created a large set of library files that I used to test the prototype system V1.99 

I am converting those files to DV80 format so the system will have an ASSEMBLER, SPRITES, GRAFIX, TOOLS etc. and lots of DEMO programs.

 

This is a personal milestone as I dreamt about building a Forth cross-compiler that could build a TI-99 Forth system 10 years ago but corporate life prevented much progress.

A "wee dram" of whisky might be in order tonight! :-)

 

Of course the ultimate goal is to make a system than can re-build itself... but I better not get ahead of myself.

 

There's a new bottle of Crown Royal Northern Harvest  (whisky of the year) with my name on it... bye for now.

 

B

Attached Files


Edited by TheBF, Sun Mar 18, 2018 9:05 PM.


#34 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Thu Mar 22, 2018 7:55 PM

I spent a lot of time this week refining and re-factoring file access code so I can extend it with a  handle based file system.

I am getting there.  I looks like I can implement some a partial working ANS/ISO Forth file wordset in about 1.5K on top of the kernel.

It's big for this little system but the design was made for desktop machines so I may have to make an smaller alternative.

 

I look forward to being able to list directories, copy files and have a MORE utility for TI files.  

 

Here is the final DSR code written in XFC99 cross-compiler Forth

By way of explanation [CC] is a short form for CROSS-COMPILING which lets you do thing with PC Forth interpreter when you need to.

[TC] is short for TARGET-COMPILING which engages the TMS9900 compiler and so you can't run that code on the PC, you can only compile.

 

The DSR code adds 299 bytes to the system which is bigger than ASM but about 130 bytes is labels and linked list headers.

​I could strip some of that our with [PUBLIC]  [PRIVATE]  directives but I won't do that until I have tried making some new device access code.

TARGET-COMPILING

2000 VALUE: DSRWKSP \ workspace in LOW RAM

\ ========================================================
               [CC] [PUBLIC] [TC]

\ This is the code used to CALL the DSR ROM code
CODE: CALLDSR ( -- )         \ *called with Forth word BLWP
             83E0 LWPI,      \ change to GPL workspace
            *R9 BL,          \ GPL R9 already has the entry address
             0BF0 DATA,      \ This normally has DATA 8 in it. :-)
             DSRWKSP LWPI,   \ back to the dummy workspace
             RTWP,           \ Return to Forth
             NEXT,
END-CODE


\ Create the VECTOR that we call with BLWP.
\               workspace    compile program address
\               ---------    -----------------------
CREATE: DSKLNK   DSRWKSP T,  T' CALLDSR [CC] >BODY T, [TC]


\ ========================================================

\                [CC] [PRIVATE] [TC]
 \ Define PAB constants
[CC] HEX [TC]
 1100 CONSTANT: DSKCARD   \ No need to scan for the Floppy DISK CARD. It's here
 4000 CONSTANT: 'ID       \ DSR ROM header addresses
 4008 CONSTANT: 'DSRLIST

\ Create the DSR card scanner
[CC] HEX [TC]

CREATE: DEV$   [CC] 08 TALLOT  [TC]  \ holds the device name: RS232 DSK3

: /DOT    ( caddr len -- caddr len')  \ cut string at the dot
           2DUP T[CHAR] . SCAN NIP -  ;

\ : >DSR$   ( link -- $) 4 +  ;     \ add 4 to the link gets to the DSR$

: =$ ( $1 $2 -- flag) OVER C@ 1+ S= 0= ; \ compare 2 counted strings

\ DSRFIND searches for a matching device NAME in the DSR ROM
\ It returns the link-address. Link-address+2 = runnable code address
: DSRFIND ( addr len -- link_addr)
           /DOT DEV$ PLACE
           'DSRLIST                    \ 1st LINK in ROM linked list
           BEGIN
              @                        \ fetch the next link
              DUP 0=                   \ test for end of list
              SWAP DEV$ OVER 4 +  =$   \ test string match in ROM
              ROT OR                   \ if either is true we're done.
           UNTIL ;

\               [CC] [PUBLIC] [TC]

\ card control lexicon
: Enable   ( CRU -- )
           CRU@ OVER <>               \ is this a different card?
           IF   0SBZ                  \ if so, turn it off
           THEN CRU! 0SBO ;           \ then turn on the requested card

: Disable  ( CRU -- )  CRU! 0SBZ ;

\ hi level commands
: DiskON  ( -- ) DSKCARD  DUP 83D0 ! Enable ;  \ 99-4A needs CRU copied to 83D0 (magic)
: DiskOFF ( -- ) DSKCARD  Disable ;

The Spoiler contains the kernel file access section.  It's not beautiful but it works and so I will lock it down for while.

 

The secret to extending it is the word PAB which returns the value of a pointer  ^PAB.  This pointer will be changed by a file handle issued by the system.

The top of VDP memory will be a "stack" of PABs. (what else would it be. It's Forth :-)  )

I will need a corresponding set of CPU buffers that will keep in LOW RAM. 

That's the theory anyway.

 

Spoiler

Edited by TheBF, Fri Mar 23, 2018 8:38 AM.


#35 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Sat Mar 24, 2018 3:05 PM

CAMEL99 FORTH Version 2.1 is available on GitHub

 

I put up the preliminary binary of CAMEL99 V2 with some TI Format source code files;  just utiltiies and examples mostly.

 

https://github.com/bfox9900/CAMEL99-V2

 

It's pretty fun to play with now.  I need to make a more integrate editor and then it would be a proper development system.

I have problems still with nested INCLUDEs so I am working through that.

 

The little movie shows you how it operates.

To my knowledge this is the first TI-Forth that only uses files for source code.  So we have moved the state of the art all the way up to 1994! :-)

 

 

 

 

Attached Files



#36 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,637 posts
  • Location:Silver Run, Maryland

Posted Sat Mar 24, 2018 8:05 PM

CAMEL99 FORTH Version 2.1 is available on GitHub

 

I put up the preliminary binary of CAMEL99 V2 with some TI Format source code files;  just utiltiies and examples mostly.

 

https://github.com/bfox9900/CAMEL99-V2

 

It's pretty fun to play with now.  I need to make a more integrate editor and then it would be a proper development system.

I have problems still with nested INCLUDEs so I am working through that.

 

The little movie shows you how it operates.

To my knowledge this is the first TI-Forth that only uses files for source code.  So we have moved the state of the art all the way up to 1994! :-)

 

You are welcome to use/modify the fbForth 2.0 editor, but it is all in ALC and requires block files in DF128 format, which could certainly be modified for your purposes.  It is more or less based on the TI Forth editor, which is written in TI Forth.

 

BTW, both TurboForth and fbForth use files for source code.  For normal Forth block I/O, they must be DF128 format and you load/write specific 1024-byte blocks, not whole files as you are doing.  TurboForth (not fbForth, yet), however, does handle interpreting strings with EVALUATE and TI text files (DV80) using INCLUDE .

 

...lee



#37 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Sat Mar 24, 2018 8:25 PM

 

You are welcome to use/modify the fbForth 2.0 editor, but it is all in ALC and requires block files in DF128 format, which could certainly be modified for your purposes.  It is more or less based on the TI Forth editor, which is written in TI Forth.

 

BTW, both TurboForth and fbForth use files for source code.  For normal Forth block I/O, they must be DF128 format and you load/write specific 1024-byte blocks, not whole files as you are doing.  TurboForth (not fbForth, yet), however, does handle interpreting strings with EVALUATE and TI text files (DV80) using INCLUDE .

 

...lee

 

That's a good idea.  I will take a look at it.

I also found another Forth editor that is kind of a minimalist approach. I might see what happens if I wake that up for a starter.

 

I still very old source code for my own block editor that I wrote for MVP Forth in the 1980s and ported to HsForth in the 1990s.

Having the Ti-Forth editor gives me a good cross section of techniques.  I have a dim memory of changing a few things on the 64 column editor for TI-Forth that improved the key response. I have know idea what I did, but I remember the emotion of having it work when I was new to Forth. :-)

 

I knew you had switched to blocks in files. I was trying to get at the "whole files" phrase that you used. That's a better way to say it.  I didn't know that TF had a file evaluator.  I have not really explored Willsy's system in detail. I have looked inside some of the tricky bits primitives to see about some things I did not get about the TMS9900.  Willsy is a crack Assembler coder.

 

BTW a while back we were speaking about end of line delimiters in TI-99 text files. From what I can see it looks like they use >20>01.  One space seems the minimum line length ending with a 01. And the end of files terminator looks like >FF.   

 

I have not really figured out how best to find the end of file except to read until I see error 5.

As I read in the E/A manual however that closes the file as well.   If you know of a better way to detect EOF before reading past the end I am all ears.

 

B



#38 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,637 posts
  • Location:Silver Run, Maryland

Posted Sat Mar 24, 2018 9:00 PM

I have not really figured out how best to find the end of file except to read until I see error 5.

As I read in the E/A manual however that closes the file as well.   If you know of a better way to detect EOF before reading past the end I am all ears.

 

B

 

You should be able to test the status byte at PAB+8 (often termed “screen offset”) for a set bit at bit 7 (LSb) when the last record has been read.  When bit 7 is set, you are at the EOF and reading the next record will throw the error you speak of.

 

...lee



#39 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Sun Mar 25, 2018 7:59 AM

 

You should be able to test the status byte at PAB+8 (often termed “screen offset”) for a set bit at bit 7 (LSb) when the last record has been read.  When bit 7 is set, you are at the EOF and reading the next record will throw the error you speak of.

 

...lee

 

That's fantastic.  Thanks! 



#40 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,637 posts
  • Location:Silver Run, Maryland

Posted Sun Mar 25, 2018 9:05 AM

That's fantastic.  Thanks! 

 

I may have misspoken.  You might need to run the STATUS DSR routine (opcode = 9) to get PAB+8 to contain the correct information.  I will check it out and get back to you.

 

...lee



#41 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Sun Mar 25, 2018 9:53 AM

 

You should be able to test the status byte at PAB+8 (often termed “screen offset”) for a set bit at bit 7 (LSb) when the last record has been read.  When bit 7 is set, you are at the EOF and reading the next record will throw the error you speak of.

 

...lee

 

 

I may have misspoken.  You might need to run the STATUS DSR routine (opcode = 9) to get PAB+8 to contain the correct information.  I will check it out and get back to you.

 

...lee

 

LOL.   I was just writing you back with that when your message came in.  

So that was all it took and it all works great now.  This lets me build a proper version of the ANS word REFILL.

: FSTAT ( -- c) 9 FILEOP DROP PAB _STAT VC@ ; \ see E/A Manual page 298 for meaning

: EOF   ( -- ?) FSTAT 1 AND ;

\ READ until EOF
: REFILL  ( -- flag )  \ flag=true if there is more data
           2 FileOp ?FILERR
           EOF 0= ;

And the LD primitive now is this:

\ load file primitive. NOT re-entrant
: LD  ( -- ior)
            OPN ( -- realpab)             \ realpab left on stack for CLS
            LINES OFF
            BEGIN
              REFILL ( -- ? )
            WHILE
              VDATA LDBUFF @ VGET       \ transfer VDP data to CPU RAM
              LDBUFF @ COUNT INTERPRET  \ interpret the new string
              1 LINES +!
            REPEAT
            CLS ;



#42 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,637 posts
  • Location:Silver Run, Maryland

Posted Sun Mar 25, 2018 10:19 AM

I may have misspoken.  You might need to run the STATUS DSR routine (opcode = 9) to get PAB+8 to contain the correct information.  I will check it out and get back to you.

 

...lee

 

LOL.   I was just writing you back with that when your message came in.  

So that was all it took and it all works great now.  This lets me build a proper version of the ANS word REFILL.

 

Well then, never mind.  :)

 

...lee



#43 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Tue Mar 27, 2018 4:48 PM

Sometimes the simplest things give me grief.  I was struggling with getting the INCLUDE function to be able to handle nested includes meaning including new files while you were inside INCLUDE.

 

It seems to be working now and the real secret was to treat the contents of >8356, called DSRNAM in the E/A manual, as a file  handle.  I had forgotten to save it before opening a new file in the word INCLUDE. Duh!

 

In order to deal with opening multiple files on demand use something I call PAB-BLOCK. That is a PAB of >20 bytes plus a >100 byte buffer right after the PAB. The ^PAB variable is initialized to >3FFF the end of VDP RAM. To make a new PAB-BLOCK you just have to subtract >120 from ^PAB and there is new PAB-BLOCK to use. 

 

The OPN primitive does this and the CLS primitive add >120 to ^PAB so we get dynamic allocation of PABs for files.

 

For CPU buffers I used my ultra-simple (oversimple?) MALLOC/MFREE functions.

 

The new code and binary V2.0.2 is up on github now but here is the business end of the word INCLUDE

 
\ load file primitive.
: LD     ( addr len --) \ Edit: stack comment fixed
           SOURCE 2>R                      \ save interpreter input source
           >IN @ >R                        \ save input string pointer
           DSRNAM @ >R                     \ save current DSR name

           1 SOURCE-ID !                   \ source ID is file (1)
           OPN                             \ open new file (sets new DSRNAM)
           50 MALLOC LDBUFF !              \ get a buffer           
           BEGIN
             REFILL
           WHILE
             VDATA  LDBUFF @ VGET          \ transfer VDP data to buffer
             LDBUFF @ COUNT INTERPRET      \ interpret the new string
             1 LINES +!
           REPEAT
           50 MFREE                        \ release the buffer using size on stack
           CLS                             \ close currently open file
\ restore everything from Rstack
           R> DSRNAM !                     \ restore old file ID
           R> >IN !
           2R> 'SOURCE 2!                  \ restore input
           SOURCE-ID OFF                   \ SOURCE-ID is conole (0)
;


Edited by TheBF, Tue Mar 27, 2018 4:51 PM.


#44 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,637 posts
  • Location:Silver Run, Maryland

Posted Wed Mar 28, 2018 11:52 AM

Nicely done!

 

I wrote an INCLUDE word for fbForth, but I am not allowing nested INCLUDEs because I would need to rewrite too many core words to accommodate it, I am afraid.  It is in the following spoiler.  I will post it later in the fbForth 2.0 thread (see my signature area below) with more details.

 

Spoiler

 

Example:  INCLUDE DSK2.TEST

 

Like you, I am requiring DV80 files.

 

...lee



#45 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Wed Mar 28, 2018 7:39 PM

Nicely done!

 

I wrote an INCLUDE word for fbForth, but I am not allowing nested INCLUDEs because I would need to rewrite too many core words to accommodate it, I am afraid.  It is in the following spoiler.  I will post it later in the fbForth 2.0 thread (see my signature area below) with more details.

 

Spoiler

 

Example:  INCLUDE DSK2.TEST

 

Like you, I am requiring DV80 files.

 

...lee

 

Very nice. That's nice how you prevent nested includes. I had been "kvetching"  over this thing for so long that I just had to make mine nestable. :-)

 

I have been waiting for the day this startup screen ran for quite a while.

 

Topic shift:

I am working on the ANS File word set and made a couple words that might save you some space in future revisions.

 

AND!  and  OR!  apply a mask to the contents of a variable.

VARIABLE FAM  \ build the file access mode here

\ and/or the contents of a variable with mask
 : AND!   ( mask addr -- ) TUCK @ AND SWAP ! ;
 : OR!    ( mask addr -- ) TUCK @  OR SWAP ! ;

\ TI-99 file access mode modifiers
 2 BASE !  \        *ctrl bits*
 : DISPLAY    ( -- ) 11110111 FAM AND! ;
 : SEQUENTIAL ( -- ) 11111110 FAM AND! ;
 : RELATIVE   ( -- ) 00000001 FAM OR! ;

 : UPDATE     ( -- ) 11111001 FAM AND! ;
 : INPUT      ( -- ) 00000100 FAM OR! ;
 : OUTPUT     ( -- ) 00000010 FAM OR! ;
 : APPEND     ( -- ) 00000110 FAM OR! ;

VARIABLE B/REC    \ bytes per record
 : VARI  ( size -- fam) B/REC ! 00010000 FAM  OR! ;
 : FIXED ( size -- fam) B/REC ! 11101111 FAM AND! ;

The ANS words assume you will pass a "file access mode" on the stack with the file name so I build up the bits in the FAM variable. The standard uses file access mode words R/W, R/O and W/O so all they need to do is configure the FAM and fetch the value to the stack. And ANS files use the word BIN as a modifier to the file access mode on the stack so that was simple. It replaces INTERNAL in TI-99 speak.

 : R/W   ( -- fam)  UPDATE  FAM @ ;
 : R/O   ( -- fam)  INPUT   FAM @ ;
 : W/O   ( -- fam)  OUTPUT  FAM @ ;

 \ ANS Forth word replaces INTERNAL
 : BIN   ( fam -- fam') 8 OR ;  \ modify FAM on stack

It's actually working out pretty well to map ANS Forth files to the old TI-99. 

 

​And of course it's simple to make nice descriptors like this:

 : DV80  ( -- ) INPUT DISPLAY 80 VARI SEQUENTIAL ;

Attached Files



#46 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,637 posts
  • Location:Silver Run, Maryland

Posted Wed Mar 28, 2018 9:02 PM

Good work, as usual.   :thumbsup:

 

I have watched with some envy how you set up PABs and VRAM record buffers automatically.  I have actually thought of doing this for fbForth 2.0, but I have been reluctant to take that responsibility from the Forth programmer.  Part of the problem for me is that VRAM space is a moving target with the possible modes.  There is little space in Bitmap mode, so the programmer is on their own there.  All is constant with Text, Graphics and Multicolor modes, however.   The kicker is Text80 mode, which moves the space pointed to by the contents of PABS .  This is not really a big problem, though.  After all, I know where the bodies are buried.  :grin:  H-m-m-m-m...

 

...lee



#47 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Thu Mar 29, 2018 7:06 AM

Good work, as usual.   :thumbsup:

 

I have watched with some envy how you set up PABs and VRAM record buffers automatically.  I have actually thought of doing this for fbForth 2.0, but I have been reluctant to take that responsibility from the Forth programmer.  Part of the problem for me is that VRAM space is a moving target with the possible modes.  There is little space in Bitmap mode, so the programmer is on their own there.  All is constant with Text, Graphics and Multicolor modes, however.   The kicker is Text80 mode, which moves the space pointed to by the contents of PABS .  This is not really a big problem, though.  After all, I know where the bodies are buried.  :grin:  H-m-m-m-m...

 

...lee

 

 

Although I am not finished yet, the plan is to use the 'FILES' word to limit how deep this stack of PAB blocks goes down into VDP RAM.  So in theory the phrase 1 FILES will limit the VDP to >120 bytes at the top of VDP RAM.

 

Would this solve your problem?

 

Bug found:

I just discovered that my DRSFIND corrupts the dictionary if it errors out.  

I think I need to set the DSR name in the PAB before I go searching but that is just conjecture at the moment.



#48 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,637 posts
  • Location:Silver Run, Maryland

Posted Thu Mar 29, 2018 8:48 AM

Although I am not finished yet, the plan is to use the 'FILES' word to limit how deep this stack of PAB blocks goes down into VDP RAM.  So in theory the phrase 1 FILES will limit the VDP to >120 bytes at the top of VDP RAM.

 

Would this solve your problem?

 

For INCLUDE , certainly—because the VRAM buffer is limited to 80 bytes.  I could generalize it to handle up to the maximum record size of 256 bytes, I suppose.  I do have to keep 1 DSR file buffer ( 1 FILES ) for blocks and screen-font files, which have there own PABs and VRAM buffers already set in stone.

 

Bitmap mode is out of the question because the Sprite Descriptor Table (SDT) is right up against the DSR file buffers, even at 1 DSR file buffer!  The maximum is 2 files—otherwise, there is no room for the SDT at all and the Bitmap Pattern Descriptor Table gets stepped on.  I would need to test for Bitmap mode with any automated file allocation system and error out of any user attempt to use it.

 

I would think that the maximum of 16 DSR file buffers is unlikely, but, if the user set up that many, there would be only 3128 bytes of VRAM left—not enough for 16 files with 256-byte records.  INCLUDE , with its 80-byte records, would work, however.  I will stop rambling now...

 

...lee



#49 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Thu Mar 29, 2018 10:26 AM

Update:  Camel99 V2.0.4 

 

BUG: DRSFIND corrupted the dictionary if device not found.  Killed.

BUG: INCLUDED crashed when given a null string. Killed.

 

Change to ?ABORT so that all error messages have a  CR ." *  " <message>

Looks a little like TI-BASIC and it HONKS too.

 

New files on GitHub. 



#50 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 551 posts
  • Location:The Great White North

Posted Sat Mar 31, 2018 11:57 AM

 ANS/ISO Forth Files Word Set for CAMEL99 Forth V2 

http://forth-standar...g/standard/file

 

 

Although the  ANS Forth files word set seem to be designed for UNIX type operating systems it was possible to get them working on the old TI-99.

 

This version is a sub-set of the total requirements, but it allows you to read and write files using file handles.

A handle is just a number assigned by the O/S that selects the correct device to operate on. This implementation creates a table in memory for 8 handles. (Handle 0 is reserved for the Forth console)

PABs are still used per TI-99 file requirements so when a file is created the PAB address is placed in the PABS table.  When a file is closed the PABS table entry is reset to zero.

 

The ANS file operations take the handle and use the SELECT word to set the current PAB. The system uses the word PAB to get the VDP address of the "Selected" PAB.

 

Using these new additions to the system I created MORE, a little program to view a DV80 text file and pause the display or escape the file as a demonstration.

\ more utility is a file viewer
\ default is DV80 files

HEX
: MORE    ( <filename>)
          BL PARSE-NAME
          R/O OPEN-FILE ?FILERR
          >R                    \ push handle onto Return stack
          BEGIN
             PAD DUP 50 R@ READ-LINE ?FILERR
          WHILE
             CR TYPE              \ print the line we read  
             KEY?                 \ test for key press  
             IF CR ." ..."        \ we got one
                KEY 0F =          \ wait for a KEY, test for escape key
                IF R> CLOSE-FILE  \ if detected we're done here
                   2DROP
                   CR CR ." >>Esc<<" ABORT
                THEN
             THEN
          REPEAT
          R> CLOSE-FILE
          2DROP DROP ;

The ANS files sub-set adds 1,184 bytes to system dictionary.

 

The spoiler contains the source code for the curious.   I will get these files up on GITHUB today if I don't find any big bugs.

 

Spoiler

Edited by TheBF, Sat Mar 31, 2018 12:08 PM.






Also tagged with one or more of these keywords: Camel99, Forth, Concatentive Programming, ANS Forth

0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users