Jump to content
adamantyr

TI-99/4a disk-based CRPG

Recommended Posts

3,600 bytes of memory left, but almost done! Just writing up gambling and sailing routines now...

 

After this it's a lot of spit and polish. You always want a nice amount of remaining memory for last minute fixes or additions, little details that just make things better.

 

I also want to seriously go through the ENTIRE listing. Because it's a 10-year effort, I have a LOT of code that's potentially left over from prior incarnations. For example, I found that I'd started writing a "selling" option that was controlled through inventory. That had to be removed since it's all going through the transaction system instead.

 

Another issue is functional clarity... I have a lot of functions that use registers for semi-permanent values. For example, R9 is used by transactions to track the current place in the transaction array. This has caused some headaches in the past because calling certain functions wipe out those values. (For example, because I use R0-R2 for most video work, I almost NEVER use those to store semi-permanent values.)

 

I've been minimizing the use of BLWP operations because they're computationally expensive, but they DO preserve registers, so I may look at making more use of them in certain places. All my register sets are kept in the scratchpad for maximum speed.

 

There's also some memory overlap in places I could better structure. Combat arrays (like battlemaps and things) is free memory to use in other modes. I toyed with the idea of creating a memory management system, but it's a lot of work. I just need to better organize my memory usage and more clearly lay out areas to use for different things.

 

There's only one major feature left I'm considering, and it's going to wait until after I have the rest of the engine done... adding elevation to the maps. I'd have to add a new data array to store elevations per square (at least 2-bits per square for 4 elevations) and I'd have to figure out how to effectively display it on the maps. My vision there is that if you're at the top of a cliff, you can look out over a forest and not have line of sight blocked... But it could end up being too much to handle. We'll see...

  • Like 4

Share this post


Link to post
Share on other sites

I'm of the opinion that we generally over estimate the cost of BLWP. By the time you've saved 4 or 5 registers on a stack or elsewhere and retrieved them again later you're probably way over the time it would take for a BLWP.

 

Just my two cents!

Share this post


Link to post
Share on other sites

Well, I got started early on my revisioning... I couldn't help myself! I looked at my old map viewing code and just winced at all the inefficiencies. Naturally, my first set of revisions broke stuff. :) But I got it all fixed now.

 

A common thing I was doing in the old code was this:

 

MOVB @THING,R1

SRL R1,8

 

This was so I could use a byte value in a word, usually for an index. But this method works better:

 

CLR R1

MOVB @THING,@>8303

 

My workspace registers are located at >8300, so >8303 is the low byte of R1. If R1 is already cleared out, then I don't even need the CLR command!

 

One thing I'm also doing is I blew away my "demo" data for now. It's just not useful for testing all the variations of transactions, map types, and other elements so instead I'm creating a total and complete "test" set. For example, the main world map is just a collection of all the terrain types for testing, a stretch of water for boat/ship testing, teleport gates to take you to other maps to test dungeons, traps, slanted maps, etc.

  • Like 1

Share this post


Link to post
Share on other sites

:thumbsup:

 

This is a little easier to read, or rather, it explicitly states the intention to the reader:

R1HI EQU >8302
R1LO EQU >8303
 
MOVB @THING,R1LO

I know it amounts to the same thing, but it makes it easier to read, I think, especially for third parties.

 

What is your assembler environment? Are you using the TI assembler? Have you run into problems with the number of labels? Are you having to assemble into separate #3 object files?

 

Mark

Edited by Willsy

Share this post


Link to post
Share on other sites

:thumbsup:

 

This is a little easier to read, or rather, it explicitly states the intention to the reader:

R1HI EQU >8302
R1LO EQU >8303
 
MOVB @THING,R1LO

I know it amounts to the same thing, but it makes it easier to read, I think, especially for third parties.

 

What is your assembler environment? Are you using the TI assembler? Have you run into problems with the number of labels? Are you having to assemble into separate #3 object files?

 

Mark

 

True, the issue is that I have four different register sets, so using labels gets complicated. :)

 

I use Textpad to compose my assembly code, which is currently broken down into 33 separate files for different components. A single file, CORE, acts as a merge file to bring them all together. It also contains AORG commands to move the code into the cartridge RAM area on my Superspace design.

 

I created my own syntax file and color scheme for Textpad, so it nicely highlights things as well.

 

For assembly, I use A99, originally written by Alan Beard, which runs in Windows at the command-line. It outputs an E/A #3 tagged object code file that I then load into E/A on Classic99. It's very good at producing an output file I can use for debugging purposes as well as giving me an exact amount of memory consumed. So far it hasn't barfed at the number of labels either!

 

I used to use the SAVE functionality through the debugger, but it doesn't work with the cartridge RAM, so instead I just do a memory dump after it completes loading. I then use a hex editor (Hex Workshop is my favorite) to hand copy the blocks of memory out into my memory files, of which there are four. It's a bit of a hassle but it works.

  • Like 1

