Jump to content
kl99

Decoding Basic Source Code from Cartridge Binaries

Recommended Posts

Hi!

I managed to decode Personal Record Keeping to its original Basic Source Code Program. It was done using Web99. I cheated a little to find the startaddress and the endaddress of the LineTable and the startaddress and endaddress of the Basic Program Lines but it's impressive that the binary can be actually decoded. Also the line length doesn't seem to be there at the beginning of each line when compared to a standard binary for a basic program. But i simply read each line til the next 0x00. Once I get Web99 to find the 4 addresses by itsself, the tool will be able to show you the Basic Code of all Command Modules that have been programmed in Basic Language.

 

I worked with the phm3013g.bin file (unzip the .rpk or use the attached file) where I discovered some "HCHAR" in its hexcode with the right tokens infront and afterwards, so I thought, hey this has to be decodable in some way to Basic.

 

After accomplishing it I figured I made it more complicated then necessary since I worked with a GROM dump that had random data in the last 2K of each 8K GROM. Further the 8K blocks on the phm3013g.bin file have a different sort order than the PC99 dumps. I should have started with the PC99 files from the start, as they give you a much cleaner picture. :D

 

phm3013.grm = phm3013g.bin 0x6000 - 0x77ff = LineNumber Table
phm30131.grm= phm3013g.bin 0x4000 - 0x57ff = BASIC Program Lines
phm30132.grm= phm3013g.bin 0x2000 - 0x37ff = BASIC Program Lines
phm30133.grm= phm3013g.bin 0x0000 - 0x17ff = some other data, probaby the GPL subprograms that RPK provides to TI Basic.

 

It could be that it's incomplete or I got something wrong. Also interesting is the use of special chars for some variables or even Subprogram Names. I had to manually replace a "LineBreak" character as Subprogram name to fix the formatting of the Source Code. Maybe the preferred to have single line characters for variables/subprograms and to save memory and they run out of standard chars.

 

Each TI Basic program files defines the beginning of the Line Number Table in Bytes 2/3 of its binary. The End of the Table in Bytes 4/5. Both Addresses actually point you to a VDP memory. Since we are running the program from cartridge ROM, not VDP, these pointers must be different here. I still need to find those two pointers in such a Grom dump.

 

Any help would be appreciated.

 

In the end I would love to be able to visualize any Basic Source Code, a cartridge contains, and even decode the GPL to GPL Source. Would love to tweak around with Car Wars for example.

phm3013g.bin

personal_record_keeping_pc99dump.zip

personalrecordkeeping-decoded2basic.txt

Edited by kl99
  • Like 4

Share this post


Link to post
Share on other sites

The line number table end address is: 24644 or >6044

The line number table start address is: 29256 or >7248 (last byte from last entry is >724B)

The range of memory addresses that are pointed from the line number table goes from 8192 or >2000 to 24632 or >6038 (length of 3 bytes)

Also interesting and I only saw that in tweaked Basic Programs (Barry Boone loader etc) that certain line number point to the same memory address:

3220 10646 FOR ]=J TO [
3290 10646 FOR ]=J TO [
4450 10646 FOR ]=J TO [
5350 10646 FOR ]=J TO [

Share this post


Link to post
Share on other sites

would be interesting to get the Basic Program running from TI Basic with the PRK plugged in. So far no luck, it's a bit difficult because of those special chars, that's why I can't use Paste in Classic99. xdt99 also fails to create a binary out of the source again.

Share this post


Link to post
Share on other sites

The 2k garbage at the end of the GROMs? Remember real GROMS are 6K.

 

PRK consists of 4 grom chips, each 6K or >17FF Bytes. Therefore the Pc99 dump files don't contain any garbage.

The phm3013g.bin is 32K large (4 times 8K), therefore it contains garbage 4 times, from >1800 to >1FFF, from >3800 to >3FFF, from >5800 to >5FFF and from >7800 to >7FFF.

Share this post


Link to post
Share on other sites

In fact, it's not garbage (well, OK, yes, from a usage point of view), it's the second and third 2K bank ORed together. Which would mean that there is some simple, incomplete decoding inside, as I would guess:

 

- Address from 0000 - 07FF: Banks 1 and 2 deselected, bank 0 selected

- Address from 0800 - 0FFF: Bank 1 selected

- Address from 1000 - 17FF: Bank 2 selected

- Address from 1800 - 1FFF: Bank 1 and bank 2 selected

  • Like 1

Share this post


Link to post
Share on other sites

I don't mean to hijack this post... But related to this, aren't there conversion programs to convert from PC 99 format to the VT99 format GROM files? And back again? I invested in PC99 and have a lot of modules in that format, and want to covert to Classic99's format.

I couldn't get the 1 bank PRK to even work, albeit I didn't have a lot of time to play with it.

Share this post


Link to post
Share on other sites

anyone knows of other command modules that have been done with Basic?

Share this post


Link to post
Share on other sites

xdt99 also fails to create a binary out of the source again.

 

The binary subprogram names shouldn't matter, even though I've never seen this before. If you're getting

.

ValueError: chr() arg not in range(256)

.

then this is due to a token table overflow -- try

.

$ xbas99.py -c prk.bas --long

.

instead to create a binary program again. Of course, either token table address is likely to be wrong in this case.
I'm still amazed, though, that they would put BASIC programs into cartridges ...

Share this post


Link to post
Share on other sites

Here's a small program showing what CALL {Char 5}(X) does.

100 X=0
110 CALL CLEAR
120 CALL {Char 5}(X)
130 CALL KEY(0,K,S)
140 IF S<>1 THEN 130
150 X=X+1
160 IF X=4 THEN 150
170 IF X=110 THEN 190
180 GOTO 110
190 END

test.zip

Edited by moocowmoo

Share this post


Link to post
Share on other sites

See attached an basic listing without errors. I verified the length of each line now to match the beginning of the next line. So there are no unused bytes, incidcating an errorfree decoding of all the Lines: 0x2000 - 0x37ff, 0x4000 - 0x57ff, 0x6000 - 0x604f.

The program is too long to run from TI Basic. You receive MEMORY FULL.

prk.bas

  • Like 1

Share this post


Link to post
Share on other sites

from phm3013g.bin here are the pointers for all the basic subprograms defined. I guess they point to the GROM space since there is no ROM memory for that module. But I couldn't verify that.

0x0150 >74C2 SUB D [stands for DISPLAY]
0x0156 >D250 SUB A [stands for ACCEPT]
0x015C >74B4 SUB P [stands for PREP]
0x0162 >70ED SUB L [stands for LOAD]
0x0168 >70F3 SUB S [stands for SAVE]
0x016E >D4F9 SUB H [stands for HEADER]
0x0174 >D6B7 SUB G [stands for GETPUT]
0x017A >7560 SUB (char)4
0x0180 >6219 SUB (char)5
0x0186 >D75E SUB (char)6
0x018C >D794 SUB (char)7
0x0192 >7181 SUB (char)8
0x0198 >70DA SUB (char)9
0x019E >7243 SUB (char)10
0x01A4 >727B SUB (char)11
0x01AA >7105 SUB (char)12

Edited by kl99

Share this post


Link to post
Share on other sites

Several of the early cartridges were done in BASIC--I think Personal Report Generator was another one. . .as was Home Financial Decisions.

Share this post


Link to post
Share on other sites

What does CALL {5}(X) mean? When I type that in TI BASIC with plugged-in PRK I'm getting a BAD NAME. Or does {xxx} mean the ASCII character with value xxx?

  • Like 1

Share this post


Link to post
Share on other sites

What does CALL {5}(X) mean? When I type that in TI BASIC with plugged-in PRK I'm getting a BAD NAME. Or does {xxx} mean the ASCII character with value xxx?

I meant the character with value 5.

Share this post


Link to post
Share on other sites

I did a research in the Cyc. The Subprograms with a special char in the PRK/Statistics module were discovered by Jan Alexandersson from Sweden.

He did also decode the TI Basic Source code manually for them, at least parts of them. Didn't check in detail yet.

 

Will link some disks where his name popped up and it was related to PRK/Statistics.

 

Credits belong to him.

 

I am linking what I found in my Disk Collection:

PRK-STA.zip

Edited by kl99
  • Like 1

Share this post


Link to post
Share on other sites

I don't mean to hijack this post... But related to this, aren't there conversion programs to convert from PC 99 format to the VT99 format GROM files? And back again? I invested in PC99 and have a lot of modules in that format, and want to covert to Classic99's format.

I couldn't get the 1 bank PRK to even work, albeit I didn't have a lot of time to play with it.

 

(Offtopic reply -- Classic99 doesn't have a format, it just expects raw binary dumps. The PC99 ROMs are raw binary dumps with a 6 byte header. When you define the ROMs in Classic99.ini Classic99 will check for such a header and should automatically remove it if it matches the load address, you just need to manually specify the ROMs in the INI and make sure you get all of them! When it doesn't work, check the debug log and make sure Classic99 did what you expected it to do with the ROM (load address, length, etc). Alternately, if you remove those first 6 bytes and then rename the file to end with G.BIN, you can use the Cartridge->User->Open option (assuming it loads at GROM >6000)).

Share this post


Link to post
Share on other sites

I was able to find the location of the Line Number Table Pointers, it should be possible to convert your own Basic Program into a GROM cartridge.

 

Since Web99 can now decode the Basic Source Code from Binaries automatically, I was able to see the Basic Source Code for the following Cartridges Modules:

ACTVACTG

CLASDATG

CRSMANG

PAYASSTG

PHM3012G

PHM3013G

PHM3014G

SALPLANG

SCHMAILG

 

Maybe there are even more. I had to add the .bin files (unzip the rpk for that) via TI99DIR into a Disk Image to add it into the Web99 Index. Therefore I didn't add all of them.

 

There doesn't seem to apply the rule as with standard Basic Programs that the Line Number Table has to be sorted in memory.

 

Here a detailed description of what is contained in the PRK Binary.
PHM3013G.BIN
>0000 - >000F Grom Header
>0010 - >0012 ??? >60 >00 >1E (seems to be the same for all Cartridges based on Basic)
>0013 - >0014 Pointer to End of Basic Line Number Table: >C03C [subtract another >6000 for the 3 console Groms]
>0015 - >0016 Pointer to Start of Basic Line Number Table: >D24B [subtract another >6000 for the 3 console Groms]
>0017 - >0019 ??? >05 >60 >32
>001A - >002F Program Header
>0030 - >0141 PRK Program Start
>0142 - >014F no data 0x00
>0150 - >01AF List of Subprogram Link Headers
>01B0 - >17FF ??? >1650 Bytes
>0219 SUB (char)5
>10DA SUB (char)9
>10ED SUB L
>10F3 SUB S
>1105 SUB (char)12
>1181 SUB (char)8
>1243 SUB (char)10
>127B SUB (char)11
>14B4 SUB P
>14C2 SUB D
>1560 SUB (char)4
>1800 - >1FFF no data (each GROM only has 6K)
>2000 - >37EF Basic Program Statements, referenced from Line Number Table
>37F0 - >37FF no data 0x00
>3800 - >3FFF no data (each GROM only has 6K)
>4000 - >57ED Basic Program Statements, referenced from Line Number Table
>57EE - >57FF no data 0x00
>5800 - >5FFF no data (each GROM only has 6K)
>6000 - >603B ??? >3C Bytes
>603C - >724B Basic Line Number Table (4 Bytes per entry)
>724C - >724F no data 0x00
>7250 - >77F9 ??? >5AA Bytes
>7250 SUB A
>74F9 SUB H
>76B7 SUB G
>775E SUB (char)6
>7794 SUB (char)7
>77FA - >77FF no data 0x00
>7800 - >7FFF no data (each GROM only has 6K)
EOF

Edited by kl99

Share this post


Link to post
Share on other sites

I am a little surprised that, upon saving, the line number table is not first sorted; but, it is, after all, a linked list and certainly does not need to be sorted to be valid. If that is truly the case, that alone could be the reason binary files of the same program do not compare as equal.

 

...lee

Share this post


Link to post
Share on other sites

I am a little surprised that, upon saving, the line number table is not first sorted; but, it is, after all, a linked list and certainly does not need to be sorted to be valid. If that is truly the case, that alone could be the reason binary files of the same program do not compare as equal.

 

...lee

 

Well, in a standard TI Basic Program ( I consider these special as they are stored in GROM) the Line Number Table is sorted. What can be unsorted in a standard TI Basic Program is the actual Data for the statements pointed from that Line Number Table. If you screw around with the Line Number Table in VDP (make them a lower number than the line before) it leads to certains lines not being shown for LIST but still executed when RUN. We all saw such programs.

 

From the TI-99/4 Home Computer Basic Interpreter Design Specification, Personal Computer Divison, December 7 1979, Revision 1:

 

The line number entries in the Line Number Table are stored in reverse lexical order, i.e. the highest line number is located at the lowest memory address. Entries in the program text segment are being made in time-order, i.e. the last line entered is stored at the lowest memory address. Entries in the program text segment are therefore not in any logical order.

 

I wonder how the interpreter then finds the next line to execute, if the Line Number Table is not sorted like in the specs.

 

Anyway. Here are the decoded Basic Files, as Web99 is not ready to be released....

Two of 9 are incomplete because the line number tables contains at least one line number twice, and Web99 doesn't handle it for GROM based Basic files yet.

 

Have fun!

ACTVACTG.BAS

CLASDATG_Incomplete.BAS

CRSMANG.BAS

PAYASSTG.BAS

PHM3012.BAS

PHM3013.BAS

PHM3014.BAS

SALPLANG_Incomplete.BAS

SCHMAILG.BAS

  • Like 1

Share this post


Link to post
Share on other sites

Also nice for these cartridges, if you change CPU Ram >8389 from "FF" to "00" and hit an error, the running program will break and gets you to Basic.

CPU Ram >8389 is the GROM/VDP Flag and gives the interpreter the info where the Basic program is running from. It is treated by the Error Handler as well, therefore the program breaks when not being in GROM mode, which you fake by changing the Memory value directly.

I couldn't do any meaning ful afterwards but maybe others know some use for it.

 

Example:

1. start PRK in Classic99 (select 2 from Master Selection Screen)

2. on first input screen (Date questions) change the memory value with Classic99 Debugger "C8389=00"

3. now enter "13" for month and hit enter

 

The cartridge program will break with * Incorrect Statement in 44544 and you are in Basic now and can toy around.

 

Summary of topic so far:

So besides being able to analyze/visualize the Basic Source Code can we actually create a GROM cartridge running our own TI Basic Program? Since it can use Subprograms that are defined in its GROM, it could be tried to be integrated in a XB GROM cartridge. If you start the cartridge, it autostarts some XB program stored in GROM. WIth the Ubergroms we are able to actually build a custom XB cartridge.

 

Challenge to everybody:

Create a "Hello World" TI Basic program in GROM format

  • Like 3

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...