-
I’m away but not gone!
Hello all,
I hope everyone has been having fun reading through and actually trying out the program code I put up on this blog!! This has been a labor of love and is still in the works. I wanted to give everyone a heads up that I’m still working on this project but with a new toddler running around, I’m keeping rather busy and can’t find the time to get back to this project! I will, I promise, but it will be later! One day you will come back to this blog and see more information and more code! Until then, enjoy what is posted and spread the word, Ultima 1 was the start of it all and must be remembered!
Take care and talk soon,
Joe “kingspud”
-
DOS TOOL KIT Tutorial
-
TUTORIAL #23 & #24 – HIGH & LOW side - indirect indexed addressing
TUTORIAL #23 – HIGH side - indirect indexed addressing “Is used to define the HIGH side of the byte for mapping directly to the PAGE 1 screen memory”.
It’s not easy trying to explain the process of how to use indirect indexing to place shapes on the graphic screen so I will use the explanation from the a great assembly book – “Apple Graphics & Arcade Game Design” by Jeffrey Stanton. Below is Jeff’s explanation starting at Chapter 5 on page 111 – Bit Mapped Graphics.
“Drawing a bit-mapped shape table anywhere on the HI-RES screen can be a simple process once the basic concept is understood. The shape table is stored sequentially in memory, either by rows or by columns. The technique, therefore, is to load each of the bytes, one at a time, into the Accumulator, find the position in memory for the screen location where you want to plot the byte, then store it in that memory location.
The difficulty lies in finding a particular memory location, given an X, Y screen coordinate. Speed is the critical factor in doing arcade animation; therefore, a technique known as Table lookup is used to locate the starting address of any single line on the Hi-Res screen. Each of the 192 screen lines has a starting address for the first position (left most) or the 0th offset. The first line of line #0 is located in memory at location $2000. The second line is at $2400, etc… Each address takes two bytes. The first part is the hi-byte, which in the later case is $24. The second byte, $00 is the lo-byte. These can be separated into two tables, one containing the lower order address of each line (call it YVERTL) and the other containing the higher order address of each line, YVERTH. Each table is 192 bytes long (0-191). The effective address of the operand is computed by adding the contents of the Y register to the address in the instruction. That is:
EFFECTIVE ADDRESS = ABSOLUTE ADDRESS + Y REGISTER
If our YVERTH table was stored at $6800 and we wanted to find the starting address on line 1 (remember lines are numbered 0 to 191), we would index into the table one position and load that value into the Accumulator,
6800:20 24 28 2C 30 24 …………. YVERTH TABLE
So LDA YVERTH,Y where Y=$01 will fetch the value $24 from memory location $6800 + $01 = $6801, and place it in the Accumulator.
Similarly, if YVERTL was stored immediately after the first table, then:
68C0:00 00 00 00…………………….YVERTL TABLE
Y register = $01
LDA YVERTL,Y will take the value $00 stored in memory location $68C0 + $01 = $68C1, then place it in the Accumulator. Eventually, we will want to store the first byte from the shape table into memory location $2400. This can be done efficiently if the two byte address is stored sequentially in zero page. Let’s store the lo byte half of the address, HIRESL, at location $26, and the hi byte half, HIRESH, at location $27 in zero page.
LDY #$01 ; Y REGISTER CONTAIN LINE
LDA YVERTH,Y ; LOOKUP HI BYTE OF START
; OF ROW IN MEMORY
STA HIRESH ; STORE ZERO PAGE
LDA YVERTL,Y ; LOOKUP LO BYTE OF ROW IN
; MEMORY
STA HIRESL ; STORE ZERO PAGE
We can change a particular Hi-Res screen memory location using zero page by indirect indexed addressing in the form:
STA (HIRESL),Y Y Reg = $03
If the computer finds a $00 in location $26 (HIRESL) and a $24 in location $27 (HIRESH), then the base address is $2400. The Accumulator stores a value into memory location $2400 + $03, or location $2403.
The final addressing mode that we must consider is Indexed Indirect Addressing. It is of the form:
LDA (SHPL,X)
It is very similar to the indirect Indexed addressing mode except the index is added to the zero page base address before it retrieves the effective address. It is primarily used for indexing a table of effective addresses stored in zero page. But in the form we are going to use it, the X register is set to 0; thus, it simply finds a base address.
The reason we must use this second form of indirect addressing is a shortage of registers in the 6502 microprocessor. We are already using the Y register in the store operation and there isn’t an indirect addressing mode of the for LDA (SHPL),X. Thus, we must go to the alternative addressing mode LDA (SHPL,X).
What this all boils down to is that we want to load a byte from a shape table into the Accumulator and store it on the screen with the following instructions:
LDA (SHPL,X) ; STORE BYTE FROM SHAPE TABLE
STA (HIRESL),Y ; STORE BYTE ON HI-RES SCREEN
We can index into the shape by incrementing the low byte SHPL by one each time, then store that byte into the next screen position on a particular line by incrementing the Y register. This zero page method is faster than doing the equivalent code with absolute index addressing, because two byte addresses can be handled with fewer instructions, less memory space, and with fewer machine cycles.
Obviously, a generalized subroutine must be developed to find the screen memory address (HIRESL & HIRESH), given a line number and a horizontal displacement. We will call this subroutine GETADR, short for Get Address.
Each time a row of shape table bytes is transferred to successive memory locations on the Hi-Res screen, the program will call the subroutine GETADR. The line’s starting memory address is then offset by the horizontal location of the shape on the screen.
Memory address = Line # starting address + horizontal offset
GETADR LDA YVERTL,Y ; LOOK UP LO BYTE OF LINE
CLC
ADC HORIZ ; ADD DISPLACEMENT INTO LINE
STA HIRESL ; STORE ZERO PAGE
LDA YVERTH,Y ; LOOK UP HI BYTE OF LINE
STA HIRESH
RTS
Where the Y register has the vertical screen value (0-191).
So what this means is by using indirect index addressing you can quickly process each screen memory location by looping through the Hi and LOW byte of the screen memory and either place a zero value in the location and clear the byte or enter a HEX value and produce a graphic image on the screen. It would be time consuming as well as a waste of programming space to try and write to each screen memory location from $2000 to $3FFF through line 0 to 191. You can loop through data base that has each HI and LOW byte definition and save a huge amount of programming space.
Here is a breakdown of a line within the HI byte data definitions code:
See small sample image above
On line # 886 we have defined a set of HI byte data regions, which after the DFB define each of the HI side byte screen locations. So for example if you were to store a byte of information within the memory location $2100, you would first have to grab the HI byte $21 then loop through the LOW side byte in the LO database section to obtain the remaining byte to draw your shape on the screen.
Remember, screen memory location $2000 is the starting upper left corner of the screen that would store a byte of information to draw points on the screen. The $20 is the HI byte and $00 is the LOW byte.
As always, if you have any questions please email me at:
Joe “kingspud”
-
TUTORIAL #22 – MAP TILE DATA “Is used to define all the byte information for each 2 x 2 sized MAP TILES used on the world map”.
All the MAP TILES in Ultima 1 are made up of 2 bytes wide by 16 byte deep, that are drawn in memory regions which corresponds to locations on the screen. Each individual map tile is a two byte wide shape and when they are read from the data string it is referenced by a number from 0 to 15 or the HEX equivalent to $00 thru $0F.
The following are the order in which the tiles are referenced:
0 = SHIP
1 = RAFT
2 = PLAINS
3 = TREES
4 = CASTLE
5 = TOWN
6 = SIGNPOST
7 = FIGHTER or main character
8 = TROLL
9 = DUNGEON ENTRANCE
10 = CART
11 = HORSE
12 = SPEEDER
13 = SPACE SHIP
14 = OCEAN
15 = DUNGEON
Since there are 82 horizontal line that make up the Ultima 1 world map, you will see a data string represented by a MAP## going from MAP1 all the way to MAP82.
To break down how each MAP TILE DATA STRING is read by the program I will use MAP70 as an example.
This example will be the same for all the MAP TILE DATA STRINGS!
First, you see the MAP70 with correlates to the 70th line on the World Map that will be shown on the screen.
Second, you see DFB which stands for Defined Byte for a defined data string. So everything after the DFB will represent the MAP TILES for the entire horizontal 70th line of the World Map.
Third, the first HEX value after the DFB will represent the number of HEX values that make up the entire MAP DATA string for MAP70. So $1E in this case is equal to the decimal value of 30, which if you count all the HEX values after the $1E will give you a total of 30 HEX values! The program uses this number to verify how many HEX values it can read in the DATA STRING before it gets to the end, without this HEX verifier it would cause the program to error by continuing to read the data string and not knowing where to end its read function.
Fourth, all the 30 HEX values after the $1E represent the amount and type of each MAP TILE shown on the world map. So for this example, the first $FE represent F = 15 and the E = OCEAN TILES. That is, there are 15 OCEAN TILES at the start of World Map horizontal line 70! The next amount and type of MAP TILE would be $1E or [1] OCEAN TILE. Then you have [3] PLAINS TILES, [1] TREE TILE, [1] PLAINS TILE, [7] OCEAN TILES, [13] PLAINS TILES, [6] OCEAN TILES, [3] TREES TILES, [1] OCEAN TILE, [3] PLAINS TILES, [1] TREES TILE, [3] PLAINS TILES, [9] OCEAN TILES, [1] DUNGEON TILE, [4] PLAINS TILES, [2] DUNGEON TILES, [15] OCEAN TILES, [13] OCEAN TILES, [4] TREES TILES, [1] PLAINS TILE, [14] OCEAN TILES, [4] TREES TILES, [8] OCEAN TILES, [5] DUNGEON TILES, [14] OCEAN TILES, [3] PLAINS TILES, [3] OCEAN TILES, [3] PLAINS TILES, and [11] OCEAN TILES. All of these data reference types make up the entire horizontal line for MAP row 70!
The reason this was created this way was the compression system I was talking about earlier in the blog. By doing each data string in this way I was able to save thousands of memory locations, which in turn allow me to have more programs on the disk.
To try and write this without the data compression would cause me to store each of these bytes in a separate memory location and if you add up all the type of each MAP TILE you would get just for this horizontal line alone, 171 bytes. Now multiply that by 82 horizontal map line and you can see that this is a lot of memory usages wasted! Remember, assembly language stores everything in a cells which are a $## HEX value of bytes, which are only readable up to 256 in numerical value.
This example is read exactly the same for each MAP DATA STRING from 1 to 82 so I’m not going to show each code line like I have been doing in the past because it is just easier to show each image from the lines of code that make up the MAP lines from MAP1 to MAP82.
As always, if you have any questions please email me at:
Joe “kingspud”
-
The tutorial is almost complete so hang in there…
Hello all,
I wanted to post this in-between blog to let everyone know that the Ultima 1 Revisited assembly program tutorial is almost complete and there are only 3 more tutorial parts left. After I finish the assembly tutorial I will post the tutorial on how to use the DOS TOOL KIT assembly editor to actually do the programming of the Ultima 1 Revisited code.
The last tutorial I will put together will be the BASIC program that runs the assembly binary files and controls all the move key functions so you can move around the [2] world map sections.
So hang in there and stay tuned because we are reaching the end of the World Map Movement assembly program tutorial.
Thanks
Joe “kingspud”
-
TUTORIAL #21 – SHAPES/TILE GRAPHCS “Is used to define all the bit information for each 16 x 14 sized SHAPE/TILE GRAPHICS used on the world map”.
All the graphic-tiles/shapes in Ultima 1 are made up of bits that are drawn on the screen. Each individual bit in a two byte wide shape is either shown ON or OFF to help represent the design of each shape displayed.
For this tutorial I need to go back in the blog a bit and explain how the actual shape is created. Below is a photo of a MOUNTAIN shape with its shape table byte references marked out.
You can see that the shape is created from [2] bytes laid side by side. They are stacked 16 high, which make a shape 14x16.
In the data reference for a MOUNTAIN shape, which you will see within the assembly code, you will see the following information:
You will notice that after the DFB you can see the first two bytes in the data file that are the same as the first two byte in the previous image of the mountain shape. This is how each shape/graphic tile is referenced in a data file so it can be drawn to the screen. Remember that one byte is made up of the two bits. So for example: HEX $08 is made up of two nibbles or four bits values. The [0] is basically 0000 and the [8] is 1000, which means the byte is 00001000. This is the same as $08! Each byte that is referenced on the shape will be placed in a graphic resolution byte that makes up the Hi-Res graphics screen. So to get the shape of the mountain drawn to the screen you have to draw each of the two bytes side by side and 16 rows deep. This is done 200 times to eventually create the entire world map section of the screen.
This is probably the coolest part of the Ultima game because once you realize how to create shapes/graphic tiles; you can make any type of shape you want just by following the example above. This is how Richard created all the cool objects in the later Ultima’s, he used the 14x16 bits process and came up with some really cool shapes. It is really only limited to your imagination and the 14x16 grid! Remember that you are not limited to one shape, you could make an object that is comprised of 2 shapes or 4 shapes or even an entire grid of shapes, the sky is the limit!
I will be going through the subroutine SHAPE/TILE GRAPHICS line-by-line and explaining what each line of code is doing and how it affects the outcome of the program.
753 **********************************
This is just a comment line to separate each subroutine and helps to define the start of the subroutine.
754 ****** SHIP TILE ****************
Line 754 is a comment line which tells the user that the SHIP TILE shape data will be referenced below.
755 SHAPE1 DFB $00,$00,$40,$00,$40,$07,$40,$03,$40,$00,
$44,$09,$4C,$1B,$5C,$3B,$5C,$3B,$4C,$19,$44,$08,$7E,$7F,$6F,$36,$7E,$1F,$7C,$0F,$00,$00
Line 755 is used to “[D]e[F]ine [B]ype” of SHAPE1 data. Each SHAPE is defined by 14 bits wide and 16 bits deep, which give it a distinct shape style. This gives a shape/graphic tile a two byte wide appearance. Each byte is referenced one after the other and when read from data it will read each shape in two byte increments or 16 times. Since four bytes make up a shape then a loop will be used to read all 32 lines of the two bytes.
Also, line 755 has a header titled SHAPE1, which is referenced from the SHPADR data subroutine and is defined by the two HI and LOW bytes for the location where SHAPE1 will reside and start its shape table in memory.
756 ****** RAFT TILE ****************
Line 756 is a comment line which tells the user that the RAFT TILE shape data will be referenced below.
757 SHAPE2 DFB $00,$00,$00,$00,$40,$00,$40,$01,$40,$03,
$40,$06,$40,$04,$40,$04,$40,$06,$40,$03,$40,$01,$40,$00,$7C,$1F,$78,$3F,$00,$00,$00,$00
Line 757 is used to “[D]e[F]ine [B]ype” of SHAPE2 data. Each SHAPE is defined by 14 bits wide and 16 bits deep. This gives a shape/graphic tile a two byte wide appearance. Each byte is referenced one after the other and when read from data it will read each shape in two byte increments or 16 times. Since four bytes make up a shape then a loop will be used to read all 32 lines of the two bytes.
Also, line 757 has a header titled SHAPE2, which is referenced from the SHPADR data subroutine and is defined by the two HI and LOW bytes for the location where SHAPE2 will reside and start its shape table in memory.
758 ****** PLAINS TILE ****************
Line 758 is a comment line which tells the user that the PLAINS TILE shape data will be referenced below.
759 SHAPE3 DFB $00,$00,$02,$00,$00,$04,$02,$00,$00,$00,
$08,$00,$00,$10,$00,$00,$00,$00,$20,$00,$00,$10,$00,$01,$00,$00,$00,$00,$00,$04,$08,$00
Line 759 is used to “[D]e[F]ine [B]ype” of SHAPE3 data. Each SHAPE is defined by 14 bits wide and 16 bits deep. This gives a shape/graphic tile a two byte wide appearance. Each byte is referenced one after the other and when read from data it will read each shape in two byte increments or 16 times. Since four bytes make up a shape then a loop will be used to read all 32 lines of the two bytes.
760 ****** TREES TILE ****************
Line 760 is a comment line which tells the user that the TREES TILE shape data will be referenced below.
761 SHAPE4 DFB $28,$00,$2A,$01,$2A,$01,$2A,$01,$28,
$00,$00,$14,$00,$55,$00,$55,$00,$55,$00,$14,$28,$00,$2A,$01,$2A,$01,$2A,$01,$28,$00,$00,$00
Line 761 is used to “[D]e[F]ine [B]ype” of SHAPE4 data.
762 ****** CASTLE TILE ****************
Line 762 is a comment line which tells the user that the CASTLE TILE shape data will be referenced below.
763 SHAPE5 DFB $03,$60,$7F,$7F,$7E,3F,$06,$30,$06,
$30,$06,$30,$06,$30,$06,$30,$06,$30,$06,$30,$06,$30,$06,$30,$06,$30,$3E,$3E,$3F,$7E,$03,$60
Line 763 is used to “[D]e[F]ine [B]ype” of SHAPE5 data.
764 ****** TOWN TILE ****************
Line 764 is a comment line which tells the user that the TOWN TILE shape data will be referenced below.
765 SHAPE6 DFB $00,$00,$3E,$3E,$22,$22,$22,$22,$22,
$22,$22,$22,$7E,$3F,$20,$02,$20,$02,$7E,$3F,$22,$22,$22,$22,$22,$22,$22,$22,$3E,$3E,$00,$00
Line 765 is used to “[D]e[F]ine [B]ype” of SHAPE6 data.
766 ****** SIGNPOST TILE ****************
Line 766 is a comment line which tells the user that the SIGNPOST TILE shape data will be referenced below.
767 SHAPE7 DFB $00,$00,$40,$01,$40,$01,$78,$0F,$78,
$0F,$78,$0F,$78,$0F,$78,$0F,$78,$0F,$40,$01,$40,$01,$40,$01,$40,$01,$78,$1F,$7E,$7F,$00,$00
Line 767 is used to “[D]e[F]ine [B]ype” of SHAPE7 data.
768 ****** CHARACTER TILE ****************
Line 768 is a comment line which tells the user that the CHARACTER TILE shape data will be referenced below.
769 SHAPE8 DFB $00,$00,$60,$01,$60,$01,$60,$01,$40,
$00,$78,$07,$7C,$0F,$62,$11,$44,$08,$78,$07,$60,$01,$70,$03,$10,$02,$10,$02,$18,$06,$00,$00
Line 769 is used to “[D]e[F]ine [B]ype” of SHAPE8 data.
770 ****** TROLL TILE ****************
Line 770 is a comment line which tells the user that the TROLL TILE shape data will be referenced below.
771 SHAPE9 DFB $00,$00,$10,$04,$70,$07,$60,$03,$40,
$01,$78,$0F,$7C,$1F,$66,$33,$66,$33,$7E,$3F,$30,$06,$30,$06,$30,$06,$30,$06,$38,$0E,$00,$00
Line 771 is used to “[D]e[F]ine [B]ype” of SHAPE9 data.
772 ****** DUNGEON TILE ****************
Line 772 is a comment line which tells the user that the DUNGEON TILE shape data will be referenced below.
773 SHAPE10 DFB $08,$04,$1F,$0E,$62,$71,$41,$20,$20,
$40,$10,$00,$08,$41,$46,$23,$03,$10,$64,$03,$30,$76,$17,$24,$12,$14,$1C,$1C,$10,$04,$10,$04
Line 773 is used to “[D]e[F]ine [B]ype” of SHAPE10 data.
774 ****** CART TILE ****************
Line 774 is a comment line which tells the user that the CART TILE shape data will be referenced below.
775 SHAPE11 DFB $00,$00,$00,$00,$00,$00,$00,$00,$00,
$00,$03,$00,$0E,$00,$78,$7F,$78,$7F,$78,$78,$30,$70,$20,$12,$20,$10,$40,$08,$00,$07,$00,$00
Line 775 is used to “[D]e[F]ine [B]ype” of SHAPE11 data.
776 ****** HORSE TILE ****************
Line 776 is a comment line which tells the user that the HORSE TILE shape data will be referenced below.
777 SHAPE12 DFB $00,$00,$00,$00,$00,$00,$00,$00,$0C,
$00,$1E,$00,$3F,$00,$7C,$3F,$70,$7F,$78,$7F,$78,$3F,$1C,$7C,$12,$48,$12,$48,$08,$24,$00,$00
Line 777 is used to “[D]e[F]ine [B]ype” of SHAPE12 data.
778 ****** SPEEDER TILE ****************
Line 778 is a comment line which tells the user that the SPEEDER TILE shape data will be referenced below.
779 SHAPE13 DFB $00,$00,$00,$00,$00,$00,$00,$00,$00,
$00,$00,$00,$00,$00,$3F,$00,$18,$00,$7C,$0C,$7E,$3F,$7E,$3F,$00,$00,$00,$00,$00,$00,$00,$00
Line 779 is used to “[D]e[F]ine [B]ype” of SHAPE13 data.
780 ****** SPACE TILE ****************
Line 780 is a comment line which tells the user that the SPACE TILE shape data will be referenced below.
781 SHAPE14 DFB $40,$00,$60,$01,$10,$02,$70,$03,$70,
$03,$70,$03,$70,$03,$70,$03,$70,$03,$78,$07,$78,$07,$7C,$0F,$7E,$1F,$7F,$3F,$7F,$3F,$70,$03
Line 781 is used to “[D]e[F]ine [B]ype” of SHAPE14 data.
782 ****** OCEAN TILE ****************
Line 782 is a comment line which tells the user that the OCEAN TILE shape data will be referenced below.
783 SHAPE15 DFB $80,$8A,$80,$A0,$85,$80,$D0,$80,$80,
$8A,$80,$A0,$85,$80,$D0,$80,$80,$8A,$80,$A0,$85,$80,$D0,$80,$80,$8A,$80,$A0,$85,$80,$D0,$80
Line 783 is used to “[D]e[F]ine [B]ype” of SHAPE15 data.
784 ****** MOUNTAIN TILE ****************
Line 784 is a comment line which tells the user that the MOUNTAIN TILE shape data will be referenced below.
785 SHAPE16 DFB $08,$04,$1F,$0E,$62,$71,$41,$20,$20,
$40,$10,$00,$08,$41,$46,$23,$23,$1C,$1C,$08,$08,$07,$07,$20,$02,$10,$44,$08,$78,$07,$10,$02
Line 785 is used to “[D]e[F]ine [B]ype” of SHAPE16 data.
These are all the shapes/graphic tiles represented on the world map. There are more shapes in Ultima 1 but they represent the monsters and are generated from a different binary file.
As always, if you have any questions please email me
Joe “Kingspud”
-
TUTORIAL #20 – SHPADR “Is used as a pointer for the SHAPE/TILE GRAPHICS used on the world map”.
All the graphic-tiles/shapes in Ultima 1 are predefined within a database SHPADR. These values consist of the type of shape used such as TREES, PLAINS, MOUNTAINS, OCEAN, etc… They are structured and referenced exactly as the MAPADR data each shape on the map is defined by a value from 0 to 15. This value is what represent a particular shape such as the fighter or the troll.
I will be going through the subroutine SHPADR line-by-line and explaining what each line of code is doing and how it affects the outcome of the program.
719 **********************************
This is just a comment line to separate each subroutine and helps to define the start of the subroutine.
720 * LOAD SHAPE ADDRESSES INTO SHPADR, LOW BYTE FIRST
This comment line tells the user what type of data will be referenced.
721 SHPADR DFB >SHAPE1
Line 721 is used to “[D]e[F]ine [B]ype” of SHAPE1 data location from the LOW byte side. Each SHAPE location is defined by a HIGH and LOW byte, which in this case is the > character representing the LOW byte location for the map addresses in MAP1. An example of a memory region address from the HIGH and LOW byte reference could be HEX $8000 or 32768. The HIGH side would be the 80 and the LOW side would be the 00 of the HEX value $8000.
Also, line 721 has a header titled SHPADR, which allows it to be called as a separate subroutine from the main subroutine.
722 DFB <SHAPE1
Line 722 is used to “[D]e[F]ine [B]ype” of MAP1 data location from the HIGH byte side. Each MAP location is defined by a HIGH and LOW byte, which in this case is the < character representing the HIGH byte location for the map addresses in SHAPE1. SHAPE1 will call to a database that will hold all the graphic tile types for a space on the horizontal line of the world map. By using a HIGH and LOW byte reference the map address is location in a memory region based on the byte reference and can be called to reference the necessary data of that map line.
723 DFB >SHAPE2
THRU
752 DFB <SHAPE16
Line 723 THRU 752 are all reference the same way with “[D]e[F]ine [B]ype” of SHAPE# data location. Each MAP location is defined by a HIGH and LOW byte will be referenced the exact same way and hold all the world map data information to help draw out the entire Ultima World map.
These are the following shape/graphic tile reference values and their equivalent shape.
SHAPE1 = SHIP
SHAPE2 = RAFT
SHAPE3 = PLAINS
SHAPE4 = TREES
SHAPE5 = CASTLE
SHAPE6 = TOWN
SHAPE7 = SIGNPOST
SHAPE8 = CHARACTER
SHAPE9 = TROLL
SHAPE10 = DUNGEON
SHAPE11 = CART
SHAPE12 = HORSE
SHAPE13 = SPEEDER
SHAPE14 = SPACE SHIP
SHAPE15 = OCEAN
SHAPE16 = MOUNTAIN
Please email me any questions you might have,
Joe “kingspud”
-
TUTORIAL #19 – MAPADR “Is used as a pointer to the World Map data points for all the graphic tile reference values”.
All the graphic-tiles/shapes in Ultima 1 are predefined within a database. These values consist of the type of shape used such as TREES, PLAINS, MOUNTAINS, OCEAN, etc… plus the amount of each type of shape within the world map. The world map is made up of 82 horizontal lines of graphic tiles; these tiles are drawn on the screen one at a time, line by line and byte by byte. The data has to be read from the MAP data file statement and uncompressed to a form that states the type and amount and then draws just a portion of the world map that is 20 tiles wide by 10 tiles deep.
I will be going through the subroutine MAPADR line-by-line and explaining what each line of code is doing and how it affects the outcome of the program.
553 **********************************
This is just a comment line to separate each subroutine and helps to define the start of the subroutine.
554 * LOAD MAP ADDRESS D
This comment line tells the user what type of data will be referenced.
555 MAPADR DFB >MAP1
Line 555 is used to “[D]e[F]ine [B]ype” of MAP1 data location from the LOW byte side. Each MAP location is defined by a HIGH and LOW byte, which in this case is the > character representing the LOW byte location for the map addresses in MAP1. An example of a memory region address from the HIGH and LOW byte reference could be HEX $8000 or 32768. The HIGH side would be the 80 and the LOW side would be the 00 of the HEX value $8000.
Also, line 555 has a header titled MAPADR, which allows it to be called as a separate subroutine from the main subroutine.
556 DFB <MAP1
Line 556 is used to “[D]e[F]ine [B]ype” of MAP1 data location from the HIGH byte side. Each MAP location is defined by a HIGH and LOW byte, which in this case is the < character representing the HIGH byte location for the map addresses in MAP1. MAP1 will call to a database that will hold all the graphic tile types and amounts for the first horizontal line of the world map. By using a HIGH and LOW byte reference the map address is location in a memory region based on the byte reference and can be called to reference the necessary data of that map line.
557 DFB >MAP2
THRU
718 DFB <MAP82
Line 557 THRU 718 are all reference the same way with “[D]e[F]ine [B]ype” of MAP# data location. Each MAP location is defined by a HIGH and LOW byte will be referenced the exact same way and hold all the world map data information to help draw out the entire Ultima World map.
Joe “kingspud”


