Jump to content


+AtariAge Subscriber
  • Content Count

  • Joined

  • Last visited

Everything posted by TheBF

  1. Backing Thinkwards Just read this article about an problem solving methodology that I had never heard of. https://newsletter.butwhatfor.com/p/invert-always-invert-avoid-failure The article describes solving problems by actively searching for ways that will fail. I never thought of it quite so brutally but it reminds of something I said once at a Forth conference and Elizabeth Rather and a few others looked at me like I was out of my mind. I said: "Forth let's me make more mistakes per minute" By that I meant that by cutting programs into tiny pieces that could be tested in seconds interactively, I could make a lot of mistakes in a short time and therefore could find the best solution faster. Looks like I didn't invent the concept.
  2. On Windows 10 I use the game recorder system on a Classic99 window. https://www.pcmag.com/how-to/how-to-capture-video-clips-in-windows-10 It's pretty ham dandy.
  3. That's the approach I took and SAMS made that quite simple.
  4. Ok I cleaned up the code. There was a lot of unused cruft in there. I also made an E/A5 program so there a little screen saver for everyone. For some strange reason I find to funny to have these eyes looking around from inside my computer. Things I learned: You must run INIT-MULTI in your startup code if you want to run the multi-tasker. DUH! It runs automatically when you compile the multi-tasker. I just write the stuff. I don't know how to USE it. (See GO in the code) This version uses only 2 extra tasks and the console task handles the up/down eye motion. EYES.zip
  5. Before I get to my key problems I had this crazy idea this morning since I have now some fluency with the graphics and multi-tasking functions. This might make a neat screen saver. EYES.mp4
  6. If it was easy everybody would be doing it. I admire your persistence.
  7. Thanks guys. I will do some work in this area. I actually coded up the Thierry code a long time back to measure it. It takes 9 ticks. So that's 5 times faster. I never used it. At that time I was on the hairy edge of exceeding my 8K program size and so I didn't go any further with it. I think I can figure out how to patch a new KEY routine into the system when the multi-tasker loads. This idea would make things more efficient for sure.
  8. I don't think I understand that Rich but that would not be the first time. Maybe you mean I can test with separate code and only call KSCAN if there is something waiting? For clarity when I say 1.2 milli-seconds above, I measure like this: 1. Read the 9901 timer and remember the number. 2. Call KSCAN : BL @>000E in ROM ( with a few setup instructions of course) - disable interrupts - change workspace - BL @KSCAN - Read the byte at >8374 (save it in R4) - etc. you know the drill 3. Read the 9901 timer again. 4. Subtract the two readings and get the absolute value. I get 56 ticks on Classic99 and I just checked again on real iron and it wobbles between 56 and 57. I multiply 56 ticks by 21.3 uS, the tick time of the 9901 timer. That gives us 1,192.8 uS or about 1.2 mS. I could go faster if I made my own KSCAN code but then I need a translation table for CRU to standard key codes and it gets big real fast. I want the compiler, the interpreter and disk services to fit into 8K so there is more RAM for programs. Forth Assembler code is in the spoiler for reference.
  9. Yes it is thanks to the clever 9900 architecture. To jump from one task to the next task is one instruction. RTWP. Then we test the task's local awake/asleep variable. If the task is asleep try the next one. Sleeping tasks run 4 instructions. (I am sure Windows is just as efficient...) YIELD RTWP * Enter next task’s workspace STWP R1 * Use the WP as base address MOV >20(R1),R0 * read the TFLAG variable JEQ YIELD * if task is asleep jump back I knew something like this was possible 35 years ago but did not know how to "git 'er done". The big revelation was to "pre-setup" R13,R14,R15 in each task when it is created so you can switch to it with RTWP not BLWP. The workspace is just memory so why keep separate vectors when the very same data is in the workspace? This little piece of code made my life feel better. Does that make me a nerd? 😂
  10. I was curious if my ideas about writing 32 bytes to the pattern table at once was hogging too much CPU time. I broke up the code that writes 32 bytes into four chunks, writing data for one character at a time. After each chunk is written there is a PAUSE to allow other tasks to run. DECIMAL \ chopped into 4 pieces for smooth multi-tasking : CHARDEF4 ( data[] ascii# -- ) >R ( hold ascii# on Rstack like a local variable) DUP [email protected] CHARDEF PAUSE 8 + DUP [email protected] 1+ CHARDEF PAUSE 8 + DUP [email protected] 2+ CHARDEF PAUSE 8 + R> 3 + CHARDEF PAUSE ; Looks like the context switching time is still so small that I can't see any difference in the face rotation. I am impressed! :) This gives more time for the travel code or whatever you need to run. This also means that I might be better off making the BALLS array index 1 character pattern at a time rather than four. This is the one big thing you have to manage with a cooperative tasker, is tuning the code to give everybody the correct amount of time. The rule of thumb is every I/O operation needs at least one PAUSE. The reality is you have to test to make sure you got what you need. The good news is that PAUSE makes it pretty simple to adjust your code. Another cool thing is it does not interfere at all with putting other jobs on the interrupt if you want to. They can interoperate seamlessly. I could move the balls with AUTOMOTION and rotate the faces with Forth code. I added screen color changes to WAIT so we see something similar to the original XB256 demo. : WAIT ( -- ) 2 SCREEN BEGIN PAUSE ?TERMINAL UNTIL 8 SCREEN ; I have a better feel for what's possible with this tasker now on TI-99. I think I have exhausted this for now. BILLYBALLS-RETUNED.mp4
  11. Make that Camel Sweat So @Retrospect just keeps cranking out the demonstrations. The one that put all the "balls in the air" was interesting for me to see what happens if I created 10 tasks to move the balls and 10 more to spin the balls. Overall the results are not bad IMHO. The overhead per task when 20 are running looks like ~1.2 mS per task at least that is what my measurements say. The code is not beautiful. I just used lots of text to define everything. I would have to add a bit more code to dynamically spawn and destroy tasks but that was not important for this test. As you can see with a cooperative tasker when I added spin it loaded the system down even though I am not spinning very quickly. Some of that is because we are calling VMBW which takes the entire machine until it is finished changing 4 character patterns. I could fix that as well if this was a real application by chunking the pattern into small pieces but that might make the animation chunky too. No such thing as a free lunch. Another thing is that waiting for a key using KSCAN is about a 1.1mS affair so that slows all the task switching down as well. The WAIT in the demo calls >0020 which scans only for BREAK and is much faster. You can what happens when I use it. Anyway this was good workout for the Camel Multi-tasker. And so far everything worked as expected. BILLYBALL-20TASKS.mp4
  12. In the words of Obiwan after he came back from the dentist... "Youthe the Forthe Luke"
  13. Well... I don't actually have that limitation in Forth because I can define the data in place in memory when I compile the program. Then I write a little piece of code (ie: a sub-routine) that makes that block of memory look like an array for me. It's more like how it's handled in Assembly Language. However I don't have all the magic functions that you can use in your XB256 box of tricks 🙂
  14. Thanks for the explanation. I am wondering if the fact that you are keeping the data twice in the program why the stack space gets consumed. (no nothing about XB256 internals) By that I mean you have it in DATA statements and then you copy the data into an array so it exists in two places in the computers memory. The only way I know of avoiding that in BASIC it to read the data from a file. Anyway you have given me no end of homework. I am going to try creating your OHBALLS demo where each of the 8 sprites is its own TASK and see how much performance degrades on my system. These are great ways for me to see if my Graphics code works as intended.
  15. Another intriguing demo. I am still noodling on how to best pixel scroll the grass. :) XB265 is a monster to try and match. I don't understand the limitations on CALL PATTERN(). Please explain.
  16. Well... although it is difficult, we can change how we act despite our "basic mechanisms" being faulty. It is not easy however. I site sober alcoholics who have stayed "on the wagon" for many years as my only evidence. They would like to get drunk, they just don't.
  17. I was just looking at that myself and wondering how to make that happen in Forth. Pixel level scrolling... very clever!
  18. Oh man now I have to really work harder!
  19. LOL. That could be arranged. I guess it should be pumpkin with Thanksgiving coming up.
  20. Ya the Forth stuff is definitely strange. And then it gets stranger with the separate tasks. It has taken me a while time to get somewhat comfortable with it. They way you describe your explosion method is how you do it when everything is in a common loop. (If I understand your code and what you wrote correctly) In theory.... I can make an explosion task. I just tell it to start and it will play it's explosion and even do some kind of fragmentation of poor Bobby and then it puts itself to sleep when it's finished. That will all happen while everything else is still running. How cool is that? So that's what I will try and see how it works out. It is a really different brain process when you can make these "baby computers" (tasks) and give them loops that have nothing to do with the main program. It is not free however. Each task in this system takes 192 bytes for the registers and system variables and each switch to task takes a some time as well. As I said before I am really grateful for your well commented examples and creative ideas.
  21. @Retrospect created some really nice demos for XB256 in the Billy Ball topic and I just couldn't resist trying to do this with Camel99 Forth. I have zero imagination about games so I need to leverage his kind of imagination if I ever want to push the system. @Retrospect did an excellent job IMHO of organizing the code around a large set of sub-routines that live in a loop to control all the activities. That is the normal way to do this kind of thing. I wondered if I could do it with a set of tasks that manage the motion of Billy and Bobby independently and also manage the shooting in a task. I don't have it done yet but the concept seems to work. It was always risky for me to try since I have to stand on the pyramid of code that I built over the past few years. Something that is interesting about this idea, something I don't think about much, but it's called re-entrant code. This is code that runs with it's own copy of data so that many tasks can use the same routine at the same time. I tried this with ROTATOR and BOUNCER, using the same code to run Billy Ball and Bobby Ball. It's kind of neat. Forth is kind a natural for this if you use the data stack for everything or use special "user variables" that can be created for each task. Another handy thing is Forth's MS word which looks like a delay in milli-seconds but while it's counting down it passes control to the next task in the task queue so everything keeps running smoothly. This makes delays much easier to manage. Here is the code and the video shows the current state of what it can do. (not very much) I also compiled MTOOLS in the video so I could show some of the stats of the tasks. The system is looking pretty stable when I can compile code while sprites are moving. The Pulse number at the end of the video is the time it takes for the entire task queue to be visited and return to the console task. 4 mS is not too bad for our favourite old computer on four active tasks. Gotta love those workspace context switches!. BillyBall-tests.mp4
  22. Quite right there is no need. My idealism is just slightly put-out by making a text file that makes a text that makes a text file... that gets assembled. I will lookup a good therapist if it gets too serious. In the mean time it is still an amazing addition to TI-99 development so "compile away!"
  23. These are really great demos. Thanks for doing them. I have used one of your designs to improve my graphics language in the past. You have raised the bar very high with these ones. As time permits I have to see how I would do this kind of thing. The way you have laid out the source code makes it very clear to understand.
  24. You might be missing nothing. Sometimes code gets released because it works. Perfection requires an infinite amount of time.
  • Create New...