Reliving the days of playing and programming the game Ultima 1 on the Apple IIe computer. This will be a journey of discovery and creation to build from scratch the entire Ultima 1 program in Applesoft Basic!
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.
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.
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…
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:
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
Sorry for taking so long to post but man have I been busy! I will try to make it a point of posting more often and talk about where I am at and what I have completed.
So I finally figured out how to move around the map and even detect collisions with mountains and oceans!!! I have posted a video of the test movement and I will also post the assembly code. I will be posting a simple tutorial on how to enter the assembly code using an Apple II emulator. This is pretty cool because you can actually program on the emulator just like on the real apple computer!
The good and bad of the program is that is works BUT it is way too slow in its refresh rate. I am working on speeding up the refresh so it is just like the game.
Check out the videos:
The movement example shows a troll as the main character moving around the map. incorporated Applesoft basic with assembly code to use the I, J, K and M keys to move UP, LEFT, RIGHT, and DOWN. I also used the B key to restart the position of the troll.
I will post the code for both the Applesoft Basic and the Assembly code soon so you can enter it on an emulator and run through the program yourself!
Enjoy the video and know that we are getting close now!
Ok, so the photo you see above is a section of map in my Ultima 1 Revisited
program! I have FINALLY figured out how to display 200 tiles from a section of
the Ultima map on the screen and it is ALL programmed is Assembly! Is that cool
or what? I think I will be able to figure out how to move around the map by
this weekend. No promises but I am close!
On the next post I will explain just how I had to create each shape/tile. I
know I explained about creating shapes earlier in the blog but I was using a specific
shape creation program. For assembly you need to create each shape and turn it from
graph paper, to binary, and finally to HEX. Pain in the a$$ process but it works
great because you can use different colors for the shapes. I will be staying
with the original colors that were in Ultima 1 and not using the colors that
are found in the Ultima rewrite.
Here is a quick example of one of the shapes:
Also, I will be posting the Excel maps when they are completed. The files
have the entire [4] maps created from separate tile images and placed in
individual cells in an excel sheet. I have to say that it looks pretty cool to
be able to see the entire Ultima map on the screen in one shot. Very cool!
Here is an example of the excel map:
I can't wait to be able to post all the code and show a video of a character
moving around the screen on a generated Ultima 1 Map!
Well, I have to get back to programming but I just wanted to let you all
know just how close we are to see it all work!
Well, from the image above I can tell you that things are progressing
nicely! The above image shows 10 tiles set in two group’s side-by-side and 10
columns deep. Now you might think to yourself, "So what is such a big deal
about this"! Well the big deal is I created this image from a program
coded entirely in Assembly language! Yes, that's right! I have been able to
figure out, “with help from Beth", how to create shapes\tiles, place
shapes on the screen, and use simple loops to create rows and columns of shapes
and this was all done totally in Assembly language! Yup, no basic here! Now
don't get me wrong, this was not some easy task! I mean this was really hard! I
have been banging on the keys for days programming, learning new code, and
reprogramming code in assembly language just to get to this point.
But oh what a point it is! I am getting close to being able to place
specific tiles in certain locations so I can reproduce the Ultima map from any
location. This is what is taking me a long time to figure out. I need to be
able to have the entire global map of Ultima placed in data strings and then be
able to pull out just an area that is 20 tiles wide by 10 tiles deep!
This is the big one that will get me closer to figuring out how to finally
move the group of tiles in a coordinate system.I will be posting my excel files that have all [4] Ultima maps setup in
an excel file.I created this file by
using a graphics program to reproduce each land tile and place it in a single
cell in an excel worksheet.So what the
file will show is the entire layout of all 4 maps!This shows everything!All the tiles from all over the global
map!Pretty cool!