Jump to content


+AtariAge Subscriber
  • Content Count

  • Joined

  • Last visited

Everything posted by TheBF

  1. I think C++ objects and object libraries are a pretty big mind shift for a BASIC programmer. If you just want to use C++ as a C compiler then it gets a little more straightforward, but even still, handling strings and arrays as pointers can be challenging for a newbie C programmer. Python would be a little bit closer would it not? And if a TI-BASIC library can be added to BACON or something like it, you have your C++ compiler (GCC) and let people program in a BASIC dialect.
  2. Looks like we need some BaCON. http://www.basic-converter.org/
  3. C as the output language of a compiler has been known to work very well. That's a good idea. Not that simple to make but it would perform well I think. Doable with something like YACC/BISON or those kind of programs I should think.
  4. Found this on a Forth board but it has nothing to do with Forth. (aren't you relieved) But it is interesting to anyone who plays with computers. http://www.worldpowersystems.com/J/codes/index.html
  5. While trolling through the library code for GForth, the GNU Forth system, I found a random number generator. I uses a very simple algorithm and might be useful to Assembly language programmers here. Here is the Forth Code: \ generates random numbers 12jan94py \ Copyright (C) 1995,2000,2003,2007 Free Software Foundation, Inc. \ This file is part of Gforth. \ Gforth is free software; you can redistribute it and/or \ modify it under the terms of the GNU General Public License \ as published by the Free Software Foundation, either version 3 \ of the License, or (at your option) any later version. \ This program is distributed in the hope that it will be useful, \ but WITHOUT ANY WARRANTY; without even the implied warranty of \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \ GNU General Public License for more details. \ You should have received a copy of the GNU General Public License \ along with this program. If not, see http://www.gnu.org/licenses/. \ From Gforth, modified for CAMEL99 system HEX 83C0 CONSTANT SEED \ RAM where TI has a number incrementing in main menu 1045 CONSTANT GEN# \ GForth uses $10450405 \ taking the 1st 16 bits : RND ( -- N ) SEED @ GEN# UM* DROP 1+ DUP SEED ! ; : RANDOMIZE ( N -- 0..N-1 ) RND UM* NIP ; (edit: CORRECTED this code with UM*) If we were to translate it to infix notation as a function in integer BASIC it would something like this: The multiplication (UM*) in Forth is unsigned, mixed multiply ( int*int->double) which is really just the TMS9900 MPY instruction. Nice and easy. DEF RND() R=SEED*GEN#+1 SEED=R The cool thing is where the TI-Forth algorithm repeats after 20,000 ints or so, this one repeats after 65,536 and the Histogram is very flat. In both cases I started with the >3567 seed value used by TI-BASIC just for consistency. (Thanks Lee) Increased my histogram samples to 320 to give all 32 buckets a potential 10 random numbers which seemed a better way to do it. Might be useful to someone making games. PS For reference I re-did the TI-BASIC histogram using 320 random samples.
  6. So I ran some of the *HAYES tester on my Forth system and guess what? I coded my bit shifting words in a way that made them FAIL. No shock because I didn't read the spec. (DUH) In the WORD [email protected] in my earlier post, I added an IF statement to cope with a 0 bit shift. Well the ANS/ISO Forth standard already anticipated that. So I recoded my shift words (LSHIFT & RSHIFT) to pass the test and now [email protected] is much faster and much simpler. I have edited the previous POST to reflect the correction. : [email protected] ( bit# addr -- ? ) BITFLD @ \ compute bit# & fetch bits in cell SWAP RSHIFT \ if bit#<>0 RSHIFT, 0001 AND ; \ mask 1 bit * The Hayes tester is set of test words and test suites for every standard Forth word that let's you confirm that a Forth WORD is doing what it's supposed to do. It looks like this for a simple word like SWAP: T{ 1 2 3 SWAP -> 1 3 2 }T ​You get OK if the output swap matches the '1 3 2' after the arrow and an error message if not. To read more: http://forth-standard.org/standard/testsuite
  7. Could the LOAD line be confiscated and used to create a proper RS232 interrupt? What I mean by proper is used for RS232 only, so as to reduce the size and complexity of the ISR allowing faster communication and lower overhead on the main program. It would require running a connection from the RS232 card. I have not looked at the drawings to see if there are any open pins on the Expansion box buss. And based on Tursi's response on multiple triggers it might want some conditioning logic added to the RS232 board. I kind of salivate knowing there is an available interrupt vector in RAM.
  8. That is excellent advice Apersson850. It's also important to balance the expected speed of your assembly code versus your XB or Pascal application speed. My point is, even if you use 8 bit RAM for your workspace, the upgrade in speed is still many many times faster than your hi level language speed. So I like the Steve Jobs approach: "Make it work, then make it better" B
  9. The think you assumed perhaps, that I am as smart as you are. It takes me a little longer to connect the dots or bits as in this case. I was out of this arena for over 20 years doing product marketing and then general management. (be kind) There are lots of rusty parts in this old head about software and Forth, but I am applying a little oil every day. B
  10. As I looked at this code I realized that the TI-99 already has a bit pattern for all the characters in the VDP RAM. In CAMEL99 I call the pattern table PDT and you can access the pattern address of any character with ]PDT. So I removed the UPPER case filter and the offset used to start all characters at >20 (space character) and substituted ]PDT. With this I can get the bit pattern for any ASCII character in the TI-charset. Then I replaced the memory character fetch ( [email protected] ) with the VDP version ( [email protected] ) so that I read the pattern from VDP RAM. After those changes I can print out any TI-99 character in this banner form without using another table of patterns. That saves a lot of space since I only need this code and it works. : BANNER ( str len -- ) 8 0 DO CR 2DUP BOUNDS \ convert str,len to end/start addresses ​ ?DO \ I is address of each char in string I [email protected] ]PDT J + [email protected] \ read VDP byte PDT[ascii,j] ​ 2 7 DO DUP 1 I LSHIFT AND IF ." #" ELSE ." " THEN -1 +LOOP ​ DROP LOOP LOOP ​ 2DROP ;
  11. As I am testing out my system I am trying to run other peoples Forth Code. This BANNER routine uses a data matrix to define big fonts. All I had to do was add my version of the UPPER routine to convert chars and my BYTES word to compile the data matrix and it worked.
  12. Actually just LWPI >8300 That way you wont't pollute R13, R14 and R15 in the Other workspace. And that only guarantees you 8300 to 830F (16 words of memory for registers) Consult the Editor Assembler manual for the usage of the memory at 8300 to 83FF
  13. Well... the TI system is using the workspace at 83E0 and it kind of assumes it owns them. So if you want a full register set for your program, it's available. And if you don't change you have to save at least some of the registers in order to use them. Also it's simpler to let TI-99 keep it's workspace when you call some of the system calls like KSCAN and such. So the good news is there is a nice space at >8300 that is waiting for your program to use as a workspace. Take it and have 16 registers to yourself. B
  14. I saw some super posts in the archives about sound ripppers and stuff related to sound so I thought I would take a run making a sound list player. All of this can be done in FB Forth or TF as well. However there are some words that will need adjustment. The missing words would be MS, which is just a quick delay loop. : MS 8 0 DO LOOP ; ( something like this, 8 is "about" the correct number for 1 MS) And PAUSE which is a noop. : PAUSE ; will fix that quickly. And ?NUMBER in CAMEL Forth is non-standard, but Lee created an equivalent in FB Forth for another one of my posts a while back. (Will find that and post here) However what a little player like this might be good for is trying out some data to listen to it for ALC programmers. You can feed it sounds lists from the keyboard and play them to see how you like the sound. Couple of things to be aware of: 1. This player turns all 4 sound channels off when it gets to the end of a list with the word SILENT. If you use the TI player you will need to add the string of bytes to turn off your sounds. 2. The BYTES word does not use commas, so sound lists tried here will have to have the commas removed. 3. UN-comment SND! for other Forth systems or use the equivalent word to write a byte to the sound chip address. 4. LSHIFT is the ANS Forth word, but TF uses << for the same thing I believe. Not sure about FB Forth . How it works: PLAY$ takes the address of a string of bytes with a count byte at the start and a time duration byte at the end. It converts the duration byte to milliseconds assuming a 1/60 of a second ISR time. It then computes the start and end address of the sound bytes and loops through them sending each one to SND! (the chip address) When the loop is completed it waits for the duration of milliseconds. PLAY Is the high level word to use for playing a sound list. It simply looks to see if there is a non-zero byte count in a sound string. While that is true is calls PLAY$. Then using the count byte it computes the address of the next string in the list and plays the next string until it hits a final ZERO. CREATE XXXX is Forth's way of making a new word in the Dictionary of words and will return the start of the data address of that new word. BYTES is a compiler directive that was created to parse the input stream, convert the data to a number and compile it into the next byte of memory. It could have been done with the C, primitive but it makes the lists harder to read ( example AA C, 7 C, DE C, ETC... ) I believe the code here will run with the CAMEL99 version in GITHUB /BIN folder. (did not try it yet) I stole some sounds from PARSEC for FIRE and EXPLODE and I must confess it was a religious experience to hear those sounds come out my Forth system. If you get it working type: 3 SHOTS at the console. That does 3 FIRE sounds and then runs the EXPLODE list. Memories...
  15. This points to some deep insights into the architecture of our brains. I don't know what exactly, but the fact that we can't see the parallel lines clearly makes me wonder what else do I misperceive? I suspect that answer is a great deal! And if anybody here sees the parallel lines clearly, they are either a mutant or should maybe see their doctor :-) Thanks Sometimes99er! B
  16. I always like the way Wirth's languages have these different data types. Forth makes you work hard for that nice stuff. So in my Pascal Envy fever I thought I would see what it would take to make a "packed array of bits" and it is more code than I thought. The overhead just to set 1 bit, according to the CLASSIC99 9901 timer is 1.8 milli-seconds in my Forth system. EDIT: New times 1.5mS to set a bit. 1.1mS to read a bit ([email protected]) This could be really sped up with assembly language code words but it's still a lot of work to strip out bits. EDIT: Here is the revised code with fixed RSHIFT and uses CELL+ and CELLS to be less platform dependant. \ BOOLEAN array experiment \ BOOLEAN data is one CELL (16 bits on TMS9900) HEX \ create & erase memory area for 'n' bits : BITS: ( n -- ) CREATE 8 / HERE OVER 0 FILL CELL+ ALLOT ; \ added 2 bytes extra \ compute bit# in a cell & cell address : BITFLD ( bit# addr[] -- bit#' addr) SWAP 10 /MOD CELLS ROT + ; : [email protected] ( bit# addr -- ? ) BITFLD @ \ compute bit# & fetch bits in cell SWAP RSHIFT \ if bit#<>0 RSHIFT, 0001 AND ; \ mask 1 bit : BIT#>MASK ( bit# -- n ) 0001 SWAP LSHIFT ; : BSET ( bit# addr[] -- ) BITFLD ( -- bit# addr) SWAP BIT#>MASK >R \ save the mask DUP @ \ -- addr bits R> OR SWAP ! ; \ or mask into bit, store in addr : BRST ( bit# addr[] -- ) BITFLD ( -- bit# addr) SWAP BIT#>MASK INVERT >R \ invert and save mask DUP @ \ -- addr bits R> AND SWAP ! ; \ mask out bits, store back in addr \ test code DECIMAL 300 BITS: ]X \ make array X of 1000 bits : FILLBITS 300 0 DO I ]X BSET LOOP ; : CLRBITS 300 0 DO I ]X BRST LOOP ; : EVENBITS ." Erasing..." CLRBITS 300 0 DO I ]X BSET 2 +LOOP ; : SHOWBITS 300 0 DO I ]X [email protected] . LOOP ;
  17. I didn't need GPL to move data from GROM to RAM. The GROMs are memory mapped devices. I set the address and then read the GROM data and put it somewhere in RAM. I did it in Forth using the routine that reads a character from a memory location. ([email protected]) Which is written in assembler. Then I can put it anywhere I want to. Am I missing something about GROMS? (very possible) : GROM ( addr -- ) \ set GROM address SPLIT 9C02 C! 9C02 C! ; : [email protected]+ ( -- c) 9800 [email protected] ; \ GROM char fetch, w/auto-incr
  18. It makes me wonder how big a "Boolean" type is in the P-Code system. Any idea? ​Oops re-read your earlier post completely. 16 bits for a Boolean. How big can you go before it hits the limit? Could you try ARRAY of CHAR ?
  19. 3 MHz clock, 14 cycles or more to do almost anything and you get a VERY slow machine. I would estimate 120,000 instructions per second or less. State of the art circa 1970s By comparison the modern MSP430 from TI which has a similar instruction set and register count to the TMS9900 does some instructions in 1 clock cycle but on average takes about 2.5 So with the same 3MHz clock it would give you 1,200,000 instructions per second. This is part of the fun of programming the old devices. You must be smarter <oldfartrant> than these kids today, programming multi-core GHz processors in Javascript.</oldfartrant>
  20. Yes. I did not run your code with 10000 primes
  21. That's great optimization. Thanks telling us about it.
  • Create New...