-
Content Count
1,549 -
Joined
-
Last visited
Posts posted by Airshack
-
-
No need to. We got Muliplan instead.
The 99/4 Equation Calculator menu option is evidence that this calculator company lacked vision and invited too many calculator engineers to the party.
I'd be interested to hear about the decision to remove that (along with the calculator style overlay ready keyboard) from the 99/4A.
Seems the calculator guys lost a battle but not before TI had already embarrassed themselves.
-
edited link above
-
... it has comments from the original TI programmers for the same code.
...lee
Wondering if any original TI Programmers are lurking about on AtariAge, or anywhere else?
Just finished listening to a four part interview with Chuck Peddle the inventor of the 6502 CPU and Commodore PET.
http://retrobits.libsyn.com/show-123-an-interview-with-chuck-peddle-part-i
Wondering if any of our guys are still around and talking?
-
You might have a look at this thread: The TI-99/4A Operating System. TI’s KSCAN is in the first of the 3 files in the ZIP file of the first post. It is the original TI source code as far as we can tell.
...lee
Hey Lee,
Did I get it all?
B @>0070 To GPL interpreter** GPL SCAN (Scan keyboard with return to GPL interpreter):* LI 11,>0070 Trick with return** Keybord scanning*KEYSCN MOV 11,@>83D8 Save R11 BL @PUSHGA Save GROM address to substack CLR 12 CRU 0 SBO >0015 Alpha lock MOVB @>8374,5 Keyboard mode SRL 5,8 MOV 5,6 JEQ >02EC 0 LI 0,>0FFF DEC 6 1 R0=>0FFF JEQ >02F4 LI 0,>F0FF DEC 6 2 R0=>F0FF JEQ >02F4 DEC 6 3 C 6,@>0072 JH >0382 >5? MOVB 6,@>8374 Keyboard mode 0 SWPB 6 MOVB 6,@>83C6 Keybord debounce (3=0, 4=1, 5=2) CLR 5 CLR 0 CLR 6 JMP >032E Mode 0,3,4,5 DATA >2925 LI 12,>0024 Mode 1,2 scan Joystick LDCR @>0405(5),3 CRU 06 and 07 LI 12,>0006 CLR 3 SETO 4 STCR 4,5 Fetch CRU SRL 4,9 JOC >0310 No fire key? MOVB @>02F1(5),@>83E7 Lbyte R3 SLA 4,1 AI 4,>16E0 GROM address Joystick table MOVB 4,@>0402(13) Write address MOVB @>83E9,@>0402(13) JMP >0322 MOVB *13,@>8376 Fetch values Y**~~Page 19: TI99/4A INTERN (Heiner Martin)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* MOVB *13,@>8377 and X MOV 3,3 Fire key ? JNE >03AA LI 1,>0005 Scan keys CLR 2 CLR 7 LI 12,>0024 SWPB 1 LDCR 1,3 Load CRU SWPB 1 LI 12,>0006 SETO 4 STCR 4,8 Fetch CRU INV 4 Invert bits MOV 1,1 0? JNE >0354 MOVB 4,7 ANDI 4,>0F00 SZC 0,4 JEQ >037A No key? MOV 1,1 Last loop? JNE >0360 MOV 5,5 Mode 1 or 2? JNE >037A MOV 2,2 Already a key? JNE >037A SETO 2 MOV 1,3 SLA 3,3 DEC 3 INC 3 SLA 4,1 Built key value in R3 JNC >036C MOV 1,1 JEQ >037A LI 1,>0001 Shorten loop DEC 1 JOC >0336 Smaller than 0? MOV 2,2 Key pressed? JNE >03AA CLR 6 Set pointer for no key MOVB 6,@>83C7 SETO 0 CB 0,@>83C8(5) JEQ >0394 BL @>0498 Time delay MOVB 0,@>83C8 MOVB 0,@>83C8(5) MOV 5,5 Mode 1 or 2? JNE >0478 End MOVB 0,@>83C9 MOVB 0,@>83CA JMP >0478 End**~~Page 20: TI99/4A INTERN (Heiner Martin)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* CB @>83E7,@>83C8(5) Same key as last time? JEQ >03E6 LI 6,>2000 Set GPL status BL @>0498 Time delay MOVB @>83E7,@>83C8 Set pointer (Lbyte R3) MOVB @>83E7,@>83C8(5) MOV 5,5 Mode 1 or 2 JNE >03E2 MOV 3,12 AI 12,>FFF8 JLT >03E2 LI 1,>0002 SRL 12,3 JOC >03DC DEC 1 MOVB @>83E7,@>83C8(1) MOVB 7,@>83C7 Last loop scanning on >83C7 MOVB @>83C7,7 LI 1,>17C0 GROM table mode 1 and 2 MOV 5,5 JNE >040E LI 1,>1790 GROM table CNTRL SLA 7,2 JOC >040E LI 1,>1760 GROM table FCTN SRL 7,15 JOC >040E LI 1,>1730 GROM table SHIFT DEC 7 JEQ >040E LI 1,>1700 GROM address table small letters A 3,1 +Key value MOVB 1,@>0402(13) Write address MOVB @>83E3,@>0402(13) JMP >041C MOVB *13,0 Values from GROM MOV 5,5 Mode 1 or 2? JNE >0478 MOVB @>83C6,@>83E7 Keyboard mode in R3 Lbyte BL @>04A2 Compare DATA >617A**~~Page 21: TI99/4A INTERN (Heiner Martin)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* JNE >0444 Small letter? CLR 12 MOV 3,3 Mode <4 JEQ >043E SBZ >0015 Activate ALPHA LOCK SRC 12,14 TB >0007 Scan ALPHA LOCK JEQ >0442 SB @>03B4,0 ->20 (Capital letter) SBO >0015 MOV 3,3 Mode 4 or 5 JNE >0456 BL @>04A2 Compare DATA >101F JEQ >0382 R0 between >10 and >1F CB 0,@>0587 5F? JH >0382 DEC 3 Mode 5 JNE >0478 CB 0,@>0025 0D (CR)? JEQ >0478 CB 0,@>02CA 0F? JH >046C SOCB @>0470,0 Set 1st bit JMP >0478 BL @>04A2 Compare DATA >809F JNE >0478 R0 smaller than >80 or bigger than >9F SZCB @>0470,0 Reset 1st bit MOVB 0,@>8375 ASCII value key on >8375 BL @POPGRA Restore GROM address MOVB 6,@>837C Set GPL status JEQ >0492 MOVB @>83D4,*15 Load VDP register 01 CLR @>83D6 Clear screen timeout counter MOVB @>0B61,*15 MOV @>83D8,11 Fetch return B *11** Time delay* LI 12,>04E2 Loop counter DEC 12 JNE >049C B *11** Compare RO with status EQU if R0 is in area of Hbyte and Lbyte* of the data value* MOV *11+,12 CB 0,12 JL >04B0**~~Page 22: TI99/4A INTERN (Heiner Martin)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* CB 0,@>83F9 JH >04B0 CB 0,0 B *11** CLEAR keyboard scanning(status EQU, if pressed):*CLRSCN LI 12,>0024 Load CRU keyboard select LDCR @>0012,3 >00 SRC 12,7 LI 12,>0006 STCR 12,8 Fetch CRU CZC @>0036,12 Right key? JNE >04DC LI 12,>0024 CRU 2nd key LDCR @>0074,3 >03 SRC 12,7 LI 12,>0006 STCR 12,8 Fetch CRU CZC @>0036,12 Right key B *11 Back
I'm guessing the time delay segment will raise issues with at least one member of this group? -
My .mag file? Okay, head over to the Berly thread, about page 15 or so and download the map *you* posted.
It is your map. I used Magellan to check a few things like tile pattern assignments and actual size of the map, and the data export to assembly code, but that's it. The map data is unmodified since the idea was to use Magellan generated data and load it from disk. Right?lava.zip <==== Early Beryl Magellan File
Magellan Graphics Editor Tool for TI-99/4A (runs on Windows): http://atariage.com/forums/topic/267322-programming-resources-for-ti-xb-graphicssprites/?p=3798140
Some graphics inspiration: http://bifi.msxnet.org/msxnet/konami/
Useful links while looking at the Viewport code from 2 June 2010
-
Remember, FUN1RT is just a label that we put at the last line of the function, line #1003. As written above the code would do an unconditional branch to address 0000 (and pretty much crash the computer). However, the 0000 is just a placeholder value so the code will assemble, and the value 0000 is modified when the code runs (which is what makes it "self modifying" code).
It is now clear what is meant by "a placeholder," and the self-modifying code example is understood. The key for me understanding this example was realizing the placeholder is only there to satisfy the assembler.
Coming from an interpreted BASIC paradigm, I was assuming the code "FUN1RT B @0" was always going to Branch to >0000. I forgot that this looks crash-worthy post-assembly, on a listing of the assembled code, yet it's modified at run-time to Branch to the intended return address.
Clever!
-
GameLp4D.a99 <==== Corrected GameLoop for Dummies commented code
Playing around with that viewport code of Owen's (and the Matthew Methodology version) has me really excited right now. At first I thought Owen's Viewport code represented some skipping ahead, or at very least some confusing thread creep. My expectations were for Matthew to transition towards the next logical conversation --KSCAN..
Loading and running the Viewport code has opened up some very interesting possibilities. It appears Owen is using the traditional KSCAN routine with his viewport code while Matthew is taking the "Roll Yer Own" approach.
What better way to learn than to pour through both code segments and test the differences?
InsaneMultitasker (Tim) correctly noted that there's nothing wrong with using the console routines. Here lies an opportunity to get familiar with the pre-written routines as well as some efficient custom routines. Win-Win!
-
Thanks Lee! Earlier posts here outline the problems with using BLWP: speed, scratchpad RAM overwriting, etc.
Looks to me like TI's KSCAN requires this... along with the REF... thus limitations to be avoided.
I'll investigate your link. Thanks!
-
After Matthew's GameLoop breakdown the thread seems to have moved along (page4), to Owen's viewport code (Beryl) with KSCAN used.
I'm going to download that code and try to figure everything out next.
Matthew mentioned his disappointment with TI's KSCAN code due to wasted speed via two delay loops.
This is probably a good time to look into how KSCAN works. Hopefully Owen's code will be helpful in unravelling yet another TI coding mystery.
Willsy posted (6 Jun 2010) KSCAN replacement code? Probably something I need to understand before moving on.
I'll start with p.250 of the E/A manual, 16.2.1 KSCAN.
-
Beware self-modifying code... I often do things like this versus using a stack...

