Monday, August 15, 2011

LAST BUT NOT LEAST.... Ultima 1 revisited program clarifications...

HI Beth,

A few things...

1.  I tested the POKE and it worked like a charm!  My initial program had the row and column values set in the main assembly program, which didn't allow for modification.  So, my test was to set the ROW and COLUMN as set variables which were equal to $1E and $1F.  I then entered in my Basic program two lines that read:

10 POKE 30,10
15 POKE 31,11

I did these lines before the BLOAD of my main assembly program and it worked!

The main character shows up on the map in the location set by the poke statements!   I tested this with different values and the character started in different locations on the map.   I love it when things work like they are suppose to.  So now I think I can use a 2 dimension array in basic with X,Y to track the main characters movement and when the player wants to save the game I can PEEK these values and BSAVE them, right???   Also, I know that the first Page of memory is 256 byte locations, do you think I should use these bytes for all of my variables or is there a better location from memory to use??  So now that I know how to use the POKE statement in my basic program I was thinking that I could use these locations for the variable such as player character map location, hit points, gold, experience, food, monster and transportation locations, etc...  right???  Then I was also thinking I could save all these values with a BSAVE when the player wants to quit and save his place in the game.  Is this the correct way of doing this?

Joe, yes, that’s exactly how you pass information back and forth, as well as loading and saving the data. However, be VERY careful with using the “first page of memory”. That is referred to as “zero-page” memory and it’s a very valuable and constrained resource. Here’s a link to how it’s being used by the system:


You don’t want to use any locations that might be in use by something else, as those may change your values or you may corrupt what it is that they do. You should reserve your use of zero-page memory for critical timing routines where you optimize using fast instructions that rely on zero-page indirect addressing, for example. For all of your program variables, find a higher location in memory and use PEEK and POKE on those addresses. (This gets back to figuring out a memory map so you can know exactly where in memory you’ve allocated all your variables, your data, your programs, etc.)


2.  Concerning the towns and castles:  Since there are probably 8 to 10 castles and 30 to 40 towns, which all seem to look slightly different.  I was thinking I SHOULD do them in assembly to save space as you mentioned but I still have the issue of the number of shapes that will be created for all these places and how do I use data compression?  The world map was easier because I only had about 12 or so main tiles on the map, less than 15 total, but the town and castle have way more.  I won’t be able to use the data compression even if I create a separate assembly program for each separate town or castle because some of the towns look like they have more than 20 shapes that make up the tiles for the town!  So that bring me to the main question:  Should I just do them in assembly and use normal data strings which use a byte for each shape #, like I did in the beginning.  This way I could create one assembly program that would generate the images for all of the towns and castles  OR should I do them in BASIC, which would use a single file that had all the shapes necessary for all the castles and town and create a ransom assess files that would have a text file that used three values for each shape, such that it would have the X,Y, and shape # for each shape in each town/castle.    Which do you think would take up more space; the BASIC program of the Assembly program????  I know that space is a critical issue and I would hate to start spending a bunch of time of one path then realize I should have done it the other way just to save a bunch a memory!!!  

Well, I think you’re fine with doing it in Basic, but I don’t see why you need three bytes for each shape. Why not just store the data in data strings like you store uncompressed maps, so each byte is the tile # and the X,Y is implied by the location of the tile # in the array? You just lay out 20 x 10 tiles for 200 bytes, for example. You could still randomly access the file every 200 bytes or so to pick off the specific town/castle you wanted, or you could have a bunch of different little data files. Regardless of whether you use basic or assembly you should keep the X & Y out of the data, imho. Save that space at least! I don’t think you need to bother with compression, since you could load in the town/castle instead of an outside map when you switch between modes, for example.

3.  I think I got where you are coming from concerning monsters and transportation tiles and the memory they use but let me reiterate just to make sure.  Since I plan on using individual memory locations for the locations of transportation tiles and monster tiles, similar to how I did the ROW and COLUMN deal.  Did you mean I should set aside a number of these locations just for a set amount of these items locations on the map?  Meaning, if I use the first page of memory and set aside 10 or 15 for each transportation tiles, which would mean two byes needed for each tile, which is basically for the X and Y location values, correct?  This way I could create arrays for each new monster or transportation tiles and save their location in each byte with their X and Y values.  Then I would able to check these values on each character move and if they fall into the map screen parameters, I could use them to draw their location on the map.   Is this what you meant or am I way off???

