-
Content Count
3,144 -
Joined
-
Last visited
Posts posted by Willsy
-
-
Is there any evidence to suggest that the graphics data in GROM has ever changed location? Can I not just assume a hard-coded address?It's in different places in each GROM set. That's why there's a vectored function in GPL to get the data from, and why I wrote this function in the first place.
It probably is larger than the GPLLNK, but I never liked the idea of relinquishing control and hoping I get it back.

Ah! OK, thanks Tursi!

-
Okay, for me, 1K in the upper cart memory address would be just fine. Would it be possible to include a jumper for 4K or 1K RAM?
(You know, since we're just kicking the tyres here!)
-
Given that GPL is a byte based assembly language, it expect it is possible to write much more compact programs in GPL than in assembly - the tradeoff being speed, of course.
Imagine if TI *had* produced a GPL processor chip (as was the rumour?) - man, that would have been something!
Mark
-
Thanks guys. I'll look at status reg #1 first as that is likely a simpler solution. Question though... How does one read a *status* register in 9900 land? We can read *VDP* registers using the normal means... Are the status regs read using the exact same technique, or is there a different address in play for those registers?
I have 80 column working just fine. The whole system adapts iteself itself if you go into 80 column mode. Thats been working (and is included) in TF V1.0 - however, I would like the system to auto-detect and just enable 80 column at start-up if the 38/50 is detected. For that though, a reliable detection mechanism is critical. Can't have it trying to sdelect 80 column mode on a 40 column system!
Mark
-
I actually wrote this code for the first version of the multicart, and you're free to reuse it. It parses the GPL vectors to find the actual character data in GROM and loads it directly, no GPLLNK needed. It does assume that the starting address IS a vector, but works on all three main revisions of the 99/4 and 99/4A GROMs.
Crikey mate! I reckon that takes more room than the GPLLNK routine

;[ GPLLNK ; This routine is based on the routine published in the July 1986 edition of ; Smart Programmer. Modified by yours truly to allow it be executed from ROM. gplws equ >83e0 ; GPL workspace gr4 equ gplws+8 ; GPL R4 gr6 equ gplws+12 ; GPL R6 stkpnt equ >8373 ; GPL stack pointer ldgadd equ >60 ; load and execute grom address entry point xtab27 equ >200e ; low mem XML table location 27 getstk equ >166c ; cpu register data - this data is copied into >200e onwards, so that it sits ; in R7 onwards gpllnk data glnkws ; [mapped to R7] set up BLWP vectors data glink1 ; [mapped to R8] rtnad data xmlrtn ; [mapped to R9] gxmlad data >176c ; [mapped to R10] GROM address for GPL XML 0F27 opcode data >50 ; [mapped to R11] Initialised to >50 where PUTSTK ; address resides ; this routine runs in it's own workspace, starting at >2000 glnkws equ >2000 ; GPLLNKs workspace of which only registers R7 thru R15 ; are used glink1 li r0,gpllnk ; we need to copy the cpu register data (above) to li r1,>200e ; RAM. R0=Source, R1=Destination li r2,5 ; R2=Word count gpllop mov *r0+,*r1+ ; copy the data above into r7 onwards... dec r2 ; copied all of it? jne gpllop ; loop if not mov *r11,@gr4 ; put PUTSTK address into R4 of GPL WS mov *r14+,@gr6 ; put GPL routine address in r6 of GPL WS mov r9,@xtab27 ; put XMLRTN address into >200e lwpi gplws ; load GPL workspace bl *r4 ; save current GROM address on stack mov @gxmlad,@>8302(r4) ; push GPL XML address on stack for GPL return inct @stkpnt ; adjsut the stack pointer b @ldgadd ; execute our GPL routine xmlrtn mov @getstk,r4 ; get GETSTK pointer bl *r4 ; restore GROM address off the stack lwpi glnkws ; load our ws rtwp ; all done - return to caller ;]
Is there any evidence to suggest that the graphics data in GROM has ever changed location? Can I not just assume a hard-coded address?
Mark
-
I'm really very interested in GPL and plan on having a serious go with it soon. The thing about assembly language on the TI is the TMS9900 instruction set - assembly language on the 99xx is *so easy*, that once you know it well, it really doesn't make sense to 'go backwards' into other languges.
Except Forth.
Sorry! But you expected me to say that, didn't you!

-
Can anyone think of a method to auto detect a V9938 or 58 in code? I seem to remember they had a special register that contained some sort of ID field, but I can't find it after scanning the data book

-
Yes and you have another step with CSAVE to create GRAM Module Files.
But once that is done you can have a Module always set up and run permanently.
That is something that Assembly or Forth could never do.
Be instantly up and running from menu screen even if the computer is turned off and on. That more then pays for the trouble.
If not for Cartidges and that Slot there would be no TurboForth cart. By the way I need to order one.
Hmmmm... every time I turn on my TI I am instantly greeted with "Menu" (assembly program) and can select 24 assembly or XBASIC program to run instantly at the touch of a button. No loading required (on my part anyway.)
And where does this reside?
Afraid you missed my point. The TI was built to access 640K of GROM from the cartridge slot in 1979. This was just the console and nothing else. Really what can you do with 8K Cartridge RAM and just a console?
(Answer: Sell cartriges like hot cakes just like TI did. Hottest item they sold, and attempted to shut down others that created them.)
I fully understand things change but give credit to what made this possible. When the TI99 was introduced it was the GROM slot that sold the machine not the DISK programs or TAPE programs. Later DISK and TAPE took off.
Everyone started with EA/MM/XB/LOGO/PASCAL or the Basic built in. All of these are GPL. Just please give credit instead of dissing GROM. All of these hacks copy what GPL does right out of the box since it was introduced.
Nobody is dissing GROM. Just pointing out a bit of evidence that contradicts your wildly inaccurate statement. All computers of this era had cartridge ports so I don't understand why this attribute "makes the computer."
I understand your affinity to GPL and I think it's great. But when you make silly arguments as to why it is the end all and be all of the TI then you really just hurt your own cause.
As far as Turbo Forth is concerned. I may be wrong but I don't think it contains much GPL or GROM.
No. No GROM and it only uses a single GPL call to load the upper case characters at startup! That's it! If I knew how to locate the characters in GROM then I could save some memory, as it is, I had to write a GPLLNK *just* to load the freaking characters!
-
Interesting stuff..
this is almost starting to read like GPL vs Turboforth trash talk :-)
Question is could you write GPL in TurboForth!
I believe you could, yes. Though, in fairness to GPL, you could also write a Forth in GPL!
-
1
-
-
@lucien2
Excellent video. And thanks for the how2 overview. Should go back and watch the video. The 6+ minutes scared me.
GPL and TF seem to be very very close indeed - they looked exactly the same speed to me. I thought TF would be a little bit faster than GPL, but it looks about the same.
Street cred to both languages/implementations. Me too, I thought TF would be maybe at least twice as fast, but I guess GPL surprises a bit.

It certainly does surprise! Would it run at that speed in a real console, running from GROM?
-
1
-
-
Could you imagine if the c64 was vic 20 comaptible and commodore were telling software houses to write to the vic20 as the base commodore system to develop for (or if you want to go back that far, make the c64 PET compatible and ask software houses to develope for the PET as the base commodore system to develop for), would the c64 have been the best selling H/C if they had pursued that policy, no, infact it probably would have resulted in people buying more vic20's and giving the c64 an afterthought (remember what happened to the 1200xl and why it resulted in people buying more 800's)
That is exactly what happened with the Commodore 128.
-
I changed the TF code from this
BEGIN RND 23 MOD TO R RND 30 MOD TO C R C GCHAR 38 < R C 1+ GCHAR 38 < AND UNTILto this
BEGIN RND 23 MOD TO R RND 30 MOD TO C R C GCHAR 40 < R C 1+ GCHAR 40 < AND UNTILto fill the holes, but there are still two holes that are not filled (maybe the random routine?).
Yeah, it's the RND routine, which is just reading from memory addresses. I'm no mathematician!
GPL and TF seem to be very very close indeed - they looked exactly the same speed to me. I thought TF would be a little bit faster than GPL, but it looks about the same.
Mark
-
1
-
-
I'll check my cart box tonight and see if I have a mini-mem in there. I'm 99% sure I do.
Of course, being a British console, all our GROMS are PAL, therefore results may differ from NTSC GROMS (joke!)

