sometimes99er Posted October 3, 2013 Share Posted October 3, 2013 Yes. I can see it in TurboForth. TF uses the console's KSCAN routine, and if you put it in a short loop the delay is noticable. Try this in TF: : TEST1 ( -- ) PAGE 500 0 DO I . KEY? DROP LOOP ; : TEST2 ( -- ) PAGE 500 0 DO I . LOOP ; But you get the keys. How cool would it be to have something fast but then unreliable ? Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2840537 Share on other sites More sharing options...
Willsy Posted October 3, 2013 Share Posted October 3, 2013 But you get the keys. How cool would it be to have something fast but then unreliable ? I take your point. I did once think about a routine whereby you tell the routine which keys you want to scan, and it checks the appropriate CRU lines; faster than a whole keyboard scan. I wonder about the de-bounce thing as well (the main cause of the delay, IIRC). It might be required for say, the BASIC interpreter, or for INPUT etc, but for games (up, down, left, right, fire) no debounce is usually used at all. I seem to recall a few years ago on the Yahoo list somebody posted a super fast KSCAN routine. Was it yourself? Can't remember now! Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2840540 Share on other sites More sharing options...
sometimes99er Posted October 3, 2013 Share Posted October 3, 2013 The bottomline being, that you can't safely reread a column without a certain amount of waiting. Doing it once a frame seems feasible. Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2840542 Share on other sites More sharing options...
matthew180 Posted October 3, 2013 Author Share Posted October 3, 2013 To debounce in software you have to read the input *at least twice* (but more samples is better) and wait some amount of time between reads, then compare the two values. It comes down to waiting between samples, and there are good ways to wait, and not so good ways to wait. The ROM routine in the 99/4A takes the easy way, i.e. not so good way by using a busy loop to waste some time between samples: read busy loop (loop: DEC Rx, JNE loop) read again to confirm The good way, although a little more involved is to sample and store the input multiple times over a period of time, which allows you to do other things like run game logic, update the screen, etc. between samples. Anywhere between 20ms and 100ms seems to be typical based on some Google searches. Here is a guy who went all out on debouncing: http://www.ganssle.com/debouncing.htm Basically, waiting between samples does not mean you have to "wait" in a loop like the console does. Something like this frees up the system and still achieves user input 30 times a second (~33.2ms between samples): toggle=0 init sample array (~40 bytes) init key array (~40 bytes) // stores key up or key down states main loop: if toggle == 0 then read inputs and store to sample array program logic, uses *key* array (not the sample array) for input values wait for vsync toggle = not toggle if toggle == 0 then read inputs and compare to previous values: if current input == last input, set key array value to input (key up or down) end main This could be used for the entire keyboard using the arrays, or just limit the inputs to the specific keys you care about and use individual variables. The sample rate could be increased to 60 times per second (16.6ms between samples) simply by removing the "toggle" variable. Finally, doing the two samples on either side of the program logic would probably suffice if the logic was running long, i.e. over a frame or two. Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2840673 Share on other sites More sharing options...
Tursi Posted October 3, 2013 Share Posted October 3, 2013 I have a fast asm kscan function in the TI Farmer combination I did (TI MOTIF), so you can check that thread and play with the function included there - it does no debounce. For gaming input, really, I don't see the harm in ignoring the key bounce. You will never get the WRONG input, it will just be on/off/on a couple of times at the transition. It only really matters when you care about discreet presses (ie: if your input is EDGE triggered instead of LEVEL triggered, or if PULSES matter, then you need debounce.) The delay mechanism instead means there is a latency between the user input and the character movement, ignoring keybounce as a problem means it takes about that long before the character moves smoothly. There's little perceptible difference. 1 Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2840997 Share on other sites More sharing options...
marc.hull Posted October 4, 2013 Share Posted October 4, 2013 That is why the suggestion was made to increase and test the sample size instead of trying to nail down a keyed event. Try to keep up Mike Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2841121 Share on other sites More sharing options...
+Vorticon Posted October 14, 2013 Share Posted October 14, 2013 Hi. I have a couple of questions regarding KSCAN: Is it necessary to zero address >8374 to select the entire keyboard at the start of a program? I have not done so in the past with no issues, but I'm trying to acquire good programming habits. is the LIMI 2/LIMI 0 set necessary with each KSCAN call? Aren't interrupts by default enabled on the TI? Thanks! Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2847634 Share on other sites More sharing options...
Tursi Posted October 14, 2013 Share Posted October 14, 2013 You should load >8374 with the key unit that you want.. at least once in the system runtime a value other than 0 needs to be loaded (5 is the usual value). I haven't dug into what '0' means, except that it's documented as "last"... I suspect it means between 3 or 5. If you override the system start up and never set either, KSCAN doesn't work with 0, but in a normal startup it is fine. Interrupts should be disabled since KSCAN changes the CRU and GROM addresses and uses a shared workspace - if it were interrupted it could malfunction. That said, there's no specific LIMI call needed for every KSCAN. Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2847659 Share on other sites More sharing options...
+Vorticon Posted October 15, 2013 Share Posted October 15, 2013 So if I understand correctly, in a normal startup >8374 is already loaded with 0? Also, are interrupts normally turned off at normal startup? Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2847757 Share on other sites More sharing options...
Tursi Posted October 15, 2013 Share Posted October 15, 2013 Interrupts are normally turned off on start of an assembly program, but there is no standard that says they must be (and you have little idea what launched your program). You're safest to do it yourself. The normal state of the machine is interrupts disabled, though, usually they are only enabled briefly, including in all GPL software (such as Editor/Assembler). The KSCAN code is not set up as you might expect if you are starting as a cartridge. The console uses mode 3, not mode 5, for the main menu. If you are looking for a rule, always scan with mode 5 at the beginning of your program, or it may malfunction in some environments. You can leave >8374 alone after the first time you set it unless you run something that changes scratchpad. Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2847879 Share on other sites More sharing options...
Willsy Posted October 15, 2013 Share Posted October 15, 2013 Yep. I always use mode 5 for KSCAN. Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2847892 Share on other sites More sharing options...
+Vorticon Posted October 15, 2013 Share Posted October 15, 2013 Got it. I have to say though that learning assembly language on the TI, by itself, is only the tip of the iceberg. There seem to be so many vagaries, exceptions, undocumented features etc... not explicitly covered in books which I have no hope of ever mastering given that my real life is far removed from the programming world, and so I have to bow in admiration to your collective mastery of such arcana. I get great comfort from the fact that no matter how stuck I am on a project, the solution is only a matter of posting on this forum (or the Yahoo ones) and waiting a few hours, or sometimes mere minutes! So thank you 1 Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2847926 Share on other sites More sharing options...
RXB Posted October 15, 2013 Share Posted October 15, 2013 Does Assembly have some problem with KSCAN mode 0? Why is mode 5 prefered over 0? GPL always uses mode 0 and other then XB I have not seen any GPL use mode 5 so again why mode 5? (Well except games that use mode 1 and 2 for left or right of Keyboard.) Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2848236 Share on other sites More sharing options...
+InsaneMultitasker Posted October 15, 2013 Share Posted October 15, 2013 You should load >8374 with the key unit that you want.. at least once in the system runtime a value other than 0 needs to be loaded (5 is the usual value). I haven't dug into what '0' means, except that it's documented as "last"... I suspect it means between 3 or 5. If you override the system start up and never set either, KSCAN doesn't work with 0, but in a normal startup it is fine. For whatever reason it sticks in my brain that mode 0 (last) simply meant to use whatever scan operation was selected previously until such time as a new scan mode was selected. Whether that works in practice one would need to test and verify. Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2848274 Share on other sites More sharing options...
+Vorticon Posted October 15, 2013 Share Posted October 15, 2013 For whatever reason it sticks in my brain that mode 0 (last) simply meant to use whatever scan operation was selected previously until such time as a new scan mode was selected. Whether that works in practice one would need to test and verify. Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2848295 Share on other sites More sharing options...
+Vorticon Posted October 15, 2013 Share Posted October 15, 2013 Well, the KSCAN entry in the EA manual states that a 0 selects the entire keyboard. Happy to go with 5 though if that is the con census Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2848297 Share on other sites More sharing options...
Willsy Posted October 16, 2013 Share Posted October 16, 2013 I think that's just incorrect. AFAIR 0 selects the *previous* keymode (which seems dumb to me - why would even need such a feature - if a programmer can't arrange his code such it can't remember *by itself* then he should knitting, not coding!). I always use 5 which is the whole keyboard, including upper/lower case, all FCTN codes, all CTRL codes... The whole shootery Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2848479 Share on other sites More sharing options...
Tursi Posted October 16, 2013 Share Posted October 16, 2013 Exactly.. there is no mode 0. The EA manual makes a lot of assumptions -- including that you are launching after the Editor/Assembler cartridge has run. 5 is the 99/4A keyboard mode. 3 is the 99/4 compatible keyboard mode (uppercase only, no control or function keys). 4 is Pascal, IIRC, but it's just a different keymap, and 1 and 2 are the left and right split keyboard/joystick scans. 0 is "whatever was set" - I believe it's there for compatibility between the 4A and the 4. If the startup system (E/A cart) sets the mode, and you always use 0, you don't have to worry about it. I'll dig through KSCAN later if nobody else does and verify 0's purpose. Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2848773 Share on other sites More sharing options...
RXB Posted October 16, 2013 Share Posted October 16, 2013 (edited) Every cart including XB, RXB, other XB carts and EA cart all use Keyscan mode 0 but do check 5. Default is not mode 5 but 0. I can not find any GPL code in any Cart that defaults to Keyscan Mode 5. Where are you guys coming up with this info on mode 5 is the defualt? XB checks other modes also and there are some uses for Keyscan mode 5 but something people may not know is that 0 works better then 5 as some keys are not seen by Keyscan mode 5. An example is in RXB when Keyscan Mode 5 is set multiple keys pressed on a real TI no longer respond while in Keyscan Mode 0 they did. I posted a video on this using RXB command CALL IO in one that does not work properly in Classic99 but tested on a real TI99/4A works as should. (up to 4 keys pressed at once detected in this CALL IO program) If you change >8374 from 0 to 5 you have some keys that no longer respond. I do not know why? http://www.youtube.com/watch?v=sHTHDngNMcE&feature=c4-overview&list=UUULwPKqrRFCtNv5_xMuOqQw Edited October 16, 2013 by RXB Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2848879 Share on other sites More sharing options...
+Lee Stewart Posted October 17, 2013 Share Posted October 17, 2013 (edited) The keyboard modes are an invention for KSCAN and are as @Tursi delineated. This is also what is very clearly laid out in the documentation of the CALL KEY subprogram in the TI-99/4A User's Reference Manual. What is not so clear from the documentation is what actually happens in KSCAN. From Thierry Nouspikel's website (http://www.nouspikel.com/ti99/keyboard.htm#quick scan), the "default" keyboard argument – 3 is stored at 83C6h. If you store 1 (left side of keyboard) or 2 (right side of keyboard) at 8374h, nothing happens at 83C6h and 8374h keeps 1 or 2 until it is changed. If, however, you store 3 (TI-99/4 keyboard mode), 4 (Pascal keyboard mode) or 5 (Standard [basic] keyboard mode) at 8374h, 83C6h will change to 0, 1 or 2 for whichever code of those three modes you stored at 8374h AND KSCAN changes 8374h to 0. What this means is that you can always restore KSCAN to using the last-used 3, 4 or 5 mode by storing 0 at 8374h when you're done with left/right modes because KSCAN will get it from 83C6h. You can check this for yourself by storing, say, 3 at 8374h (this can easily be done in fbForth, TI Forth, TurboForth or Classic99's debugger) and watching 8374h and 83C6h to verify what I've said. Furthermore, typing uppercase and lowercase letters now all appear in uppercase because you've put the keyboard in TI-99/4 mode. You will now need to store 5 in 8374h to get back to Standard mode; but, after that, it's only necessary to store 0 at 8374h after using 1 or 2. ...lee Edited July 6 by Lee Stewart Corrected Thierry's URL 1 Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2848971 Share on other sites More sharing options...
Tursi Posted October 17, 2013 Share Posted October 17, 2013 Thank you, Lee! Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2849437 Share on other sites More sharing options...
+Vorticon Posted October 18, 2013 Share Posted October 18, 2013 I saw this today on the Yahoo listserv, and I thought it was fascinating. Essentially the author, James Abbatiello, is able to coerce TI BASIC to run a small assembly language program. Take a look: 10 REM Escape the BASIC sandbox20 REM by James Abbatiello <abbeyj@...>30 REM Displays an animated Hello, World!40 REM message using machine language.50 REM Works even without Extended BASIC60 REM and without the 32K memory expansion.100 CALL CLEAR110 PRINT "PRESS"120 PRINT "1 FOR TI-99/4A"130 PRINT "2 FOR TI-99/4A (alt)"140 PRINT "3 FOR TI-99/4A V2.2"150 CALL KEY(5,C,S)160 IF (C < 49) + (C > 51) THEN 150170 PRINT "INITIALIZING ..."180 V(0)=885190 V(1)=882200 V(2)=846210 L=V(C-49)220 A$=CHR$(INT(L/256))&CHR$(L-256*INT(L/256))230 FOR I = 1 TO 126240 READ C250 A$=A$&CHR$©260 NEXT I270 OPEN #1:A$800 DATA 128,168,165,172,172,175,140,128810 DATA 183,175,178,172,164,129,0,0820 DATA 0,0,0,0,0,0,0,0830 DATA 0,0,0,0,0,0,0,0840 DATA 0,0,0,0,0,0,0,74850 DATA 0,0,0,0,0,0,0,0860 DATA 0,0,0,0,131,130,2,0870 DATA 2,244,2,11,64,0,6,0880 DATA 19,250,208,111,252,0,10,17890 DATA 23,252,215,224,131,247,2,2900 DATA 131,76,215,203,5,139,208,114910 DATA 19,242,219,193,255,254,16,251920 DATA 0,0,0,0,0,0,0,0930 DATA 0,0,0,0,0,0,0,0940 DATA 0,0,0,0,0,0,0,0950 DATA 0,0,0,0,0,0The first thing we need is the address of some specific code in GROM but this unfortunately varies in the different GROM versions and I have no way to detect which value is appropriate. I resorted to asking the user. Armed with this, we use it as the first two bytes of a long string. Then we take this string and try to OPEN it.For the following explanation you might want to follow along in your own copy of TI Intern. When we try to open this weird filename we'll end up at G>401E (Basic OPEN). From there we'll call G>4BA1 to build a PAB. There's a bug here but not one that I exploit. The code takes the length of the input string and adds >0E to it to compute the length of the entire PAB and then it tries to allocate this much space. Only one byte is used for this length so passing in a long name can cause this calculation to overflow, leading us to allocate less space than needed. We'll end up writing past the end of the allocated space and overwriting something (probably part of the line number table). If we ever want to return to BASIC this would be a problem. The string I use is not long enough to trigger this bug.Eventually we'll try to actually open this file by calling G>03D9 (DSRLNK). This is expecting a string like "DSK1" or "DSK1.FOO" and it wants to find the first period (if any) and then treat the part to the left as the device name. It will copy this device name into the FAC (at >834A) but only if it fits. First it looks for a period and stores its index (or the length of the entire string if there is no period) in >8355. It then uses "CGE @>8355,>08" to check the length and make sure it is 7 bytes or less. However this doesn't work properly for long strings because it is a signed comparison. So if you have a string of length >80 or longer it will still pass this check. Then the code uses "MOVE @>8354 TO @>834A FROM VDP*>8356" to try to copy the device name into the FAC and conveniently copies the entire string, blindly overwriting whatever was there. This is nice for us because it copies our string unmodified right into the scratchpad.Let's take a closer look at that string. Here's a hex dump along with the addresses that it will end up being copied to:Addr Offset 834A 0000 03 ?? 80 A8 A5 AC AC AF8352 0008 8C 80 B7 AF B2 AC A4 81835A 0010 00 00 00 00 00 00 00 008362 0018 00 00 00 00 00 00 00 00836A 0020 00 00 00 00 00 00 00 008372 0028 00 4A 00 00 00 00 00 00837A 0030 00 00 00 00 00 00 83 82 8382 0038 02 00 02 F4 02 0B 40 00838A 0040 06 00 13 FA D0 6F FC 008392 0048 0A 11 17 FC D7 E0 83 F7839A 0050 02 02 83 4C D7 CB 05 8B83A2 0058 D0 72 13 F2 DB C1 FF FE83AA 0060 10 FB 00 00 00 00 00 0083B2 0068 00 00 00 00 00 00 00 0083BA 0070 00 00 00 00 00 00 00 0083C2 0078 00 00 00 00 00 00 00 000000-0001 is the address in GROM. It can be >0375 (Classic99 and my actual hardware), >0372 (as in TI Intern), or >034E (V2.2).0002-000F is the string " HELLO, WORLD!" with a leading space and the >60 BASIC screen bias.0029 is >4A which will overwrite the GPL substack pointer at >83730036-0037 contains the address of the entry point of our program (>8382).0038-0061 contains the actual program:ENTRY LI R0,756 768 - len(" HELLO, WORLD!") LI R11,>4000 VDP write addressWSTR DEC R0 at end of screen? JEQ ENTRY if so, start over at topWAITVBL MOVB @->400(R15),R1 wait for vblank SLA R1,1 JNC WAITVBL MOVB @>83F7,*R15 low byte of VDP write address LI R2,>834C address of " HELLO, WORLD!" MOVB R11,*R15 high byte of VDP write address INC R11WCHAR MOVB *R2+,R1 load byte of string JEQ WSTR done when we hit NUL terminator MOVB R1,@-2(R15) write byte to screen JMP WCHARThe rest of the bytes are just filler/padding. We end up overwriting quite a lot of stuff in the scratchpad including R0 through R4 in the interrupt workspace.After copying the string to the scratchpad the GPL will continue running until it hits RTN or RTNC. The interrupt handler might execute between any of these instructions and update the timer at >8379 or the VDP status byte at >837B so we have to be careful not to rely on having anything in those locations. This bit me at first and I it took a while to figure out why things would work properly one time and not the next.At this point the RTN will pop a GROM address off the GPL subroutine stack. We've set that pointer to >4A so the address will be fetched from >834A. Hopefully we've managed to arrange for that to point at these GPL instructions: DST @>8300,@>8380 Fetch address in >8300 (for XML) XML >F0 and executeThis copies our start address from >8380 to >8300 and then calls XML >F0 which jumps to an address stored in >8300. And we're off and running! I don't suppose anybody wants to try their hand at making a more interesting payload for this? -- James Abbatiello 9 Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2849894 Share on other sites More sharing options...
+Vorticon Posted October 28, 2013 Share Posted October 28, 2013 Hi. What is the best way to track time on the TI short of using a real time clock? Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2855172 Share on other sites More sharing options...
Willsy Posted October 28, 2013 Share Posted October 28, 2013 Hook the isr. Increment a byte on each interrupt. On the 60th count increment your seconds byte and do a cascading check on minutes and hours. Accuracy would only be okay while interrupts are enabled. Disk access etc would stop the clock. Maybe there's a better way with the 9901? Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2855243 Share on other sites More sharing options...
Tursi Posted October 28, 2013 Share Posted October 28, 2013 There are only two "real time" parts in the 99/4A - the VDP and the 9901. You can count VDP interrupts (as long as you can guarantee you will never miss one) to get 1/60th second resolution, or you can use the 9901 timer mode for more control over the duration. You will still need to respond to timer expiries (and without a bit of hackery, you can't get an interrupt - Theirry's page shows Jeff Brown's trick for it), and count them yourself. 1 Quote Link to comment https://forums.atariage.com/topic/162941-assembly-on-the-994a/page/11/#findComment-2855245 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.