I know my project completion rate is trash, but this is something I've been extremely passionate about. I believe there has been a lie perpetuated by the calculator community, spread by my betters and those who know more about the architecture than I ever will:
C programming is not viable for the B/W calculators in any meaningful way.
There were efforts back in the day I remember, a port of SDCC, GlassOS, and KnightOS to do C programming on the B/W and color calculators. However, they seemed to have fizzled out.
I believe we have been sleeping on a toolchain, though. Z88DK is a mature toolchain with tons of target platforms, even for the Ti calculators. I use z88dk for C programming on an Intel 8080, with better binary output than even the Aztec C compiler so why not for the z80 with more instructions and registers?
If one digs around the documentation online ( which is not all put together, you have to hunt for it ), you can quite easily create 8xp and 8xk programs for the z80 calculators. You can even make them for Ion, MirageOS, and shells for the Ti 82 and 86 even.
Right now, I am working on creating a DoorsCS option for the compiler. But while I am doing this, I find that alot of the Ti includes don't really....include much of anything. They include some core ROM calls but that's it. Core functions like CSC key codes and per-pixel character drawing just don't seem to be present for the Ti platform.
I want this project to be:
1. Creating a DoorsCS build option for the Ti calculators, including the CSE
2. Documenting the #pragmas in one place because there's some crazy stuff that isn't easy to find
3. Documenting which functions EXIST and which DON'T EXIST for the SPECIFIC PLATFORM of the Ti calculator.
I'll try to post my effort updates here.
Please let me know what you think!
Okay, I have no idea why the header will not work but I tried and I looked at it in a hex viewer but still nothing.
The code compiles, but only runs by exiting out to the shell or OS.
Also, there is NO Icon. There should be the included icon in the header.
I use this compile command:
zcc +ti84p -subtype=dcs -create-app -o DCSHELLO.8xp main.c
I've copied/pasted the ti83p_crt0.asm to ti84p_crt0.asm and I've added the -subtype=dcs option, and it does do the header code. However, yeah, it doesn't run my Hello World code that runs otherwise.
CRT0 file:
https://pastebin.com/Zm3Uqz2A
8xp file:
https://drive.google.com/file/d/1SNJInMgj0fqNJxd5AR8AIbJA4wyMl5nQ/view?usp=sharing
***UPDATE***
I got a working DoorsCS header! I can now program in C for DoorsCS!
Granted, none of the DCS functions are wrapped in C yet ( I'll work on that later ), but for now, you can create a default DoorsCS program!
I need to work on changing the crt0 so you can add your own icon, description, and ALEs. I may also add entries to allow for the other kinds of DoorsCS executables.
Working CRT0 file:
https://pastebin.com/L3wN2XEW
Working example:
https://drive.google.com/file/d/1hR6ykcFy7dZPMd7Zv2fCm_eBodIs-4hn/view?usp=sharing
It looks like the last Ti calculator features were added in like 2001 for z88dk and have rotted away ever since. The crt0 files they use, use the CLASSIC way of injecting code into the binary. This won't work to add your own icons and such that aren't inlined. I need to try and make a new DoorsCS library in the NEW way z88dk does things. On to that!
Nice work, I have toyed with z88dk a few times and used it a little ages ago in the monochrome days.
Ironically do use it on the CE but in z80 mode but that's very specific way so not overly helpful.
Looking forward to your results!
I am having difficulty in figuring out the linker for z88dk
Right now, the crt0.asm files are the files that have the code that sets up the executable, as far as I can tell its the header bit and then your compiled/assembled code goes beneath it. There is a #pragma for the program's name, and I can add pragmas for icons and descriptions, however, it has to be INLINED. There cant' be pointers as far as I can tell. DoorsCS works by having a pointer to the icon, description, and ALE OR a null pointer on each in the header.
Supposedly the "new" way of linking files ( not the classic ) can allow for this but I can't get it to work.
I'll take a look at it some more but I am far more interested in which functions are actually available for the TI calculators.
Currently reading alot of the documentation. I "think" the best path forward is to try to get this to work in the Classic linker? The New one does seem to be pretty cool but I think it may be more trouble than it is worth. I'll figure that later.
I have tested the GRAPHICS.H functions for the Ti 83+. This is a collection of platform-agnostic drawing functions.
WORKING:
- PLOT/UNPLOT/XORPLOT/POINT - these manipulate/test pixels
- C_PLOT/C_UNPLOT/C_XORPLOT/C_POINT - these manipulate 4x4 blocks like PLOT, but these blocks are treated as such: pixels. Drawing at x>24 and y>16 will not show anything.
- GETMAXX/GETMAXY - returns drawable screen dimensions
- MULTIPOINT - Tests a horizontal or vertical line of pixels for block test
- DRAW/UNDRAW/XORDRAW/DRAWTO/UNDRAWTO/DRAWR- Lines functions
- DRAWB/UNDRAWB/XORBORDER - box and selection box functions
- CIRCLE/UNCIRCLE - circle functions
- CLG/CLGA/XORCLGA - screen clear/fill/subfill functions
- SPRITES - All sprite functions seem to work and you can inline asm the sprite data and access it via pointers to be super fast and basically asm!
- BKSAVE/BKRESTORE - background save/restore routines, works similarly to sprites
NOT WORKING/UNEXPECTED BEHAVIOR:
- XORDRAWTO/XORDRAWR - Not working as intended - documentation leads me to believe that all xor functions should invert the pixels, which does not seem to happen. However, the cursor does seem to travel as expected. Look closely at the pixels, perhaps some indices start at numbers they shouldn't inside these functions.
- UNDRAWR - Drawing relative to -16, -16 draws to the right and up for some reason?
- FILL - hangs execution and requires a hardware reset
- X11 - For some arcane and unholy reason, probably by a demon from the Lesser Key, X11 functionality does seem to work! No idea why you would ever try to use it on a z80 calculator XD. HOWEVER, when you compile the suggested cross-platform program, it must set your calculator's ram into a strange state because it becomes unstable and unpredictable after the fact, requiring a hardware reset. I am confident that this would require a dive into the x11 compatibility layer and changing some pointers, but that is not in the scope of this project.
UNTESTED:
- GFX_SET_FATPIX - This makes the vertical element twice as wide, apparently this is only for high-res z80 platforms.
- STENCILS - Kind of a skill issue, I'm not sure how to actually interpret the documentation correctly so I feel if I test this...garbage in, garbage out.
- VECTOR IMAGES - again, I'm not sure I understand the documentation quite well enough to test this yet. I'll get back to it!
Also, yes, the sound.h library does work! Just note that you'll have to do some extra lines of code if you wan to use the pragma "GimmieSpeed" to shift into the 15mhz operating speed or else your notes might sound 120% higher in pitch
Now I gotta try and figure out the IO functionality. To me, this is the other side of the most important aspect; drawing to the screen is awesome, but if we can't use all the tricks for input then the C toolchain by default is nigh useless. I'm also confident using z88dk's fastmem calls and such can allow for extremely powerful wrappers of the ti os functions.
Another win: -lm compilation option works as expected and provides a full math.h capability. However, the -lm option produces horrendously slow (but small) code. Experimentation on the faster floating point libraries would be warranted.
I have alot of thoughts on feedback for this project and the goal in general, but I need to get them in order first before expressing them.
In conjunction with my effort to reevaluate the toolchain/update it, I want to port a couple of my projects. I think I'll try and port my logic simulator
I am starting the porting process and I am finding alot of bit rot ( it hasn't been touched for a quarter century ), and the getk() function does seem to work and is wrapped in the correct bcall, but the return values are all out of whack for the Ti 84+. It expects ascii codes I think and not all of these codes exist on the keyboard. I must get the getk() ironed out and possibly patched for the calculators, and I suspect graylib also doesn't play 100% with whatever controller is in the current b/w calculators
I have found that the *getk()* function does NOT work as shown in the examples. Perhaps some of these examples were built with other calculators in mind and hard-coded keys are a terrible idea ( one must have define guards in the includes and such ).
Here's the reworked getk() return table:
Note that there are some duplicate keys. Some diving into the asm will be necessary to try and correct this.
Here's the errata:
- The ON key crashes the calculator into a hang when detecting via getk().
- 2nd and ALPHA do not get detected as pressed but they do offer alternate codes. However, they make the map so convoluted that its practically unusable. I have a theory that these are integer, not byte, return codes.
- DEL/LEFT - 8
- CLEAR/RIGHT - 9
- STAT/1 - 49
- MATH/2 - 50
- PRGM/COMMA - 44
- ZOOM/DECIMAL - 46
Here's the include file if you want to use it now:
https://pastebin.com/5ckmuLRQ
Note that this is the getk() codes BEFORE I edit/fix it up
***EDIT***
I think the return codes are 16 bit, not 8 bit. Does anyone have ideas on how to check this? The getk_decode.asm has the code, but Im not sure what setout is ( the return memory address? How is it read? )
Quote:
The ON key crashes the calculator into a hang when detecting via getk().
getk uses the _GetKey romcall to read keys, which never registers ON presses.
For reference, the implementation of getk:Code: getk with irrelevant-to-83+ code removed:
_getk:
call tiei
rst $28
defw getkey
call tidi
jp getk_decode
Quote:
I think the return codes are 16 bit, not 8 bit. Does anyone have ideas on how to check this? The getk_decode.asm has the code, but Im not sure what setout is ( the return memory address? How is it read? )
It's definitely a one-byte output; setout is a label within getk_decode:Code: setout:
ld l, a
ld h, 0
ret
The result is output in HL, but with the high byte always 0.
As for what they return from getk_decode, it looks to me like this is intended for treating the keypad like a traditional computer keyboard (like basically every other platform that z88dk targets). Walking through the implementation:
Code: ; - **** ALPHA KEY **** - Switch Numeric / Alphanumeric key tables -
cp TIALPHAKEY
jr nz, no2nd
ld a, (KFlag)
xor 255
ld (KFlag), a
jr z, KFReset
ld hl, TiKeyTab1
ld (KTabPointer+1), hl
jr KFSet
KFReset:
ld hl, TiKeyTab2
ld (KTabPointer+1), hl
KFSet:
xor a
jr setout
Pressing ALPHA toggles KFlag and returns 0. If the flag is set then we use TIKeyTab2 below, otherwise TiKeyTab1. So they're using ALPHA as a kind of shift-lock. Confusingly, this is achieved via self-modifying code since KTabPointer+1 is the address operand of the next instruction.
Code: no2nd:
; - **** ALPHA KEY **** - END -
KTabPointer:
ld hl, TiKeyTab1
symloop:
cp (hl)
jr z, chfound
inc hl
inc hl
push af
xor a
or (hl)
jr z, isntsym
pop af
jr symloop
chfound:
inc hl
ld a, (hl)
jr setout
isntsym:
pop af
setout:
ld l, a
ld h, 0
ret
It then iterates over two-byte entries in the key table, looking for one where the first byte is the same as the system key code that was gotten. If none is found, return the system key code unmodified. When an entry is found, return the second byte of the table entry.
The table itself basically just maps key codes to ASCII characters where there are reasonable equivalents:Code: .TiKeyTab1
defb $04 ;Down
defb 10
defb $02 ;Left
defb 8
...
defb $9A
defb 'A'
defb $9B
defb 'B'
defb $9C
defb 'C'
defb $9D
defb 'D'
Cross-referencing with ti83plus.inc, these are as I expect. The value of 4 for down is the same as kDown, and kCapA is 9A for example.
So this all makes a kind of sense, but I think the fall-through behavior of returning unmapped keycodes without any translation is pretty confusing and might make this function useless unless you specifically want alphanumeric input.
Thanks so much, Tari!
I can understand wanting to make getk completely agnostic to make the Ti keyboard similar to other machine keyboards, but this implementation makes it practically useless if you want to make a Ti calculator program.
I suppose I should roll my own ti_getk() function and use that
I found this:
https://en.wikibooks.org/wiki/TI_83_Plus_Assembly/Input and I think I can roll this into a ti_getk() which can then be macroed to ti_getchar() and a ti_getch()
If you roll your own ti_getk(), could you also add holding 2 arrow keys down as more keycodes? I think xLIB did so back in the day, for diagonal movement.
NVM, this would be doable by checking if both arrows return as held.
I'm not actually sure because "checking if both are down" isn't what you may think. As far as I know, the ti 83+ keyboard does not work like the CE keyboard, there aren't key scan groups that go into built bytes. Someone else could correct me though.
Ah, do a direct port read? Yeah, I'm sure I could do that!
But it then goes to terry davis's most important question:
*Is this too much voodoo for our purposes, for our mission statement...is this too much voodoo...this is voodoo, the question is, is this too much...this is the hardest question, right here, in programming*
I'll have to work on this at home but I'm pretty stoked, yeah.
I'll do it by a local function, then I'll look into adding it to z88dk, see if they'll let me do a pr for this.
Those ports for the keypad are the same from, iirc, the 81 all the way to the CE. So making keypad-wrapped port read functions for all TI-8X (82, 83, 83+, 85, 86) would be beneficial for z88dk.
Found the 86's ports:
https://jaymzroo.tripod.com/lessons/86ports.txt
81's:
https://www.ticalc.org/cgi-bin/zipview?text/calcinfo/ti81v18k.zip;PORTS.TXT
82:
http://karma.ticalc.org/guide/lesson16.html
And Finally, James Malcolm's guide, which is "focused on the TI86, much of this applies to any z80-based TI calculator: TI85, TI83/+, TI84/+, TI82":
https://jgmalcolm.com/z80/advanced/read
This sounds like a really cool project, and even though i dont own any of the other calculators or other brands, I am going to keep checking this out because this is intresting!