Share this post


Link to post
Share on other sites

:thumbsup:

 

This is a little easier to read, or rather, it explicitly states the intention to the reader:

R1HI EQU >8302
R1LO EQU >8303
 
MOVB @THING,R1LO

I know it amounts to the same thing, but it makes it easier to read, I think, especially for third parties.

 

What is your assembler environment? Are you using the TI assembler? Have you run into problems with the number of labels? Are you having to assemble into separate #3 object files?

 

Mark

 

Has to be MOVB @THING, @R1LO

Share this post


Link to post
Share on other sites

 

Has to be MOVB @THING, @R1LO

Good catch! This should fix that issue:

 

 

R1HI EQU 2
R1LO EQU 3

 

Tada! :)

Share this post


Link to post
Share on other sites

Good catch! This should fix that issue:

R1HI EQU 2
R1LO EQU 3

Tada! :)

 

You need to get more sleep, Mark. That makes R1HI and R1LO equivalent to R2 and R3—not what you intended, I think.

 

...lee

Edited by Lee Stewart
  • Like 1

Share this post


Link to post
Share on other sites

Go easy on Mark. Small niggling little errors in assembly are VERY frequent. :) Especially mucking about with mnemonic labels! Fortunately those get caught by the compiler...

 

95% of the time when I have a bug in my code that ISN'T caught by the compiler, I have a MOV where I needed a MOVB, or an INCT where I wanted an INC.

 

A good point on this, though, is that the word/byte separation on the TMS9900 is unfortunate in that it forces us to waste some cycles just to get things in the right positions for calculations. It's really too bad they couldn't add another addressing mode to push bytes into specifically high or low locations in the word.

  • Like 1

Share this post


Link to post
Share on other sites

Just messing with him. We’re good friends and I’m sure I’ll catch hell when he logs on in a few hours! :evil: He has caught plenty of my gaffes, I must say!

 

...lee

  • Like 1

Share this post


Link to post
Share on other sites

A good point on this, though, is that the word/byte separation on the TMS9900 is unfortunate in that it forces us to waste some cycles just to get things in the right positions for calculations. It's really too bad they couldn't add another addressing mode to push bytes into specifically high or low locations in the word.

 

The problem is not really the addressing mode but the bus control. Two solutions:

 

- add two more pins to the CPU for controlling the upper and lower byte (as done with Intel's x86 or x64 platforms)

- reduce the data bus lines to 8 and add the A15 line (as done with TMS9995)

 

That is, when you do a MOVB to an odd address on the Geneve, there is only one memory access.

Share this post


Link to post
Share on other sites

 

You need to get more sleep, Mark. That makes R1HI and R1LO equivalent to R2 and R3—not what you intended, I think.

 

...lee

AHA! LMAO!! Yes you're right! And you're right, I need to get more sleep. I'd just got back from a very loud band rehersal, with the sound of my (cranked) Vox AC30 ringing in my ears, typed that on the computer ('er indoors left it switched on) and went straight to bed - that'll teach me! :)

  • Like 1

Share this post


Link to post
Share on other sites

Just messing with him. We’re good friends and I’m sure I’ll catch hell when he logs on in a few hours! :evil: He has caught plenty of my gaffes, I must say!

 

...lee

Yep - it's all good, and all good fun, as all hobbies should be. Lee and I probably have around 1000 private messages in Atariage - there's plenty of history and plenty of leg pulling :)

  • Like 1

Share this post


Link to post
Share on other sites

 

The problem is not really the addressing mode but the bus control. Two solutions:

 

