Saturday, July 30, 2011

Wow, I figured out how to do the compression part of the program!



Hello everyone,
Well I figured out the new programming method to compress the data for the entire world map that saves me a huge amount of bytes.  The screen shot above is from a BRUN of the new program with about 4 new subroutines that work out the compressed data strings.
The Ultima 1 world map is [4] separate maps that are side by side totaling 180 tiles wide by 90 tiles deep!
Previously I would have had to spend 180x90 = 16200 bytes to create the world map!!! "This would not work by the way!"
Now, the total amount to bytes I will use for the entire world map is approximately 90x15 "15 is the average amount of byte groups" = 1350!!! That is almost a 15000 byte savings!
 The new compression program works as follows:
 1. Since each world map line has different types of tiles and different amounts of each tile I used a value at the beginning of each data string that represents the total number of bytes in the data string.
Previously I was going to have to enter 180 total bytes for each of the 90 map line but now I setup each map line as follows:
Exam: MAP1 DFB $0C,$F9,$F9,$F9,$F9,$F9,$F9,$F9,$F9,$F9,$F9,$F9,$F9
 So the $0C represents the twelve total groups of bytes, which will be used in a loop checker. The twelve bytes represent 15 ocean tiles each per byte group!  The 9 is the # that represents an ocean tile/shape.
2. I initialize values for ROW and COLUMN, which for testing start at 0,0.Since I have ROW start at 0 I end up looking through MAP1 data string first.
3.I have a subroutine that first reads the initial byte, which in this case is the $0C and places it in a variable.
4.Then I read the data string again and place each of the seven bytes into an array called PREPMAP,X with the $0C used as a loop checker.
5.I have a subroutine that reads the first byte in the PREPMAP array and stores the value in two variables: HBYTE and LBYTE.
6.I have another subroutine that shifts the HBYTE to get only the F only into the byte.
7.I have the next subroutine shift the LBYTE to get the 9 only into the byte.
8.Now I use HBYTE as a loop checker and place 15 ocean tiles in a TMPSTORE array that is 180 byte long. This subroutine loops again through all 12 bytes, again through the HBYTE and LBYTE and places them in the same TMPSTORE array.
9.Once all 180 bytes are stored in the TMPSTORE array I use another subroutine that gets the value of COLUMN and retrieves that 20 bytes starting at the column value and stores them in an array called MAPSTORE.I run through this process with a loop 10 tiles to get all 200 tiles reference numbers.
10.Now that I have all 200 tiles I was able to use my existing draw subroutines with just a number of tweaks. The tweaks consisted of drawing out the tiles by reading in groups of 20 so I could keep the draw pattern as a top to bottom approach as 10 tiles down and 20 columns to the right.
I know I can clean these processes up and make them faster and cleaner but I just need to spend more time on them and refine each one.
So now I am spending my time recreating the entire [4] maps in excel with all the inidivual tiles images placed in individual cells.  The world map will be 180 tiles wide by 90 tiles deep.
When this is complete I will be able to enter all the data strings for all 90 map lines and move on to the ship movement part of the world map.  I bet you though I forgot about this movement process that happens on the world map.  I have a good idea how to get this to work and not add any really code to the program.  It will add another shape to the program and new parameters for the movement checker.
Talk soon,
Joe
 
 

Friday, July 29, 2011

So what is the plan....

So what is the plan...
Hello everyone,
Well, you have all probably been wondering what the heck I’m doing and what type of plan I’m following.  So far I’ve been spending most of my time trying to figure out how to program the movement part of Ulima 1 and boy has this been insane!  Trying to learn a new language is hard enough but trying to figure out how to re-engineer a game that has little to no information on it is near impossible.  I’ve had some major breakthroughs and some downfalls as you have seen on this blog but things are progressing and I feel as if I’m on the right path.  My plan for this project is to take each main part of the game and program it in sections.  As each section is completed and functional, “key word here” I will move on to the next main section of the game.  As I see it, there are 12 sections to the game:
1.  World map movement
2.  World map monster encounters
3.  Dungeon movement
4.  Dungeon monster encounters
5.  Castle and town movement
6.  Castle and town guard combat
7.  Space movement and encounters
8.  Big Boss encounter
9.  Monster encounters and combats functions – Total combat system
10. Character stats and progressions
11. Title images and menu systems
12. Buying, selling, and stealing items
13. Creation of all shapes/tiles that are used in the game
14. Missions, assignments, and requests from kings
15. Anything else I forgot!
The sections I see as being the most involved will be the monster encounters/combat system, dungeon movement, space movement, and mission, assignments, king requests.
Like any program these seem to be subroutines within the main program and it becomes an issue of space as well as functionality.  The hard part for me is trying to figure out how much is accomplished in assembly and how much is in basic.  My assumption when Richard was programming this game was very familiar with basic at the time but not so with assembly.  I understand he had help with the assembly part by a friend named Ken.  Ken did the tile movement part of the game and probably showed Richard how to program other sections of the game in assembly to help make the game faster and more efficient.
I know that certain section will be created in assembly and loaded into memory just like the world map movement section.
No matter what, you will all be informed and updated as to the progress of each section and when they are complete.  I have posted my email address, which I will do here again so anyone can contact me for questions, program files and code or even to just leave comments.
Thanks for hanging around and watching the show because it can only get better!
Sincerely,
Joe

