+Lee Stewart Posted July 20, 2014 Author Share Posted July 20, 2014 Well—I finally finished my translation of the 40/80-column fbForth editor. Now for the painful job of debugging it! It's currently occupying 2148 bytes. There are surely tweaks that could reduce that; but, I must first get what I have cleaned up! Maybe sometime this week for the next beta. ...lee 1 Quote Link to comment Share on other sites More sharing options...
Omega-TI Posted July 21, 2014 Share Posted July 21, 2014 In case anyone may be interested in slapping a label on a future fbForth cartridge, there is a file with three different styles... << HERE >> 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted July 27, 2014 Author Share Posted July 27, 2014 I know—my debugging has taken far too long! I got side-tracked on an OOo Writer macro for about a week—kept banging my head against a longstanding bug in OOo's macro recorder. Now, back to debugging the 40/80-column editor. It's probably going to be awhile yet because I keep running into indirection errors I made in translating from Forth to ALC. I keep forgetting (I'm old, dontcha know) that I can only execute indirect addresses in registers! I also just discovered that I'd loaded a jump table address into a register and jumped to it (the DATA statement!?!) instead of indirectly to the contained address! Oh, well—I'll eventually get there thanks to Classic99's Debugger. It's still painful, though. I keep thinking there must be some tricks I'm missing. I have used the X instruction to manipulate jumps, which was inspired by @Tursi's implementation of the bitmap LINE word a few posts back. Right now, however, I'm just going to focus on making the editor work. Then, perhaps, I can reduce its footprint—I don't know. Anyway—I'm back on it... ...lee 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted July 28, 2014 Author Share Posted July 28, 2014 I am now much farther along than I ever thought possible. I think I only have TAB and -TAB (moving the cursor forward and backward by words through the block being edited) to fix. They almost work, but not quite. As long as everything holds up through this storm that's passing through in the next hour or so, I should have another beta in a day or two! ...lee 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted July 28, 2014 Author Share Posted July 28, 2014 I am pretty much done with the 40/80-column editor. I need to fix a couple of routines that should be setting the dirty bit, but are not. I also may include a navigation menu à la @Willsy's TurboForth editor. I should have a new beta by day's end. For those interested in how I used the X instruction to vary jumping in the TAB and -TAB routines, here they are for your delectation: ;[*++ TAB *++ These instruction codes need to be updated whenever changes *++ are made to increase the distance between "X R2" and either *++ of the jump targets, TABBL or TABNOB. JEQTAB EQU >1306 ; "JEQ TABBL" for X instruction JNETAB EQU >1609 ; "JNE TABNOB" for X instruction TAB MOV @EDBLK,R0 ; get block address A @CUR,R0 ; get cursor address LI R4,1024 ; load counter with maximum S @CUR,R4 ; adjust to cursor location LI R2,JEQTAB ; set jump address for "blank found" TAB01 CB *R0,@CONBL ; is it a blank? X R2 ; execute jump instruction TAB02 DEC R4 ; decrement counter JEQ TABNOB ; jump if we're done: INC R0 ; increment block address INC @CUR ; increment block cursor JMP TAB01 ; let's check another character TABBL LI R2,JNETAB ; set jump address for "blank not found" JMP TAB02 ; continue *++ we found the next word or reached the end of the block TABNOB BL @DCUR ; update CURPOS etc. B @VEDLP ; return to editor loop ;]* ;[*++ -TAB *++ These instruction codes need to be updated whenever changes *++ are made to increase the distance between "X R2" and any *++ of the jump targets, BTABL1, BTBNOB or BTABL2. JEQBT1 EQU >1306 ; "JEQ BTABL1" for X instruction JNEBTB EQU >1609 ; "JNE BTBNOB" for X instruction JEQBT2 EQU >130C ; "JEQ BTABL2" for X instruction BTAB MOV @EDBLK,R0 ; get block address A @CUR,R0 ; get cursor address MOV @CUR,R4 ; load cursor location INC R4 ; correct counter LI R2,JEQBT1 ; set jump address for "blank found" the 1st time BTAB01 CB *R0,@CONBL ; is it a blank? X R2 ; execute jump instruction BTAB02 DEC R4 ; decrement counter JEQ TABNOB ; if we're done, finish up in TAB routine DEC R0 ; decrement block address DEC @CUR ; decrement block cursor JMP BTAB01 ; let's check another character BTABL1 LI R2,JNEBTB ; set jump address for "blank not found" JMP BTAB02 ; continue *++ we found a non-blank character BTBNOB LI R2,JEQBT2 ; set jump address for "blank found" the 2nd time JMP BTAB02 ; continue *++ we found the blank before the previous word or reached the beginning of the block BTABL2 INC @CUR ; restore cursor to 1st char of word we just passed JMP TABNOB ; finish up in TAB routine ;]* ...lee 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted July 28, 2014 Author Share Posted July 28, 2014 OK—The beta 6 files are posted in the Post #1 of this thread. Let me know what problems you find—particularly with the 40/80-column editor, which is now part of the resident dictionary and is invoked by <block#> EDIT 1 EDIT will start the editor with block #1 of the current blocks file (default is FBLOCKS). More detailed instructions are to be found in the fbForth 1.0 manual in the development thread. I have yet to edit the fbForth 2.0 manual. It'll come. I'm just not quite finished with the fbForth 2.0 cartridge. ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted July 28, 2014 Author Share Posted July 28, 2014 I found an error in the name field of VED , the main function of the 40/80-column editor. It doesn't hurt the editor's function, but VED won't be found with a name search. Instead, there are two LINE words found! That's what happens with cut-n-paste when one is not extremely careful. I will post a corrected version in Post #1 later today or tomorrow. ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted July 28, 2014 Author Share Posted July 28, 2014 Post#1 has the corrected beta 6a files. Please test and apprise me of any problems you find. I have just two more libraries I would like to add to cartridge space before I officially release fbForth 2.0: File I/O—This should be pretty simple because I will probably just translate the original TI Forth library from the blocks file—though I probably should try to improve it a little. Floating Point Math—This will be the library I adapted from the Geneve MDOS library for TurboForth, but this time tailored to fbForth. I don't remember whether @Willsy and I determined if it was faster than the console routines. I know that the display of scientific notation is better. Probably all of the transcendental routines are faster than those in the console, which were written in GPL. I think there might have been an improvement of the accuracy of the SIN routine. The XML-based console routines (+, -, *, /, etc.) might be faster, however, because the console ROMs are on a 16-bit bus. ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted July 29, 2014 Author Share Posted July 29, 2014 Here's the ALC for the 40/80-column editor (all 2366 bytes of it!), in case anyone is interested in perusing/improving it: * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< * >>>>>>>>>>>>>>>>>>>>> 40/80 Column Editor <<<<<<<<<<<<<<<<<<<<<< * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< * ;[*++ OLDCUR variable array +++ Storage for old cursor pattern *++ OLDCUR is located in low RAM ; 8 bytes ;]* ;[*++ CUR variable +++ Storage for block cursor CUR EQU $RNUM+$UVAR ; contains cursor position in block) ;]* ;[*++ S_H variable +++ Storage for 40-column page flag S_H EQU FREEPD ; 0|1 for left|right screen half ;]* ;[*++ EDBLK variable +++ Current block buffer address EDBLK EQU FREEPD+2 ; current block buffer address ;]* ;[*++ CURCH variable +++ Char under cursor (one byte) CURCH EQU FREEPD+4 ; char under cursor (one byte) ;]* ;[*++ EDPAD variable +++ Address of PAD upon entering the editor EDPAD EQU FREEPD+6 ;]* ;[*++ LIN# variable +++ Temp storage for Forth block line# LIN# EQU FREEPD+8 ; temporary storage for Forth block line# ;]* ;[*++ COL# variable +++ Temp storage for Forth block column# COL# EQU FREEPD+10 ; temporary storage for Forth block column# ;]* ;[*++ BLKPOS variable +++ Temp storage for Forth block cursor address BLKPOS EQU FREEPD+12 ; temporary storage for Forth block cursor address ;]* ;[*++ LNSTRT variable +++ Starting line# for call to LINE. LNSTRT EQU FAC+2 ; temporary storage for starting line# for LINE. ;]* ;[*++ LNCNT variable +++ Number of lines for call to LINE. LNCNT EQU FAC+4 ; temporary storage for # of lines for LINE. ;]* * ( RKEY required variables) ;[*++ BLINK variable +++ Cursor blink logger BLINK EQU ARG ; init, 0 ;]* ;[*++ OKEY variable +++ Old key for repeat comparison OKEY EQU ARG+2 ; init, 0 ;]* ;[*++ KC variable +++ Key counter for repeat KC EQU ARG+4 ; init, 0 ;]* ;[*++ RLOG variable +++ Has short or long wait value for repeat logging RLOG EQU ARG+6 ; init, 150 ;]* ;[*++ RL constant +++ Short wait value for key repeats RL DATA 30 ;]* ;[*++ RH constant +++ Long wait value for start of key repeats RH DATA 450 ;]* ;[*++ BOX constant array +++ Editor's cursor pattern BOX DATA >FC84,>8484,>8484,>84FC ; editor's cursor ;]* ;[*++ CON01 constant +++ >0001 CON01 DATA >0001 ; constant for use in various places ;]* ;[*++ CONFF constant +++ >FF CONFF BYTE >FF ; byte constant >FF for comparison ;]* ;[*++ CONBL constant +++ >20 CONBL BYTE >20 ; byte constant >20 = ASCII blank EVEN ;]* ;[*++ CN8000 constant +++ >8000 CN8000 DATA >8000 ; constant for use in various places ;]* ;[*++ Navigation menu string (NAVMNU) NAVMNU BYTE 158 TEXT "F1:Del F2:Ins F3:Del Line F4:Nxt Block " TEXT "F5:30 spcs L/R F6:Prv Block F7:Del EOL " TEXT "F8:Ins Line F9:Exit ESDX:Cursor ^V:Tab " TEXT "ENT:Nxt Line ^8:Ins Blank Line FV:-Tab" EVEN ;]* ;[*++ !CUR ( n --- ) +++ Store new block cursor (n) in CUR *++ Store new block cursor position (n) in CUR *++ STCUR expects n on stack STCUR CLR R0 ; zero R0 C *SP,R0 ; new block cursor pos > 0? JGT STCUR1 ; jump if so MOV R0,*SP ; no, store 0 on stack STCUR1 LI R0,>3FF ; load 1023 for comparison C R0,*SP ; 1023 > new block cursor pos? JGT STCUR2 ; jump if so MOV R0,*SP ; no, store 1023 on stack STCUR2 MOV *SP+,@CUR ; pop new block cursor pos RT ; return to caller ;]* ;[*++ +CUR ( n --- ) +++ Add n to block cursor PLCUR DECT R ; make room on return stack to MOV LINK,*R ; save return A @CUR,*SP ; add current block cursor pos to num on stack BL @STCUR ; update cursor position MOV *R+,LINK ; pop return address RT ; and return ;]* ;[*++ LINE. +++ Display LNCNT lines beginning with line LNSTRT *++ This routine expects two 16-bit values after call: *++ 1. The starting line number in LNSTRT *++ 2. The number of lines to be typed in LNCNT *++ *++ Called by: *++ BL @LINE. *++ *++ Register usage: *++ R0: VRAM screen destination for VMBW *++ R1: RAM Forth block buffer source for VMBW *++ R2: character count for VMBW *++ R3: # lines to process *++ R4: calculation of VRAM screen address *++ R5: " " " " " LINE. MOV @LNSTRT,R4 ; load starting line # (0-15) MOV R4,R1 ; copy for RAM source calc SLA R1,6 ; * 64 to get starting line offset A @EDBLK,R1 ; Forth buffer starting address MOV @LNCNT,R3 ; load # of lines to process (1-16) AI R4,3 ; calc starting screen row MPY @$SWDTH(U),R4 ; calc starting screen-row offset AI R5,3 ; calc starting screen-column offset A @$SSTRT(U),R5 ; calc VRAM starting screen address MOV R5,R0 ; copy to R0 for VMBW LI R2,64 ; load characters/screen-line (assume 80-column MODE) LIMI 0 ; disable interrupts because VMBW doesn't MOV @$VDPM(U),R5 ; 80-column mode? JEQ LINE.1 ; jump if so LI R2,34 ; load characters/line for 40-column mode MOV @S_H,R4 ; right half of 40-column screen? JEQ LINE.1 ; jump if not AI R1,30 ; correct Forth buffer source address LINE.1 BLWP @VMBW ; type a line A @$SWDTH(U),R0 ; calc VRAM screen address for next line AI R1,64 ; calc Forth buffer address for next line DEC R3 ; are we done? JNE LINE.1 ; do another if not LIMI 2 ; restore interrupts RT ; return to caller ;]* ;[*++ LISTL ( block# --- ) +++ Display left half (40-col) or full (80-col) screen LISTL *++ Save stuff DECT R ; make room on return stack to MOV LINK,*R ; save return DECT R ; make room on return stack to MOV @$BASE(U),*R ; save current radix *++ Load requested block and update pointers MOV *SP,@$SCR(U) ; update last block accessed (SCR) BL @BLA2F ; load requested block DATA BLOCK MOV *SP,@EDBLK ; get block buffer address (save stack spot) *++ Type left header ======================================================= *++ Type "BLOCK #n" at top left LI R2,0 ; load x LI R3,0 ; load y BL @GXY ; place text cursor LI R4,B#TXT ; text to type BL @MSGTYP ; type it MOV @$SCR(U),*SP ; get block # to stack BL @BLA2F ; type it DATA DOT *++ Type units digits of line numbers down left side LI R2,16 ; load # of line #s LI R3,LN#S ; next char to write MOV @$SWDTH(U),R0 ; set starting screen address to row 1 SLA R0,1 ; row2 INC R0 ; row 2, column 1 LIMI 0 LSTL01 A @$SWDTH(U),R0 ; next row MOVB *R3+,R1 ; get next char to write BLWP @VSBW ; write it DEC R2 ; are we done? JNE LSTL01 ; nope, write next char *++ Type tens digits (1) of line numbers down left side LI R0,0 ; load x LI R6,13 ; load y LI R1,>3100 ; ASCII[>31] LI R2,6 ; load count BL @__VCHR ; type vertical line of 6 1s *++ Type left side of editing box LI R0,2 ; load x LI R6,3 ; load y LI R1,>CF00 ; ASCII[207] LI R2,16 ; load count BL @__VCHR ; type vertical line *++ Type top row of tens digits LI R2,3 ; load x LI R3,1 ; load y BL @GXY ; place text cursor LI R4,TL10S ; text to type BL @MSGTYP ; type it *++ Type top of editing box LI R2,3 ; load x LI R3,2 ; load y BL @GXY ; place text cursor LI R4,TLLIN ; text to type BL @MSGTYP ; type it *++ Type bottom of editing box LI R0,>CD00 ; get ASCII[205] to R0 MSB for FILL1 (VDP fill routine) LI R1,19 ; load y MPY @$SWDTH(U),R1 ; multiply by SCRN_WIDTH AI R2,3 ; add x A @$SSTRT(U),R2 ; calculate actual VRAM start address for FILL1 LI R1,34 ; put 40-col cnt in R1 for FILL1 MOV @$VDPM(U),R4 ; 80-col mode? JNE LIST02 ; jump if not LI R1,64 ; 80-col cnt LIST02 LIMI 0 ; disable interrupts because FILL1 & VSBW don't BL @FILL1 ; do VFILL *++ Type corners of editing box LI R2,4 ; count LI R3,CNRDAT ; address of corner data MOV @$VDPM(U),R0 ; 80 column? JNE CORNER ; jump if not AI R3,8 ; else point to 80 column data CORNER LI R1,>C900 ; ASCII[201] in msb CRNLP MOV *R3+,R0 ; get address A @$SSTRT(U),R0 ; add SCRN_START BLWP @VSBW ; write to screen AI R1,>0100 ; increment ascii character DEC R2 ; decrement counter JNE CRNLP ; loop if not finished *++ Type right side of 40-column editing box MOV @$VDPM(U),R0 ; 80-column mode? JEQ LIST03 ; jump if so LI R0,37 ; load x LI R6,3 ; load y LI R1,>D000 ; ASCII[208] LI R2,16 ; load count BL @__VCHR ; type vertical line JMP LIST04 LIST03 *++ Type right side of 80-column editing box LI R0,67 ; load x for right side LI R6,3 ; load y LI R1,>CF00 ; ASCII[207] LI R2,16 ; load count BL @__VCHR ; type vertical line *++ Type remainder of top row of tens digits for 80-column editing box LI R2,33 ; load x LI R3,1 ; load y BL @GXY ; place text cursor LI R4,TR10S ; text to type BL @MSGTYP ; type it *++ Type remainder of top of 80-column editing box LI R2,33 ; load x LI R3,2 ; load y BL @GXY ; place text cursor LI R4,TLLIN ; text to type BL @MSGTYP ; type it LIST04 *++ Store 0 in S_H CLR @S_H *++ Type current block CLR @LNSTRT ; starting line = 0 LI R0,16 ; 16 lines to display MOV R0,@LNCNT ; copy for LINE. BL @LINE. ; display the block *++ Clean up and return MOV *R+,@$BASE(U) ; pop old radix and restore it MOV *R+,LINK ; pop return address RT ; and return B#TXT BYTE 8 TEXT " BLOCK #" LN#S TEXT "0123456789012345" TL10S BYTE 31 TEXT "0 1 2 3" TR10S BYTE 31 TEXT "3 4 5 6" TLLIN BYTE 34 BYTE >30,205,205,205,205,206,205,205,205,205,>30 BYTE 205,205,205,205,206,205,205,205,205,>30,205 BYTE 205,205,205,206,205,205,205,205,>30,205,205,205 EVEN *++ location data for corner chars - 40 column mode CNRDAT DATA 2*40+2 ; top left DATA 2*40+37 ; top right DATA 19*40+2 ; bottom left DATA 19*40+37 ; bottom right *++ location data for corner chars - 80 column mode DATA 2*80+2 ; top left DATA 2*80+67 ; top right DATA 19*80+2 ; bottom left DATA 19*80+67 ; bottom right *++ patterns for editing box BDCHRS DATA >0000,>003C,>3C30,>3030 ; ASCII[201], top left corner DATA >0000,>00F0,>F030,>3030 ; ASCII[202], top right corner DATA >3030,>303C,>3C00,>0000 ; ASCII[203], bottom left corner DATA >3030,>30F0,>F000,>0000 ; ASCII[204], bottom right corner DATA >0000,>00FC,>FC00,>0000 ; ASCII[205], horizontal line segment DATA >0000,>00FC,>FC30,>3030 ; ASCII[206], hashed horizontal line segment DATA >3030,>3030,>3030,>3030 ; ASCII[207], vertical line segment DATA >3060,>C070,>380C,>1830 ; ASCII[208], broken vertical line segment ;]* ;[*++ LISTR ++* Display right half of 40-column editor screen LISTR DECT R ; make room on return stack to MOV LINK,*R ; save return *++ Type left side of 40-column editing box LIMI 0 LI R0,2 ; load x LI R6,3 ; load y LI R1,>D000 ; ASCII[208] LI R2,16 ; load count BL @__VCHR ; type vertical line *++ Type right side of editing box LI R0,37 ; load x for right side LI R6,3 ; load y LI R1,>CF00 ; ASCII[207] LI R2,16 ; load count BL @__VCHR ; type vertical line *++ Type top row of tens digits LI R2,3 ; load x LI R3,1 ; load y MOV R3,@S_H ; Store 1 in S_H (interleave to get a free 1) BL @GXY ; place text cursor LI R4,TR10S ; text to type BL @MSGTYP ; type it *++ Type current block CLR @LNSTRT ; starting line = 0 LI R0,16 ; 16 lines to display MOV R0,@LNCNT ; copy for LINE. BL @LINE. ; display the block MOV *R+,LINK ; pop return address RT ; and return ;]* ;[*++ PTR ++* Get address of block cursor to BLKPOS PTR MOV @EDBLK,@BLKPOS ; load beginning block address A @CUR,@BLKPOS ; calculate address of cursor position RT ;]* ;[*++ R_C ++* Get cursor's row and column to LIN# and COL#, respectively *++ Called with: *++ BLWP @R_C *++ *++ Returns: *++ LIN#: Forth block line# *++ COL#: Forth block column R_C DATA UTILWS,R_CENT R_CENT MOV @CUR,R0 ; get block cursor position MOV R0,R1 ; copy for column calc SRL R0,6 ; divide by 64 to get line# MOV R0,@LIN# ; store it MOV R0,R2 ; temp copy SLA R2,6 ; calc col 0 of line# S R2,R1 ; calc column MOV R1,@COL# ; store it RTWP ;]* ;[*++ CMV ++* Copies from low RAM to high RAM or vice versa *++ Pass data in data statements after call as follows: *++ BL @CMV *++ *++ Register usage for input: *++ R0: src *++ R1: dst *++ R2: count *++ R3: inc|dec *++ CMV MOVB *R0,*R1 ; copy src to dst A R3,R0 ; add inc|dec to src A R3,R1 ; add inc|dec to dst DEC R2 ; done? JNE CMV ; copy another if not RT ;]* ;[*++ BLPAD ++* Copies 66 blanks to PAD BLPAD DECT R ; make room on return stack to MOV LINK,*R ; save return MOV @EDPAD,R0 ; PAD address to R0 LI R1,66 ; initialize counter BLPAD1 MOVB @CONBL,*R0+ ; write blank to next PAD location DEC R1 ; decrement counter JNE BLPAD1 ; jump if not done (=0) MOV *R+,LINK ; pop return address RT ; and return ;]* ;[*++ ERASHF ++* Erase from cursor to EOL ERASHF *++ 66 blanks to PAD BL @BLPAD *++ copy remainder of line (from cursor to end of line) to PAD BL @PTR ; get block cursor address MOV @BLKPOS,R0 ; copy it to R0 MOV @EDPAD,R1 ; PAD address to R1 BLWP @R_C ; get cursor line# and column# LI R2,64 ; initialize counter S @COL#,R2 ; correct count LI R3,1 ; we're copying from low RAM to high RAM BL @CMV ; do the copy *++ Blank remainder of line *++ ...BLKPOS and COL# should be correct from above BL @BLNKS ; blank the source of the copy *++ Re-display line, set dirty bit and return to editor loop B @RELINE ; re-display line etc. ;]* ;[*++ .CUR ++* Update CURPOS from CUR, with 40-column left|right display changes *++ DCUR updates CURPOS from CUR, with possible 40-column left|right display changes. DCUR DECT R ; make room on return stack to MOV LINK,*R ; save return DCUR04 BLWP @R_C ; get LIN# and COL# of Forth block cursor MOV @COL#,R2 ; block column to R2 for GXY AI R2,3 ; calc screen column MOV @LIN#,R3 ; block line# to R3 for GXY AI R3,3 ; calc screen row MOV @$VDPM(U),R0 ; 80-column mode? JEQ DCUR01 ; jump if so *++ 40-column adjustments MOV @S_H,R0 ; left half of block? JEQ DCUR02 ; jump if so *++ right-half adjustments CI R2,32 ; [COL#+3]>32? JGT DCUR03 ; jump if so DECT SP ; reserve stack space for block# MOV @$SCR(U),*SP ; push block# to stack BL @LISTL ; show left half of block JMP DCUR04 ; re-update CURPOS DCUR03 AI R2,-30 ; move screen cursor left 30 JMP DCUR01 ; update CURPOS *++ left-half adjustments DCUR02 CI R2,37 ; [COL#+3]<37? JLT DCUR01 ; jump if so BL @LISTR ; display right half of block JMP DCUR04 ; re-update CURPOS *++ Adjust CURPOS DCUR01 BL @GXY ; update CURPOS MOV *R+,LINK ; pop return address RT ; and return ;]* ;[*++ DELLIN ++* Delete current line DELLIN *++ Copy line to be deleted to PAD BLWP @R_C ; get line# and column# of block cursor DECT SP ; reserve stack space MOV @COL#,*SP ; push column# to stack NEG *SP ; negate it BL @PLCUR ; update block cursor to beginning of line BL @PTR ; get address of block cursor MOV @BLKPOS,R0 ; copy to R0 for CMV src MOV @EDPAD,R1 ; copy PAD address to R1 for CMV dst LI R2,64 ; 64 to R2 for cnt for CMV LI R3,1 ; low RAM to high RAM for CMV BL @CMV ; copy the line to PAD *++ move rest of block up 1 line MOV @BLKPOS,R0 ; initialize src to beginning of copied line MOV R0,R1 ; make it dst AI R0,64 ; correct src to beginning of next line LI R2,960 ; initialize cnt to copy 15 lines (1024-64) S @CUR,R2 ; correct it to current cursor location BL @CMV ; do the copy (R3 still set to 1) *++ blank last line MOV @EDBLK,R0 ; get address of current block AI R0,960 ; correct to beginning of last line LI R1,64 ; load counter DELLN1 MOVB @CONBL,*R0+ ; write a blank to next location DEC R1 ; done? JNE DELLN1 ; jump if not *++ cursor should still be pointing to beginning of original line *++ Redraw display with line changes, mark block as dirty and return to editor loop B @REDRAW ;]* ;[*++ BLNKLN ++* Pastes (inserts) a 64-char blank line to start of current block line# BLNKLN *++ Copy lines down 1 line in prep for blanking or pasting to current line BL @INSLIN ; make room for pasting *++ Blank current line# *++ ...BLKPOS and COL# should be correct from INSLIN BL @BLNKS *++ Redraw display with line changes, mark block as dirty and return to editor loop B @REDRAW ;]* ;[*++ PSTELN ++* Pastes (inserts) a 64-char line from PAD to start of current block line# PSTELN *++ Copy lines down 1 line in prep for blanking or pasting to current line BL @INSLIN ; make room for pasting *++ Copy line to be pasted from PAD to beginning of current line# *++ ...BLKPOS should be correct from INSLIN MOV @EDPAD,R0 ; copy PAD address to R0 for CMV src MOV @BLKPOS,R1 ; copy to R1 for CMV dst LI R2,64 ; 64 to R2 for cnt for CMV LI R3,1 ; low RAM to high RAM for CMV BL @CMV ; copy the line to PAD *++ Redraw display with line changes, mark block as dirty and return to editor loop B @REDRAW ;]* ;[*++ INSLIN ++* Insert line, preparing for pasting or blanking INSLIN DECT R ; make room on return stack to MOV LINK,*R ; save return *++ Get block cursor to start of current line and get its address BLWP @R_C ; get line# and column# of block cursor DECT SP ; reserve stack space MOV @COL#,*SP ; push column# to stack NEG *SP ; negate it BL @PLCUR ; update block cursor to beginning of line BL @PTR ; get address of block cursor for caller *++ Copy lines down 1 line in prep for blanking or pasting to current line MOV @EDBLK,R0 ; initialize src for CMV AI R0,959 ; correct to end of 1 line before end of block MOV R0,R1 ; initalize dst for CMV AI R1,64 ; correct to end of block LI R2,960 ; initialize cnt for CMV S @CUR,R2 ; correct cnt SETO R3 ; set R3 to -1 for copy from high RAM to low RAM for CMV BL @CMV ; do the copy MOV *R+,LINK ; pop return address RT ; and return ;]* ;[*++ RELINE ++* Redraw current line, updating CURPOS and marking block dirty RELINE LI R2,13 ; set up to emit CR LIMI 0 BL @EMT ; emit CR to put display cursor at beginning of line *++ Type current line of block MOV @LIN#,@LNSTRT ; starting line # <--ensure LIN# is still correct!!! CLR @LNCNT INC @LNCNT ; display 1 line BL @LINE. ; display the block *++ Update CURPOS etc. BL @DCUR *++ Mark block as dirty and return to editor loop B @DIRTY ;]* ;[*++ +.CUR ( n --- ) +++ Increment Forth block cursor by n and updates CURPOS *++ PLDCUR increments Forth block cursor by n and updates CURPOS PLDCUR DECT R ; make room on return stack to MOV LINK,*R ; save return BL @PLCUR ; call +CUR BL @DCUR ; call .CUR MOV *R+,LINK ; pop return address RT ; and return ;]* ;[*++ TAB ++* Tab forward one word *++ These instruction codes need to be updated whenever changes *++ are made to increase the distance between "X R2" and either *++ of the jump targets, TABBL or TABNOB. JEQTAB EQU >1306 ; "JEQ TABBL" for X instruction JNETAB EQU >1609 ; "JNE TABNOB" for X instruction TAB MOV @EDBLK,R0 ; get block address A @CUR,R0 ; get cursor address LI R4,1024 ; load counter with maximum S @CUR,R4 ; adjust to cursor location LI R2,JEQTAB ; set jump address for "blank found" TAB01 CB *R0,@CONBL ; is it a blank? X R2 ; execute jump instruction TAB02 DEC R4 ; decrement counter JEQ TABNOB ; jump if we're done: INC R0 ; increment block address INC @CUR ; increment block cursor JMP TAB01 ; let's check another character TABBL LI R2,JNETAB ; set jump address for "blank not found" JMP TAB02 ; continue *++ we found the next word or reached the end of the block TABNOB BL @DCUR ; update CURPOS etc. B @VEDLP ; return to editor loop ;]* ;[*++ -TAB ++* Tab backward one word *++ These instruction codes need to be updated whenever changes *++ are made to increase the distance between "X R2" and any *++ of the jump targets, BTABL1, BTBNOB or BTABL2. JEQBT1 EQU >1306 ; "JEQ BTABL1" for X instruction JNEBTB EQU >1609 ; "JNE BTBNOB" for X instruction JEQBT2 EQU >130C ; "JEQ BTABL2" for X instruction BTAB MOV @EDBLK,R0 ; get block address A @CUR,R0 ; get cursor address MOV @CUR,R4 ; load cursor location INC R4 ; correct counter LI R2,JEQBT1 ; set jump address for "blank found" the 1st time BTAB01 CB *R0,@CONBL ; is it a blank? X R2 ; execute jump instruction BTAB02 DEC R4 ; decrement counter JEQ TABNOB ; if we're done, finish up in TAB routine DEC R0 ; decrement block address DEC @CUR ; decrement block cursor JMP BTAB01 ; let's check another character BTABL1 LI R2,JNEBTB ; set jump address for "blank not found" JMP BTAB02 ; continue *++ we found a non-blank character BTBNOB LI R2,JEQBT2 ; set jump address for "blank found" the 2nd time JMP BTAB02 ; continue *++ we found the blank before the previous word or reached the beginning of the block BTABL2 INC @CUR ; restore cursor to 1st char of word we just passed JMP TABNOB ; finish up in TAB routine ;]* ;[*++ DIRTY ++* Set current block's dirty bit DIRTY *++ set update bit for block MOV @EDBLK,R2 ; load block address DECT R2 ; adjust to block # location SOC @CN8000,*R2 ; set update bit *++ Because this is the last routine called by all callers, *++ we will branch directly back to the editor loop. B @VEDLP ; return to editor loop ;]* ;[*++ ASCII ++* Character processing routine for VED ASCII CLR R1 ; zero R1 preparing for byte copy MOVB @KYCHAR,R1 ; copy new char to HIGH BYTE OF R1 CI R1,>2000 ; not too low? JLT ASCERR ; jump if too low CI R1,>7E00 ; not too high? JGT ASCERR ; jump if too high BL @PTR ; get block cursor address to BLKPOS MOV @BLKPOS,R2 ; load block cursor position MOVB R1,*R2 ; copy new char to block at cursor position *++ set up to emit new character CLR R2 ; clear R2 because xferring only 1 byte MOVB @KYCHAR,@F_R2LB ; move char to LSB of R2 for EMT LIMI 0 BL @EMT ; emit character *++ increment cursors etc. DECT SP ; reserve space on stack LI R0,1 ; load 1 for cursor advance MOV R0,*SP ; push 1 to stack BL @PLDCUR ; call +.CUR *++ set update bit for block and return to editor loop B @DIRTY *++ set up for error tone ASCERR LI R2,7 ; load error tone for EMT LIMI 0 BL @EMT ; emit error tone ASCEXT B @VEDLP ; return to editor loop ;]* ;[*++ BLNKS ++* Blank remainder of current line in block *++ BLKPOS and COL# must be current!! BLNKS DECT R ; make room on return stack MOV LINK,*R ; save return *++ Should not need these 2 statements because all callers have already set them * BL @PTR ; get address of block cursor * BLWP @R_C ; get block line# and column# MOV @BLKPOS,R0 ; copy block cursor to R0 LI R1,64 ; initialize counter S @COL#,R1 ; calculate count BLNKS1 MOVB @CONBL,*R0+ ; store blank in next location DEC R1 ; decrement counter JNE BLNKS1 ; jump if not 0 MOV *R+,LINK ; pop return address RT ; and return to caller ;]* ;[*++ FLIP ++* Move cursor 30 chars left or right (to start in 80-column mode) *++ Move cursor 30 columns left or right for 40-column editor or to beginning *++ of block for 80-column editor FLIP MOV @$VDPM(U),R0 ; TEXT80 mode? JNE FLIP01 ; jump if not CLR @CUR ; zero block cursor BL @DCUR ; update cursors and display JMP FLIPEX ; we're outta here! FLIP01 DECT SP ; reserve stack space LI R0,30 ; load cursor step MOV @S_H,R1 ; left half of 40-column editor? JEQ FLIP02 ; jump if so NEG R0 ; right half, so go other direction FLIP02 MOV R0,*SP ; push cursor step to stack BL @PLDCUR ; update cursors etc. FLIPEX B @VEDLP ; return to editor loop ;]* ;[*++ REDRAW ++* Redraw screen, updating CURPOS and marking block dirty REDRAW MOV @S_H,R0 ; test which half of screen (40-column editor) JEQ REDRW1 ; jump if left half BL @LISTR ; show right half of block JMP REDRW2 REDRW1 DECT SP ; reserve stack space for block# MOV @$SCR(U),*SP ; push block# to stack BL @LISTL ; show left half of block *++ Update CURPOS etc. REDRW2 BL @DCUR *++ Mark block as dirty and return to editor loop B @DIRTY ;]* ;[*++ DEL ++* Delete character under cursor *++ Delete one character and close up line DEL BL @PTR ; get cur_addr MOV @BLKPOS,R1 ; dst to R1 for CMV MOV R1,R0 ; initialize src for CMV INC R0 ; correct src LI R2,64 ; initialize cnt for CMV BLWP @R_C ; get block lin# and col# S @COL#,R2 ; correct cnt MOV R2,R4 ; save cnt for later LI R3,1 ; set copy direction for CMV BL @CMV ; close the gap left by deleted char DEC R4 ; correct R4 A @BLKPOS,R4 ; get location of last char of line MOVB @CONBL,*R4 ; store blank in that location *++ Re-display line, set dirty bit and return to editor loop B @RELINE ; re-display line etc. ;]* ;[*++ INS ++* Insert blank char at cursor *++ Insert a blank and move rest of line 1 char right INS BL @PTR ; get cur_addr LI R2,64 ; initialize cnt for CMV BLWP @R_C ; get block lin# and col# S @COL#,R2 ; correct cnt MOV @BLKPOS,R1 ; initialize dst for CMV A R2,R1 ; add # of chars DEC R1 ; correct to last char of line MOV R1,R0 ; initialize src for CMV DEC R0 ; correct to penultimate char of line SETO R3 ; set copy direction for CMV (high RAM to low) BL @CMV ; allow room for the extra char MOV @BLKPOS,R0 ; get insertion point MOVB @CONBL,*R0 ; store a blank there *++ Re-display line, set dirty bit and return to editor loop B @RELINE ; re-display line etc. ;]* ;[*++ PCHCUR ++* Display cursor or char under cursor *++ Character to be displayed at CURPOS must already be in MSB of R1 PCHCUR MOV @CURPO$(U),R0 ; copy screen CURPOS to R0 for VSBW LIMI 0 ; disable interrupts because VSBW doesn'y BLWP @VSBW ; display cursor or character under cursor LIMI 2 ; re-enable interrupts RT ; return to caller ;]* ;[*++ RKEY ++* Get next key and repeats *++ RKEY is key acquisition/repetition and cursor blinking routine. *++ *++ Register usage: RKEY DECT R ; make room on return stack to MOV LINK,*R ; save return RKEYLP LIMI 0 ; disable interrupts because KSCAN doesn't BLWP @KSCAN ; scan the keyboard (interrupts will be enabled at return) INC @BLINK ; increment blink logger LI R3,180 ; load 180 C @BLINK,R3 ; has it been 180 clicks? JLT RKEY01 ; jump if not MOVB @CURCH,R1 ; copy character under cursor JMP RKEY02 ; restore it RKEY01 LI R1,>1E00 ; load cursor character RKEY02 BL @PCHCUR ; display cursor or char under cursor SLA R3,1 ; load 360 C @BLINK,R3 ; has it been 360 clicks? JNE RKEY03 ; jump if not CLR @BLINK ; clear blink logger RKEY03 CB @KYCHAR,@CONFF ; no key? JEQ RKEY05 ; jump if so *++ We have a key! SZCB @CN8000,@KYCHAR ; force KYCHAR byte to ASCII MOV @KC,R3 ; save key counter for test INC @KC ; increment key counter for wait CLR @BLINK ; zero blink logger MOV R3,R3 ; waiting to repeat? JEQ RKEYEX ; finish up and exit if not *++ waiting to repeat C @RLOG,@KC ; long enough? JLT RKEY04 ; jump if so *++ We may not have waited long enough yet. CB @OKEY,@KYCHAR ; same key? JEQ RKEYLP ; wait some more if same key *++ We're outta here! MOV @CON01,@KC ; load key counter with 1 JMP RKEYEX ; finish up *++ we've waited long enough RKEY04 MOV @RL,@RLOG ; load short wait time for repeat logger MOV @CON01,@KC ; load key counter with 1 JMP RKEYEX ; clean up and back to editor loop *++ No key was pressed. RKEY05 MOV @RH,@RLOG ; re-init RLOG CLR @KC ; zero key counter JMP RKEYLP ; scan keyboard again *++ End of RKEY processing RKEYEX MOVB @KYCHAR,@OKEY ; current key to old key MOVB @CURCH,R1 ; character under cursor to R1 BL @PCHCUR ; restore it to display MOV *R+,LINK ; pop return address RT ;]* ;[*++ NXTBLK++* Load next block NXTBLK DECT SP CLR *SP DECT SP MOV @$SCR(U),*SP INC *SP BL @LISTL BL @STCUR BL @DCUR B @VEDLP ;]* ;[*++ PRVBLK ++* Load previous block PRVBLK DECT SP CLR *SP DECT SP MOV @$SCR(U),R0 DEC R0 JGT PRVBK1 LI R0,1 PRVBK1 MOV R0,*SP BL @LISTL BL @STCUR BL @DCUR B @VEDLP ;]* ;[*++ BCK ++* Exit the 40/80-column editor BCK CLR R2 ; set column = 0 for GXY CLR R3 ; set row = 0 for GXY BL @GXY ; update CURPOS LI R0,>00F0 ; load PDT offset for cursor char, ASCII[30] A @$PDT(U),R0 ; get its PDT address LI R1,OLDCUR ; load RAM source for old cursor LI R2,8 ; load byte count LIMI 0 ; disable interrupts because VMBW doesn't BLWP @VMBW ; write the pattern BL @CLS$ ; clear screen BL @BLA2F ; call into Forth for ABORT, we won't be back DATA ABORT ;]* ;[*++ MOVCUR ++* End of the next 5 routines MOVCUR DECT SP ; make room on stack MOV R0,*SP ; push new cursor offset to stack BL @PLDCUR ; update cursors etc. B @VEDLP ; back to editor loop ;]* ;[*++ LFTCH ++* Move left one character position LFTCH SETO R0 JMP MOVCUR ;]* ;[*++ RTCH ++* Move right one character position RTCH LI R0,1 JMP MOVCUR ;]* ;[*++ DOWNLN ++* Move down to same character position on next line DOWNLN LI R0,64 JMP MOVCUR ;]* ;[*++ UPLN ++* Move up to same character position on previous line UPLN LI R0,64 NEG R0 JMP MOVCUR ;]* ;[*++ NXTLN ++* Move down to first character position of next line NXTLN BLWP @R_C MOV @LIN#,R0 SLA R0,6 MOV R0,@CUR JMP DOWNLN ;]* ;[*++ VEDCMD ++* Jump table for VED VEDCMD DATA ASCII,ERASHF,NXTBLK,DEL,INS,ASCII,PSTELN DATA DELLIN,LFTCH,RTCH,DOWNLN,UPLN,PRVBLK DATA NXTLN,FLIP,BCK,TAB,BLNKLN,BTAB ;]* ;[*** VED *** ( block# blkpos --- ) +++ 40/80-column editor's main, endless loop * DATA BSAV_N * VED__N DATA 3+TERMBT*LSHFT8+'V','ED'+TERMBT * VED DATA $+2 * VED_P BL @BLF2A * DATA _VED->6000+BANK1 _VED *++ Insure we're in TEXT or TEXT80 mode *++ Initialize EDPAD (location of PAD while in editor) MOV @$DP(U),R0 AI R0,68 MOV R0,@EDPAD *++ 66 blanks to PAD BL @BLPAD *++ Load border characters LIMI 0 LI R0,201 ; load first border character code SLA R0,3 ; * 8 A @$PDT(U),R0 ; get offset into PDT LI R1,BDCHRS ; load address of border character patterns LI R2,64 ; load byte count BLWP @VMBW ; write new patterns *++ Save cursor pattern LI R0,>00F0 ; cursor pattern offset into PDT (ASCII 30) A @$PDT(U),R0 ; compute address in PDT LI R1,OLDCUR ; RAM storage LI R2,8 ; 8 bytes BLWP @VMBR ; save it for later *++ Load our cursor LI R1,BOX ; RAM location of our cursor pattern BLWP @VMBW ; store our cursor pattern (R0 & R2 still good) *++ Clear screen BL @CLS$ ; R0,R1,R2,R7 trashed; interrupts enabled at return *++ Display navigation menu LI R2,0 ; load x LI R3,20 ; load y BL @GXY ; place text cursor LI R4,NAVMNU ; text to type BL @MSGTYP ; type NAVMNU *++ Swap top 2 stack cells BL @BLA2F DATA SWAP *++ List left half of screen for TEXT or full screen for TEXT80 BL @LISTL *++ Update cursors' positions BL @STCUR BL @DCUR *++ Initialize variables CLR @BLINK CLR @OKEY CLR @KC MOV @RH,@RLOG ; load long wait time for repeat logger *++ Infinite editor loop--- *++ All keystroke processing routines, except BCK, will come back *++ here for another keystroke. VEDLP *++ Get character under cursor MOV @CURPO$(U),R0 LIMI 0 BLWP @VSBR MOVB R1,@CURCH LIMI 2 ??? *++ Get a key BL @RKEY *++ Process keystroke CLR R2 ; clear keystroke register MOVB @KYCHAR,@F_R2LB ; load keystroke in LSB of R2 CI R2,>16 ; is it TAB? JNE VED01 ; jump if not LI R2,>10 ; load jump table offset for TAB VED01 CI R2,>1E ; is it BLNKLN? JNE VED02 ; jump if not LI R2,>11 ; load jump table offset for BLNKLN VED02 CI R2,>7F ; is it -TAB? JNE VED03 ; jump if not LI R2,>12 ; load jump table offset for -TAB JMP VED04 ; process jump table VED03 CI R2,>13 ; compare to highest jump table offset + 1 JLT VED04 ; jump if less CLR R2 ; set jump table offset for ASCII VED04 SLA R2,1 ; correct jump table offset AI R2,VEDCMD ; get jump table target MOV *R2,R2 ; copy address from table B *R2 ; branch to proper keystroke routine ;]* ;[*** WHERE *** ( offset block# --- ) +++ Enter editor at point of load error * DATA VED__N * WHER_N DATA 5+TERMBT*LSHFT8+'W','HE','RE'+TERMBT * WHERE DATA DOCOL * WHERP DATA SWAP,TWOM,VED,SEMIS ;]* ;[*** EDIT *** ( block# --- ) +++ Entry into 40/80-column editor * DATA WHER_N * EDIT_N DATA 4+TERMBT*LSHFT8+'E','DI','T '+TERMBT * EDIT DATA DOCOL * EDITP DATA ZERO,VED,SEMIS ;]* ;[*** ED@ *** ( --- ) +++ Re-edit last block edited * DATA EDIT_N * EDAT_N DATA 3+TERMBT*LSHFT8+'E','D@'+TERMBT * EDAT DATA DOCOL * EDATP DATA SCR,AT,EDIT,SEMIS ;]* ...lee 2 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 1, 2014 Author Share Posted August 1, 2014 For the File I/O words, unless there are justifiable objections, I think I'm going to remove the high-level Forth references to the following words because they are only used by other File I/O words. I will explain this in the manual for fbForth 2.0 and also explain how one might define the words if they are really needed: What follows is an excerpt from Chapter 8 of the fbForth 1.0 Manual— The words that follow are available for the advanced user and their utility can be worked out by examining their definitions in block 47ff in FBLOCKS. They are lower-level words that are used in the definitions of the above file I/O words. GET-FLAG ( --- b ) retrieves to the stack the flag/status byte b from byte 1 the current PAB. The high-order 3 bits are used for DSR error return, except for “bad device name”. With the “bad device name” error, this error return will be 0; but, the GPL status byte (837Ch) will have the COND bit set (20h). The low-order 5 bits are set by routines that set the file type prior to calling OPN , which reads these bits. See table below for the meaning of each bit of the flag/status byte: Flag/Status Byte of PAB (Byte 1) Bits Contents Meaning ------------------------------------------------------- 0‒2 Error Code 0 = no error. Error codes are decoded in table below. 3 Record Type 0 = fixed-length records; 1 = variable-length records. 4 Data Type 0 = DISPLAY; 1 = INTERNAL. 5‒6 Mode of Operation 0 = UPDATE; 1 = OUTPUT; 2 = INPUT; 3 = APPEND. 7 File Type 0 = sequential file; 1 = relative file. Error Codes in Bits 0‒2 of Flag/Status Byte of PAB Error Code Meaning -------------------------------------------------------- 0 No error unless bit 2 of status byte at address 837Ch is set ( then, bad device name). 1 Device is write protected. 2 Bad OPEN attribute such as incorrect file type, incorrect record length, incorrect I/O mode or no records in a relative record file. 3 Illegal operation; i.e., an operation not supported on the peripheral or a conflict with the OPEN attributes. 4 Out of table or buffer space on the device. 5 Attempt to read past the end of file. When this error occurs, the file is closed. Also given for non-extant records in a relative record file. 6 Device error. Covers all hard device errors such as parity and bad medium errors. 7 File error such as program/data file mismatch, non-existing file opened in INPUT mode, etc. PUT-FLAG ( b --- ) writes the flag/status byte b on the stack to the current PAB to clear the error bits and set the file type prior to calling OPN . See table after GET-FLAG for the meaning of each bit. CLR-STAT ( --- ) clears the error code in bits 0‒2 of the flag/status byte of the current PAB. CHK-STAT ( --- ) checks the error code in bits 0‒2 of the flag/status byte of the current PAB. If it is not 0, an appropriate error message is printed. I/OMD ( --- b ) gets the flag/status byte b of the current PAB, clears the I/O mode bits (5 & 6) and leaves it on the stack in preparation for setting the I/O mode with an I/O word. CHAR-CNT! ( n --- ) stores the character count n in the current PAB prior to a write operation. CHAR-CNT! is used by WRT . CHAR-CNT@ ( --- n ) retrieves the character count n from the current PAB of the last read operation. It is used by RD . N-LEN! ( b --- ) stores in the current PAB the length byte b of the file descriptor associated with the current PAB. For “DSK1.MYFILE”, this would be 11. DOI/O ( n --- ) executes the DSRLNK word with the I/O opcode n on the stack. The current PAB must be updated with the information required by opcode n before executing DOI/O . See Section 18.2.1 of the Editor/Assembler Manual for details or consult the definitions in block 47ff in FBLOCKS of the I/O words, OPN , CLSE , RD , WRT , RSTR , LD , SV , DLT and STAT , all of which use this low-level word in their definitions. ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 4, 2014 Author Share Posted August 4, 2014 The File I/O words are done! After a day or two of testing, I will post beta 7. I had to move things around a little. The space left in banks 0 – 2 is 1524, 162 and 406 bytes, respectively. I obviously have breathing room in bank 0, but I can move a little from bank 1 if bank 1 gets too tight. I need to be careful, however, because I am about to attempt the Floating Point Library, which will consume all of bank 3 and cause some spillover into other banks to get all of the high-level definitions done. Not long, now—I hope! ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 5, 2014 Author Share Posted August 5, 2014 BTW—if anyone is interested in testing the file I/O words, I could post beta 7 now—let me know! I just did not wish to foist a possibly(likely) flawed system on anyone. ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 8, 2014 Author Share Posted August 8, 2014 I think I will post beta 7 sometime tomorrow. The file I/O words are mostly tested and working. I had run into a couple of snags that were driving me nuts until I realized I had forgotten the CFA names for the likes of VMBR and its siblings. I was using VMBR (the ALC low-level routine's name) instead of _VMBR in the high-level Forth ALC! I also ran into a brick wall with DLT (delete file) in Classic99 until I checked it with MESS, where it worked. I could not find anywhere in the docs for Classic99 (I'm one mod behind) that deleting a file in FIAD mode is not supported, but that may well be the case. I will update to the latest mod of Classic99 to be sure. Anyway—soon... ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 8, 2014 Author Share Posted August 8, 2014 I will post beta 7 later today. I need to update FBLOCKS to remove the "File I/O Library" option. FBLOCKS is getting smaller and smaller! I need to bulk it up with more stuff. Certainly, one such application will be a font editor. But, first—I have to go into town to get my new glasses. ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 8, 2014 Author Share Posted August 8, 2014 Post#1 has the beta 7 files I just posted. Please test and apprise me of any problems you find. And now—on to the Floating Point Math Library! Regarding running fbForth 2.0 beta 7 on real iron, @Astharot is trying it, but has run into difficulty. We're trying to work it out; but, I have not yet created a cartridge to test. I will be doing that later this month. However, if anyone else has tried it or is about to, I would very much like to hear how you fare(d). ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 13, 2014 Author Share Posted August 13, 2014 Uh-oh! Now what? I just got this message from Asm994a: !!! Fatal Error: Out of symbol table space I'm not sure what to do now. One thing that comes to mind is to take advantage of the fact that only one label in the Floating Point Library (FPL) is needed by the rest of the fbForth code. That would allow me to assemble the FPL separately with an AORG directive and patch it into the last bank. However, I still may be in trouble with the additional FP words I need to define; but, I guess it's worth a try. Any other ideas? ...lee Quote Link to comment Share on other sites More sharing options...
Willsy Posted August 13, 2014 Share Posted August 13, 2014 (edited) Wow! Never seen that error before. I wonder if we could get hold of Cory Burr and ask him to modify the assembler? Either that, or I need to dust off the Java TMS99xx assembler that I started but never finished! Are there any labels that you can remove from your source code? There probably are, if you look. For example, in TF, my dictionary entries look like this: labelh data <pointer to previous dictionary header> data <word length and flags> entryp data $+2 ; entry point for executable code See that label "entryp" (entry-point) above? It's only needed *if* source code elsewhere needs to refer to that code. If it's not executed/called elsewhere in your code-base then you don't need a label for it. My convention in TF was to give them all labels, but it wasn't really necessary - though I never encountered that error message before! How many labels do you have? Looking at the end of the LST file for TF (I have an old build on this machine) I have 1458 labels in the entire TF code-base. Of course fbForth is larger (32K Eprom?)? Any idea what the limit is? Mark Edited August 13, 2014 by Willsy Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 13, 2014 Author Share Posted August 13, 2014 Wow! Never seen that error before. I wonder if we could get hold of Cory Burr and ask him to modify the assembler? Either that, or I need to dust off the Java TMS99xx assembler that I started but never finished! Are there any labels that you can remove from your source code? There probably are, if you look. For example, in TF, my dictionary entries look like this: labelh data <pointer to previous dictionary header> data <word length and flags> entryp data $+2 ; entry point for executable code See that label "entryp" (entry-point) above? It's only needed *if* source code elsewhere needs to refer to that code. If it's not executed/called elsewhere in your code-base then you don't need a label for it. My convention in TF was to give them all labels, but it wasn't really necessary - though I never encountered that error message before! How many labels do you have? Looking at the end of the LST file for TF (I have an old build on this machine) I have 1458 labels in the entire TF code-base. Of course fbForth is larger (32K Eprom?)? Any idea what the limit is? Mark I have 2829 labels before I add the FPL. Asm994a chokes about halfway through the FPL. My guess is the max is somewhere near 3000 lab els, but I don't really know. I have so many labels because of the splitting out of the dictionary headers. It will be very painful to try to strip out labels—though doable, of course! ...lee Quote Link to comment Share on other sites More sharing options...
TheMole Posted August 13, 2014 Share Posted August 13, 2014 It would probably require a bit of work, but you could consider moving to the gcc assembler (it works stand-alone without the C compiler as well). Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 13, 2014 Author Share Posted August 13, 2014 In the split-out Dictionary header list, there are two threaded lists, the name fields and the parameter field addresses (PFAs). I don't think I ever use the code field address (CFA) pointers. The CFA is always calculated from the the PFA by backing up 2 bytes. That's an excess of ~400 gratuitous labels!?! That's also the approximate number of labels in the FPL ALC. I guess I need to bite the bullet and delete the CFA pointers to see if I get a successful assembly without them. ...lee Quote Link to comment Share on other sites More sharing options...
Tursi Posted August 13, 2014 Share Posted August 13, 2014 (edited) It /is/ a bit of work, but most of the things that the GCC assembler doesn't like can be fixed with a straight search-and-replace. Edited August 13, 2014 by Tursi Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 14, 2014 Author Share Posted August 14, 2014 OK—I removed the CFA pointers and re-assembled. There are now 2804 symbols and everything appears to be working. Now on to defining the Forth part of the Floating Point Library and testing the library! Hopefully, I'll have enough room in the symbol table, but I'm cutting it close! I may yet have to assemble the FPL separately. ...lee 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 16, 2014 Author Share Posted August 16, 2014 I am now puzzling over how to handle floating point (FP) number output. I would like to maintain backward compatibility with TI Forth's (TIF) block-loaded library (fbForth 1.0's is the same code); but, I don't really like the format used in TIF. TIF has 4 words for displaying an FP number, viz., F. , F.R , FF. and FF.R . Those that end in ' R ' right-justify the output in a specified field-width equal to or larger than the expected output of the number. The two that begin with ' F. ' are free-form output and the other two are fixed-format output that are specified by two numbers, the number of digits following the decimal point and the maximum number of digits to output. The reason for these specifications is that the Convert-Number-to-String (CNS) GPL routine used by TIF and fbF10 requires those specific inputs. With fbForth 2.0, I will be using a different FP Library (FPL), which I modified (with permission) from the Geneve FPL to work with TurboForth 1.2 and now with fbForth 2.0 The new CNS routine is more versatile than the corresponding GPL routine. The fixed-format outputs are specified by three numbers, two that specify the number of digits (including the space for the sign, used or not) to the left of the decimal point (DP) and the number of digits (including the DP) to the right of the DP, and one that is a format specifier. The format specifier allows two different E-notation outputs in the fixed format; whereas, the only way with the GPL CNS routine to get E-notation is by specifying free-format output—and, you only get E-notation then when the number won't fit the specs otherwise. I suppose I could define the four aforementioned words just as they are in TIF/fbF10 and define a fixed-format word for fbForth 2.0 that incorporates all of the new specs. The only problem I see with that is someone learning fbForth 2.0 without prior knowledge of TIF/fbForth10 being confused by the different number-of-digit specs for FF. and FF.R vis-à-vis those for the new CNS routine. Thoughts? ...lee Quote Link to comment Share on other sites More sharing options...
Willsy Posted August 17, 2014 Share Posted August 17, 2014 To quote Charles Moore: "simplify and add lightness." :-) 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 17, 2014 Author Share Posted August 17, 2014 Perhaps, then, I shall do it my way and just provide the code for the old words so the user can add them as need arises. ...lee Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.