- add two more pins to the CPU for controlling the upper and lower byte (as done with Intel's x86 or x64 platforms)

- reduce the data bus lines to 8 and add the A15 line (as done with TMS9995)

 

That is, when you do a MOVB to an odd address on the Geneve, there is only one memory access.

Could they not have just left the bus as it is and added an extra instruction, like:

 

MOVBL (move byte to low byte)

 

I haven't checked the instruction group that MOV is in, but there might be room in the instruction part of the op-code for it. I remember that Cory Burr added a number of additional opcodes to Win994A that added a real stack to the virtual 9900 and instructions for branching to subroutines that saved their return address on the stack, and the appropriate return instruction. Lovely.

 

An instruction like MOVBL would probably be quite slow internally, but as long as it wasn't slower than the de-facto method of using two instructions to do it then at least it would save a few bytes here and there!

 

Oh well... 1976 was a long time ago...!

Edited by Willsy

Share this post


Link to post
Share on other sites

I used to use the SAVE functionality through the debugger, but it doesn't work with the cartridge RAM, so instead I just do a memory dump after it completes loading. I then use a hex editor (Hex Workshop is my favorite) to hand copy the blocks of memory out into my memory files, of which there are four. It's a bit of a hassle but it works.

 

Have a look in the Classic99 debugger at the "Save memory as..." option after you load it - you can save any block of main RAM as a set of EA#5 programs right from within Classic99. There's a separate option to dump cartridge memory as a cartridge image if that's more helpful, though it's 8k only.

 

I guess I'm reading here you have four blocks, but if I can add something to this to make your life easier, let me know.

Share this post


Link to post
Share on other sites

 

Have a look in the Classic99 debugger at the "Save memory as..." option after you load it - you can save any block of main RAM as a set of EA#5 programs right from within Classic99. There's a separate option to dump cartridge memory as a cartridge image if that's more helpful, though it's 8k only.

 

I guess I'm reading here you have four blocks, but if I can add something to this to make your life easier, let me know.

 

Well what I'm doing is loading code into the >6000 block, THEN switching to the >A000 block for the remaining 3. The low RAM is untouched because it's occupied with the E/A loader crap, and so I can't really overwrite the whole thing. In the game itself I just use it for RAM space; the upper half of the block stores all the map data for example.

 

From what I see on your "Save Memory" screen, I only have the option to specify High RAM, Low RAM, and VDP RAM. A fourth option to specify ANY area of memory as a fourth 8k block would work.

 

Fortunately I don't need to resort to the SuperSpace II cartridge for this; paged memory in cartridge RAM would be even more tricky to handle... I'd have to write a custom loader at that point.

Share this post


Link to post
Share on other sites

Could they not have just left the bus as it is and added an extra instruction, like:

 

MOVBL (move byte to low byte)

 

If registers were in the CPU, this would certainly be possible. But the registers of the TMS architecture are all in memory.

 

Remember that the CPU does not have an A15 line? That is, the 9900 sees its memory as 32K words @ 16 bits. That is, it is in some sense "even more 16 bit" than we could feel comfortable with.

 

When I had a closer look at the x86 architecture to prepare some slides for my lectures, I was a bit surprised to learn that this read-before-write is not a general problem but pretty much TMS9900-specific.

Share this post


Link to post
Share on other sites

For assembly, I use A99, originally written by Alan Beard, which runs in Windows at the command-line. It outputs an E/A #3 tagged object code file that I then load into E/A on Classic99. It's very good at producing an output file I can use for debugging purposes as well as giving me an exact amount of memory consumed. So far it hasn't barfed at the number of labels either!

 

I used to use the SAVE functionality through the debugger, but it doesn't work with the cartridge RAM, so instead I just do a memory dump after it completes loading. I then use a hex editor (Hex Workshop is my favorite) to hand copy the blocks of memory out into my memory files, of which there are four. It's a bit of a hassle but it works.

 

xas99 can generate E/A5 image files directly from the source code. It will output one or more chunks for each xORG segment, so you can put code directly into different memory areas in one go.

  • Like 1

Share this post


Link to post
Share on other sites

:thumbsup: Gonna use xas99 for my next project. [... snipped .... moved to the correct topic/thread ]

Edited by Willsy

Share this post


Link to post
Share on other sites

Woops. I see I've taken this thread totally off topic. Apologies to Adamantyr. I'll repost this in the appropriate thread.

Share this post


Link to post
Share on other sites

No problem Willsy, it happens. :)

 

Principal coding on the engine is now complete! Everything in game SHOULD have code now driving it... I may have missed something in one place or another, but I got over 3k left of space for fixes and tuning.

 

The only stuff I don't have active is disk swapping mechanisms (which I may just toss; my original design was going to be runnable on a native TI with options stored to prompt for disk swaps and such) and end game mechanics, which I'll work on after most of the content is complete.

 

I had to work a bit on getting boat mechanics in place... a big pain is that you really can only own a single boat at a time since I only have memory to track one. I had to make sure it could swap freely between free boats and owned boats and store the necessary data so you could find it again. (Don't want you taking your boat out to a remote island, entering a cave, and coming back out to find it's gone!)

 

Now I have to go back to Visual Studio to complete my transaction parser... I've made a few changes to them so I need to update that so I can create records for testing. I got a ton of test data to write up and add in so I can start making sure the engine does what it's supposed to.

 

I tried putting a complete listing here for everyone to see but the forum rejected it as too long... well, the text output IS over 540k. :)

  • Like 1

Share this post


Link to post
Share on other sites

Thanks Owen!

 

Did a bit more clean-up work today... I had a TON of memory labels that were just scattered about. Plus I have a lot of memory that can be re-used in different modes. (Travel mode uses a large buffer for calculating the map view, for example, that could be re-used in combat mode for other things.)

 

So I used a spreadsheet to figure out the overlapping areas and redid my maps. Hopefully this works without a hitch... if I had any buffer overrides anywhere I may be finding out about them the hard way soon enough. :) The good thing is it's revealed that I actually have a little over 2k of free space in the low RAM I can use for potential other things!

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.

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...