Jump to content
IGNORED

xdt99: New TI 99 cross-development tools available


ralphb

Recommended Posts

How do you specify the start address of an E/A#5 images when assembling using the -i option? I'm trying to assemble Flying Shark, but it insists on starting in >2000 instead of >A000. The documentation mentions it respects SFIRST, SLAST, SLOAD, but how does that work if you have code in both upper and lower memory?

  • Like 1
Link to comment
Share on other sites

I'm getting this error trying to build Bouncy's Obstacle Course (https://github.com/Rasmus-M/obstacle) using the latest xdt99.

C:\Users\Rasmus\Google Drive\Obstacle course>xas99.py -R -S -L obstacle-course.lst -b src/obstacle-course.a99
Traceback (most recent call last):
  File "C:\Users\Rasmus\TI-99-4A\xdt99\xas99.py", line 3481, in <module>
    status = main()
  File "C:\Users\Rasmus\TI-99-4A\xdt99\xas99.py", line 3378, in main
    asm.assemble(dirname, basename)
  File "C:\Users\Rasmus\TI-99-4A\xdt99\xas99.py", line 2310, in assemble
    self.assemble_pass_2()
  File "C:\Users\Rasmus\TI-99-4A\xdt99\xas99.py", line 2330, in assemble_pass_2
    self.pragmas.process(self, pragmas)
  File "C:\Users\Rasmus\TI-99-4A\xdt99\xas99.py", line 2013, in process
    name, value = pragma.split('=')
ValueError: not enough values to unpack (expected 2, got 1)

I'm not using any pragmas, so I don't know what to look for.

Link to comment
Share on other sites

  • 3 weeks later...

Thanks for your reports, Rasmus!

 

I've released a new version of xas99 that will fix the pragma parsing in your second example.

 

For the first example, using SFIRST etc. won't work with non-contiguous addresses.  But take for example this program:

 aorg >2000
 data 1,1,1,1

 aorg >a000
 data 2,2,2,2

 aorg >c000
 data 3,3,3,3

If you just assemble with -i and nothing else, you'll get those files:

cassiopeia ~/ti99/xdt99/test > xas -i splimg.asm 
cassiopeia ~/ti99/xdt99/test > ll *.img
-rw-rw---- 1 ralph ralph 14 Jun 22 20:28 splimg.img
-rw-rw---- 1 ralph ralph 14 Jun 22 20:28 splimh.img
-rw-rw---- 1 ralph ralph 14 Jun 22 20:28 splimi.img
cassiopeia ~/ti99/xdt99/test > hd splimg.img
00000000  ff ff 00 0e 20 00 00 01  00 01 00 01 00 01        |.... .........|
0000000e
cassiopeia ~/ti99/xdt99/test > hd splimh.img
00000000  ff ff 00 0e a0 00 00 02  00 02 00 02 00 02        |..............|
0000000e
cassiopeia ~/ti99/xdt99/test > hd splimi.img
00000000  00 00 00 0e c0 00 00 03  00 03 00 03 00 03        |..............|
0000000e

You could also add some SAVE directives

 save >2000,>4000
 save >a000,>e000

but that would only join the 2nd and 3rd chunk:

-rw-rw---- 1 ralph ralph   14 Jun 22 20:31 splimg.img
-rw-rw---- 1 ralph ralph 8192 Jun 22 20:31 splimh.img
-rw-rw---- 1 ralph ralph   20 Jun 22 20:31 splimi.img

(You're still seeing three files, as the second SAVE results in binary of 8192 + 6 bytes, which doesn't fit into one chunk.)

 

Would that work for you, or are you looking for something else?

 

EDIT: Oh, and I also removed # from the list of invalid chars in labels, since you seem to be using those.  I think there is no danger of interpreting those #s in labels are w#/b#/s#/x#.

Edited by ralphb
Link to comment
Share on other sites

9 hours ago, ralphb said:

Would that work for you, or are you looking for something else?

Thanks for the fixes. Regarding support for # in labels, that's great, but does it also work for the IDEA plugin? Regarding the -i option, I still don't understand how you control which area is saved first and therefore controls the start execution address? Like in your first example if you want execution to start at >a000. 

Link to comment
Share on other sites

12 hours ago, Asmusr said:

Thanks for the fixes. Regarding support for # in labels, that's great, but does it also work for the IDEA plugin?

Not yet.  Could you please test it first for a while?  I want to make sure that it doesn't interfere with modifiers, even though values (your a#1) and addresses (w#1) occupy different domains.  Meaning that both @w#1 and DATA w#1 are illegal expressions.  EDIT: But it's still possible that the parser will confuse the two.

 

12 hours ago, Asmusr said:

Regarding the -i option, I still don't understand how you control which area is saved first and therefore controls the start execution address? Like in your first example if you want execution to start at >a000. 

Oh, my bad, I didn't read your question properly.  The only solution right now is to reorder the SAVE directives, as the first SAVE range will become the first file.  I admit that I had to test that myself to see if it works.

 

Would that work for you, or do you prefer a command line option?  Using SAVEs has the advantage that it's a property of the program, so this information won't get lost.  Of course, I could also add a new directive like ENTR, but that would only make sense for images and maybe object code (as alternative for END symbol).

Edited by ralphb
Link to comment
Share on other sites

Sorry, I don't know what I was testing yesterday, but there IS a problem, not just with the parser, but also ambiguous statements:

; modifiers vs labels

a#1  data 1
b#2  data 2
x#3  data 3

     clr  @a#1
     movb b#9, @b#2
     jmp  x#3
     data a#1, b#2 - 2, x#3 - 4
     
     end

The last 3 statements have a syntax error.  Also note that the jmp statement is ambiguous: jump to label "3", or "x#3"?

 

I'd rather not change the modifier char # now, since that might break quite a few programs (including mine).  Could you think of a different way to express those labels?  Unicode ❤️ is possible!  ? 

Edited by ralphb
Link to comment
Share on other sites

45 minutes ago, ralphb said:

Oh, my bad, I didn't read your question properly.  The only solution right now is to reorder the SAVE directives, as the first SAVE range will become the first file.  I admit that I had to test that myself to see if it works.

 

Would that work for you, or do you prefer a command line option?  Using SAVEs has the advantage that it's a property of the program, so this information won't get lost.  Of course, I could also add a new directive like ENTR, but that would only make sense for images and maybe object code (as alternative for END symbol).

Using save if fine. However, I tried to add this to Knight Lore (https://github.com/Rasmus-M/Knight-lore):

save >a000,
save >2000,

and got this error:

Traceback (most recent call last):
  File "C:\Users\Rasmus\TI-99-4A\xdt99\xas99.py", line 3484, in main
    Util.writedata(os.path.join(path, name), data, mode)
  File "C:\Users\Rasmus\TI-99-4A\xdt99\xas99.py", line 83, in writedata
    with open(filename, mode) as f:
OSError: [Errno 22] Invalid argument: 'kl:'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Rasmus\TI-99-4A\xdt99\xas99.py", line 3500, in <module>
    status = main()
  File "C:\Users\Rasmus\TI-99-4A\xdt99\xas99.py", line 3493, in main
    sys.exit('File error: {:s}: {:s}.'.format(e.get_filename, e.strerror))
AttributeError: 'OSError' object has no attribute 'get_filename'

If I add an end address to the save directives it works fine.

  • Sad 1
Link to comment
Share on other sites

Hmm, I cannot reproduce this right now.  Where file did you put the SAVEs in (Source/knightlore.a99?) and how do you assemble the file (-R -i -q -L x)?

 

But it also occurred to me that I should make paths separator-agnostic (/ vs \).  Another thing was that I had to change the capitalization of one path, but the effort to make Linux open files with case-insensitive paths would be quite high.

 

Link to comment
Share on other sites

Just going to throw something out there in case it might be something useful.  For the Geneve, with the GenLINK program, there are various options for saving a block of memory using the PSAVE command.  Not sure if you may be able to use something along the lines of these "types" to reflect command line switches for your linking process.

 

PSAVE

syntax: PSAVE image_filename,[type],[start],[stop]

PSAVE is a variation of the SAVEALL command which only saves one program segment at a time.  You, as a programmer, are in control of how large each segment is and in what order they are to be loaded from disk.  PSAVE also allows you to save SYSTEM/SYS style program images.

Each of the three optional parameters is a 32-bit linker expression.  The length of an image saved with the PSAVE command, Stop minus Start, can not exceed the maximum length allowed for the Type specified.

 

The "types" recognized by PSAVE are:

 

0            MDOS fast-ram image, not last in chain of images.

               max length = >3DFA, flag byte = 'F'

 

1            MDOS fast-ram image, last in chain of images.

               max length = >3DFA, flag byte = 'F'

 

2            MDOS slow-ram image, not last in chain of images.

               max length = >3DFA, flag byte = 'G'

 

3            MDOS slow-ram image, last in chain of images.

               max length = >3DFA, flag byte = 'G'

 

4            TI-99/4A program image, not last in chain of images.

               max length = >1FFA, flag byte = >FF

 

5            TI-99/4A program image, last in chain of images.

               max length = >1FFA, flag byte = >00

 

6            GRAM program image, not last in chain of images.

               max length = >2000, flag byte = >01..>08

 

7            GRAM program image, last in chain of images.

               max length = >2000, flag byte = >01..>08

 

8            TI-99/4A rom bank 0 at >6000, not last in chain of images.

               max length = >2000, flag byte = >09

 

9            TI-99/4A rom bank 0 at >6000, last in chain of images.

               max length = >2000, flag byte = >09

 

10          TI-99/4A rom bank 1 at >6000, not last in chain of images.

               max length = >2000, flag byte = >0A

 

11          TI-99/4A rom bank 1 at >6000, last in chain of images.

               max length = >2000, flag byte = >0A

 

12          TI-99/4A 4k rom bank at >6000 (like Mini-Memory cart),

               not last in chain of images.

               max length = >1000, flag byte = >0B

 

13          TI-99/4A 4k rom bank at >6000 (like Mini-Memory cart),

               last in chain of images.

               max length = >1000, flag byte = >0B

 

14          Program image of any length, no header added to data,

               like SYSTEM/SYS, but there are certainly other uses.

               A 90k byte SYSTEM/SYS is saved with a command like:

 

               PSAVE "SYSTEM/SYS",14,>00000,>16500

Link to comment
Share on other sites

3 hours ago, ralphb said:

Hmm, I cannot reproduce this right now.  Where file did you put the SAVEs in (Source/knightlore.a99?) and how do you assemble the file (-R -i -q -L x)?

I put it in knightlore.a99 right after "def  start", and then ran makecart.bat, which is doing:

xas99.py -R -i -q -L knightlore.lst Source/knightlore.a99 -o kl1

It results in kl1 to kl9 being created and the mentioned error.

 

 

Link to comment
Share on other sites

20 hours ago, Asmusr said:

I put it in knightlore.a99 right after "def  start", and then ran makecart.bat, which is doing:


xas99.py -R -i -q -L knightlore.lst Source/knightlore.a99 -o kl1

It results in kl1 to kl9 being created and the mentioned error.

Oh, now I see it -- it's kind of  a Windows problem ... ?  In addition to kl1 ... kl9, xas99 also creates an another file kl: (ASCII '9' + 1), which is invalid on Windows filesystems (macOS as well?).

 

The reason for that many files is that the SAVEs

 SAVE >2000,
 SAVE >A000,

are redundant, or rather duplicative.  The first SAVE will include the entire range >2000->FFFF, and the second one >A000->FFFF again.  For the first SAVE, you'll want to put an upper bound, e.g., >4000, and then the second one is OK, resulting in 4-5 files (because of the headers).

  • Like 2
Link to comment
Share on other sites

Beery, I must admin that I still haven't got around to play with my Geneve, so I need some time to understand your proposal.

 

In the context of xas99, I assume you'd like that xas99 provides assembled binaries as one of those types if a new profile parameter, say -P, is given?  But what is the file format for the PSAVE'ed files?  Is there more to it that just the loading address (I would assume so)?

Link to comment
Share on other sites

On 6/25/2022 at 8:30 AM, ralphb said:

Beery, I must admin that I still haven't got around to play with my Geneve, so I need some time to understand your proposal.

 

In the context of xas99, I assume you'd like that xas99 provides assembled binaries as one of those types if a new profile parameter, say -P, is given?  But what is the file format for the PSAVE'ed files?  Is there more to it that just the loading address (I would assume so)?

 

PSAVE places the 6 byte header for each file at the front of the file (type, length, load address) and then the [Start],[Stop] is the range for the filetype for the remainder of the file as specified by the "type" code used .  In this way, at least for the TI-99/A, you can have UTIL1, UTIL2, UTIL3, UTIL4, and even UTIL5 as all 8K files (or shorter file lengths) that can get saved to >A000->BFFF,>C000->DFFF,>E000,>FFFF, >6000->7FFF, AND >2000->3FFFF.  In reality, I guess one could mix the order up during the load process.

 

PSAVE UTIL1,4,>A000,>AFFF (not last chain in file, 4K length)

PSAVE UTIL2,4,>B000,>BFFF (not last chain in file, 4K length)

PSAVE UTIL3,4,>C000,>CFFF (not last chain in file, 4K length)

PSAVE UTIL4,4,>D000,>DFFF (not last chain in file, 4K length)

PSAVE UTIL5,4,>E000,>EFFF (not last chain in file, 4K length)

PSAVE UTIL6,4,>6000,>6FFF (not last chain in file, 4K length, if using an 8K supercart)

PSAVE UTIL7,4,>7000,>7FFF (not last chain in file, 4K length, if using an 8K supercart

PSAVE UTIL8,5,>2000,>2FFF (last chain in file, 4K)

 

The above is an example of how it can be used for saving files for the TI-99/4A.

 

At least with the Geneve's LINK program, you can specify using the BLOCK command, where individual blocks of object files get loaded into a memory space, and then the PSAVE command can save the resultant program image file out to the individual's need.

 

The PSAVE type "14" is a special type which has no header, and is a straight memory save of a Program image file out to whatever length is necessary that a loader can handle.  For the Geneve, the MDOS operating system is saved as a file with no header.  It is also possible to save a memory range for special needs in a headerless file either with LINK or with the Geneve operating system.  

 

 

 

 

  • Like 1
Link to comment
Share on other sites

On 3/30/2022 at 9:56 PM, Asmusr said:

[after typing "r0 <enter>", plugin inserts variable "r_blablabla_0"]

Rasmus, I've reviewed your post, and I've come up with three possible improvements:

  • If I added registers to the list of suggestions (somewhat like you did), you'd always have 16 additional entries that you'd never select, but which are there to prevent a match with a variable entry.  I find that ugly.
  • Another improvement would be to match only prefixes, so if you type "r0", the entry "random_entry_0" would not be matched (but "r0_initial_value" would).  I'm not sure if this is possible, but I'll ask.
  • Another option I see is to introduce a new directive REQU that is only used for register aliases.  As a consequence, random variables will no longer be offered.

I currently prefer option 3, but what do others think?  Any other suggestion?

 

EDIT: Option 4: Just type 'r0 <space><enter>", but again this is just a hack.

Edited by ralphb
Link to comment
Share on other sites

On 7/1/2022 at 10:41 AM, ralphb said:

Rasmus, I've reviewed your post, and I've come up with three possible improvements:

  • If I added registers to the list of suggestions (somewhat like you did), you'd always have 16 additional entries that you'd never select, but which are there to prevent a match with a variable entry.  I find that ugly.
  • Another improvement would be to match only prefixes, so if you type "r0", the entry "random_entry_0" would not be matched (but "r0_initial_value" would).  I'm not sure if this is possible, but I'll ask.
  • Another option I see is to introduce a new directive REQU that is only used for register aliases.  As a consequence, random variables will no longer be offered.

I currently prefer option 3, but what do others think?  Any other suggestion?

I prefer r0 thru r15 to firstly be the plain register reference.
 

Edited by sometimes99er
  • Thanks 1
Link to comment
Share on other sites

7 hours ago, ralphb said:

I currently prefer option 3, but what do others think?  Any other suggestion?

Option 3 sounds good, and I guess it could also improve performance? Option 2 would also work since it's very unlikely I would have other labels starting with r0-r9.

  • Thanks 1
Link to comment
Share on other sites

  • 1 month later...

I've pushed the newest version of all tools to GitHub.  Please note that I pulled out common functions into xcommon.py, so if you download just a single tool file, you will also need xcommon.

 

For a description of changes, please refer to MANUAL.diff.  Hopefully it is clear from context to which tools each change applies.  The new IDEA plugin with register alias support is here.  It wasn't that easy to implement, and I hope performance didn't suffer.

 

I'll make a new release some time later if there are no errors.

  • Like 6
Link to comment
Share on other sites

  • 3 weeks later...

I have been using the new version for a couple of weeks without any issues. I updated my Knightlore project to use the requ directive, and it seems to work fine. I don't remember if this is a new issue, but IntelliJ marks save >a000, as an error because there's nothing after the comma.

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

I've pushed version 3.5.2 to GitHub.  The new plugin can be found here.

 

I've also fixed some bugs in xga99.  The most embarrassing one was sign error when multiplying or dividing in an expression.  Related, using negative values now yields the correct number of bits depending on whether the value occurs in a byte or word context.  Finally, I may have corrected a possible label mishandling, but I'm no longer sure.  I've also harmonized error reporting, so please watch for any unwanted changes.

 

Again. I'll make a new release some time later if there are no errors.

  • Like 3
  • Thanks 1
Link to comment
Share on other sites

  • 1 month later...

Perhaps an unusual circumstance, but when xas99 produces more than 10 banked binaries, the individual binaries are out of sorting order for the complete set of files. This presents a problem when trying to concatenate (in order) all of the files into a single file via the Windows command-line COPY command because there is no combination of wildcards to force the correct order. Might one of the following be a future option for xas99?

  1. Serialize the filenames with fixed-width file numbers, e.g., _b01.bin, _b02.bin, ..., _b10.bin, ...; or _b001.bin, _b002.bin, ..., _b010.bin, ...; etc.; and/or
  2. Concatenate the binaries into a single, ordered, binary file.

...lee

  • Like 1
Link to comment
Share on other sites

On 11/17/2022 at 12:55 PM, Lee Stewart said:

Perhaps an unusual circumstance, but when xas99 produces more than 10 banked binaries, the individual binaries are out of sorting order for the complete set of files. This presents a problem when trying to concatenate (in order) all of the files into a single file via the Windows command-line COPY command because there is no combination of wildcards to force the correct order. Might one of the following be a future option for xas99?

  1. Serialize the filenames with fixed-width file numbers, e.g., _b01.bin, _b02.bin, ..., _b10.bin, ...; or _b001.bin, _b002.bin, ..., _b010.bin, ...; etc.; and/or
  2. Concatenate the binaries into a single, ordered, binary file.

...lee

Hi Lee, you might be interested in my github fork of xas99.py, where I added a -B option to automatically concatenate the banks into a single file.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

On 11/17/2022 at 9:55 PM, Lee Stewart said:
  1. Serialize the filenames with fixed-width file numbers, e.g., _b01.bin, _b02.bin, ..., _b10.bin, ...; or _b001.bin, _b002.bin, ..., _b010.bin, ...; etc.; and/or

I pushed a change where I pad all bank suffixes with 0 to the same length.  Please get files xas99.py and xcommon.py to update (or PeteE's version).

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

  • 1 month later...

Just wanted to say that XBAS99.py is making my life a whole lot easier, in my work on Hell's Heart (my next big TI BASIC project), right now.  The tool is much appreciated, for its allowing me to get from plaintext source to tokenised code accessible to Classic99 in about 5 seconds flat. 

 

That having said, one issue I experienced is just that as written (at least on Windows and Python 3.11), it was necessary to change all the string conversion in XBAS99.PY to Latin1 rather than ASCII, as my program uses the full range of characters available to (i.e., which can be typed under) TI BASIC.  Which is to say, 127-159 and 176-198 inclusive.  Now, I grant the use of the latter is an oddball rarity (though extremely useful to me under present circumstances, as I need a fairly large number of tokens in a distinct range, separate from characters representing any printable graphic).  However, the prior is probably a more typical necessity (given both Extended BASIC and Console BASIC can assign patterns to characters beyond the 7-bit ASCII range, and so read them in from DATA statements or DISPLAY AT the character sequence as a string literal). 

 

Anyway, for me, the fix was simply changing any use of the .encode or .decode methods to Latin1.  i.e., s.encode(encoding='latin1')

 

Thanks a lot for the tool.  The best way to work on (while actively testing) a large TI BASIC or Extended BASIC program, it seems to me. 

  • Like 3
  • Thanks 1
Link to comment
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...