I've been playing around with SDCC to see if I could get C code to compile and run on the calc, and since I managed to figure it out, I decided to post it here. There is an old thread that did something similar, but there was a mistake in it and is strangely specific to the TI-84+CSE. I decided instead of bumping something like a year old up, to just make a fresh post on how I figured out how to do it.
This tutorial will be under a Linux environment. If you are using Windows, you will probably need to install Cygwin.
1. Install SDCC. This is how we will compile our code.
2. Download binpac8x and extract "binpac8x.py". After we compile our code, we use this to turn it into a TI-83+/TI-84+ program.
3. Make a new file called "hello.c".
4. Copy and paste in this code[1]:
Code:
5. Compile the C code using SDCC[2].
Code:
6. This will give us a hex file that is formatted in a strange way. So what I do is "deformat" the hex file by getting rid of all the extra information attached to it to essentially just give us a raw hex string[3].
Code:
7. Now since we have a raw hex string, we can convert this directly to a binary file.
Code:
8. Our code is compiled, but the calc will have no clue what to do with it until the package it up as a TI-83+ program file. Let's go ahead and package this program up with the name "HELLO".
Code:
9. We get "~tmp.8xp" as an output, let's rename that to "hello.8xp" so it doesn't get deleted in the next step.
Code:
10. And we're done! But if you type "ls", you will see, we've made a mess! Luckily, we can clean it all up with a single command:
Code:
And that is it! You can transfer "hello.8xp" to your calculator and see that the program does, indeed, work. You can also take all of these steps and throw them into a single "build.sh" file.
Code:
If you name this "build.sh", then you can build your entire program by simply typing "bash build.sh hello". It will compile "hello.c" into "hello.8xp".
Hope this is helpful!
Notes:
[1] It's important that "main" is at the top of your code. When it compiles, the first function will be what it executes first, so main must be at the top. Also note that "_PutC" uses ".dw 0x4504" and "_NewLine" uses ".dw 0x452E". These addresses are specific to the monochrome calculators. On the TI-84+CSE, they would be "0x44FB" and 0x4525" respectively.
[2] "-mz80" says "compile this to Z80 assembly". "--no-std-crt0" says "don't do a bunch of linking stuff we don't need". "--reserve-regs-iy" says "don't mess with the iy register, because everything will explode if we do". "--data-loc" is where in RAM it will store our variables. I chose appBackupScreen (DON'T set it to 0 or it will crash the calculator!). If you are using a TI-84+CSE, you will need to change this value to something else. "--code-loc" is where our code starts in RAM. I chose "usermem" since, well, that's where it starts. On the TI-84+CSE, usermem is "0xA60B".
[3] If you notice, we have "BB6D" as a header here. This has to be changed to "EF69" if you are using a TI-84+CSE.
This tutorial will be under a Linux environment. If you are using Windows, you will probably need to install Cygwin.
1. Install SDCC. This is how we will compile our code.
2. Download binpac8x and extract "binpac8x.py". After we compile our code, we use this to turn it into a TI-83+/TI-84+ program.
3. Make a new file called "hello.c".
4. Copy and paste in this code[1]:
Code:
void _PutC(char c);
void _NewLine();
void print(char* str);
int main() {
print("Hello, World!\n");
return 0;
}
void print(char* str) {
int i;
for (i = 0; str[i] != 0; i++) {
if (str[i] != '\n')
_PutC(str[i]);
else
_NewLine();
}
}
void _PutC(char c) {
__asm
pop bc
pop de
pop hl
ld a, l
push hl
push de
push bc
rst 0x28
.dw 0x4504
__endasm;
(void)c;
}
void _NewLine() {
__asm
rst 0x28
.dw 0x452E
__endasm;
}
5. Compile the C code using SDCC[2].
Code:
sdcc -mz80 --no-std-crt0 --reserve-regs-iy --data-loc 0x9872 --code-loc 0x9D95 hello.c -o ~tmp.hex
6. This will give us a hex file that is formatted in a strange way. So what I do is "deformat" the hex file by getting rid of all the extra information attached to it to essentially just give us a raw hex string[3].
Code:
echo BB6D$(cut -c 10- < ~tmp.hex | sed 's/..$//' | tr -d '\n') > ~tmp.hxs
7. Now since we have a raw hex string, we can convert this directly to a binary file.
Code:
xxd -r -p < ~tmp.hxs > ~tmp.z80
8. Our code is compiled, but the calc will have no clue what to do with it until the package it up as a TI-83+ program file. Let's go ahead and package this program up with the name "HELLO".
Code:
python binpac8x.py ~tmp.z80 -O "HELLO"
9. We get "~tmp.8xp" as an output, let's rename that to "hello.8xp" so it doesn't get deleted in the next step.
Code:
mv ~tmp.8xp hello.8xp
10. And we're done! But if you type "ls", you will see, we've made a mess! Luckily, we can clean it all up with a single command:
Code:
rm ~tmp*
And that is it! You can transfer "hello.8xp" to your calculator and see that the program does, indeed, work. You can also take all of these steps and throw them into a single "build.sh" file.
Code:
#Compile our code
sdcc -mz80 --no-std-crt0 --reserve-regs-iy --data-loc 0x9872 --code-loc 0x9D95 $1.c -o ~tmp.hex
#Deformat our hex file into a raw hex string
echo BB6D$(cut -c 10- < ~tmp.hex | sed 's/..$//' | tr -d '\n') > ~tmp.hxs
#Convert our hex string into a binary file
xxd -r -p < ~tmp.hxs > ~tmp.z80
#Package the binary file as a TI-83+/TI-84+ program
python binpac8x.py ~tmp.z80 -O $1
#Fix the program's name so it doesn't get deleted
mv ~tmp.8xp $1.8xp
#Clean up
rm -f ~tmp*
If you name this "build.sh", then you can build your entire program by simply typing "bash build.sh hello". It will compile "hello.c" into "hello.8xp".
Hope this is helpful!
Notes:
[1] It's important that "main" is at the top of your code. When it compiles, the first function will be what it executes first, so main must be at the top. Also note that "_PutC" uses ".dw 0x4504" and "_NewLine" uses ".dw 0x452E". These addresses are specific to the monochrome calculators. On the TI-84+CSE, they would be "0x44FB" and 0x4525" respectively.
[2] "-mz80" says "compile this to Z80 assembly". "--no-std-crt0" says "don't do a bunch of linking stuff we don't need". "--reserve-regs-iy" says "don't mess with the iy register, because everything will explode if we do". "--data-loc" is where in RAM it will store our variables. I chose appBackupScreen (DON'T set it to 0 or it will crash the calculator!). If you are using a TI-84+CSE, you will need to change this value to something else. "--code-loc" is where our code starts in RAM. I chose "usermem" since, well, that's where it starts. On the TI-84+CSE, usermem is "0xA60B".
[3] If you notice, we have "BB6D" as a header here. This has to be changed to "EF69" if you are using a TI-84+CSE.