Photon...
battle of the Chibi Photonic hunters!
Introduction to the Photon
Series...
Photon is a 'Tron' Light cycle type game... I
used to make these games in Basic on the CPC... I thought it would be fun
to try to do the same in assembly...
Originally the game was written for Z80
systems, but I have ported it to the 6502 and 68000
Lesson
Photon1
- Introduction and Data Structures
Photon is a tron style game written for many different systems
Lets start by having a quick look at the game, and the structure
of the game RAM, and the settings which define objects and
movements. |
 |
See
Photon folder
|
|
 |
Photon
Photon does not use bitmap graphic,
all the graphics are drawn at the pixel level... to port to a
new system you just need a PSET function to set a pixel and a
POINT function to read a pixel back...
All other graphics are drawn using
a LINE function, which uses the PSET function - PHOTON is
essentially a simple game, a tutorial on LINE and VECTOR image
drawing (With Scaling) AND a tutorial in Pixel plotting on each
system.
photon uses VECTREX packet format
for it's title graphics (Yes it uses the same format as the old
home console!), and a slightly tweaked Cpacket format (2 bytes
per line rather than 3) I designed to save space for it's font
and other bits... Akusprite Editor now has crude export
functions for these formats!
In this series, we'll look at the basic codebase, and the platform
specific modifications for each platform.
Photon is available on pretty much all the systems covered in my
tutorials, on the Z80,6502 and 68000! |

|
Photon is a one player (Vs CPU) Light Cycle game - you have to
stay alive longer than your opponent to win a level.
Death occurs when you hit a wall or light trail.
Each win progresses the level (Shown bottom right), and increases
CPU difficulty (Shown top right), and adds objects to the screen.
The player has a 'boost' power (count in bottom left) to
accelerate... you have four lives per game (shown top left)
Photon's CPU AI is hardly amazing - the game is really a 'tech
demo' for pixel plotting and multiplatform vector drawing. |
 |
The drawing engine has it's own vector font, and is capable of
scaling all vector objects (only powers of 2... eg 1/4x 1/2x 1x 2x
4x)
This allows the same title screen data to be drawn smaller on the
gamegear... and fonts to be shown at different sizes |
 |
Photon supports many different systems - porting it to a new
system really just consists of substituting the PSET and POINT
routines |
 |
Ram Definitions
The Player and CPU have various parameters for their position
Direction is the current direction of
movement - the game is controlled with Left and Right to turn -
this is the current direction.
X and Y are the current
position in pixels (2 byte word)
Xacc and Yacc are the
current 'acceleration' - these are added/subtracted from the
position each tick.
CpuTurn is used by the AI to decide which
direction the CPU will turn next time.
|
 |
