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.
Joe “kingspud”
No comments:
Post a Comment