Saturday, June 21, 2025

TUTORIAL #15 – MVRHT

 TUTORIAL #15 – MVRHT “Is used to move the main character to the RIGHT 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… MVRHT 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 MVRHT subroutine.

 

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

 

378  **********************************

 

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

 

379  ***** MOVE RIGHT ****************

 

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

 

 

380  *

 

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

 

381  MVRHT                LDA   CHAR

 

Line 381 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 381 has a header titled MVRHT, which allows it to be called as a separate subroutine from the main BASIC PROGRAM; “ULTIMA”. 

 

382                                CMP  #$0B ;HORSE

 

Once the value of CHAR is loaded into register A, Line 382 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.

 

383                                BEQ JUMPY2

 

Line 383 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 JUMPY2.   JUMPY2 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 384.

 

384                                CMP  #$00 ;SHIP

 

Line 384 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.

 

385                                BEQ JUMPY

 

Line 385 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 JUMPY.    JUMPY 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 386.

 

386                                CMP  #$01 ;RAFT

 

Line 386 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.

 

 

387                                BEQ JUMPY

 

Line 387 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.   JUMPY 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 388.

 

388                                CMP  #$0A  ;CART

 

Line 388 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.

 

 

389                                BEQ JUMPY2

 

Line 389 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 JUMPY2.   JUMPY2 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 390.

 

390                                CMP  #$0C  ;LANDSPR

 

Line 390 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 LANDSPR shape.

 

 

391                                BEQ JUMPY1

 

Line 391 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.   JUMPY1 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 392.

 

 

392                                CMP  #$07  ;PLAYER

 

Line 392 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 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.

 

 

393                                BEQ JUMPY2

 

Line 393 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 JUMPY2.   JUMPY2 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 394.

 

394                                RTS

 

Line 394 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 MVRHT will be complete and return to the original line statement that called it. 

 

395  JUMPY                  LDX  #$6F

 

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

 

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

 

396                                LDA   MAPSTORE,X

 

Line 396 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.

 

397                                CMP  #$0E

 

Line 397 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.

 

398                                BEQ JUMPY3

 

Line 398 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 JUMPY3.   JUMPY3 is the actual part of the MVRHT 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 399.

 

399                                RTS

 

Line 399 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.

 

400  JUMPY1                LDX  #$6F

 

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

 

Also, line 400 has a header titled JUMPY1, which allows it to be called as a separate SUB-subroutine from the MVRHT subroutine”.  The JUMPY 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.

 

401                                LDA   MAPSTORE,X

 

Line 401 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.

 

402                                CMP  #$0F

 

Line 402 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.

 

403                                BEQ RHCNT

 

Line 403 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 RHCNT.   RHCNT is the direct call to the return statement, which says there was a collision and the subroutine is returning back to the main subroutine. 

 

404                                CMP  #$03

 

Line 404 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.

 

405                                BEQ RHCNT

 

Line 405 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 RHCNT.   RHCNT is the direct call to the return statement, which says there was a collision and the subroutine is returning back to the main subroutine. 

 

406                                JMP JUMPY3

 

Line 406 tells the program to “[J]u[MP]” to the subroutine JUMPY3.    JUMPY3 is the actual part of the MVRHT 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.

 

407  JUMPY2                LDX  #$6F

 

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

 

408                                LDA   MAPSTORE,X

 

Line 408 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.

 

409                                CMP  #$0E

 

Line 409 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.

 

410                                BEQ RHCNT

 

Line 410 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 RHCNT.   RHCNT is the direct call to the return statement, which says there was a collision and the subroutine is returning back to the main subroutine. 

 

411                                CMP  #$0F

 

Line 411 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.

 

412                                BEQ RHCNT

 

Line 412 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 RHCNT.   RHCNT is the direct call to the return statement, which says there was a collision and the subroutine is returning back to the main subroutine. 

 

413  JUMPY3               JSR    CLRSET

 

Line 413 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 413 also has a header name JUMPY3 so it can also be referenced and can be called to run within the MVRHT subroutine.  Sub-subroutine JUMPY3 is used to update the variables that define the new column value.  Since this is the move RIGHT subroutine, we are only worried about the column and not the row values.   The ROW variable is for UP and DOWN movement.

 

414                                LDA   ROW

 

Line 414 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.

 

415                                STA   ROWNO

 

Line 415 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.

 

416                                INC   COLUMN

 

Line 416 is used to “[INC]rement” whatever value is in COLUMN by 1! 

 

417                                INC   COLMADD

 

Line 417 is used to “[INC]rement” whatever value is in COLMADD by 1! 

 

418                                LDA   COLUMN

 

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

 

419                                STA   COLUMN1

 

Line 419 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.

 

 

420                                JSR    START8

 

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

 

421                                INC   $FB

 

Line 421 is used to “[INC]rement” the value held within memory location $FB by 1! 

 

422  RHCNT                  RTS

 

Line 422 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 MVRHT will be complete and return to the original line statement that called it. 

 

Also, line 422 has a header titled RHCNT, which allows it to be called as a separate sub-subroutine from the MVRHT subroutine.

 

After the MVRHT 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 right arrow key and wanted to move your character to the RIGHT 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 JUMPY3 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.

 

Joe “kingspud”

 

 

No comments:

Post a Comment