![TUTORIAL #20 – SHPADR “Is used as a pointer for the SHAPE/TILE GRAPHICS used on the world map”.
All the graphic-tiles/shapes in Ultima 1 are predefined within a database SHPADR. These values consist of the type of shape used such as TREES, PLAINS, MOUNTAINS, OCEAN, etc… They are structured and referenced exactly as the MAPADR data each shape on the map is defined by a value from 0 to 15. This value is what represent a particular shape such as the fighter or the troll.
I will be going through the subroutine SHPADR line-by-line and explaining what each line of code is doing and how it affects the outcome of the program.
719 **********************************
This is just a comment line to separate each subroutine and helps to define the start of the subroutine.
720 * LOAD SHAPE ADDRESSES INTO SHPADR, LOW BYTE FIRST
This comment line tells the user what type of data will be referenced.
721 SHPADR DFB >SHAPE1
Line 721 is used to “[D]e[F]ine [B]ype” of SHAPE1 data location from the LOW byte side. Each SHAPE location is defined by a HIGH and LOW byte, which in this case is the > character representing the LOW byte location for the map addresses in MAP1. An example of a memory region address from the HIGH and LOW byte reference could be HEX $8000 or 32768. The HIGH side would be the 80 and the LOW side would be the 00 of the HEX value $8000.
Also, line 721 has a header titled SHPADR, which allows it to be called as a separate subroutine from the main subroutine.
722 DFB <SHAPE1
Line 722 is used to “[D]e[F]ine [B]ype” of MAP1 data location from the HIGH byte side. Each MAP location is defined by a HIGH and LOW byte, which in this case is the < character representing the HIGH byte location for the map addresses in SHAPE1. SHAPE1 will call to a database that will hold all the graphic tile types for a space on the horizontal line of the world map. By using a HIGH and LOW byte reference the map address is location in a memory region based on the byte reference and can be called to reference the necessary data of that map line.
723 DFB >SHAPE2
THRU
752 DFB <SHAPE16
Line 723 THRU 752 are all reference the same way with “[D]e[F]ine [B]ype” of SHAPE# data location. Each MAP location is defined by a HIGH and LOW byte will be referenced the exact same way and hold all the world map data information to help draw out the entire Ultima World map.
These are the following shape/graphic tile reference values and their equivalent shape.
SHAPE1  = SHIP
SHAPE2  = RAFT
SHAPE3  = PLAINS
SHAPE4  = TREES
SHAPE5  = CASTLE
SHAPE6  = TOWN
SHAPE7  = SIGNPOST
SHAPE8  = CHARACTER
SHAPE9  = TROLL
SHAPE10  = DUNGEON
SHAPE11  = CART
SHAPE12  = HORSE
SHAPE13  = SPEEDER
SHAPE14  = SPACE SHIP
SHAPE15  = OCEAN
SHAPE16  = MOUNTAIN
Please email me any questions you might have,
Ultima_revisited@yahoo.com
Joe “kingspud”](http://24.media.tumblr.com/tumblr_lwxfb59kqw1qjrzteo1_500.jpg)