Book Review - "Apple Graphics & Arcade Game Design"


Book review time,
Today I will be reviewing one of the Assembly books I’m using to help recreate Ultima 1.  The book is titled “Apple Graphics & Arcade Game Design” by Jeffrey Stanton.  Right off the bat I will say this book is incredible!  Without this book I would never have figured out the correct method of placing shapes on the screen in any location using bit mapped graphics and lookup tables.   This book is definitely for the advanced user because it assumes you have some previous knowledge of the apple memory addressing and an understanding of how the apple memory works.   It does take a progressive approach in that it starts at a low level with topics covering screen layout, screen switches and controls, colors and background fill, graphics animation using shapes tables and character generators.   It starts with Lo-Res graphics and continues on to Hi-Res graphics, Bit Mapped Graphics, Arcade Graphics, and Games that scroll.  There are a total of 8 chapters and the book has 288 pages with an index.  The book was written in 1982 at the peak of apple graphics arcade programming.
The table of contents is as follows:
Chapter 1 – Applesoft Hi-Res
Chapter 2 – Lo-Res Graphics
Chapter 3 – Machine Language access to Applesoft Hi-Res routines
Chapter 4 – Hi-Res Screen Architecture
Chapter 5 – Bit Mapped Graphics
Chapter 6 – Arcade Graphics
Chapter 7 – Games that Scroll
Chapter 8 – What makes a good game?
Each chapter is well written with detailed information and program listings.  Jeffrey gives examples in Basic, machine code, and assembly code throughout the book.  As the chapters progress so does the assembly code for each program.  In the chapter covering Lo-Res graphics he gives a great example of a breakout program with ideas on color, paddle control, and memory addressing.  But the meats of the book to me were the chapters on Hi-Res graphics and bit mapping.  These chapters alone would constitute the price of the book!  I learned so much from reading these two chapters that I now have a much better understanding of how I place a shape on the screen, just how each memory location is setup in Hi-Res graphics with regard to each line on the graphics page 1 or page 2.  He explains how you can use table lookup with indirect indexing to help place shapes anywhere on the graphics screen faster than if you tried to address each one separately.   Each chapter also includes a flow chart to help you understand how the program works before you see the actual assembly code.  This is incredibly helpful because the Assembly programs in the book are complicated.   You have to read through the program a number of times just to get a sense of how things are working.  What is nice is that he writes his programs in a no nonsense fashion, where they each have a clean top to bottom flow.  Don’t get me wrong, these programs are advanced and you need a high level of understanding of HEX and indexing.  He also covers paddle usage, scroll graphics as in the game defender and space invaders.  The chapter on Arcade Graphics covers explosions, collisions, steerable space ships, scorekeeping, and page flipping.  Page flipping is especially important to help with fast screen graphics manipulation.  This process allows you to draw an image on page 1 then while the use is looking at page 1 you draw another image on page 2, flip to this image to show the change, then you draw again on page 1 and flip back to page 1 image to show another change to the user.  This generates a smooth graphics frame sequence of moving images without the delay or flicker.    Jeffrey uses a lot of Remarks to help give a better understanding of the program while you are typing it in.  The programs in the book look like they were programs that were assembled and printed out, giving the user a clear, error free code listing.  One of the best parts about this book is that I was able to assemble all the programs in DOS TOOL KIT with very little manipulation of the code.  They complied and started with remarkable ease.  He has a very clean style of writing and gives a lot of detail concerning each topic and discussion.  The programs are well written with lots of comments and remarks.  Again I will say this is an advanced assembly programming book but it is still manageable if you give it a lot of reading time.  This book covers everything you need to know to get you comfortable with programming in apple assembly.   If you want to gain a better understanding of how the memory is used to program games and learn how to program the apple in assembly language then run don’t walk to eBay and buy this book!  Be aware that this is a rare book that people are charging an arm and a leg for so don’t get burned by a ridiculous amount.  I would say that if you are serious about learning apple assembly language programming and want to follow this blog to learn how to program the Ultima 1 game then you need this book!  If you see it for under $50 then buy it because you will not find a better programming book out there that covers all you need to know about arcade game graphics and design.   
Price  - N/A
Date: 1982
Rating is on a 1 to 10 scale with 10 being the highest.
Depth  - 9
Programming – 9
Sample codes - 8
Quality – 8
Bulk - 8
Information – 8
Humor – 5
Overall rating –8 

