Showing posts with label code apple IIe. Show all posts
Showing posts with label code apple IIe. Show all posts

Saturday, June 21, 2025

TUTORIAL #23 – HIGH side

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 #20 – SHPADR

 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”

 

 

TUTORIAL #19 – MAPADR

 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.

 

 

 

 

 



TUTORIAL #16 – MVLFT

 TUTORIAL #16 – MVLFT “Is used to move the main character to the LEFT on a key press, plus follow all collision detection requirements per character shape used”. 


All the movement within Ultima 1 is based on “key press” functions because this game was created way before the mouse!  In the original Ultima 1 you have four keys representing the North, South, East, and West movement, which consisted of the following keys:  [ENTER],[ /], [ ; ] ,  [’ ].  Based on the represented shape on the screen ie. Fighter, horse, cart, etc… MVLFT will also perform the required collision detections of the specific terrain on the screen based on the type of shape used.  Each shape has a different type of collision detection so for example; the horse can travel over plains, trees, but not ocean or mountains.  The ship and raft can travel over ocean tiles but not any other tiles.  The land speeder can travel over plains but not trees or mountains.  Etc…  These types of collision detections are performed within the MVLFT subroutine.

 

I will be going through the subroutine MVLFT line-by-line and explaining what each line of code is doing and how it affects the outcome of the program.

 

423  ***** MOVE LEFT ****************

 

This is just a comment line to separate each subroutine and helps to define the start of the MOVE LEFT subroutine. 

 

 

424  *

 

This is just a comment line for use as a line spacer.

 

425  MVLFT                  LDA   CHAR

 

Line 425 is used to “[L]oa[D] register [A]” or register A with the value in the variable CHAR!  So, you are setting the register A to equal the value which was initial setup in the subroutine INITIAL.  As the transportation mode changes so does the CHAR value.  So when a numeric key from 1 thru 6 is pressed the value of CHAR get updated and modified.  

 

Also, line 425 has a header titled MVLFT, which allows it to be called as a separate subroutine from the main BASIC PROGRAM; “ULTIMA”. 

 

426                                CMP  #$0B ;HORSE

 

Once the value of CHAR is loaded into register A, Line 426 is used to “[C]o[MP]are” what is in register A to the HEX value #$0B or decimal value of 11!  The value in CHAR is the number representing the shape/tile graphic for the main character shown on the computer screen.  Each character or graphic tile has a numeric value constant with the shape in the shape database.  So as CHAR changes it stores a new value of the main character shape/graphic tile such as fighter, horse, cart, ship, etc...  The [ ; ] symbol is a remark symbol that tell the compiler to ignore everything after the ;.  The HORSE reference tells anyone reading the code that #$0B is a value that represents the HORSE shape.

 

427                                BEQ BUMPY2

 

Line 427 is used to “[B]ranch on Result Zero Z[=]1”, which means that if the value in register A is compared to #$0B and it equals this value, in this case 11, then the program will branch or call jump to subroutine BUMPY2.   BUMPY2 is the collision detection part of the subroutine for the HORSE, which decides if it collides with specific terrain types and if the collision is legal.  Otherwise the program moves on to the next code line 428.

 

428                                CMP  #$00 ;SHIP

 

Line 428 is used to “[C]o[MP]are” what is in register A to the HEX value $00 or the decimal value of 0!  The value in CHAR will represent the shape/tile graphic for the SHIP in the middle of the screen.  The [ ; ] symbol is a remark symbol that tell the compiler to ignore everything after the ;.  The SHIP reference tells anyone reading the code that #$00 is a value that represents the SHIP shape.

 

429                                BEQ BUMPY

 

Line 429 is used to “[B]ranch on Result Zero Z=1”, which means that if the value in register A is compared to #$00 and it equals this value, in this case 0, then the program will branch or call jump to subroutine BUMPY.    BUMPY is the collision detection part of the subroutine for the SHIP, which decides if it collides with specific terrain types and if the collision is legal.  Otherwise the program moves on to the next code line 430.

 

430                                CMP  #$01 ;RAFT

 

