Willsy Posted December 11, 2013 Share Posted December 11, 2013 Yeah I noticed that with mine yesterday add I was posting it. For TF the solution would be (in the "not found" code-path) LATEST @ DUP LATEST ! HERE ! Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 11, 2013 Share Posted December 11, 2013 Sorry: make that H ! not HERE ! HERE is read-only. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 14, 2013 Author Share Posted December 14, 2013 Making headway! Attached is an excerpt from the fbForth 1.0 manual, which is an explanation of the CRU words implemented in fbForth along with the fbForth TMS9900 Assembler code for them. I wonder whether the explanations are clear enough, over the top or need more information? Let me know. CRU Words.pdf ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 18, 2013 Author Share Posted December 18, 2013 In the process of insuring that the copy of FBLOCKS in the manual is the same as the file, I wrote a routine, BLKOUT , to output to a file a range of blocks from the current blocks file formatted as presented in the manual. I may include it in FBLOCKS. Here it is in case you're interested: * BASE->R HEX 0 VARIABLE OUTBUF 4E ALLOT ( line output buffer) PABS @ OUTBUF 1400 FILE OUTFIL ( output file definition) OUTFIL SET-PAB 50 REC-LEN OUTPT VRBL ( file type DV80) ( header string for each block) 424C VARIABLE BLK# 4F43 , 4B20 , 2320 , 2020 , ( "BLOCK # ") : ASCII ( Change all non-ASCII chars to '#') OUTBUF 43 + OUTBUF DO ( set up to scan buffer) I C@ 20 < I C@ 7E > OR ( char not ASCII?) IF ( yes) 23 I C! ( change char to '#') THEN LOOP ; : HDR ( n --- ) ( output header with block # on stack) BASE->R DECIMAL ( force decimal base) BLK# OUTBUF 0A CMOVE ( initialize header) 0 <# #S #> ( make block # a double number & convert to text) OUTBUF 7 + SWAP CMOVE ( copy converted # to header) 0A WRT ( write 10 bytes to file) R->BASE ; ( restore number base) : FTR OUTBUF 1 BLANKS 1 WRT ; ( output footer line of 1 blank) : BLKOUT ( n1 n2 --- ) ( block output routine) BASE->R DECIMAL ( force decimal base) 1+ SWAP OUTFIL OPN DO ( open output file; set up block output loop) I . I BLOCK I HDR ( log current block to display; load block; do header) 10 0 DO ( set up line output loop) OUTBUF 4 BLANKS ( initialize line number output) I 0 <# #S #> ( convert line # to text) 3 OVER - OUTBUF + SWAP CMOVE ( copy line #) DUP OUTBUF 4 + 40 CMOVE ( copy 64 chars to line buffer) ASCII ( convert non-ASCII chars to '#') 44 WRT ( write line to file) 40 + ( point to next line in block buffer) LOOP DROP FTR ( drop extra line pointer; write footer) LOOP CLSE R->BASE ; ( close file; restore number base) ( Output instructions to console) CR CR ." *Send line-numbered blocks from current blocks file to a text file." CR CR ." Usage: F-D" 22 EMIT ." DSK<n>.<outfilename>" 22 EMIT CR ." <start block> <end block> BLKOUT" CR CR ." --WARNING--Do NOT change to/from TEXT80 mode while using BLKOUT !!!" CR CR R->BASE * ...lee Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 18, 2013 Share Posted December 18, 2013 Making headway! Attached is an excerpt from the fbForth 1.0 manual, which is an explanation of the CRU words implemented in fbForth along with the fbForth TMS9900 Assembler code for them. I wonder whether the explanations are clear enough, over the top or need more information? Let me know. CRU Words.pdf ...lee This is great Any objection if I copy this concept for TF? Mark Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 18, 2013 Author Share Posted December 18, 2013 This is great Any objection if I copy this concept for TF? Mark Have at it! ...lee Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 18, 2013 Share Posted December 18, 2013 Thanks. That's my Saturday morning booked Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 19, 2013 Author Share Posted December 19, 2013 (edited) I know we've talked about the details of joystick/keyboard capture in the Assembly on the 99/4A thread (in particular, here: http://atariage.com/forums/topic/162941-assembly-on-the-994a/page-11?do=findComment&comment=2848971); but, I'm still undecided about how I should handle restoring the keyboard to normal scan mode after joystick scanning. TI Forth's word JOYST ( keybdno --- char xstat ystat ) "restores" the keyboard scan mode with HEX 4 8374 C! , which I never understood because 4 selects the "Pascal Keyboard", whereas the system originally initializes to mode 5 (Standard or Basic Keyboard). For fbForth, I am inclined to use HEX 0 8374 C! , which restores the keyboard mode before the left (1) or right (2) joystick was selected. My reasoning is that the user might actually have changed the keyboard mode to other than "Standard" and want that back. If I were to force the "Standard" keyboard with HEX 5 8374 C! , that would, then, be a surprise. Of course, the user may have selected other than the "Standard" keyboard mode by accident, in which case HEX 0 8374 C! would "restore" that wrong mode. What do you think? 0 or 5? ...lee Edited December 19, 2013 by Lee Stewart Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 19, 2013 Share Posted December 19, 2013 Neither. Use the CRU and read the joysticks at the hardware level, and bypass TI's KSCAN routine. It's tens of times faster: ; JOYST ( joystick# -- value ) ; Scans the joystick returning the direction value _joyst mov *stack,r1 ; get unit number ai r1,6 ; use keyboard select 6 for #0, 7 for #1 swpb r1 li r12,36 ldcr r1,3 li r12,6 stcr r1,5 swpb r1 inv r1 andi r1,>001f mov r1,*stack li r12,_next mov r12,@>83d6 ; defeat auto screen blanking mov @bank1_,@retbnk ; return to bank 1 if interuupts should fire limi 2 ; briefly enable interrupts limi 0 ; and turn 'em off again b @retb0 ; return to caller in bank 0 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 20, 2013 Author Share Posted December 20, 2013 Neither. Use the CRU and read the joysticks at the hardware level, and bypass TI's KSCAN routine. It's tens of times faster: ... That presents a compatibility problem with old TI Forth code—not using the CRU, but the stack effects. JOYST would need to accept 1 or 2 rather than 0 or 1 for input (easy enough to effect) and leave the character code, x status and y status that TI Forth programmers are wont to getting. I suppose I could work up something to see whether I can keep down the code bloat. Perhaps I should actually code two versions, say, JOYKSC and JOYCRU , and then let the user map JOYST to whichever one they want to use. Of course, I then still need the answer to my question. BTW, Mark, why did you choose 0 and 1 for joysticks 1 and 2? ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 20, 2013 Author Share Posted December 20, 2013 I know what I'll do! I'll define a user variable, JMODE , that defaults to 0 for TI-Forth-compatible mode and can be set to any other value for CRU mode. I will still need to decide on 0 or 5 for restoration of the keyboard mode for JMODE = 0. ...lee 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 20, 2013 Author Share Posted December 20, 2013 (edited) A-a-a-n-d...here is my solution: * HEX 26 USER JMODE ( 0=TI Forth; ~0=CRU) ( Scans the joystick returning the direction value) ( fbForth TMS9900 Assembler code) ASM: JCRU ( joystick# -- value ) *SP R1 MOV, ( get unit number) R1 5 AI, ( use keyboard select 6 for #1, 7 for #2) R1 SWPB, R12 24 LI, ( <-----This line FIXED!!! ) R1 3 LDCR, R12 6 LI, R1 5 STCR, R1 SWPB, R1 INV, R1 001F ANDI, R1 *SP MOV, 83D6 @() CLR, ( defeat auto screen blanking) ;ASM : JKBD ( kbd --- chr xstat ystat ) ... ; ( This is the old TI Forth JOYST word that uses KSCAN) : JOYST ( kbd|joyst --- [chr xst yst]|n ) JMODE @ IF JCRU ELSE JKBD THEN ; ( Now, JMODE decides which of the above words to execute) * @Willsy? I stole most of your code! The differences are Changed from joysticks 0 and 1 to 1 and 2 for consistency with TI Forth; Don't need to restore R12 because it is only ever used for CRU stuff in fbForth, except in rare circumstances; Just zeroed the screen-blanking timer because KSCAN always increments it prior to testing for 0 (don't know if it is tested elsewhere); I don't think I need the LIMI 2/LIMI 0 combo in fbForth (How would I test that?) Let me know if you see anything wrong with my code changes from your code. ...lee Edited December 21, 2013 by Lee Stewart Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 20, 2013 Share Posted December 20, 2013 Looks good to me! You won't need the limi instructions. They're there to service the speech synth in TF. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 21, 2013 Author Share Posted December 21, 2013 I corrected a mistake in line 10 of my last post. I forgot that the '36' was decimal—I needed to convert it to '24' because it's in hexadecimal mode! Unless I'm doing something wrong, JCRU only works with joysticks. It does not respond to the keyboard joystick keys. At least, that's how it's working in Classic99, i.e., the arrow keys and the Tab key (fire). Is there any way around this? Is that how it works in TF, @Willsy? ...lee Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 21, 2013 Share Posted December 21, 2013 Well it's reading the joysticks at the hardware level so it will sound how you configure classic 99 wrt joystick emulation. On my installation the joystick is mapped to the cursor keys and the fire button is the tab button. This is confirmed to work in TF in classic 99. Mark Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 21, 2013 Share Posted December 21, 2013 Depend. Not sound. Bloody tablets! Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 21, 2013 Author Share Posted December 21, 2013 Depend. Not sound. Bloody tablets! How in the hell does 'depend' morph to 'sound'?! Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 22, 2013 Author Share Posted December 22, 2013 Wow! I had a serious misconception about what the left and right keyboard keys returned compared to joystick returns. I thought the values were the same, i.e., that 8375h would show a key value for a joystick direction and that 8376h and 8377h would show those directions when the appropriate key was pressed. What was I thinking?! I now think I understand what's going on. fbForth's JKBD (TI Forth's JOYST ) first checks for a keypress. If it finds one, it invents values that a joystick would have left in 8376h and 8377h and reports those along with the character code. If no keypress, it reports the actual values left in 8376h and 8377h from KSCAN's sampling of the joystick and also reports FFh for the "keypress". fbForth's JCRU , on the other hand, only gets actual joystick positions, so only works with actual joysticks. I guess I was hoping to make JCRU work with the keyboard, as well. That would mean, of course, that I would need to write my own keyboard scan routine without the serious delay loop that's in KSCAN. I'm not sure I want to do that. I think I'll leave it to the user to change JMODE to a non-zero value to run joystick-only mode (without KSCAN) with JOYST and leave it at 0 to run JOYST with KSCAN. Anybody care? ...lee Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 22, 2013 Share Posted December 22, 2013 I think the keyboard scan is both slow and cumbersome. Further more, how does it represent multiple simultaneous states that are possible with a joystick? Is possible to have three simultaneous states on the joystick. E g. Up, right and fire. How is this reported in JKBD? In the TF version, the joystick state is a bit-field. Here is the description for JOYST: http://turboforth.net/lang_ref/view_word.asp?ID=132 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 22, 2013 Author Share Posted December 22, 2013 I think the keyboard scan is both slow and cumbersome. Further more, how does it represent multiple simultaneous states that are possible with a joystick? Is possible to have three simultaneous states on the joystick. E g. Up, right and fire. How is this reported in JKBD? ... JKBD first checks 8375h. If it finds 18 (12h), it abandons further checking, reporting 12h and two 0s. If it finds 255 (FFh), it assumes joystick use and checks 8377h (x-status) and 8376h (y-status), reporting FFh and both direction values. If it finds any other nonzero value, it checks for key values that represent the 8 possible directions, reporting the key value and the corresponding directions. That's pretty much everything the hardware-level JCRU (same as TF's JOYST) reports except the simultaneous 'fire' and joystick position. I will check to see whether KSCAN is capable of that and change JKBD if it is. ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 22, 2013 Author Share Posted December 22, 2013 (edited) @Willsy et al.— KSCAN reports simultaneous 'fire' and joystick positions, so I modified the original JKBD code to do so, as well. Obviously, if a user is using the keyboard as the joystick, simultaneous 'fire' and direction determination are impossible because 'fire' is a keystroke, even the joystick button, and KSCAN has only one location to store the keystroke, viz., 8375h. Furthermore, KSCAN does not translate the keycode to directions to store at 8376h and 8377h—it reserves that operation for its CRU sampling of the joystick position: * : JKBD ( kbd --- chr xstat ystat ) 8374 C! ?KEY DROP 8375 C@ DUP 12 = OVER 0FF = OR IF 8377 C@ 8376 C@ ELSE DUP CASE 4 OF 0FC 4 ENDOF 5 OF 0 4 ENDOF 6 OF 4 4 ENDOF 2 OF 0FC 0 ENDOF 3 OF 4 0 ENDOF 0 OF 0 0FC ENDOF 0F OF 0FC 0FC ENDOF 0E OF 4 0FC ENDOF DROP DROP 0 0 0 0 ENDCASE ENDIF 0 8374 C! ; * For comparison, here is the original code: : JKBD ( kbd --- chr xstat ystat ) 8374 C! ?KEY DROP 8375 C@ DUP DUP 12 = IF DROP 0 0 ELSE 0FF = IF 8377 C@ 8376 C@ ELSE 8375 C@ CASE 4 OF 0FC 4 ENDOF 5 OF 0 4 ENDOF 6 OF 4 4 ENDOF 2 OF 0FC 0 ENDOF 3 OF 4 0 ENDOF 0 OF 0 0FC ENDOF 0F OF 0FC 0FC ENDOF 0E OF 4 0FC ENDOF DROP DROP 0 0 0 0 ENDCASE ENDIF ENDIF 0 8374 C! ; What this means is that JKBD will handle the joystick just as does JCRU . JKBD has the advantage of giving the same information for both the joystick and its keyboard emulation, i.e., character code, x-status (0, FCh or 4) and y-status (0, FCh or 4). Its disadvantage, of course, is the long timing loop in KSCAN. JCRU will only report the hardware bitstring (1=Fire, 2=W, 4=E, 8=S and 16=N) for the joystick and 'fire' button—the keyboard is not sampled. As I indicated in an earlier post, JOYST will execute JKBD by default or the user can set JMODE to 1 to have JOYST execute JCRU . ...lee Edited December 22, 2013 by Lee Stewart Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 23, 2013 Author Share Posted December 23, 2013 @Willsy? @Vorticon? @JonnyBritish? @jacquesg? Anyone? I'm trying to resist further changes to fbForth until after I finish the manual (probably by month's end!); but, I keep running into stuff that seems to need fixing. One problem I have puzzled over for a long time is cleaning up a failed colon ( : ) definition. VLIST will list it because it is pointed to by LATEST ; but, ' , -FIND and (FIND) will not find it, so FORGET will not work! It's easy enough to execute SMUDGE to make it visible to FORGET , but that seems cumbersome. It may be best to simply make it clear to the user that the word can be removed by resetting the smudge bit before defining any other words and, then FORGETting it. I suppose it could just be ignored; but, it does clutter up the dictionary. Thoughts? ...lee Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 23, 2013 Share Posted December 23, 2013 It's actually non-trivial. I spent a while looking at this in TF. TF can spot 'structural' errors during the compilation of a colon-definition - things like missing LOOP after a DO - that kind of thing. In those cases, it can rewind LATEST and HERE (HERE also needs to be reset, otherwise you'll leak memory). It can do this, because ; does the checking at the end of a definition. However, when things come to an abrupt end, such as the case of a miss-spelled word (thus the word wasn't found) then ; never gets a chance to run, because ABORT runs. Thus you end up with an orphaned definition. I thought about this for TF, and determined that a new word was required: KILL. KILL will remove the word, regardless of smudge, restore LATEST, and set (not necessarily restore) HERE to the first free address. I never got around to implementing it though - ran out of ROM space! Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 23, 2013 Author Share Posted December 23, 2013 It's actually non-trivial. I spent a while looking at this in TF. TF can spot 'structural' errors during the compilation of a colon-definition - things like missing LOOP after a DO - that kind of thing. In those cases, it can rewind LATEST and HERE (HERE also needs to be reset, otherwise you'll leak memory). It can do this, because ; does the checking at the end of a definition. However, when things come to an abrupt end, such as the case of a miss-spelled word (thus the word wasn't found) then ; never gets a chance to run, because ABORT runs. Thus you end up with an orphaned definition. I thought about this for TF, and determined that a new word was required: KILL. KILL will remove the word, regardless of smudge, restore LATEST, and set (not necessarily restore) HERE to the first free address. I never got around to implementing it though - ran out of ROM space! That's pretty much what happens in fbForth and TI Forth. If the user reacts to a malformed colon-defined word, say XXX , immediately with SMUDGE XXX FORGET , everything is restored. HERE , LATEST and CONTEXT are all properly restored. If a word definition is started with CODE or ASM: , the smudge bit is not set, so something like ASM: XXX ... ;ASM can immediately be FORGOTten with no toggling of the smudge bit. I'm still thinking I should just give users the information and leave it up to them. After all, the dictionary functions perfectly well whether or not the offending word is removed—it's just aesthetically offensive in addition to taking up space. ...lee Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 23, 2013 Share Posted December 23, 2013 I'm still thinking I should just give users the information and leave it up to them. After all, the dictionary functions perfectly well whether or not the offending word is removed—it's just aesthetically offensive in addition to taking up space. I'm inclined to agree. Hand-holding is an anathema in the Forth world (though, in this particular case, I see no problem with it - I mean, why would you *want* to leave a half-finished definition in memory?). Anyway, as you say, as long as things are documented, people can work around it, and even invent their own words to fix the problem. That is the Forth way afterall - DIY 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.