Thursday, July 28, 2011

Yeah, I did it… but wait there is a catch…



Hello again everyone and welcome to another blog regarding Ultima 1 revisited, where I try to figure out how Ultima 1 was programmed and recreate it in assembly from scratch!

So, as of today I finally figured out the movement part as you can see in the video above and it is a lot faster than the previous movement video test.

This was a bitch! I mean, really! REALLY!!!

Working with the DOS TOOL KIT is a very slow and grueling process. Each time you compile your program you have first save the file which takes 5 of so minutes depending of the size of the file! Plus you have to wait about 10 or so minutes for it to compile after you save it. Uhg! By the way, you better save first before you compile because the assembly editor moves the compiler into memory and by doing this it erases whatever program is in memory at the time. Found this out the hard way!

Well as the title alludes to there is a catch or snag in this programming code! Yes I figured out how to move a character around the map, which by the way checks collisions with mountains and oceans! When I was working out the code for the test I only used a small portion of the upper left section of the Ultima map to do my test. Once I realized I was able to get it working I started entering in all the data points for each tile on the map from the left to the right! Well the problem with the Ultima 1 world map is that it is made up of 4 individual maps or kingdoms, which are only access by having a ship.

So let me take you back a few days when I was on cloud nine thinking I’d just figured out how to cure cancer figuratively. “Yes, programming in assembly is that hard!” LOL.

So here I am with a big smile on my face when I start entering in all the tile date values for each map line from top to bottom and I get to about line 24 out of 80! I hit enter to input the line and bam… I get a memory full error! What! Are you kidding me! I’m not even half way with the map tiles, let alone the rest of the ultima program and I run out of bytes! Well, in the midst of committing seppuku I realize I better go to the one source that can bring me to the light! BETH!!

Here is what she had to say in an email I sent her:

Hi Beth,

I bet you never though this email would come but finally I figured out how to move around the screen and it look and feels just like the game.

Funny thing is I didn’t use the method you mentioned where you scroll with the 90% of the existing tiles and just generate the last 10%. I used table look ups and since the redraw is fast enough in assembly I was able to redraw using a column or row shift based on the key pressed. When the key direction is pressed I just re-read the new map tiles and redraw them all on the screen. I know this isn’t the correct method but I tried to work out the other method and kept hitting a brick wall! I will try to work it out but for now it works like it is suppose to. I will post a video very soon so you can see the progress. I’m totally jazzed! This is huge for me and I can now work on the other parts of the game.

Hey, however it works is good enough. When I did my version of U3 I didn’t do the 90% shift thing either, because as you note just redrawing from in-memory tiles can be fast enough. If you don’t need the extra speed, don’t sweat it. You can work out the math on how many cycles per tile it will actually save you to determine how much speed boost you’ll get – I could believe anywhere from 4x to none at all, depending on how you implement the algorithms. Congrats again on getting it to draw!

I do have a few questions if it is ok…

1. I worked out the map and the entire map is about 180 tiles wide X 180 tiles deep approximately. Well, this is a lot of bytes to use and if I calculated right that would need 32,400K or bytes for each tile value!!! How is this possible? The map is huge and basically has 4 separate maps that make up the entire global map. I have to make sure that Richard didn’t use the back side of the disk for game use and put some of the maps on the back side. Even though, how would I put all the individual byte information for each tile to be represented if we are talking 8k for each map and 32k total?