Line 430 is used to “[C]o[MP]are” what is in register A to the HEX value $01 or the decimal value of 1!  The value in CHAR will represent the shape/tile graphic for the RAFT in the middle of the screen.  The [ ; ] symbol is a remark symbol that tell the compiler to ignore everything after the ;.  The RAFT reference tells anyone reading the code that #$01 is a value that represents the RAFT shape.

 

 

431                                BEQ BUMPY

 

Line 431 is used to “[B]ranch on Result Zero Z=1”, which means that if the value in register A is compared to #$01 and it equals this value, in this case 1, then the program will branch or call jump to subroutine RAFT1.   BUMPY is also the collision detection part of the subroutine for the RAFT, which decides if it collides with specific terrain types and if the collision is legal.  Otherwise the program moves on to the next code line 432.

 

432                                CMP  #$0A  ;CART

 

Line 432 is used to “[C]o[MP]are” what is in register A to the HEX value $0A or the decimal value of 10!  The value in CHAR will represent the shape/tile graphic for the CART in the middle of the screen.  The [ ; ] symbol is a remark symbol that tell the compiler to ignore everything after the ;.  The CART reference tells anyone reading the code that #$0A is a value that represents the CART shape.

 

 

433                                BEQ BUMPY2

 

Line 433 is used to “[B]ranch on Result Zero Z[=]1”, which means that if the value in register A is compared to #$0A and it equals this value, in this case 10, then the program will branch or call jump to subroutine BUMPY2.   BUMPY2 is the collision detection part of the subroutine for the CART, which decides if it collides with specific terrain types and if the collision is legal.  Otherwise the program moves on to the next code line 434.

 

434                                CMP  #$0C  ;SPEEDER

 

Line 434 is used to “[C]o[MP]are” what is in register A to the HEX value $0C or the decimal value of 12!  The value in CHAR will represent the shape/tile graphic for the LAND SPEEDER in the middle of the screen.  The [ ; ] symbol is a remark symbol that tell the compiler to ignore everything after the ;.  The LAND SPEEDER reference tells anyone reading the code that #$0C is a value that represents the SPEEDER shape.

 

 

435                                BEQ BUMPY1

 

Line 435 is used to “[B]ranch on Result Zero Z=1”, which means that if the value in register A is compared to #$0C and it equals this value, in this case 12, then the program will branch or call jump to subroutine LANDSPR.   BUMPY1 is the collision detection part of the subroutine for the LANDSPR, which decides if it collides with specific terrain types and if the collision is legal.  Otherwise the program moves on to the next code line 436.

 

 

436                                CMP  #$07  ;PLAYER

 

Line 436 is used to “[C]o[MP]are” what is in register A to the HEX value $07 or the decimal value of 7!  The value in CHAR will represent the shape/tile graphic for the main FIGHTER character in the middle of the screen.  The [ ; ] symbol is a remark symbol that tell the compiler to ignore everything after the ;.  The PLAYER reference tells anyone reading the code that #$07 is a value that represents the PLAYER shape.

 

 

437                                BEQ BUMPY2

 

Line 437 is used to “[B]ranch on Result Zero Z[=]1”, which means that if the value in register A is compared to #$07 and it equals this value, in this case 7, then the program will branch or call jump to subroutine BUMPY2.   BUMPY2 is also the collision detection part of the subroutine for the PLAYER, which decides if it collides with specific terrain types and if the collision is legal.  Otherwise the program moves on to the next code line 438.

 

438                                RTS

 

Line 438 is used to “[R]e[T]urn from [S]ubroutine”, which means that after the SUB-subroutine of each character tile shape reference is called and updated, it returns back and then subroutine MVLFT will be complete and return to the original line statement that called it. 

 

439  BUMPY                 LDX  #$6D

 

Line 439 is used to “[L]oa[D] register [X]” or register X with the value equal to 109!  So, you are setting the value of X to equal the HEX value of $6D, which equals decimal value of 109.  NOTE: $6D is equal to the value of the square to the left of the main character on the screen.  So when you see $6D is it talking about one of four squares surrounding the main character on the screen.  Each of the movement subroutines does this check to the corresponding square next to the character tile on the screen.

 

Also, line 439 has a header titled BUMPY, which allows it to be called as a separate SUB-subroutine from the MVLFT subroutine”.  The BUMPY subroutine is used to check the collision detection parameters for the SHIP and the RAFT, which only allows OCEAN movement.

 