Well, again, don’t use the first page of memory. Find another block somewhere for this type of data. I would argue you still need 3 bytes for each, one byte for the type of transportation (e.g. 1 = cart, 2 = horse, 3 = ship, etc.) and an X, Y for that as well. Otherwise yes, what you say sounds correct!

4.  Concerning front and back buffers:  I understand now what you mean about using these two pages of graphics and will start testing them.  I know now that I have to add Page 2 "$4000 and up" graphics memory locations right after my Page 1 graphics locations used for indirect indexing.   After that I will have to create another addition to my program to incorporate these two page swaps.  The question I have is:  You say to draw on screen two that is not seen by the user but how do I draw on the screen when I don't know which direction the player wants to go?  My understanding was I would start with the initial map view on Page 2, while Page 1 is blank!  Then show Page 2 and when the player makes a move I would draw on Page 1 then switch them.  Is this incorrect?  If so, I'm not sure how to implement the page flipping for the game.  I see there being a delay between page flips due to the amount of time it takes to get the new information concerning the direction move.  I also see how the 90% could make a huge difference with speed due to the page flip delay!!!  I need to figure out how to get the 90% shift working because I already notice that the redraw is not fast enough!!!  I will do more testing on the 90% map shift because I have to get this working in the program and then utilize page flipping at its most!

It’s easy for me to say, but don’t overthink this too much. It’s actually pretty simple.

1.       Get user input for direction they want to move
2.       Copy the 90% of the front buffer to the new location in the back buffer – shifted by user input
3.       Draw the remaining 10% of the back buffer required
4.       Flip the pages
5.       Goto 1

Since you aren’t trying for constant animation, you don’t have to keep things running. You can always wait for use input. If you were animating (say you wanted to have the water tiles always moving so it looked like all the waves were in motion) you wouldn’t wait for the user input at step 1, you’d just check to see if there was any.

To break this down further:

Step 2:
You can literally copy screen-memory lines from the front-buffer to the back buffer. You just need to copy them from the current location to the shifted location. So instead of copying from $2000 to $4000 directly, you might copy from $2000 down a full tile to $4080 or whatever it is in the event the user decided to move up.

Step 4:
Flipping the pages is very fast. All that happens here is you switch which hi-res screen the user is seeing. As I recall, this is done like so (where K can be 0 or 1):

POKE49236+K,0                               //set hi-res graphics page (K)

And to keep things consistent, you might want to follow it with this:

POKE230,32+(32*(K=0))                 //set hi-res plotting page (for basic, 32 = page 1, 64 = page 2)

And of course this clears the current plotting screen to black (if you need to do so)

CALL-3086                                       //clear current hi-res screen to black


5.  I had an idea that I wanted to get your opinion on:  I was thinking of using a main location array in the BASIC program that would have the main character map location tracked at all times.  This array would basically have the X,Y coordinates of the characters location on the world map.  My thinking was I could use this array values for a number of issues:

 A.  I could have all the town, castle and signpost X,Y locations on the world map saved in a data file and check after the player hits the ENTER key, which is the key used to enter these locations.  Once the enter key is hit I could check against the players X,Y position and if it matches an X,Y value within the database I would know exactly which town, castle, or signpost for that matter, which the player was trying to enter!!!  Then all I have to do is a simple CALL statement to the portion of the assembly program that draws that town or castle of updates the quest when the signpost is visited.  What do you think?? 

B.  Also this would work out great for when I want to board a transportation tile because when the player hit the "B" key for board I could check this value against the values save for all the purchased transportation tiles on the map!!  What do you think?

C.  Also, also... "hehe"   I what be able to use this X, Y value for the monsters to track too.  I know in the game that if you move on the map while a monster is near it will move after you.  So I thought that I could use this X,Y value to help the monster's track the player’s location and attack this location accordingly.  Again, what do you think?

All of the above sounds good! I worry a bit when you say “data file”. As long as you mean a data block in memory, cool. You don’t want to be loading an actual disk file every time the player hits ENTER, though! I’m assuming you meant in-memory locations.

Also, as a bit of an aside, check out this article:


I realize you’re not really concerned with how to do smooth animation on the Apple ][ (at least not yet), but this goes into that, which is a whole topic in and of itself. What I thought you might find immediately interesting was to check out how this program interfaces with its assembly bits. It involves a fairly integrated Basic and Assembly program which both read/write data used by the other, with calls from the Basic program to the Assembly program(s). Sound familiar? Check out how they made it work and maybe it will help further inform your own efforts!



I know these are a lot of questions but what better way then to go to the source!!!

Thanks again,

Joe

No comments:

Post a Comment