Okay, I don’t know exactly how he did U1, so I’m speculating. I can give you some different approaches to try, though. Conceptually, you should consider the Disk Drive as something akin to a swap file – it’s like extra memory you can use, it’s just slow to read/write so you want to avoid it. That said, what happens is that loads are done at critical points to swap out data files and program code – thus allowing one to essentially be in an entirely different program when in a dungeon, say, than up on the surface.

So, swaps can occur on the surface as well, when you move between maps. That’s one point – so you’d only have to have a single 8k map in memory at a time, and then you’d swap in the new map when you approached the edge of the current one.

Also, how many tile types are there on the map itself? 15 or less? Then you’re wasting a lot of bits. You should make your maps nibble-based. The top 4 bits of any byte are tile A, the low 4 bits are tile B. That means you only need 90x180 = 16.2 k for the whole thing and 4.05k for a single map. And that’s storing it RAW instead of RLE which I recommend against. See my later note for more on that topic.

2. How do you separate assembly code if you run out of space in a certain memory region? If I start my assembly program at $6000 and use the entire free memory range up to $95FF, how would I continue using the rest of memory for my database of tiles?

You separate out your data and routines by how big they are. Then you figure out where in the memory map you want them to go. You then can use Basic to do some like BLOAD to load the individual data/code files into exactly where you want them in memory.

This tile memory usage for the maps is mind bending and I just don’t understand how he was able to put in a database of all the tile references when they would take up so much memory!!!

Another possibility is that he used RLE compression. That will pack it down tremendously. RLE stands for “Run-Length Encoded”. It works like so…

The data is always:

1. A value representing a run of N1 tiles.

2. Type of tile X.

3. A value representing a run of N2 tiles

4. Type of tile Y.

5. Etc.

So if my map row looks like this:

01 01 01 00 00 04 04 04 04 05 05 01 01 01 01 01 01 01 01 01 01

This encodes to (hex here)

03 01 02 01 04 04 02 05 0A 01

And if I’m nibble-based, I can ditch all the zeros and pull this down to:

31 21 44 25 A1

So…5 bytes now take the place of 22.

The longer the runs, the better compression you get. So taking a guess that you get 4x compression, that should pull your maps total down quite a bit. I bet you get better compression than that, especially if you can use nibbles instead of bytes.

Also, if the map uses a major portion of the disk how do I put in the towns, castles, and dungeons? This seem like I don’t have enough space on a single disk but Ultima 1 only comes on one disk.

Compression algorithms. J

Joe

So now I’m at a cross road because I realize I have to change the program I just spent months on trying to get working correctly and I have to utilize a new set of subroutines that will read compressed data strings. This is definitely going to change a lot of my program code.

Well I’m off to work on the problem but while I’m doing that please enjoy the video and if you have any questions please email me at:


I would love to hear from you whether it be comments, criticism, or requests for info, I will try to answer your questions as soon as I can.

Talk to you soon,

Joe

Friday, July 1, 2011

Programming in a new direction...

Hello everyone,
Well, since my last blog you all saw the movement test and can tell that this method is not functional for a game. So I've been testing some new code and it is working a lot faster than the last program. So far I'm able to draw a tree shape across 20 rows and 10 columns with almost instant draw time.  I’m basically storing each byte, of the 32 bytes that make up a set shape, directly into the memory region that make up the Hi-Res page 1 screen. So, it kind of works like this; you have a memory region that starts at address $2000 for the top-left corner of the screen in Hi-Res page 1 graphics. This address makes up [1] byte of screen memory. I store the first byte of the tree shape in address $2000 and then store the next byte of the tree shape in address $2400. This basically places each byte starting at $2000 and I go down a line to $2400, to the next line $2800, and so on... When I get to the 16th line I step to the right one byte and start drawing the rest of the shape in the next 16 lines. So I use 10 separate subroutines for each row and these 10 subroutines loop through for the 20 shapes.
Due to this new draw process I had to lay out the shape byte values in a different way from before.  They are now set so the first 16 bytes are for the first 16 address bytes of memory and the next 16 bytes are for the next 16 address bytes of memory.  So the first two addresses are $2000 and $2080… the next two are $2100 and $2180 then so on…



I was able to figure out a process where you use an address such as $2000,Y The Y is like an array that lets you increment one place to the right as you increase the value of Y. It works really cool!
I have this working but it only draws trees across the entire screen. I need it to draw separate shapes within the entire screen to make sure it works correctly. I will post this code and video soon to show just how fast the screen draw is.
I will work on the subroutines that draw separate shapes from the map section.
Talk to you soon,
Joe