The Game Engine needs some settings for the Level logic.
KeyTimeout is for 'ignoring' player keys
after a press
BestLevel is the highest level the player has
got to - effectively a highscore.
Level is the current level (duh!)
CpuAI is the CPU intelligence... lower means
tighter corner turning making the CPU harder to trap.
Lives is player lives
Tick is used to handle player boost - normal
speed is an update every other tick... boost is an update every
tick
Boost is used to mark player boost as enabled
(Cpu doesn't use boost)
BoostPower is the remaining 'Boost' - 99
units per level
ShownBoostPower is the visible boost - used
when redrawing the boost in the bottom left corner
RandomSeed is the random seed for random
number generation |
 |
The Line and vector routines need some bytes of data
XposDir and YposDir define
if the movement are Up/Left or Down/Right
Xpos24 and Ypos24 are
the current pixel position (24 bit)
Scale is the scaling factor... 1 2 4 = 1x 2x
4x ... -1 -2 -4 = 1/2 1/4 1/8
LineColor is the line color (obviously!) |
 |
 |
Note:
All these addresses are relative to the base address
'UserRam'... this is so the RAM data can be located where ever
free ram exists on the target platform.
So the game can work on ROM machines, this is the only
writable data, The is no self modifying code or altered data
within the other areas of code.
|
Constants and Data definitions
Directions defines the 4 directions in the
form of 2 words... these can be added to the position to affect a
move |
 |
Next we have some Random Number Lookup tables
|
 |
We need to reset the player and Cpu location and settings each
level... we have the defaults here.
|
 |
Next we have the text messages used in the
game.
|
 |
Finally we have the Obstruction objects...
These are put in random places in the level to get in the way!
These are in 'Cpacket format' (Compressed Vectrex Packet)... a
format I made based on the 'Packet' format used by the Vectrex
console.
It uses a 7 bit X movement, a 7 bit Y movement, and a 2 bit
Command
There are 2 possible command -
1.Move drawing cursor to position (Byte 2 bit 7 = 0)
2. Draw from drawing cursor to position (Byte 2 bit 7 = 1)
A Byte 2 bit 7 = 1 is the end of the list. |
 |
 |
The
Multiplatform code handles most of the game logic and vector
drawing routines - As they are converted from the Z80 version
we're not going to cover them here - all the function and
variable names are the same as is the structure - so please
watch Z80 lessons Photon 2-5 if you want to know more about how
the multiplaform code works.
|
Much of the code of
Photon is the same as the code in Yquest and the Simple series...
we're not going to cover things like setting up the screen or
reading the Joypad...
We've covered it so many times before it's getting boring!
|
 |
Data Definitions & Starting the game
Each system needs some platform specific settings.
The first is an address of RAM for system vars - the game needs less
than 256 bytes - this is the entirety of the RAM needed - the rest
of the game can run from ROM
We define some screen size vars - these set the scale for objects
and font., and the boundaries of the screen for drawing the level.
We also define some 'colors' ... the game uses up to 5 colors
(Background 0 and 4 more)... we can use all of these on the Atari
ST. |
 |
When the game starts we clear the game ram, we use 'CLDIR0' to do
this, it clears D1 bytes from address A3
We then show the Main menu. |
 |
Main Game Loop
At the start of the loop, we update the 'Tick'
The Tick is 1 or 0 - this is used by the multi-platform code for
boost (during which player moves at 2x speed)
If Boost is ON we lower the delay - we need to speed the game up
because redrawing the 'Boost counter' is too slow. |
 |
During the pause loop we check the keypreses... If a key is not
held down we release the keytimeout .
The timeout means if we hold left we don't keep rotating around...
We have to press left multiple times.
We store any keypresses in D2 - and wait until D1 reaches Zero. |
 |
If the Keytimeout is not cleared we will ignore Left / Right
keypresses.
First we turn off Boost (it will be turned back on if FIRE is held)
When we process Left or Right we INC/DEC the 'Player Direction' then
run the SetPlayerDirection routine which handles the rest of setting
the movement for the player.
If Fire is pressed then we check if any 'Boost power' is left..
If there is, then we turn boost power on.
Once the keypresses are handled, we update the player with 'Handle
Player'
Then we update the CPU with 'Handle CPU'
That's it... We jump back to the start of the loop for the next
tick. |
 |
PSET - Plot Pixel / POINT - Read pixel color
The PSET command will set a pixel of the screen...
The 16 bit X co-ordinate is defined by register D1
The 8 Bit Y co ordinate is defined by D4
D2 is the new color for the pixel (0-3)
Each byte of the screen contains 8 different pixels, so we need a
mask to alter the one pixel we want to change.
GetScreenPos will calculate the address of the screen byte we want
to change (in A3)
We also load a mask from PixelLookup, The mask to keep the screen
pixels we don't want to change will be in D1... the mask for the
pixel we want to change is D3
The Atari ST screen format is a little odd, it's spilt into blocks
of 8 bytes / 4 Words.
Each Word is a bitplane for 16 pixels, Bitplane 0-3, To change the
color of a pixel we need to change 4 bytes, each of which is 2 bytes
apart.
We test each bit of the color we want to set, and use our masks
accordingly to set the bitplanes of the screen bytes.
We've now set the color of the pixel! |
 |
POINT works in reverse to PSET... returning the color in D0 for
pixel D1,D4
Once again, we get the pixel mask, and read in the screen bytes,
ANDing it with D1 to get one pixel.
We use this to process the bitplanes, and convert the bitplanes back
to a color number in D0 |
 |
 |
The POINT routine here is excessive - as
PHOTON doesn't care what color a pixel is, just if it's black or
not.
ALSO, it would be quicker to calculate the color number via
bitshifts, rather than filling a byte and looking it up... but
POINT is hardly used in this game, so speed isn't a problem, and
the example here is easily ported to other systems, or converted
for other screen modes
|
Much of the code of
Photon is the same as the code in Yquest and the Simple series...
we're not going to cover things like setting up the screen or
reading the Joypad...
We've covered it so many times before it's getting boring!
|
 |
Data Definitions & Starting the game
Each system needs some platform specific settings.
The first is an address of RAM for system vars - the game needs less
than 256 bytes - this is the entirety of the RAM needed - the rest
of the game can run from ROM
We define some screen size vars - these set the scale for objects
and font., and the boundaries of the screen for drawing the level.
We also define some 'colors' ... the game uses up to 5 colors
(Background 0 and 4 more)... we can use all of these on the Atari
ST. |
 |
When the game starts we clear the game ram, we use 'CLDIR0' to do
this, it clears D1 bytes from address A3
We then show the Main menu. |
 |
Main Game Loop
At the start of the loop, we update the 'Tick'
The Tick is 1 or 0 - this is used by the multi-platform code for
boost (during which player moves at 2x speed)
If Boost is ON we lower the delay - we need to speed the game up
because redrawing the 'Boost counter' is too slow. |
 |
During the pause loop we check the keypreses... If a key is not
held down we release the keytimeout .
The timeout means if we hold left we don't keep rotating around...
We have to press left multiple times.
We store any keypresses in D2 - and wait until D1 reaches Zero. |
 |
If the Keytimeout is not cleared we will ignore Left / Right
keypresses.
First we turn off Boost (it will be turned back on if FIRE is held)
When we process Left or Right we INC/DEC the 'Player Direction' then
run the SetPlayerDirection routine which handles the rest of setting
the movement for the player.
If Fire is pressed then we check if any 'Boost power' is left..
If there is, then we turn boost power on.
Once the keypresses are handled, we update the player with 'Handle
Player'
Then we update the CPU with 'Handle CPU'
That's it... We jump back to the start of the loop for the next
tick. |
 |
PSET - Plot Pixel / POINT - Read pixel color
The PSET command will set a pixel of the screen...
The 16 bit X co-ordinate is defined by register D1
The 8 Bit Y co ordinate is defined by D4
D2 is the new color for the pixel (0-3)
Each byte of the screen contains 8 different pixels, so we need a
mask to alter the one pixel we want to change.
GetScreenPos will calculate the address of the screen byte we want
to change (in A3)
We also load a mask from PixelLookup, The mask to keep the screen
pixels we don't want to change will be in D1... the mask for the
pixel we want to change is D3
The Amiga screen is split into 4 bitplanes, All the screen pixels
for a bitplane are held in a block.
The screen is 40 bytes wide and 200 lines tall, so the screen memory
is made up of 40*200 bytes of bitplane 0, then 40*200 bytes of
bitplane 1, 40*200 bytes of bitplane 2 and finally 40*200 bytes of
bitplane 3
We test each bit of the color we want to set, and use our masks
accordingly to set the bitplanes of the screen bytes.
We've now set the color of the pixel! |
 |
POINT works in reverse to PSET... returning the color in D0 for
pixel D1,D4
Once again, we get the pixel mask, and read in the screen bytes,
ANDing it with D1 to get one pixel.
We use this to process the bitplanes, and convert the bitplanes back
to a color number in D0 |
 |
 |
The POINT routine here is excessive - as
PHOTON doesn't care what color a pixel is, just if it's black or
not.
ALSO, it would be quicker to calculate the color number via
bitshifts, rather than filling a byte and looking it up... but
POINT is hardly used in this game, so speed isn't a problem, and
the example here is easily ported to other systems, or converted
for other screen modes
|
Much of the code of
Photon is the same as the code in Yquest and the Simple series...
we're not going to cover things like setting up the screen or
reading the Joypad...
We've covered it so many times before it's getting boring!
|
 |
Data Definitions & Starting the game
Each system needs some platform specific settings.
The first is an address of RAM for system vars - the game needs less
than 256 bytes - this is the entirety of the RAM needed - the rest
of the game can run from ROM
We define some screen size vars - these set the scale for objects
and font., and the boundaries of the screen for drawing the level.
We also define some 'colors' ... the game uses up to 5 colors
(Background 0 and 4 more)... we can use all of these on the x68000 |
 |
When the game starts we clear the game ram, we use 'CLDIR0' to do
this, it clears D1 bytes from address A3
We then show the Main menu. |
 |
Main Game Loop
At the start of the loop, we update the 'Tick'
The Tick is 1 or 0 - this is used by the multi-platform code for
boost (during which player moves at 2x speed)
If Boost is ON we lower the delay - we need to speed the game up
because redrawing the 'Boost counter' is too slow. |
 |
During the pause loop we check the keypreses... If a key is not
held down we release the keytimeout .
The timeout means if we hold left we don't keep rotating around...
We have to press left multiple times.
We store any keypresses in D2 - and wait until D1 reaches Zero. |
 |
If the Keytimeout is not cleared we will ignore Left / Right
keypresses.
First we turn off Boost (it will be turned back on if FIRE is held)
When we process Left or Right we INC/DEC the 'Player Direction' then
run the SetPlayerDirection routine which handles the rest of setting
the movement for the player.
If Fire is pressed then we check if any 'Boost power' is left..
If there is, then we turn boost power on.
Once the keypresses are handled, we update the player with 'Handle
Player'
Then we update the CPU with 'Handle CPU'
That's it... We jump back to the start of the loop for the next
tick. |
 |
PSET - Plot Pixel / POINT - Read pixel color
Screen memory on the x68000 is a little weird, but super simple!
even when the screen is 16 color, each pixel uses a word (2 bytes) -
though only the bottom nibble does anything.
Also, although each line of the screen is 256 pixels, each line
takes 1024 bytes of ram, therefore our formula for the address of a
pixel is:
Addr= (Ypos * 1024) + (Xpos * 2)
To set or read a pixel, we just write or read a word to that
location. |
 |
Our clear screen will do the same, but we'll write in 32 bit
longs, so we divide the total bytes by 4 |
 |
 |
While
the screen layout of the x68000 is slightly surprising, it's super
easy to work with, and is about the simplest we'll come across!
|
Much of the code of
Photon is the same as the code in Yquest and the Simple series...
we're not going to cover things like setting up the screen or
reading the Joypad...
We've covered it so many times before it's getting boring!
|
 |
Data Definitions & Starting the game
Each system needs some platform specific settings.
The first is an address of RAM for system vars - the game needs less
than 256 bytes - this is the entirety of the RAM needed - the rest
of the game can run from ROM
We define some screen size vars - these set the scale for objects
and font., and the boundaries of the screen for drawing the level.
We also define some 'colors' ... the game uses up to 5 colors
(Background 0 and 4 more)...
On the Sinclair QL these colors use 3 bitplanes - Bit 0 is the Green
component, Bit 1 is red, and Bit 2 is blue. |
 |
When the game starts we clear the game ram, we use 'CLDIR0' to do
this, it clears D1 bytes from address A3
We then show the Main menu. |
 |
Main Game Loop
At the start of the loop, we update the 'Tick'
The Tick is 1 or 0 - this is used by the multi-platform code for
boost (during which player moves at 2x speed)
If Boost is ON we lower the delay - we need to speed the game up
because redrawing the 'Boost counter' is too slow. |
 |
During the pause loop we check the keypreses... If a key is not
held down we release the keytimeout .
The timeout means if we hold left we don't keep rotating around...
We have to press left multiple times.
We store any keypresses in D2 - and wait until D1 reaches Zero. |
 |
If the Keytimeout is not cleared we will ignore Left / Right
keypresses.
First we turn off Boost (it will be turned back on if FIRE is held)
When we process Left or Right we INC/DEC the 'Player Direction' then
run the SetPlayerDirection routine which handles the rest of setting
the movement for the player.
If Fire is pressed then we check if any 'Boost power' is left..
If there is, then we turn boost power on.
Once the keypresses are handled, we update the player with 'Handle
Player'
Then we update the CPU with 'Handle CPU'
That's it... We jump back to the start of the loop for the next
tick. |
 |
PSET - Plot Pixel / POINT - Read pixel color
The PSET command will set a pixel of the screen...
The X co-ordinate is defined by register D1
The Y co ordinate is defined by D4
D2 is the new color for the pixel (0-3)
Each word of the screen memory contains 4 different pixels, so we
need a mask to alter the one pixel we want to change.
The first byte contains the Green bits and the flashing bits (We
don't use flashing)
The second contains the Red bits and the Blue Bits
GetScreenPos will calculate the address of the screen byte we want
to change (in A3)
We also load a mask from PixelLookup, The mask to keep the screen
pixels we don't want to change will be in D1... the mask for the
pixel we want to change is D3.
The colors are defined by 3 bits. the first byte contains the Green
bits. We test the first bit of the color we want to set in D2, and
use our masks to set the screen pixel as needed.
We then move to the next byte and do the same for the Red and Blue
bits.
After we do the Red bits, we shift our masks right by one bit to
move them to the position of the 4 red bits.
We've now set the color of the pixel! |
 |
The GetScreenPos will calculate the memory address of the WORD
containing the pixel
because each word contains 4 pixels, we shift the Xpos to the right
twice,
we then multiply the Xpos by two (2 bytes per 4 pixels), and the
Ypos by 128 (256 pixels per line, 4 pixels per word/2 per byte))
We add this to the screen base $20000 |
 |
POINT works in reverse to PSET... returning the color in D0 for
pixel D1,D4
Once again, we get the pixel mask, and read in the screen bytes,
ANDing it with D1 to get one pixel.
We use this to process the bitplanes, and convert the bitplanes back
to a color number in D0 |
 |
 |
The POINT routine here is excessive - as
PHOTON doesn't care what color a pixel is, just if it's black or
not.
ALSO, it would be quicker to calculate the color number via
bitshifts, rather than filling a byte and looking it up... but
POINT is hardly used in this game, so speed isn't a problem, and
the example here is easily ported to other systems, or converted
for other screen modes
|
Much of the code of
Photon is the same as the code in Yquest and the Simple series...
we're not going to cover things like setting up the screen or
reading the Joypad...
We've covered it so many times before it's getting boring!
|
 |
Data Definitions & Starting the game
Each system needs some platform specific settings.
The first is an address of RAM for system vars - the game needs less
than 256 bytes - this is the entirety of the RAM needed - the rest
of the game can run from ROM
We define some screen size vars - these set the scale for objects
and font., and the boundaries of the screen for drawing the level.
We also define some 'colors' ... the game uses up to 5 colors
(Background 0 and 4 more)...
On the Genesis we can use all of these! |
 |
We need to fill the screen with consecutively numbered tiles so we
can set pixels of the screen.
We're using the 'FillAreaWithTiles' function we wrote in the simple
series. |
 |
When the game starts we clear the game ram, we use 'CLDIR0' to do
this, it clears D1 bytes from address A3
We then show the Main menu. |
 |
Main Game Loop
At the start of the loop, we update the 'Tick'
The Tick is 1 or 0 - this is used by the multi-platform code for
boost (during which player moves at 2x speed)
If Boost is ON we lower the delay - we need to speed the game up
because redrawing the 'Boost counter' is too slow. |
 |
During the pause loop we check the keypreses... If a key is not
held down we release the keytimeout .
The timeout means if we hold left we don't keep rotating around...
We have to press left multiple times.
We store any keypresses in D2 - and wait until D1 reaches Zero. |
 |
If the Keytimeout is not cleared we will ignore Left / Right
keypresses.
First we turn off Boost (it will be turned back on if FIRE is held)
When we process Left or Right we INC/DEC the 'Player Direction' then
run the SetPlayerDirection routine which handles the rest of setting
the movement for the player.
If Fire is pressed then we check if any 'Boost power' is left..
If there is, then we turn boost power on.
Once the keypresses are handled, we update the player with 'Handle
Player'
Then we update the CPU with 'Handle CPU'
That's it... We jump back to the start of the loop for the next
tick. |
 |
 |
The Genesis
joypad reading code handles 'KeyTimeout' differently to the other
systems. The buttons on the genesis seem to 'bounce' when pressed
down, meaning they will briefly release even when held.
Therefore we've moved the keyrelease code to after the delay.
|
PSET - Plot Pixel / POINT - Read pixel color
The PSET command will set a pixel of the screen...
The X co-ordinate is defined by register D1, The Y co ordinate is
defined by D4
D2 is the new color for the pixel (0-3)
Each pixel uses one nibble, so Each 8 pixel line of a tile uses one
long. We use CalcVramAddr to get the ram address of the line we need
to change, we use PrepareVramRead to select the read address, and
read the long into D7, we then use PrepareVramWrite to select that
address for writing.
We now use the 'Pixel mask' with the bottom 3 bits of the X
position, this gets the mask for the one of the 8 pixels in the long
we want to change... we flip the bits, this gives us the mask for
the 7 pixels we want to keep.
We now use the 'ColorMask' this gives us a long with all the pixels
set to the same color, we AND this with our pixel mask, this
gives us the pixel we want in the color we want.
We AND the current screen long with the background mask, and OR in
the new pixel color, we write it back to VRAM
We've now set the color of the pixel! |
 |
CalcVramAddr will calculate the Long of the pixel.
A line of a tile is 4 bytes, and there are 8 lines per tile, so we
multiply the Xposition by 8*4
The bottom 3 bits of the Yline are multiplied by 4 (4 bytes per
line)
There are 40 tiles in a line, so we multiply the remaining bits by
40*8*4 (TilesPerLine*LinesPerTile*BytesPerLine).
The first tile on our screen is Tile 1, so we add 32 to the address |
 |
When we have an address we want to read or write we must shift the
bits of the address into the weird format needed by the Genesis VDP.
We also set bit 14 if we want the port to Write, otherwise it will
Read. |
 |
POINT works in reverse to PSET... returning the color in D0 for
pixel D1,D4
We get the screen long, then shift the bits of the long according to
the xposition (0-7) within that long.
This gives us the color number of the pixel.
|
 |
 |
The POINT routine here is excessive - as
PHOTON doesn't care what color a pixel is, just if it's black or
not.
ALSO, it would be quicker to calculate the color number via
bitshifts, rather than filling a byte and looking it up... but
POINT is hardly used in this game, so speed isn't a problem, and
the example here is easily ported to other systems, or converted
for other screen modes
|
 |
The
Classic NeoGeo cannot alter the Sprite/Fix data as it's held in
ROM. It should be noted that the NeoGeo CD does not have this
limitation, but that system is not covered by these tutorials.
|
Bitmap Tiles
To work around the 'ROM' limitation, we'll create a grid of tiles
which represent every combination of a 2x4 pixel block.
This will create a block of 256 sprite patterns. We will create
multiple colored versions to allow for color.
|
 |
We'll then fill the screen with scaled tiles, effectively creating
a 192x124 screen with 'color attributes' in 2x4 pixel blocks. |
 |
This isn't really a
viable solution, as it's made the NeoGeo lower resolution than the
C64!
It's just a bit of a 'fun' experiment to try to work around the
'rules' of the NeoGeo Rom!
|
 |
Data Definitions & Starting the game
Each system needs some platform specific settings.
The first is an address of RAM for system vars - the game needs less
than 256 bytes - this is the entirety of the RAM needed - the rest
of the game can run from ROM
We define some screen size vars - these set the scale for objects
and font., and the boundaries of the screen for drawing the level.
Unfortunately, we don't have enough sprites for a high res screen.
We also define some 'colors' ... the game uses up to 5 colors
(Background 0 and 4 more)...
We've defined 4 different banks of sprites, so we can use all 4
colors. |
 |
We need to use the NeoGeo hardware sprites to fill the screen.
we define 96 horizontal sprites, each has 30 vertical tiles....
These are scaled as small as possible while filling the screen.
We will switch these tiles to show pixels onscreen |
 |
When the game starts we clear the game ram, we use 'CLDIR0' to do
this, it clears D1 bytes from address A3
We then show the Main menu. |
 |
Main Game Loop
At the start of the loop, we update the 'Tick'
The Tick is 1 or 0 - this is used by the multi-platform code for
boost (during which player moves at 2x speed)
If Boost is ON we lower the delay - we need to speed the game up
because redrawing the 'Boost counter' is too slow. |
 |
During the pause loop we check the keypreses... If a key is not
held down we release the keytimeout .
The timeout means if we hold left we don't keep rotating around...
We have to press left multiple times.
We store any keypresses in D2 - and wait until D1 reaches Zero. |
 |
If the Keytimeout is not cleared we will ignore Left / Right
keypresses.
First we turn off Boost (it will be turned back on if FIRE is held)
When we process Left or Right we INC/DEC the 'Player Direction' then
run the SetPlayerDirection routine which handles the rest of setting
the movement for the player.
If Fire is pressed then we check if any 'Boost power' is left..
If there is, then we turn boost power on.
Once the keypresses are handled, we update the player with 'Handle
Player'
Then we update the CPU with 'Handle CPU'
That's it... We jump back to the start of the loop for the next
tick. |
 |
PSET - Plot Pixel / POINT - Read pixel color
The PSET command will set a pixel of the screen...
The X co-ordinate is defined by register D1, The Y co ordinate is
defined by D4
D2 is the new color for the pixel (0-3)
Each tile is 2x4, so we skip 1 bit of the Xpos, and 2 bits of the
Ypos
We need to calculate the tile number we need to change, The tiles
are vertically organized, and each tile is 2 bytes, so we multiply
the Ypos by 2, each sprite contains up to 32 tiles, so we multiply
the Xpos by 64
We now use the 'Pixel mask' to calculate the Y offset of the sprite
pattern we need to use.
If the bottom bit of X is 1, We then multiply this by 16 - this is
because there are 2 strips of vertical pixels in each pattern.
We now calculate which bank of tiles we want to use according to the
color, we AND the current pattern used by the tile with $FCFF -
removing the current color.
We then OR in the new color, and pixel data, setting the pixel,
while keeping any other set pixels unchanged.
We've now set the color of the pixel! |
 |
POINT works in reverse to PSET... returning the color in D0 for
pixel D1,D4
We get the tile from the screen, and mask the pixel we want to look
at, returning it the pixel is set or not.
|
 |
The clear screen routine sets all the visible tiles to zero. |
 |
| |
Buy my Assembly programming book on Amazon in Print or Kindle!



Available worldwide! Search 'ChibiAkumas' on your local Amazon website!
Click here for more info!
Buy my Assembly programming book on Amazon in Print or Kindle!



Available worldwide! Search 'ChibiAkumas' on your local Amazon website!
Click here for more info!
Buy my Assembly programming book on Amazon in Print or Kindle!



Available worldwide! Search 'ChibiAkumas' on your local Amazon website!
Click here for more info!
|