-
Posts
4,470 -
Joined
-
Last visited
Content Type
Profiles
Forums
Blogs
Gallery
Events
Store
Posts posted by TheBF
-
-
6 hours ago, mizapf said:
As our machine language programs have direct hardware control, the VRAM address auto-increment should be used, of course. I sometimes wonder how things would like like when we had a full multitasking operating system (maybe for the Geneve 2020?). It would be reasonable to block all direct access to hardware, only offering a system call interface (which would be our XOPs). In that case, we would need lots of simple routines in the kernel, like filling VRAM space.
(I just had a short look at the TMS99000 manual; interestingly, there is no restriction on memory access in the user mode, so any memory-mapped device would be directly accessible. But at least some CRU address ranges are restricted to kernel mode, and a memory-mapped device could then be guarded by a CRU bit.)
My multi-tasker makes sure anything critical runs to completion before giving up the device. If the task switch overhead is low, which it can be on the 9900, you can turn off interrupts when you enter a time critical routine and turn them on when you leave. BUT... you must make sure those routines that do this are fast and small. In my case it's cooperative tasking so interrupts are not required.
The big problem can be disk I/O which was not written with this in mind so they make cooperative tasking clunky stealing time while waiting for the drive.
- 1
-
1 hour ago, Asmusr said:
VSMW is looping for you. All you need is:
CLR R0 LI R1,>2000 LI R2,768 BLWP @VSMW
The problem is there are many coding styles and ways to pass parameters in assembly. I even find it difficult to reuse my own routines from one game to the next.
I thought there was one of those in the conventional system but I couldn't remember the name. Thanks!
-
For screen clearing and/or initializing any part of VDP RAM I have preferred to write a little routine that I called VFILL.
It's like VMBW but writes the same byte over and over. The parameters are:
- R0 VDP address
- R1 the byte that will written
- R2 number of bytes you want to write.
I don't have conventional source code for it so I won't put anything here that might muddy the water for a new Assembly language coder.
I suppose I could go all academic and say I will leave that as an exercise for the reader.
-
I take your point. It bugs me to do a register adjustment, to force a jump, that then just ends up running NEXT.
In a commercial project I would be obedient but here...
Maybe we can just keep this between us.
- 2
- 1
-
It breaks the the rule of structured programming for of one entry and one exit point, but it does give you some efficiency when it works out.
- 1
-
Searching for Text
Just like GDMike I need a search routine for ED99. I had done some work to create a new Forth2012 word but it was clunky. It used a pre-defined buffer for the input string which is really not cool.
I think I have something better now.
The hard core part is COMPARE and in Camel99 Forth it is build onto top of an Assembler word from the original Camel Forth called S=.
CODE S= ( Caddr1 Caddr2 cnt1 -- n ) R2 POP, \ adrs2 -> R2 R1 POP, \ adrs1 -> R1 TOS R0 MOV, \ cnt -> R0 TOS CLR, \ clear output flag (0 means a match) NE IF, \ if count<>0 do search BEGIN, R1 *+ R2 *+ CMPB, \ compare & auto increment NE IF, \ mismatch found, LT IF, TOS DEC, \ $1<$2 ELSE, TOS INC, \ $1>$2 ENDIF, NEXT, \ Return to Forth ENDIF, R0 DEC, \ decr. loop counter EQ UNTIL, \ loop while R0 > 0 ENDIF, NEXT, \ Return to Forth ENDCODE
It's very low overhead to make S= function like ANS Forth COMPARE
: COMPARE ( addr n addr2 n2 -- -1|0|1) ROT MIN S= ;
. I borrowed an idea from the late Neil Baud with 3RD and 4TH. These routines work like PICK but are much faster. In fact on the 9900 they are the same two instructions as OVER.
CODE 4TH ( a b c d -- a b c d a ) \ same speed as OVER TOS PUSH, 6 (SP) TOS MOV, NEXT, ENDCODE
Armed with that fire power I now have a proper SEARCH for the system.
\ search.fth for Camel99 Forth Brian Fox 26Jun2020 ( c-addr1 u1 c-addr2 u2 -- c-addr3 u3 flag ) \ Search the string specified by c-addr1 u1 for the string specified by c-addr2 \ u2. If flag is true, a match was found at c-addr3 with u3 characters remaining \ If flag is false there was no match and c-addr3 is c-addr1 and u3 is u1. \ \ NEEDS DUMP FROM DSK1.TOOLS \ debug only NEEDS 3RD FROM DSK1.3RD4TH \ CODE like OVER but for 3rd and 4th items NEEDS COMPARE FROM DSK1.COMPARE \ MARKER /SEARCH ( 2OVER is macro for more speed) : 2OVER ( d d2 -- d d2 d) POSTPONE 4TH POSTPONE 4TH ; IMMEDIATE : 4DUP ( d d2 -- d d2 d d2) 2OVER 2OVER ; : 2NIP ( a b c d -- c d ) 2SWAP 2DROP ; : SEARCH ( string1 len1 string2 len2-- string3 len) 2SWAP ( -- caddr2 u2 caddr1 u1 ) BEGIN DUP ( test u1 ) WHILE 4DUP COMPARE 0= IF 2NIP TRUE EXIT \ jump to ';' THEN 1 /STRING \ remove 1st char REPEAT ;
- 2
-
8 hours ago, arcadeshopper said:
Yes the HDX MOD uses battery backed ram to load the DSR ROM for the RS232 card..
www.ti99-geek.nl/Projects/ti99hdx/ti99hdx.html
Thanks for the reply. I notice you are out of those baby boards. Any thoughts on when another run will be made? I don't think I am going the HDX route for now.
I would like to try my crazy idea of putting my own RS232 driver on the board.
It's easy to BLIT the original code from Forth so I can keep the bank switch idea if your board supports that functionality as I saw in the original project online.
Or if all else fails I can always put the ROM back.
-
The weirdest bug
Last month I went through my VDP routines to make them compliant with advice from Tursi that hitting the VDP ports in any way with Interrupts on was a no/no.
I was still randomly getting an error every now and again in the debugger but I couldn't pin-point when it would happen.
I opened up the heat map for a different reason yesterday and I saw this line running slowly through the entire memory map!
When the line hit the VDP port addresses that green comet flew through the heatmap.
I traced it to the code that runs when a Forth variable runs. The cursor variable was being repeatedly read in the input loop.
CODE: DOVAR ( -- addr) \ Executor that executes a "VARIABLE" *SP DECT, \ make room in TOS R4 *SP MOV, \ mov TOS register to stack R8 R4 MOV, \ put contents of PFA in TOS NEXT, END-CODE
I still do not know why it did it. I moved the code to another place in the source code so see what would happen...
The line went away but I am still seeing: Warning: PC >A072 reading VDP with LIMI 2
It is still happening at address >A072 but a different piece of code is there now.
More sleuthing to do.
It's tough when you use homemade tools.
- 2
-
Lol.
I knew I could get a PASTEALL function going pretty quickly but it was easier than I thought.
Here is the code:
: PASTEALL BEGIN CLIPBOARD? WHILE INSRT-LINE CLIP2LINE SPINNER REPEAT LIST UPDATED ;
- 2
-
Thank you. This is the first big application I have released to the community beyond the Forth system itself so I am a little shy.
I noticed the "outbreak" of editors too. Maybe it's another virus circulating.
Ok I am with you on all those features. I can expand the exit window have more lines as well with a few tweeks if that has value to you.
-
Files larger than 511 lines
- I made a prototype that gave me 1000 lines.
- I am wasting tons of space using a record based internal structure which bugs me. I am looking at alternatives.
-
80 columns support with the F18A
- It current runs in 80 columns out of the box but I have to preload my 80 column library first. I will make a version with that)
-
Printing to PIO (I like my old trusty dot-matrix parallel printer )
- Cool! I can make a PRINT command that takes the TI-99 device string as a parameter so you should be able to "print" to any legal TI-99 device.
- Ultimately I want PRINT to run as a separate task. That requires that I write my own drivers (PIO is pretty trivial) since the DSRs don't behave well in a cooperative environment.
-
BLOCK copy/paste
- I have that on a todo list down the road. I will need to provide an inverted char set which I can do simply enough, and select a keystroke to "mark" a section and a keystroke to copy the section to clipboard. (DOS used to use ENTER to end the marking process so that will do)
- Then I need a command key to paste the entire clipboard rather that just one line. Control P sounds like a mnemonic choice. I can add control P pretty quickly.
I will keep noodling on this and post an update when I am happy with the results.
- 4
-
Files larger than 511 lines
-
2 minutes ago, BeeryMiller said:
Sorta, yes. MDOS on the Geneve uses it's master DSR and does not use the DSR on the card. If you think you are going to go that route, you are going to need to support TI, Myarc, and CorComp. The Geneve has a test routine to identify the cards I think Jeff White came up with years ago.
Beery
OK. Good to know.
Supporting all those platforms is way outside my scope.
It's not really a practical idea unless everyone gets a new RS232 card with the battery RAM.
I supposed it wouldn't be too much to write a loader or use some existing loader to allow others to use a card like this. (?)
For me it's about wasting memory in program space for the driver when there is address space devoted to the job on the card. ?
I understand the serial port cards are hard to come by now but it might be fun to mod a second card at CRU >1500 for this purpose.
It would certainly be the way to go for writing new DSRs for the card.
- 1
-
Programmable RS232 DSR ?
I didn't want to start another topic so I am putting this here.
I find the RS232 DSR code pretty useless for my (very tiny) world. In a cooperative multi-tasking system blocks of code that don't yield when they are busy are very bad.
This has meant that I ignore it and wrote my own driver.
After building and using a super cart it occurred to me that the RS232 might benefit from a battery backed-up RAM, letting the programmer load a driver that works for them.
Has this ever been done?
Any thoughts?
I must confess that thought of being able to compile a Forth driver into the card and/or blit a memory image into it when a program starts, makes me salivate just a little.
- 2
-
ED99 V1.0
I am finally modestly content with the ED99 editor. Here is ZIP file with the whole thing wrapped up as an EA5 program. (Thanks Tursi for that amazing emulator)
I also uploaded a video showing ED99 in operation so people can get a quick start on how to use it.
Features I like:
- Cut and Paste to a line clipboard
- DIR and CAT commands available at command line
- Holds 10 files simultaneously. (needs 1M SAMS card)
(Not mentioned in the video but the Forth DSK1.TOOLS is buried inside the editor so you actually have a working Forth development system here)
Also DSK1.ED99DOC now also has the BYE command documented. No need to turn off the machine)
Things to add:
-
Expand the max file size beyond 511 lines
- Might have to change the internal data organization
- And some UNDO capability
- File MERGE command
- File COPY command
- File PRINT command via RS232. (background is the goal)
- 1
- 1
-
I found a paper that gives two options.
https://dl.acm.org/doi/pdf/10.1145/146559.146561
Token-Pointer Threading
The Code Field contains a token signifying if this is a primitive or a secondary.
The Parameter Field contains:
- Primitives: the machine-language definition of the word, ended with a jump to next . (the Forth interpreter)
- Secondaries: a list of pointers to the subwords in the definition, terminated with a pointer to return
Token-token Threading
The Code Field contains a token signifying if this is a primitive or a secondary.
The Parameter Field contains:
- Primitives: the machine-language definition of the word, ended with a jump to next.
- Secondaries: a list of tokens of the sub-words in the definition, terminated with the token for return.
- 1
-
On 6/22/2020 at 5:28 PM, apersson850 said:
How do they mix 16-bit and 8-bit codes? Or is that not possible?
I have not looked deeper than the surface. Got sidetracked working on my editor.
From what I gather there are different ways people do it. Anything is possible and probably somebody has tried it with Forth.
I will have to look into it further. I would think there would have to be a primary token that tells the interpreter the next 2 bytes are a (table,token) pair?
How is it handled in USCD Pascal?
-
ED99 SAMS Library Option for faster editor performance
The published source code for ED99 uses the DSK1.SAMSFTH library file which allows SAMS card access written in Forth.
There is a native code version of the same functionality called DSK1.SAMS. You can improve the SAMS speed by about 40% by using this library.
Open the source code for ED99 in an editor and look and the NEEDS lines at the top the file.
Change the line FROM DSK1.SAMSFTH -to- FROM DSK1.SAMS
When you recompile ED99 you will find that memory purges, file loads and saves are faster and scrolling line by line is faster as well.
- 1
-
Bug Fix to ED99 keyboard speed
In my various attempts to solve the repeating key problem I added a line to RKEY that read a key and threw it away. It was a failed attempt to prevent random characters in the output.
This obviously slows down the ability to read keys from a fast typist and it is no longer needed since the real problem was corrected in KEY?
I forgot to remove this line from the RKEY library file.
Fortunately it is an easy fix and you can do it yourself.
INCLUDE DSK2.ED99 in the CAMEL99 system (wait 1 minute for the compile) {or you could use the E/A editor if you are in a hurry}
When the PURGE has completed type: EDIT DSK1.RKEY
Page down to the following code:
: RKEY ( -- char) (RKEY) DROP VPOS VC@ \ read char from screen BEGIN PAUSE TMR@ 1FFF > \ read 9901 timer, compare to 50% expired IF CURS @ \ true? fetch cursor char ELSE DUP \ false? use screen char THEN VPUT (RKEY) ?DUP UNTIL SWAP VPUT ; \ put the char back
- Cursor to the line (RKEY) DROP.
- Press FCNT 3 or Alt 3 on a PC and remove the line.
- Press escape and type SAVE
- Type REMOVE to remove the editor but keep all the support code.
- Type INCLUDE DSK2.ED99 to re-compile the editor.
You will find the keyboard now has normal response.
- 1
-
Do all the TI99 games use the interrupt driven sound player?
It can be done from within the user program so that the program has intimate knowledge of where the list is playing at any given moment using a cooperative thread.
The 9900 makes this pretty efficient by using a separate workspace for the player thread. It does take some fine tuning to make the music play at consistent speed so that might persuade people to take the interrupt method but there are other ways to do it.
- 1
-
Trying ED99 in 80 column mode
After Forth starts type:
INCLUDE DSK1.80COL
The screen resets into 80 column mode. type:
INCLUDE DSK2.ED99
-
Camel99 Forth Update 2.62
This is a bug fix for the KSCAN routine that made repeating key (RKEY) routine fail erratically.
There are now two E/A5 binary programs
- CAMEL99 is the 8K program which loads at >A000 as before
- CAML99SC is the 8K program which loads at >6000 and requires a SuperCart or Classic99 Emulator. This program gives you 8K more CPU RAM.
With RKEY working this version has a working version of ED99, an text editor for Camel99 Forth that handles 10 files simultaneously. It requires a SAM 1M card
It is possible to copy multiple lines to the clipboard, with ^C, from one file, change to another file and paste lines into the other file.
It works in 40 columns and seems to compile and run fine in 80 columns (looking forward to someone testing that for me)
More loadable functions are coming... ( COPY file into current file, LOAD current file as Forth code, THRU compile specific line numbers as Forth code and a background printer would be nice)
The editor uses the common key commands that we are used to in the simple TI Editor. For fancy stuff you press escape (FNCT BACK) which drops you into the Forth interpreter.
To compile the editor at the Forth ok prompt type: INCLUDE DSK2.ED99
Here are the key commands:
Function Key ----------- --------- TAB TAB PGDN FCTN 6 DEL-CHAR PC Delete / FCTN 1 Insert/Overwrite PC Insert / FCTN 2 Insert NEW-LINE FCTN 8 DEL-LINE FCTN 3 Cursor LEFT PC Arrow / FCTN S Cursor RIGHT PC Arrow / FCTN D Cursor Down PC Arrow / FCTN X Cursor Up PC Arrow / FCNT E Previous Page PGUP / FCTN 4 ENTER ENTER ( Inserts a new line as well) ESCAPE to commands Esc COPY-LINE Ctrl C ( non-destructive) Goto end of line Ctrl D BSPACE & del char Ctrl Backspace Start of line Ctrl U / PC Home PASTE Ctrl V CUT Ctrl Y Next File No. Ctrl > Tab left Ctrl TAB Previous File No. Ctrl <
Here is the slightly updated text commands:
ED99 Interpreter Commands --------------------------- : GET <dsk?.path> load file, remain in interpreter : EDIT [ <dsk?.path? ] Optional file path. Edit the current file OR Load path : GO ( LINE# ) GOTO the line # in the file : FILE ( file# ) select the file# segment : >> Goto next file# : << Goto previous file# : SAVEAS <dsk?.path> save current file as new file path name : SAVE Save the current file with current file path. : PURGE Erase memory for the current file number. : PURGEALL Erase the memory segments for all files. : SAVEALL Save all files that have been updated
New START file:
I have changed the DSK1.START file so that it loads DSK1.MARKER and DSK1.LOADSAVE. This allows the START file to load binary font file and then remove the loader from memory.
This happens so fast that it doesn't seem to be a big inconvenience. If you don't like it comment it out of the DSK1.START.
If you need help creating new fonts see the "SRC" files on DSK2. These examples are pretty easy for a TI-99 programmer but just ask if you need help.
\ V2.1 START file loads NEEDS/FROM and then loads ANS Forth extensions S" DSK1.SYSTEM" INCLUDED NEEDS MARKER FROM DSK1.MARKER MARKER RECLAIM NEEDS LOAD-FONT FROM DSK1.LOADSAVE S" DSK2.FONT0230" LOAD-FONT RECLAIM HEX 17 7 VWTR CR RP0 40 + HERE - DECIMAL . ." bytes free" CR CR .( Ready) HEX
Replaced with V2.62b
- 2
- 1
-
So it's not as fancy as ATOM but it runs on a TI-99.
So for anyone who wants to review/beat it up, here is what I will call V 0.9 of ED99.
It requires a SAMS card or Classic99 with SAMS enabled.
It also requires Camel99 V2.62 which I have not published but I will shortly.
It will run on 2.61 but the repeating key will clobber the file contents randomly. Not cool.
Notes:
- User commands can be seen at the bottom of the file.
- On the PC the Esc key drops you out of the editor into the Forth interpreter at the bottom of the screen.
- In lieu of documentation review the CASE statement on line 377 to learn the keyboard controls.
- Many are the same as the TI Editor to minimize the learning curve.
- 10 files can be loaded at the same time.
- CTRL Y yanks lines from the file an puts them on a line-stack. This takes a couple of seconds for a file of 500 lines but it works.
- CTRL V will put the line-stack line back into the file.
- In the Forth interpreter you can "INCLUDE DSK1.DIR" to have access to a "dir" command to see what's on your disks.
- There is only about 7K of memory left when the editor and TOOLS are loaded. I will be working some solutions to expand that memory.
Spoiler\ ED99 SAMS memory file editor for CAMEL99 Forth Apr 2020 Brian Fox NEEDS .S FROM DSK1.TOOLS NEEDS CASE FROM DSK1.CASE NEEDS READ-LINE FROM DSK1.ANSFILES NEEDS PAGED FROM DSK1.SAMSFTH NEEDS -TRAILING FROM DSK1.TRAILING NEEDS VTYPE FROM DSK1.VTYPE NEEDS .R FROM DSK1.UDOTR NEEDS RKEY FROM DSK1.RKEY .( .) HERE CR .( ED99 Multi-file Editor V0.9 BFox 2020) CR 80 CONSTANT TOPBAR 81 CONSTANT BOTBAR 1000 CONSTANT 4K \ cursor characters DECIMAL 95 CONSTANT ULINE 30 CONSTANT BAR 31 CONSTANT BOX \ screen management & record constants C/L@ CONSTANT WIDTH \ screen width. Detects 40/80 columns 80 CONSTANT #80 \ length of file records 16 CONSTANT EL/SCR \ editor lines per screen 128 CONSTANT RECSIZE 500 CONSTANT MAXLINES WIDTH 1- CONSTANT RMARGIN VARIABLE INSERTING \ utility words : GETXY ( -- COL ROW) VROW 2@ ; : BLANKS ( adr len -- ) BL FILL ; : BETWEEN ( n lo hi -- ? ) 1+ WITHIN ; : CURSOR ( char -- ) CURS ! ; .( .) \ graphics helpers HEX 0800 CONSTANT PDT \ "pattern descriptor table" : ]PDT ( char# -- 'pdt[n]) 8* PDT + ; : CHARDEF ( addr char# --) ]PDT 8 VWRITE ; : HLINE ( col row char cnt --) 2>R >VPOS 2R> VFILL ; : COLORS ( fg bg -- ) SWAP 4 LSHIFT SWAP + 7 VWTR ; : FORTHCOLOR 1 7 COLORS ; : EDCOLOR F 5 COLORS ; HEX CREATE DBLN 0000 , FF00 , FF00 , 0000 , CREATE SGLN 0000 , 0000 , FF00 , 0000 , CREATE VERT A0A0 , A0A0 , A0A0 , A0A0 , CREATE ABOX FC84 , 8484 , 8484 , 84FC , .( .) HEX : DEF-CHARS DBLN TOPBAR CHARDEF SGLN BOTBAR CHARDEF ABOX BOX CHARDEF ; \ busy spinner ... VARIABLE SPIN# CREATE SCHARS CHAR | C, CHAR / C, CHAR - C, CHAR \ C, : SPINCHAR ( -- char ) SPIN# @ 1+ 3 AND DUP SPIN# ! SCHARS + C@ ; : SPINNER ( -- ) SPINCHAR GETXY >VPOS VC! ; \ SCREEN formatting ... DECIMAL .( .) \ Multiple file manager indexed via the SEG variable in SAMS. \ SAMS implementation uses only SEGMENTS 1..15 \ SEG variable indexes into FILENAMES and editor state variables DECIMAL CREATE FILENAMES \ counted strings 15 bytes + COUNT BYTE S" deadbeefdeadbee" S, \ SEG=0 NOT USED S" DSK1.UNTITLED " S, \ 1 S" DSK1.UNTITLED " S, \ 2 S" DSK1.UNTITLED " S, \ 3 S" DSK1.UNTITLED " S, \ 4 S" DSK1.UNTITLED " S, \ 5 S" DSK1.UNTITLED " S, \ 6 S" DSK1.UNTITLED " S, \ 7 S" DSK1.UNTITLED " S, \ 8 S" DSK1.UNTITLED " S, \ 9 S" DSK1.UNTITLED " S, \ 10 : FILENAME ( -- caddr) SEG @ 16 * FILENAMES + ; \ EVARS can hold 10 different values. One for each SAMS segment : EVAR: ( -- addr ) \ nil 1 2 3 4 5 6 7 8 9 10 CREATE 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , DOES> SEG @ CELLS + ( -- addr) ; EVAR: LASTLINE EVAR: TOPLINE EVAR: SOL \ start of line EVAR: EROW EVAR: ECOL EVAR: UPDT : UPDATED UPDT ON ; : ERASELN ( col row -- )AT-XY VPOS WIDTH BL VFILL ; \ EROW is screen row we are editing,TOPLINE the topline on the screen. : REC# ( -- n ) EROW @ TOPLINE @ + ; \ the record we are editing : .FILENAME ( -- ) 0 0 AT-XY ." #" SEG @ 2 .R ." | " VPOS 16 BL VFILL FILENAME COUNT VTYPE UPDT @ IF ." *" THEN ; : .LINE# ( -- ) RMARGIN 12 - 0 AT" Line " REC# 3 .R ." /" LASTLINE @ 3 .R ; : RULER$ ( -- addr len) S" 0----+----1----+----2----+----3----+----4----+----5----+----6----+----7-" ; : .TOPBAR ( -- ) RULER$ SOL @ /STRING C/L@ MIN 0 1 >VPOS SWAP VWRITE ; : .BOTBAR ( -- ) 0 18 C/L@ BOTBAR HLINE ; : .HEADER ( -- ) .FILENAME .LINE# .TOPBAR ; : DRAW.SCR ( scr# -- ) PAGE .HEADER .BOTBAR ; \ compute address of 128 byte record in any SAMS segment : ]RECORD ( n -- addr) RECSIZE * PAGED ; : [REC#]RECORD ( -- ) REC# ]RECORD ; : WRITELN ( VDPaddr CPUaddr -- ) SOL @ + OVER WIDTH VWRITE ; : LIST ( -- ) 0 2 >VPOS ( -- VDPaddr ) TOPLINE @ DUP EL/SCR + SWAP DO ( VDPaddr ) I ]RECORD WRITELN WIDTH + ( -- VDPaddr' ) LOOP DROP ; .( .) DECIMAL : PROMPT: ( -- ) 0 19 ERASELN ; : STATUS: ( -- ) 0 1 ERASELN ; : CLIP ( n n1 n2 -- n1..n2) ROT MIN MAX ; : ?ERR ( ERR# $addr len -- ) ROT ?DUP IF PROMPT: TYPE . KEY DROP ABORT THEN ; : ?OPENERR ( n -- ) ?DUP IF . TRUE ABORT" Open error" THEN ; : ?R/WERR ( n -- ) ?DUP IF . TRUE ABORT" R/W error" THEN ; : ?CLOSERR ( N -- ) ?DUP IF . TRUE ABORT" Close error" THEN ; .( .) DECIMAL : LOADDV80 ( addr len -- ) 2DUP FILENAME PLACE DV80 R/O OPEN-FILE ?OPENERR >R TOPLINE OFF LASTLINE OFF BEGIN PAD DUP 80 R@ READ-LINE ?R/WERR ( -- pad len ?) WHILE LASTLINE @ ]RECORD ( pad len record) SWAP CMOVE SPINNER LASTLINE 1+! REPEAT R> CLOSE-FILE ?CLOSERR ; .( .) \ save SAMS memory, remove trailing zeros VARIABLE SH \ save handle var is simpler inside DO/LOOP : SAVEDV80 ( addr len -- ) DV80 W/O OPEN-FILE ?OPENERR SH ! LASTLINE @ 1+ 0 ?DO I ]RECORD #80 -TRAILING 1 MAX SH @ WRITE-LINE ?R/WERR SPINNER LOOP SH @ CLOSE-FILE ?CLOSERR ; .( .) \ cursor movement DECIMAL : HOMECURS ( -- ) EROW OFF ECOL OFF ; : COL&ROW ( -- ecol erow) ECOL @ EROW @ 2+ ; \ Editor's X,Y on vdp : PUTCURS ( -- ) COL&ROW AT-XY ; : EDLINE ( -- addr len ) [REC#]RECORD #80 ; : BLKCURS ( -- n ) ECOL @ SOL @ + ; \ cursor pos. in record : 'CHAR ( -- adr ) [REC#]RECORD BLKCURS + ; \ address in disk block : !CHAR ( n -- ) 'CHAR C! ; : 'EOL ( -- adr ) EDLINE 1- + ; \ End of Line address : RIGHTSIDE ( -- addr len) EDLINE BLKCURS /STRING ; : 'SCRPOS ( -- vdpaddr) COL&ROW >VPOS ; : RELINE ( -- ) RIGHTSIDE DROP ( -- addr ) WIDTH ECOL @ - ( -- addr bytestoend) 'SCRPOS ( -- addr bytestoend vdpaddr) SWAP VWRITE PUTCURS ; .( .) : REDRAW ( -- ) .HEADER LIST PUTCURS ; : |MARGINS| ( n -- n') 0 RMARGIN CLIP ; \ left/right text window scrolling : SOL+! ( n -- ) SOL @ + |MARGINS| SOL ! ; \ 0..79 virtual screen wih : HORIZONTAL ( n -- ) SOL+! REDRAW ; \ +n slide right, -n slide left : TOPLINE+! ( n -- ) TOPLINE @ + 0 MAXLINES 15 - CLIP TOPLINE ! ; : LASTLINE! ( -- ) LASTLINE @ REC# MAX LASTLINE ! ; \ decrement a varible, clip at zero : SAFE-! ( n addr -- ) TUCK @ SWAP - 0 MAX SWAP ! ; : LEFT ( -- ) \ automatically scrolls screen if at limits ECOL 1 OVER SAFE-! @ 0= IF -1 HORIZONTAL THEN RELINE ; : RIGHT ( -- ) ECOL 1+@ RMARGIN > IF 1 HORIZONTAL RMARGIN ECOL ! THEN RELINE ; \ end allows escaping from a routine in an IF statement : END ( -- ) S" EXIT THEN " EVALUATE ; IMMEDIATE : AT-EOF? ( -- ?) REC# LASTLINE @ = ; : MEMFULL? ( -- ) LASTLINE @ MAXLINES = ; : .MEMFULL ( -- ) PROMPT: ." Mem full" HONK 1000 MS REDRAW ; : +LINE ( -- ) AT-EOF? IF HONK END EROW DUP @ 1+ SWAP ! EROW @ 15 > IF 1 TOPLINE+! 15 EROW ! THEN LASTLINE! REDRAW ; : -LINE ( -- ) EROW 1 OVER SAFE-! @ 0= IF -1 TOPLINE+! THEN REDRAW ; : -TAB ( -- ) ECOL -8 HORIZONTAL REDRAW ; : +TAB ( -- ) ECOL 8 OVER +! @ RMARGIN > IF 8 HORIZONTAL RMARGIN ECOL ! THEN REDRAW ; : TOSTART ( -- ) ECOL OFF SOL OFF RELINE REDRAW ; \ this is complicated because we manage 2 cursor variables \ ECOL and SOL (start of line) : TOEND ( -- ) EDLINE -TRAILING NIP DUP RMARGIN < IF |MARGINS| ECOL ! ELSE WIDTH SOL ! ECOL OFF RIGHTSIDE -TRAILING NIP |MARGINS| ECOL ! THEN RELINE REDRAW ; .( .) \ page movement : PGUP ( -- ) TOPLINE @ 0= IF EROW OFF ELSE -16 TOPLINE+! THEN REDRAW ; : PGDN ( -- ) REC# EL/SCR + LASTLINE @ > IF HONK END 16 TOPLINE+! REDRAW ; \ EDITOR functions DECIMAL .( .) : WRITECHAR ( c -- ) DUP !CHAR VPUT RIGHT UPDATED ; : DELCHAR ( -- ) RIGHTSIDE 1 /STRING \ get string right of cursor, cut leading char 'CHAR SWAP 1+ MOVE \ write buffer back to CURSOR position +1 space RELINE UPDATED ; : PUSHRIGHT ( -- ) RIGHTSIDE PAD PLACE PAD COUNT 'CHAR 1+ SWAP 1- MOVE \ write back at 'CHAR+1 BL !CHAR \ blank at cursor position RELINE UPDATED ; .( .) HEX : TOGGLE ( -- ) INSERTING DUP DUP @ -1 XOR SWAP ! @ IF BAR CURSOR PROMPT: ." Inserting" ELSE BOX CURSOR PROMPT: ." Overwrite" THEN PUTCURS ; DECIMAL : BSPACE ( -- ) LEFT INSERTING @ IF DELCHAR ELSE BL DUP !CHAR VPUT THEN PUTCURS ; : ESCAPE ( -- ) FORTHCOLOR PROMPT: ." Forth ok" [CHAR] _ CURSOR CR QUIT ; \ VDP clipboard is a stack of lines in VDP RAM HEX 1000 CONSTANT CLIPBASE \ start of VDP RAM clipboard : VDPHEAP ( -- vaddr) VP @ ; : VMALLOC ( n -- vaddr ) VP +! VDPHEAP ; : VFREE ( -- ) VDPHEAP #80 - CLIPBASE MAX VP ! ; DECIMAL \ clipboard management : LINE2CLIP ( -- ) [REC#]RECORD #80 VMALLOC #80 VWRITE ; : CLIP2LINE ( -- ) VDPHEAP [REC#]RECORD #80 VREAD VFREE ; DECIMAL : MARK-EOF ( -- ) S" <End of File>" LASTLINE @ 1+ ]RECORD 13 + SWAP MOVE ; \ Need to double buffer record moves for page to page transfers : DEL-LINE ( -- ) AT-EOF? 0= IF LASTLINE @ 1+ REC# ?DO H @ I 1+ ]RECORD OVER #80 CMOVE ( heap) I ]RECORD #80 CMOVE SPINNER LOOP ELSE [REC#]RECORD RECSIZE BLANKS -LINE THEN LASTLINE @ 1+ ]RECORD #80 BLANKS 1 LASTLINE SAFE-! MARK-EOF REDRAW UPDATED ; HEX : CUT ( -- ) VDPHEAP CLIPBASE < IF HONK END LINE2CLIP DEL-LINE UPDATED ; : DEL-CHAR ( -- ) EDLINE -TRAILING 0 MAX \ blank line? IF DELCHAR ELSE DEL-LINE THEN UPDATED ; : COPY-LINE ( -- ) VDPHEAP CLIPBASE < IF HONK END LINE2CLIP ; DECIMAL : INSRT-LINE ( -- ) LASTLINE 1+! REC# LASTLINE @ ?DO H @ I ]RECORD OVER #80 CMOVE I 1+ ]RECORD #80 CMOVE SPINNER -1 +LOOP UPDATED ; : NEW-LINE ( -- ) MEMFULL? IF HONK END INSRT-LINE [REC#]RECORD #80 BLANKS RELINE REDRAW UPDATED ; : PASTE ( -- ) CLIPBASE VDPHEAP >= IF HONK END INSRT-LINE CLIP2LINE REDRAW UPDATED ; : +FILE ( -- ) SEG @ + 1 10 CLIP SEG ! REDRAW .FILENAME PUTCURS ; : ENTER ( -- ) MEMFULL? IF .MEMFULL END ECOL @ 0= IF EDLINE 2DUP PAD PLACE BLANKS INSRT-LINE +LINE PAD COUNT [REC#]RECORD SWAP MOVE ELSE +LINE NEW-LINE THEN TOSTART ; .( .) HEX : KEYHANDLER ( char -- ) \ TI-99 BASIC key codes used CASE 01 OF +TAB ENDOF \ TAB 02 OF PGDN ENDOF \ FCTN 6 03 OF DEL-CHAR ENDOF \ PC Delete / FCTN 1 04 OF TOGGLE ENDOF \ PC Insert / FCTN 2 06 OF NEW-LINE ENDOF \ FCTN 8 07 OF DEL-LINE ENDOF \ FCTN 3 08 OF LEFT ENDOF \ FCTN S 09 OF RIGHT ENDOF \ FCTN D 0A OF +LINE ENDOF \ FCTN X 0B OF -LINE ENDOF \ FCNT E 0C OF PGUP ENDOF \ FCTN 4 0D OF ENTER ENDOF \ ENTER 0F OF ESCAPE ENDOF \ Esc 83 OF COPY-LINE ENDOF \ ^C 84 OF TOEND ENDOF \ ^D 93 OF BSPACE ENDOF \ ^backspace 95 OF TOSTART ENDOF \ ^U / PC Home 96 OF PASTE ENDOF \ ^V 99 OF CUT ENDOF \ ^Y 9D OF 1 +FILE ENDOF \ ^+ B7 OF -TAB ENDOF \ ^TAB BB OF -1 +FILE ENDOF \ ^- ENDCASE ; .( .) DECIMAL : PARSE-PATH ( -- addr len) BL PARSE-WORD 2DUP [CHAR] . SCAN NIP 0= ABORT" '.' Path expected" ; : .LINES ( -- ) CR LASTLINE @ DECIMAL . ." lines" ; : (SAVE) ( -- ) FILENAME COUNT SAVEDV80 .LINES UPDT OFF ; .( .) : (PURGE) ( -- ) \ erases 4K pages at once 16 0 DO I 4K * PAGED 4K BLANKS SPINNER LOOP TOPLINE OFF LASTLINE OFF SOL OFF UPDT OFF S" DSK1.UNTITLED" FILENAME PLACE HOMECURS ; HEX : EDIT ( -- ) DECIMAL DEF-CHARS EDCOLOR DRAW.SCR INSERTING ON TOGGLE BOX CURSOR CLIPBASE VP ! \ set clipboard in VDP RAM SAMS-ON LIST BEGIN RKEY DUP BL [CHAR] ~ BETWEEN IF INSERTING @ IF PUSHRIGHT THEN WRITECHAR ELSE KEYHANDLER THEN AGAIN ; DECIMAL \ User commands : GO ( page# --) 1 LASTLINE @ CLIP TOPLINE ! EDIT ; : FILE ( n -- ) SEGMENT EDIT ; : SAVEAS ( -- ) PARSE-PATH FILENAME PLACE (SAVE) ; : SAVE ( -- ) BL PARSE-WORD NIP 0> ABORT" Use SAVEAS command" (SAVE) ; : LOAD ( -- ) ." Purge " (PURGE) ." Loading" PARSE-PATH 2DUP FILENAME PLACE LOADDV80 MARK-EOF .LINES ; : PURGE ( -- ) (PURGE) MARK-EOF DRAW.SCR PROMPT: ." Ready" ; : PURGEALL ." Purging segments" CR 11 1 DO I DUP . SEGMENT (PURGE) MARK-EOF LOOP 1 SEGMENT ; CR ." ED99 loaded. " HERE SWAP - DECIMAL . .( bytes used) PURGE
- 1
-
Beware of feature creep.
Your imagination is infinite.
I chose to make a line-stack for cutting so when you cut lines they pile up on the line-stack and when you Paste they come off the line-stack.
The line stack is in VDP RAM at the moment.
The feature I really miss is ctrl Z. Undo. Gotta study some methods on how to do that without sucking up the entire machine.
- 2
- 1
-
Ok so there be a future use for CALL. All good. Just curious.
I am finalizing a working version of my ED99 SAMS editor with my repaired repeating KSCAN routine. (rather embarrassing)
Anyway it is working pretty well now. I just added some commands for the user to "GO" to a line number.
- 1
-
Just now, GDMike said:
No absolutely nothing.. but in forth when I was doing a similar thing CALL was
: CALL decimal ;
So does the user need to type it or can they just type CHAR(XXX) ?
- 1
Assembly code samples
in TI-99/4A Development
Posted
I don't use the conventional tools but I make use of Assembler macros to help my brain. I have written up the ideas in "psuedo" Assembler code.
(Do people use a macro-assembler for the TI-99?)
The concept is that a "leaf" is the native 9900 sub-routine and you keep them for those little fast things and you know you will never nest them.
For bigger sub-routines I like the stack that Apersson created but I automate it with macros. With a good macro assembler you can get the code to a pretty hi level.
(Some Assembler coders might call that heresy)