440                                LDA   MAPSTORE,X

 

Line 440 is used to “[L]oa[D] register [A]” or register A with the value in the array MAPSTORE,X and stored it in register A.

 

441                                CMP  #$0E

 

Line 441 is used to “[C]o[MP]are” what is in register A to the HEX value $0E or the decimal value of 14!  This value is what is equal to the OCEAN graphic tile/shape and if the comparison matches then it is a valid movement and continues with the redraw of the screen.  If the comparison does not match then it is a collision and the subroutine returns back to the main subroutine.

 

442                                BEQ BUMPY3

 

Line 442 is used to “[B]ranch on Result Zero Z[=]1”, which means that if the value in register A is compared to #$0E and it equals this value, in this case 14, then the program will branch or call jump to subroutine BUMPY3.   BUMPY3 is the actual part of the MVLFT subroutine that when called has passed all the collision detection and draws the new screen display of the new location for the character shape on the world map.  Otherwise the program moves on to the next code line 443.

 

443                                RTS

 

Line 443 is used to “[R]e[T]urn from [S]ubroutine”, which means that the collision detection did not pass for the movement direction so the subroutine is returned and awaits another movement command.

 

444  BUMPY1               LDX  #$6D

 

Line 444 is used to “[L]oa[D] register [X]” or register X with the value equal to 110!  So, you are setting the value of X to equal the HEX value of $6D, which equals decimal value of 110.

 

Also, line 444 has a header titled BUMPY1, which allows it to be called as a separate SUB-subroutine from the MVLFT subroutine”.  The BUMPY subroutine is used to check the collision detection parameters for the LAND SPEEDER, which allows for OCEAN and PLAIN movement but not through the TREES or MOUNTAINS.

 

445                                LDA   MAPSTORE,X

 

Line 445 is used to “[L]oa[D] register [A]” or register A with the value in the array MAPSTORE,X and stored it in register A.

 

446                                CMP  #$0F

 

Line 446 is used to “[C]o[MP]are” what is in register A to the HEX value $0F or the decimal value of 15!  The value of 15 is equal to the MOUNTAIN graphic tile and this is a collision check to see if the move will cause the character to move on top of the MOUNTAIN shape on the world map.

 

447                                BEQ LFCNT

 

Line 447 is used to “[B]ranch on Result Zero Z[=]1”, which means that if the value in register A is compared to #$0F and it equals this value, in this case 15, then the program will branch or call jump to subroutine LFCNT.   LFCNT is the direct call to the return statement, which says there was a collision and the subroutine is returning back to the main subroutine. 

 

448                                CMP  #$03

 

Line 448 is used to “[C]o[MP]are” what is in register A to the HEX value $03 or the decimal value of 3!  The value 3 is equal to the graphic tile/shape of the TREE.

 

449                                BEQ LFCNT

 

Line 449 is used to “[B]ranch on Result Zero Z[=]1”, which means that if the value in register A is compared to #$03 and it equals this value, in this case 3, then the program will branch or call jump to subroutine LFCNT.   LFCNT is the direct call to the return statement, which says there was a collision and the subroutine is returning back to the main subroutine. 

 

450                                JMP BUMPY3

 

Line 450 tells the program to “[J]u[MP]” to the subroutine BUMPY3.    BUMPY3 is the actual part of the MVLFT subroutine that when called has passed all the collision detection and draws the new screen display of the new location for the character shape on the world map.

 

451  BUMPY2               LDX  #$6D

 

Line 451 is used to “[L]oa[D] register [X]” or register X with the value equal to 110!  So, you are setting the value of X to equal the HEX value of $6D, which equals decimal value of 110.

 

452                                LDA   MAPSTORE,X

 

Line 452 is used to “[L]oa[D] register [A]” or register A with the value in the array MAPSTORE,X and stored it in register A.

 

453                                CMP  #$0E

 

Line 453 is used to “[C]o[MP]are” what is in register A to the HEX value $0E or the decimal value of 14!  The value 14 is equal to the graphic tile/shape of the OCEAN.

 

454                               BEQ LFCNT

 