SUB1 MOV R11,@SUB1RT+2 ... SUB1RT B @0Matthew - this is an awesome thread you've got running
This is giving me some great ideas for a few programs I'd have trouble writing without getting out of my dsr/utility/input-driven serial-event processing mindset 
This sparked my interest! I'm guessing here:
SUB1 MOV R11, @SUB1RT+2 * this stores the PC/return address of the calling code into a hard memory location immediately following this routine ???
<code>
SUB1RT B @0 *I don't get what the '@0' does or how it somehow gets ignored and replaced with the stored return address at SUB1RT+2 ???
-
Looking forward to playing a new TI game! Sweet!
-
Thanks for the feedback guys!
I just finished page three of this wonderfully informative 19 page thread. Again, I'm humbled by all the help I've received. Matt's approach to learning Assembly Language is something that has grabbed my attention but more importantly, it's really helping me learn while staying engaged.
The Gameloop code from page three of this thread took me a while to wrap my mind around. In the process I read multiple user's comments and did some research into the TMS9900 Guide and TI's E/A manual.
I've attached a version of Matthew's GameLoop code with "For Dummies" style comments and additional information in an attempt to encapsulate everything I have learned while pouring through the code. A beginner with some of the same questions as myself, and very few of the expert-like assumptions of a proficient Assembly programmer, may find the additional comments useful. Hopefully I'm not stepping on any toes doing so.
This week I was able to demo the BASIC gameloop v Assembly Gameloop programs to Sparkdrummer at the July VAST meeting in PHX. We had a lot of fun looking at this code and comparing its performance to BASIC.
Thanks again! - James
-
1
-
-
Recognize the controllers yet not the system?
https://www.shopgoodwill.com/viewItem.asp?ItemID=41150926
This is a Sears rebranded Atari 2800 (not 2600) with the worst joysticks ever made for any system.
http://www.jwnyc.com/games/videoarcade2.html
May be a cool pickup for Atari fans though. Guessing the REAL 2800/Sears Video Arcade II joysticks are tough to find.
-
1
-
-
I'm another TIer in Ottawa.
So far it appears Canada has the most TI people.
-
This is the best Arizona based TI newsletter out there. Thanks Ralph!
Ps - When are the guys from VAST meeting again?
-
RANDNO’s upper limit is 65535 = 2^16 - 1.
...lee
I always forget to count that damn zero.
-
Thanks For the rapid feedback Lee! I read that about the source operand having to be larger than the first word of the destination operand, for "normal division to occur." Otherwise the resulting quotient won't fit inside a 16-bit word.You may understand this perfectly well, but the above code snippet might indicate otherwise. Just to be sure, DIV does operate on a 32-bit dividend in R4—R5. The only caveat is that R4 (MSW) must be smaller than R3, the divisor. Otherwise, the overflow bit will be set and R4—R5 will be untouched. R4 is not ignored. It is the MSW of the 32-bit dividend. It so happens as you indicated, that the dividend happens to fit in the 16 bits of the LSW.
...lee
What I meant by "ignored" (R4) is this specific code does nothing with the number (integer quotient) in R4 after the DIV executes. It's only concerned with the remainder.
Seem right you? Otherwise, I will move on with the assumption that it's all understood.
The big takeaway here was learning the peculiarity of the DIV OpCode, which is only peculiar to me because there's nothing similar going on with BASIC regarding which end of the equation needs to be smaller.
-
This is the highly anticipated (well, for Owen anyway.
) game loop post!*********************************************************************** Plot a random character*PLOT* Only draw on the VSYNC C @VSYNC,@NUM01 * If VSYNC is not active, return JEQ PLOT01 B *R11PLOT01 MOV R11,*R10+ * Push return address onto the stack* Get a random screen location BL @RANDNO * Get a random number (in R5) LI R3,768 CLR R4 * Dividend will be R4,R5 DIV R3,R4 * Make a number between 0 and 767 MOV R5,R0 * Move to R0 for the VDP routine AI R0,NAMETB * Adjust to the name table base* Get a random character 40, 48, 56, 64 BL @RANDNO * Get a random number (in R5) SRL R5,14 * Make a number between 0 and 3 SLA R5,3 * Multiply by 8 (number is now 0, 8, 16, 24) A @CHR040,R5 * Add to the base character MOV R5,R1 SWPB R1 * Remember, the MSB goes to the VDP! BL @VSBW DECT R10 * Pop return address off the stack MOV *R10,R11 B *R11*// PLOT
Hey Matthew,
I was able to easily understand most of this post up to the point where your code started plotting random characters on the screen. The DIV OpCode is where I started to stumble as I've never really used it before. I went to p.88 of the E/A manual as a reference.
To help in my understanding of the logic I added comments as notes. A way to further clarify what exactly is going on between registers during the Divide, etc.
Here's what I came up with in order for it all to be clear in my mind:
*********************************************************************** Plot a random character*PLOT* Only draw on the VSYNC C @VSYNC,@NUM01 * If VSYNC is not active, return JEQ PLOT01 B *R11PLOT01 MOV R11,*R10+ * Push return address onto the stack* Get a random screen location BL @RANDNO * Get a random number (in R5)... between 0 and 65,535 (2^16 -1) LI R3,768 * by cleverly using 768 as a divisor we assure any DIV remainder is ALWAYS 0-767 CLR R4 * Dividend will be 32-bit R4&R5 (two words used by DIV) which is really just* a 16-bit dividend (R5) with leading zeros in R4 to satisfy the TI DIV OpCode DIV R3,R4 * divides destination operand (a consecutive 2-word workspace, R4&R5) by 768* Makes a number between 0 and 767 (see E/A manual p.88) in R5* - the resulting integer quotient (R4) is ignored here, does not matter* - the resulting integer remainder (R5) is ALWAYS between 0 and 767* MOV R5,R0 * Move to R0 for the VDP routine AI R0,NAMETB * Adjust to the name table base* Get a random character 40, 48, 56, 64 BL @RANDNO * Get a random number (in R5), again 0-65,535 SRL R5,14 * Make a number between 0 and 3 using Shift Right Logical* Shifts bits in R5 right 14 times and fills left with zeros, leaving 2 LS-bits SLA R5,3 * Multiply by 8 (number is now 0, 8, 16, 24) using Shift Left Arithmetic* Shifts bits 1&0 left to positions 4&3, and fills in the right bits (2,1,0) with zeros A @CHR040,R5 * Add to the base character MOV R5,R1 SWPB R1 * Remember, the MSB goes to the VDP! BL @VSBW DECT R10 * Pop return address off the stack MOV *R10,R11 B *R11*// PLOT
Does this all seem correct to you? I want to make sure my understanding of the situation is correct.I'm finding this thread incredibly helpful. Forgive my snails pace as I pick my way through the lessons. To me it seems to be moving along quite well yet based on the dates of your original posts I'm moving along a bit slower than Owen and the guys from 2010. Thanks again!
-James
-
Where may one find Panzer Strike?
-
While certain specialized applications like interfacing require coding on real hardware, everything else is so much easier and faster when done in emulation first.
I absolutely get the special nostalgic feeling of coding on real hardware, and some of us create amazing stuff doing just that like Marc Hull for example, but there comes a point where the aggravation of aging and flaky hardware is counterproductive in my view...
Have you tried Tidbit? Allows programming BASIC with labels in place of line numbers which really improves the BASIC experience.
Editing on a modern PC + Tidbit = a delight!
-
2
-
-
Would there be any interest in a series of "how-to" videos showing how to do various things in TurboForth?
Yes! I'd like to see some sort of TI version of this:
"If so please say so here and give an idea of the topics you'd like to see covered and I'll see what I can do."
An introduction to include workflow and supporting software: editor, emulator, etc. it doesn't have to be ultra professional, just informative. The following example was made with an iPhone in just 30 minutes and one take:
Example: https://youtu.be/YwQL1-CZGO8
^^^Includes the all-important "how-to" on getting code written and imported into the emulator, and then exported to the TI itself. Ideal for beginners new to the TI Cult.
"If anyone else wants to make some videos, of TurboForth, fbForth, or Camel 99 Forth please go right ahead. I'd love to get more TIers at least having a dabble with Forth!"
It'd be nice to have a pinned thread to go to or an agreed upon YouTube central channel.
-
1
-
-
This was posted on Facebook:
Bit of a hatchet job if you ask me. It also contains a number of facial errors.
Thanks to Stefan Holtgen for posting it.
I wasn't aware of the video game console part of the story. Wondering if any details exist?
-
RoLB and ROLB are the same, but R0LB is not. It should be R0LB in this case.
And yes, END marks the physical end of what should be assembled, not the logical end of the main program.
Yep! I must have had R<zero>LB in there. Good to know RoLB = ROLB so no case sensitivity. I was using the "END" as I had with BASIC I suppose. So it's an Assembler Directive, not an OpCode.
You can make code absolute or relocatable. When it's absolute, it's always possible to fully resolve all addresses during assembly. You know for example that the code should load at >A000, so you know that an address, like KALLE, that's >10 bytes down the code must be >A010. The CPU can only execute absolute code.
Is it safe to assume I'll be writing strictly relocatable code vs absolute code?
Thus the assembler will resolve the address relative the code segment start, and then the loader will finally resolve the address by adding the code segment loading address. When that's completed, the code in memory is now absolute and can be executed.
The way you phrased this makes it easy for me to understand. I didn't get that earlier in my reading.
But the loader supplied with the TI 99/4A is more clever than that. It's not only a loader capable of loading relocatable code, but it's a linking loader. That implies that you can load code that contains addresses that are completely unknown at assembly time.
Same comment as above.
That piece of code also contains the directive DEF KALLE, to indicate that the definition of KALLE is external, and thus made available to other programs.
I didn't realize this was happening with DEF making it external/global. This is quite powerful and a big potential time saver.
Wondering if this how SPECTRA by Retroclouds works? A collection of arcade game enabling routines imported by REF's at the beginning of my code?
- You have loaded this code, with DEF KALLE inside, before you load the code that contains REF KALLE.
My Assembler workflow includes using Classic99 with the E/A Cart, Option 3 Load and Run.
With multiple source code files I'd have to load.... say... the VDP Routine file before the Main Program file. I'd need DEFs in the VDP Routine file and associated REFs in the Main Program file. I'd have to remember to load the VDP Routine file first.
How do most people automate this?
I anticipate issues with several or more support (DEF) packages.
In the example above, you got away with REF VSMW at assembly time, because it simply tells the assembler that it's up to the loader to fix the VSMW reference. But at load time, it would have exploded, since the label VSMW wasn't actually externally DEFined by any other program.
This really clears up a lot regarding REF v DEF.
This whole concept is a powerful one, since it allows you to build libraries of frequently used functions, and include external definitions in these libraries. They may then be externally referenced from other programs, so that you can load the same library as one code file, and use it from different other code files. This is exactly what the E/A system provides for you.
Also seems it'd become tedious if you had more than a few libraries to load.
Since the tagged object code loader can load relocatable code at any address it finds convenient, it doesn't matter how big the library is. Your program will always load after it, regardless of where that's in memory. This was a capability inherited from the system used in the TI 990 minicomputers, and was more powerful than what was available in several contemporary home computers.
Always appreciate a little History with my daily computer lessons! THANK YOU! Great reply!
-
Just got it running! A couple of typos is all: ROLB in place or RoLB and had my END before the subroutines.
Pound sign screen happily flashing away now. Subroutine call working! Time for bed. -j
-
1
-

ti-99/4 (not A) equation calculator
in TI-99/4A Computers
Posted · Edited by Airshack