-
@Willsy
Thanks my friend. Just read the TF code once, and I got most of it, apart from some [email protected], [email protected], @ and COMPILE stuff. Where would one look this up most easily ?

Good morning!
Ok, a quick explanation of the code.
I'll skip the definition of the graphics, I'm sure you understand that.
Let's look at the color data:
CREATE COLORS 2 C, 3 C, 4 C, etc....
CREATE simply creates an entry in dictionary with the name that follows CREATE. So, in the above code, a dictionary entry called COLORS is created. When we *execute* COLORS (by simply using it's name in the code) it is programmed to simply push the address of the word (the address of the 'code space') of the word. Who programs COLORS to do this? CREATE does! (You could think of CREATE as a class and COLORS as an object of type CREATE, with one single method - to push the address of its code-space).
Ok, I hope that wasn't too hard to understand. Next, we use C, ("compile a char") to 'compile' numbers (called literals) directly into memory.
So...
2 C, 3 C, 4 C, 5 C, 6 C, 8 C, 8 C,
...compiles 2 3 4 5 6 8 and 8 (as bytes) into memory. TF takes care of where they will be compiled (there is an internal pointer called HERE which always points to the *next* compilation address - C, uses HERE to get the address, and increments HERE by 1 afterwards).
So, by "compiling" those numbers *directly after* COLORS, we find that when we execute COLORS the address returned is the address of first byte of the numbers we just compiled. What we just did is *exactly* the same as this in machine code:
colors data 2,3,4,5,6,8,8
So, using simple terms, we compiled a list of bytes, and COLORS returns the address of the start of that list.
Try this in TF:
CREATE LIST 1 C, 2 C, 3 C, 4 C, 5 C, 6 C, : TEST LIST 6 0 DO DUP I + [email protected] . LOOP DROP ;
[email protected] means "fetch byte". Words in Forth have prototypes, a bit like C, but their format is different, because Forth is stack based. Forth "prototypes" are called "stack signatures". Here is the stack signature for [email protected]:
[email protected]: address -- byte
The important thing in a time signature is the -- symbol. The stuff on the left shows the stack BEFORE the word executes. The stuff on the right shows the stack AFTER the word executes. So, we can see that [email protected] expects an address on the stack, and replaces that address with the value (byte) at that address.
Here is SWAP:
SWAP: a b -- b a
So, swap takes the top two stack items, a and b and exchanges them, giving us b a.
[email protected] is the same as [email protected] - however, it reads a byte from VDP:
[email protected]: vdp_address -- byte_value
VALUEs are very much like variables:
9900 VALUE TI ok:0 TI . 9900 ok:0 50 TO TI ok:0 TI . 50 ok:0
1+ and 2+ add 1 and two to the top-of-stack:
1+: a -- a+1
2+: a -- a+2
2DUP DUPlicates the top TWO items:
2DUP: a b -- a b a b
The word 3DROP needs special explanation. 3DROP is a "compiling" word. Compiling words are quite unique to Forth, so it usually takes people a while to get their head around them.
The first thing to notice is the word IMMEDIATE after the end of the definition of 3DROP - this is very important. When 3DROP is compiled into memory, nothing very special happens. It just gets compiled like any other word. However, when 3DROP is referenced in another word, something very special happens....
Normally, when the compiler is compiling a word, it just compiles a call to each word that it finds. However, if the word referenced is marked as IMMEDIATE, rather than compiling it, the compiler instead EXECUTES the word. So, when the compiler is compiling MAIN-LOOP it sees a reference to 3DROP and instead of compiling 3DROP, it executes it. Ok, so what happens then? Well, 3DROP actually compiles some words itself into memory (pointed to by HERE). It compiles a DROP then a 2DROP. Where do these get compiled to? They get compiled into the current location in MAIN-LOOP because that was where HERE was pointing to when 3DROP executed!
So, 3DROP is a macro that compiles its payload into the "current definition".
So, MAIN-LOOP looks like this in the source code:
IF 4 OR 1 HCHAR ELSE 3DROP THEN
However, in memory, it looks like this:
IF 4 OR 1 HCHAR ELSE DROP 2DROP THEN
Hope this helps to de-mystify Forth a little bit. It really is very simple. It's like a "super machine-code" - very very simple.

-
1
-
-
Man, I wish this was around when I was writing TurboForth... This would have made life a lot easier.
Any idea of the component costs?
-
Here it is in TurboForth:
: SHAPE1 DATA 4 $C0C0 0 0 0 33 DCHAR ; SHAPE1 : SHAPE2 DATA 4 $3F3F 0 0 0 34 DCHAR ; SHAPE2 : SHAPE3 DATA 4 $FFFF 0 0 0 35 DCHAR ; SHAPE3 : SHAPE4 DATA 4 0 $C0C0 $C0C0 $C0C0 36 DCHAR ; SHAPE4 : SHAPE5 DATA 4 $C0C0 $C0C0 $C0C0 $C0C0 37 DCHAR ; SHAPE5 : SHAPE6 DATA 4 $3F3F $C0C0 $C0C0 $C0C0 38 DCHAR ; SHAPE6 : SHAPE7 DATA 4 $FFFF $C0C0 $C0C0 $C0C0 39 DCHAR ; SHAPE7 : SHAPE8 DATA 8 $0000 $0000 $0000 $3F7F $0103 $0303 $0303 $FFFF ; CREATE COLORS 2 C, 3 C, 4 C, 5 C, 6 C, 8 C, 8 C, 9 C, 10 C, 11 C, 12 C, 2 C, 14 C, 15 C, : INIT 1 GMODE 13 SCREEN 4 1 0 COLOR 7 0 DO \ define bricks and set colours from colour table... SHAPE8 I 8 * 40 + DCHAR I 5 + COLORS I CELLS + DUP [email protected] SWAP 1+ [email protected] COLOR LOOP ; 0 VALUE SEED $8379 [email protected] TO SEED : RND SEED 31421 * 6927 @ + DUP TO SEED ; : 3DROP COMPILE DROP COMPILE 2DROP ; IMMEDIATE 0 VALUE R 0 VALUE C 0 VALUE BRICK : MAIN-LOOP INIT BEGIN BEGIN RND 23 MOD TO R RND 30 MOD TO C R C GCHAR 38 < R C 1+ GCHAR 38 < AND UNTIL RND 7 MOD 8 * 40 + TO BRICK R C BRICK 1 HCHAR R C 1+ BRICK 1+ 1 HCHAR \ do shadow tests... R C 2+ 2DUP GCHAR DUP 39 < IF 4 OR 1 HCHAR ELSE 3DROP THEN R 1+ C 2DUP GCHAR DUP 39 < IF 2 OR 1 HCHAR ELSE 3DROP THEN R 1+ C 1+ 2DUP GCHAR DUP 39 < IF 3 OR 1 HCHAR ELSE 3DROP THEN R 1+ C 2+ 2DUP GCHAR DUP 39 < IF 1 OR 1 HCHAR ELSE 3DROP THEN AGAIN ; MAIN-LOOP
http://www.youtube.com/watch?v=CUP9vu0lNB0
Hope you like it.

[Edit: No CPU overdrive was used in the above videos. Just paste the code into classic99 to try it out. Enjoy]
-
1
-
-
SLA R0,8
SRA R0,8
Aww bum! Beaten to it

-
I am trying to convert a signed byte to a signed word and am running into issues. The code below is what I am using but it doesn't seem to work. Any thoughts ?
*R0 contains a signed number in the low byte
ANDI R0,>00FF mask out unneeded data
CI R0,128 is number negative ?
Jl OUT no so we are done
NEGNUM AI R0,-127 0-127 are positive 128-255 are negative
NEG R0 turn R0 into a negative word
OUT RT
Doesn't seem to ever create a negative word. If someone has a better (or working) way I am all ears....er eyes....
SLA Rx,8
SRA Rx,8

-
Installed and working nicely on my ageing XP SP3 system - no problems at all!
Now for 9938 emulation, and my life will be complete

Thanks for all you do for us TIers...

-
Ok, so, to be clear, its not a bug in classic99 per se, its an issue with the design of the original TI GPL interpreter, yes?

-
It's in Simplified 99/4 Assembly Language by Ken Culp.

-
... that the TI Assembler had a bit shift. Never read that in the ED/AS manual.
As we all know, the assembler can resolve simple arithmetic at assembly time to calculate addressed, but I didn't know it could do bit shifts.
The symbol // is used for a bit shift, and it does a right shift, shifting in zeros on the left:
MSB EQU >8000 ; switch on MSB BIT14 EQU MSB//1 ; ooh! nice! BIT13 EQU MSB//2 ; splendid!
-
Chapter 5, section 5.6, page 162 is the start of the Assembly File IO in the attached book "Simplified 99/4 Assembly Language" by Ken Kulp. This is a brilliant book.
I think you'll find it explains everything you need to know. It doesn't explain reading the disk catalog, but don't make that your first File IO project, choose something simpler to start with! Like, writing "hello mother" to a file, and then reading it back etc!
Hope you like the attached.
Mark
-
1
-
-
I'll see if I can put some sort of document together if adamantyr doesn't beat me to it. Iirc its covered quite well in one of the assembly books. I'll look it up tomorrow .

Bricks (demo)
in TI-99/4A Development
Posted
I also know nothing about GPL, but I would have thought that the GPL version would use the same number of variables as any other languages. To understand what mean, you have to stop thinking in terms of languages, and think in terms of algorithms.
Let's a take a bouncing ball that bounces off the screen edges. The minimum number of variables is 4:
Current x coordinate
Current y coordinate
x direction (1 or -1)
y direction (1 or -1)
You could *possibly* do it with 3 variables, using a screen address instead of x and y coordiantes, but that just makes screen edge detection more complex.
So, GPL, XB, Assembly: The *algorithm* still needs 4 (or 3!) variables. The *language* makes no difference. Therefore I don't really agree that GPL uses less variables for a given job/task. The number of variables is inherent in the algorithm, and once you have broken the algorithm down into its most efficient form, that is how many variables you need, in *any* languge.
I do agree that GPL is cool though! I will definatlely try it out!