Line 454 is used to “[B]ranch on Result Zero Z[=]1”, which means that if the value in register A is compared to #$14 and it equals this value, in this case 14, then the program will branch or call jump to subroutine LFCNT.   LFCNT is the direct call to the return statement, which says there was a collision and the subroutine is returning back to the main subroutine. 

 

455                                CMP  #$0F

 

Line 455 is used to “[C]o[MP]are” what is in register A to the HEX value $0F or the decimal value of 15!  The value 15 is equal to the graphic tile/shape of the MOUNTAIN.

 

456                                BEQ LFCNT

 

Line 456 is used to “[B]ranch on Result Zero Z[=]1”, which means that if the value in register A is compared to #$15 and it equals this value, in this case 15, then the program will branch or call jump to subroutine LFCNT.   LFCNT is the direct call to the return statement, which says there was a collision and the subroutine is returning back to the main subroutine. 

 

457  BUMPY3              JSR    CLRSET

 

Line 457 tells the program to “[J]ump to the [S]ub[R]outine” with the header CLRSET.   The subroutine CLRSET takes the specific variables used within the DRAW subroutine and clears them to zero when the screen is redrawn for the character movement.

 

Line 457 also has a header name BUMPY3 so it can also be referenced and can be called to run within the MVLFT subroutine.  Sub-subroutine BUMPY3 is used to update the variables that define the new column value.  Since this is the move LEFT subroutine, we are only worried about the column and not the row values.   The ROW variable is for UP and DOWN movement.

 

458                                LDA   ROW

 

Line 458 is used to “[L]oa[D] the [A]ccumulator” or register A with the value held in ROW.  We won’t be changing this value but we do need it for reference where the screen will start drawing form.

 

459                                STA   ROWNO

 

Line 459 is used to “[ST]ore the [A]ccumulator” which will be the value obtained from the variable ROW.  This will now be used as a temporary ROW variable that can be modified without disturbing the original ROW value.

 

460                                DEC   COLUMN

 

Line 460 is used to “[DEC]rement” whatever value is in COLUMN and subtract 1 from it! 

 

461                                DEC   COLMADD

 

Line 461 is used to “[DEC]rement” whatever value is in COLMADD and subtract 1 from it! 

 

462                                LDA   COLUMN

 

Line 462 is used to “[L]oa[D] the [A]ccumulator” or register A with the value from COLUMN after it has been decremented in line 461. 

 

463                                STA   COLUMN1

 

Line 463 is used to “[ST]ore the [A]ccumulator” which has the value obtained from COLUMN.  COLUMN1 will now be used as a temporary COLUMN variable that can be modified without disturbing the original COLUMN value.

 

 

464                                JSR    START8

 

Line 464 tells the program to “[J]ump to the [S]ub[R]outine” with the header START8.   The subroutine START8 is where the process of redrawing the screen takes place after the movement process has occurred.

 

465                                DEC   $FB

 

Line 465 is used to “[DEC]rement” the value held within memory location $FB and subtract 1 from it! 

 

467  LFCNT                   RTS

 

Line 467 is used to “[R]e[T]urn from [S]ubroutine”, which means that after the SUB-subroutine of each character tile shape reference is called and updated, it returns back to here and then subroutine MVLFT will be complete and return to the original line statement that called it. 

 

Also, line 467 has a header titled LFCNT, which allows it to be called as a separate sub-subroutine from the MVLFT subroutine.

 

After the MVLFT subroutine completes you should have accomplished the following:

 

Depending on what type of shape/graphic tile you had as your main character shape, you will have pressed the left arrow key and wanted to move your character to the LEFT one space on the world map.  To be able to do this the subroutine will check what type of character shape is being used, then check to see if the terrain you are about to move into is non-collision type terrain.  The subroutine check the value of the terrain shape against the legal movement values and if it is ok it continue on to the Sub-subroutine BUMPY3 that modifies the variable and returns out of the subroutine getting ready to draw the new world map screen display.  If there is a collision detected against a terrain type that is not legal, then the subroutine just returns out of the main subroutine and waits for a new movement key press.

 

As always, please email me any questions you might have.

 

Ultima_revisited@yahoo.com

 

Joe “kingspud”