TUTORIAL #13 – LOADSHP “Is used to store each of the 10
graphic tile/shapes that will be displayed on the vertical column of the
display screen”
I will be going through the subroutine LOADSHP line-by-line and explaining what each line of code is doing
and how it affects the outcome of the program.
At this point you have stored all the shapes with the array
MAPSTORE and will now pull each shape reference number out at an increment of
20 to obtain each 20th shape on the column. These will be used to
store the two sets of bytes that make up the entire shape that will be drawn to
the screen.
324 ********************************
This is just a comment line to separate each subroutine and
helps to define the start of the LOADSHP subroutine.
325 LOADSHP LDA MAPCOUNT
Line 325 is used to “[L]oa[D] register [A]” with
the value held in MAPCOUNT. Right before
the subroutine LOADSHP is called, MAPCOUNT is set equal to zero through line 56-57. So, register A will have the value zero
placed in it.
Also, line 325 has a header titled LOADSHP, which allows it
to be called as a separate subroutine from the main program. This subroutine is a key part of the program
because it loads and stores the bytes of the 10 graphic tiles/shapes that are
displayed on the each line of the 160 horizontal lines that display a column of
shapes of the mapworld on the screen.
This subroutine will read each of the 32 lines that make up each
shape/tile graphic and store it temporarily which saves memory since we don’t have
to save all 200 tiles at one time. Once
the subroutine has stored all 10 shapes/tile graphics, it will move to the next
subroutine that writes the tiles to the screen.
326 STA TMAPCNT
Line 326 is used to “[ST]ore
the [A]ccumulator” or take the value that has
been stored in register A and place it in variable TMAPCNT, which in this case
equals 0! By setting TMAPCNT to 0 it
establishes can be used as a temp counter along with MAPCOUNT. This allows the original MAPCOUNT variable to
increment up as it is used to eventually load all 160 graphics lines that
represent all the shapes on the screen.
TMAPCNT can then be reset each time it goes though the 32 line loop of
each graphic tile/shape and this way MAPCOUNT can keep a running total. So, let’s say MAPCOUNT goes through a couple
of loops and is now equal to 64, TMAPCNT will have reset twice to those 32 line
increments and will continue to increment through each 32 line loop but will
start at the MAPCOUNT value that was left off.
This give a loop within a loop so to speak. The main loop with MAPCOUNT will increment up
to 160 and the TMAPCNT loop will loop 5 times at 32 line increments yet each
time TMAPCNT gets used it starts from 0 thru 32, then starts at 32 thru 64,
then 64 thru 96, then 96 thru 128, and finally 128 to 160! So you can see it was necessary to have a
temp counter loop along with the main counter of MAPCOUNT to keep track of each
32 line loop without resetting or a affecting the original MAPCOUNT variable.
327 LOADSP1 LDX MAPCOUNT
Line 327 is used to “[L]oa[D] register [X]” with
the value held in MAPCOUNT. So, register
X will now have the value that is held in MAPCOUNT, which in the beginning is
zero. The reason you MAPCOUNT is used with the X
register is because register A is being used and X will be used to call each 20th
shape from the MAPSTORE array out of the entire 200 shapes.
Also, line 327 has a header titled LOADSHP1, which allows it
to be called within the main LOADSHP subroutine since it will be used within
the main loop.
328 LDA MAPSTORE,X
Line 328 is used to “[L]oa[D] the [A]ccumulator”
or register A with the value held in array MAPSTORE,X! So, you will be setting the value of A to
equal each shape reference number from 0 to 199 in increments of 20 held within
array MAPSTORE.
329
ASL A
Line 329 is used to “[A]ccumulator
[S]hift [L]eft
one bit” which takes the binary value in register A and shifts in one bit to
the left. So, if register A equals HEX
34 or decimal 52, then the binary value equals 00110100, which is in the accumulator. Now you shift the binary value to the left by
one and you get 01101000, which equals HEX 68 or decimal 104.
330
TAX
Line 330 is used to “[T]ransfer
[A]ccumulator to index X”
which takes the value in register A and transfers it to register X. So, if register A equals HEX 34 or decimal
52, then register X will now equal HEX 34 or decimal 52.
331 LDA
SHPADR,X
Line 331 is used to “[L]oa[D] the [A]ccumulator”
or register A with the value equal to that held in array SHPADR,X! As
mentioned above, the SHAPE1 address is stored in a memory location for example
in HEX memory location $6800. When you load
A with the address from SHPADR,X you will get the 00 byte from the $6800
address and load it in register A.
332 STA LOW
Line 332 is used to “[ST]ore
the [A]ccumulator” or take the value that has
been stored in register A and place it in variable LOW, which in this case is equal to HEX
value $00. Again, LOW is a used to represents the low byte of the
memory address location where SHPADR 0 starts.
333 LDA SHPADR+1,X
Line 333 is used to “[L]oa[D] the [A]ccumulator”
or register A with the value equal to that held in array SHPADR+1,X! As
mentioned above, the SHAPE1 address is stored in a memory location for example
$6800. When you load A with the address
from SHPADR+1,X you will get the 68 byte from the $6800 address and load it in
register A.
334 STA HIGH
Line 334 is used to “[ST]ore
the [A]ccumulator” or take the value that has
been stored in register A and place it in variable HIGH, which in this case is equal to
HEX value $68. Again, HIGH is a used to represents the high byte of the
memory address location where SHPADR 1 starts.
335 LDX STEPPB
Line 335 is used to “[L]oa[D] register [X]” or register
X with the value equal to zero! So, you
are setting the value of X to equal the HEX value of $00, which equals decimal
value of 0
336 LDY #$00
Line 336 is used to “[L]oa[D] register [Y]” or
register Y with the value equal to one!
So, you are setting the value of Y to equal the HEX value of $01, which
equals decimal value of 1.
337
LOADSHP1 LDA (LOW),Y
Line 337 is used to “[L]oa[D] the [A]ccumulator”
or register A with the value in the array LOW from array location 0. Remember when we used Map Address 1 on line
841, well now we are using the format Shape address instead and it is setup
like an array with a starting memory location and all the bytes in the address
are stored within the array. So, as in
Tutorial #6 when we needed to retrieve the HEX value $0C, now we will get the
next number in the sequence since Y equals 0 we are going to retrieve the first
shape/tile graphics byte:
So a shape address example is:
800 SHAPE1 DFB $00,$00,$40,$00,$40,$07,$40,$03,$40,$00,$44,$09,$4C,$1B,$5C,$3B,$4C,$19,$44,$08,$7E,$7F,$6F,$36,$7E,$1F,$7C,$0F,$00,$00
Earlier in the blog I showed examples of how a shape is
created and how the bytes represent where each pixel will be displayed to
create the specific shape such as a horse, a knight, a ship, etc. With this Sub-subroutine we will be loading
all the bytes that make up the specific tile graphic/shape into two temporary
arrays. We need two sets of arrays
because each shape is two bytes wide and we will be drawing two bytes at a
time. So as each set of bytes are loaded into the TEMP arrays, they will be
drawn as two sets of bytes line by line on the screen in 32 lines.
Line 337 has a header titled LOADSHP1, which allows it to be
called again from a separate statement to be used as a loop. In this case the loop is used 32 times to
store each of the two sets of bytes which are each 16 bytes high, making for a
shape that is 2x2 or 32 lines deep.
338 STA TEMP,X
Line 338 is used to “[ST]ore
the [A]ccumulator” or take the value that has
been stored in register A and place it in variable TEMP,X, which in this example would
equal HEX value $00, the first HEX in this particular shapes database index.
800 SHAPE1 DFB $00,$00,$40,$00,$40,$07,$40,$03,$40,$00,$44,$09,$4C,$1B,$5C,$3B,$4C,$19,$44,$08,$7E,$7F,$6F,$36,$7E,$1F,$7C,$0F,$00,$00
339 INY
Line 339 is used to “[IN]crement
register [Y]” or take the value that has been
stored in register Y and add 1 to it.
340 LDA (LOW),Y
Line 340 is used to “[L]oa[D] the [A]ccumulator”
or register A with the next value in the array LOW from array location 1, since
it was just incremented. So, as in
Tutorial #6 when we needed to retrieve the HEX value $00, now we will get the
next number in the sequence since Y equals 1 we are going to retrieve the second
shape/tile graphics byte:
So the next shape address example is:
800 SHAPE1 DFB $00,$00,$40,$00,$40,$07,$40,$03,$40,$00,$44,$09,$4C,$1B,$5C,$3B,$4C,$19,$44,$08,$7E,$7F,$6F,$36,$7E,$1F,$7C,$0F,$00,$00
With this Sub-subroutine we will be loading all the bytes
that make up the specific tile graphic/shape into two temporary arrays. We need two sets of arrays because each shape
is two bytes wide and we will be drawing two bytes at a time. So as each set of
bytes are loaded into the TEMP arrays, they will be drawn as two sets of bytes
line by line on the screen in 32 lines.
341
STA TEMP1,X
Line 341 is used to “[ST]ore
the [A]ccumulator” or take the value that has
been stored in register A and place it in variable TEMP1,X, which in this case equal HEX
value $00.
342 INC STEPPB
Line 342 is used to “[INC]rement”
the variable STEPPB by 1 or take the value that has been stored variable STEPPB
and add 1 to it. STEPPB is used to
increment each stage of the 32 lines for each shape. So as each shape is stored with 32 lines of
bytes, when the next loop starts again it will maintain an incremental of 32
and store the next shapes byte values for the next shapes of the column.
343 INY
Line 343 is used to “[IN]crement
register [Y]” or take the value that has been
stored in register Y and add 1 to it.
344 INX
Line 344 is used to “[IN]crement
register [X]” or take the value that has been
stored in register X and add 1 to it.
345 CPY #$20
Line 345 is used to “[C]om[P]are [Y]” what is in
register Y to the value HEX $20 or the decimal value of 32. Since the value is equal to, in this case, 32,
then Y will continue to be compared to this value and if it doesn’t equal this
value it will call LOADSHP1 again, increment X and Y again, and try to compare
Y against value 32 again. This happens
until Y finally equal 32. Once this is
accomplished it will finish the LOADSHP1 subroutine loop and then return to the
subroutine that called it. Remember, 32
is equal to the number of lines that make up two stacked images for a 2x2
graphic tile. Each shape has 16 lines
and the two shapes together make up the 32 lines total.
346 BLT
LOADSHP1
Line 346 is used to “[B]ranch
on [L]ess [T]han”,
which means that as long as the value in register Y is less than [<] 32 it
will continue to call the subroutine with the header LOADSHP1. Once the value of Y is greater than [>] 32
it will bypass line 346 and continue to line 347.
347
LDA MAPCOUNT
Line 347 is used to again “[L]oa[D] the [A]ccumulator”
or register A with the value held in variable MAPCOUNT! Since MAPCOUNT will have incremented up 32
times within the loop, this time you will be entering the value of MAPCOUNT into
register A as it is finished the 32 line loop.
348
CLC
Line 348 is used to “[CL]ear [C]arry” which loads zero into the carry flag. On the 6502, the carry is kept in a one-bit
register called the carry status flag. Like
the A, X, and Y registers, the carry status flag can be loaded with a constant,
either zero or one. Loading a zero is
called clearing, and there is the instruction, CLC (Clear Carry), which loads
zero into the carry flag. This is
similar to the way LDA #!0 is often referred to as clearing the A register with
zero.
349
ADC #20
Line 349 is used to “[A]d[D] with [C]arry” which
adds to the A register. It also adds the
number in the carry flag (either zero or one). If the result is less than 256,
it clears the carry flag; otherwise, it sets the carry flag. The ADC instruction is the only add
instruction on the 6502. So in this case
you are taking the value of MAPCOUNT and adding 20 to it. So for example: If column was to start at 30 the program
needs to know that since the screen only holds 20 graphic tiles on a horizontal
line, then 30 + 20 would be 50, which should be the last column read for the
map database address. Since all hundred
and something map tiles are in the database, it would be a waste of memory to
have to store all those tiles at one time.
This make is easier to just check for the 20 tiles after the original
column tile value.
350 STA MAPCOUNT
Line 350 is used to “[ST]ore
the [A]ccumulator” or take the value that has
been stored in register A and place it in variable MAPCOUNT.
351 INC TCOUNT
Line 351 is used to “[INC]rement”
the variable TCOUNT by 1 or take the value that has been stored variable TCOUNT
and add 1 to it. Variable TCOUNT or
“Temporary Count” is used as a temporary 10 count loop cycle that gets reset
after each 10 counts.
352 LDA TCOUNT
Line 352 is used to “[L]oa[D] the [A]ccumulator”
or register A with the value equal to what has been stored in variable TCOUNT! So, you are setting the value of A to equal
the decimal value of TCOUNT, which in this case has just been increased by 1.
353 CMP #$0A
Once the value of TCOUNT is loaded into register A, Line 353
is used to “[C]o[MP]are”
what is in register A to the HEX value #$0A or decimal value of 10! The value in TCOUNT is the number of
shapes/graphic tiles that will be drawn down each column on the screen. So as TCOUNT increments it is used to help
store the shapes that will be drawn on a vertical column totaling 10 separate
shapes/graphic tiles.
354 BLT
LOADSP1
Line 354 is used to “[B]ranch
on [L]ess [T]han”,
which means that as long as the value in register A is less than [<] 10 it
will continue to call the subroutine with the header LOADSP1. Once the value of A is greater than [>] 10
it will bypass line 354 and continue to line 355.
355 LDA #$00
Line 355 is used to “[L]oa[D] the [A]ccumulator”
with the HEX value of zero! So you could
think of it as [A] holding the value of [0].
356 STA STEPPB
Line 356 is used to “[ST]ore
the [A]ccumulator” or take the value that has
been stored in register A and place it in variable STEPPB, which in this case
equals zero!
357 STA TCOUNT
Line 357 is used to “[ST]ore
the [A]ccumulator” or take the value that has
been stored in register A and place it in variable TCOUNT, which in this case
equals zero! By setting TCOUNT to zero it
lets the variable TCOUNT to be reset and used again within another counter loop
for the next 10 shapes.
358 INC TMAPCNT
Line 358 is used to “[INC]rement”
the variable TPCNT by 1 or take the value that has been stored variable TPCNT
and add 1 to it. Variable TPCNT or
“Temporary Point Count” is used as a temporary 20 count loop cycle that gets
reset after each 20 counts.
359 LDA TMAPCNT
Line 359 is used to “[L]oa[D] the [A]ccumulator”
or register A with the value equal to what has been stored in variable TMAPCNT! So, you are setting the value of A to equal
the decimal value of TMAPCNT, which in this case has just been increased by 1.
360 STA MAPCOUNT
Line 360 is used to “[ST]ore
the [A]ccumulator” or take the value that has
been stored in register A and place it in variable MAPCOUNT.
361 RTS
Line 361 is used to “[R]e[T]urn from [S]ubroutine”,
which means that all the actions in the LOADMAP subroutine have been
completed. In this case, since LOADSHP
was initiated from BEGIN when the program it will return to that
subroutine. On further call to this
subroutine it will continue to be called from subroutine START1 instead.
So, when subroutine LOADSHP finishes you should have the
following accomplished:
Each time the subroutine LOADSHP is called it will store the
10 shapes/graphic tiles that make up a single vertical column of shapes on the
display screen. Remember that there are
a total of 200 shapes that make up the section of viewed world map that is displayed
on the screen. So it first goes through
the MAPSTORE array and pulls out each shape reference number then takes that
number and stores each byte of information in the two arrays TEMP and TEMP1
through a loop that increments up to 32.
It does 32 times because there are 32 lines in each shape. After it finishes storing the shapes it jumps
the loop by 20, which is the next shape in the array MAPSTORE that would be
displayed. It has to jump by 20 because
there are 20 shapes that are drawn across the screen so it would be 0 to 19,
then 20 to 39, etc… for each 20th
shape is will store the next column shape in the sequence till it stores all 10
shapes/graphic tiles. The main reason
why it is done this way instead of drawing the horizontal shapes is because of
the 256 limitation. If I were to count
up in a loop for the 20 shapes that go across the screen I would surpass the
256 limit and cause an error in the loop.
So now I have 10 shapes temporarily stored in two arrays and
next I will start drawing them to the display screen. Once the 10 shapes are drawn to the screen I
can store over the values I just used for TEMP and TEMP1 arrays.
This subroutine will get called 20 times to store all 200
shapes/graphic tiles for the section of world map that will be drawn on the
display screen.
As always, please email any questions you might have.
Joe