The main purpose for this web site is to produce legal future reference for those people who would like to be involved with assembly programming side of the C64 scene. This documentation differs through various assembly coding techniques, commands, etc. By reading through this documentation, you should soon end up creating cool, exciting and possibly crazy programs in no time. Later on in this documentation, you will learn how to create your own games, that involve moving sprites, animating background objects, playing SID music, adding scores, etc. Hopefully you should be able to understand assembly programming in approximately one or two months. Oh and you'll be having a go at making a C64 game in no time.
Chapter 2: WHAT IS AN ASSEMBLER?
WHAT IS AN
ASSEMBLER?
An assembler is a programming language that allows
you to program in a different way, compared to the BASIC programming language.
BASIC is a very easy programming language, but assembly language is more
professional and it can do a lot more enhanced techniques. Many demo
programmers, such as Civitas (The demo group which I'm in) use an assembler,
which creates cool demos, effects etc.
WHAT TYPE OF
ASSEMBLERS ARE THERE?
Assemblers may differ, as
different commands are used, but they all build the same routines. You write a
program listing in an assembler, and then you need to assemble it before you
create a runnable file and test your file. There are different types of
assemblers, which have their own features. The assemblers are as
follows:
LDX #$00 (LDX
#0), LDY #$00 (LDY #0)
This command sets the
starting loop, at a value of 0. This command is very useful for writing control
loops in your own programs. You can change various commands for your program, by
indicating LDX #nn, where nn is the number you want to
start.
When you are using LDX, or LDY loops, you can start from 0 to 256, or ($00 - $FF). Easily done
LDA #$00 (LDA
#0)
This
command allows you to set a value. This value could be used for either
raster splits, charsets, colours, RAM, etc.
STA $xxxx (STA
xxxxx)
When
you set values, using LDA you can build the type of RAM which are using, when
entering STA. For example if you want to build a black screen, then you
enter:
LDA #$00
STA $D020
STA $D021
Quite simple eh? I'm sure it is. Ah, but you can't just LDA and STA things, you can also use LDX and LDY and instead of use STA, you can use STX or STY, for example:
LDX #$00
STX $D020
STX $D021
LDY #$00
STY $D020
STY $D021
Let us say for example you
wanted to draw a black screen, but you want a red frame. You could use LDA and
STA like as the example below:
LDA #$02
STA $D020
LDA #$00
STA $D021
Or then again, you would prefer to tidy your code, by using the X,Y method, for example:
LDX #$02
LDY #$00
STX $D020
STY $D021
There, that is MORE tidy!
INX , INY
These are two command that are
use to increment a value which is inside a timed loop. These can also be used
for continuous moving of objects, flashing, rasters, etc.
CPX #$00, CPY
#$00
These are
comparing loop values of a loop, which is the value of X or Y. Basically if you
use 0 as start loop and want the C64 to count the loop 255 times, then we CPX or
CPY the limit. I'll show you how to use these later on :o)
BNE $xxxx
This command is used in a loop.
For example, compare a value and if it does not match, go to the looping
command. For example:
LDX
#$00
LDY #$00
LOOP INC
VALUE
LOOP INC VALUE
INX
OR
INY
CPX
#$FF
CPY #$FF
BNE
LOOP
BNE LOOP
Easy!
INC $xxxx or INC
VALUE
The INC
command is used to increment a value. For example, this command can be used for
creating your own sprite movements, timers, etc.
DEC $xxxx or DEC
VALUE
DEC is
opposite to INC. Instead of incrementing a value, this command decrements a
value. Yet again it can be used for practically the same as with INC, but goes
the opposite way :o)
BCC & BCS
BCC & BCS are similar to the
BNE command, but these are more special. Many C64 programs use BCC and BCS for
their programs, I.E. some nice little game I made in the past, that use
collision detection with an enemy and player, I used the following
command:
LDX #$00
LOOP LDA ENEMYPOS+$00,x
CMP COLLISION
BCC NO COLLISION
CMP COLLISION+$02
BCS NO COLLISION
LDA ENEMYPOS+$01,x
CMP COLLISION+$03
BCC NO COLLISION
CMP COLLISION+$04
BCS NO COLLISION
INC $D020
RTS
NO
COLLISION INX
INX
CPX #$10
BNE LOOP
Pretty simple, but we will take a look at this when we start a simple little two player game project.
CMP #$00 (or CMP
#0)
The
command CMP #$nn compares a value that IS/NOT in a loop. For example you can
compare values for positions of sprite movements and set the stopping values
rather than just have them continuously looping :o)
JSR $xxxx, JSR
ROUTINE
The
JSR routine is always used inside or outside an Interrupt ReQuest (IRQ) flag,
which jumps to a routine, but allows you to continue your programming. For
example:
LDX #$00
JSR $1048
JSR
COLOURWASH
JSR ANIMATE
JSR $1021 ;Play
music
JMP $xxxx, JMP
ROUTINE
JMP is
similar to JSR, but this time it jumps to a routine that you want. For example,
freezing your own program
HOLD JMP HOLD
There are also a couple of special JMP routines, which are JMP $EA81 and JMP $EA31, these are of course used in IRQ routines
CLC
ADC #$00 or (ADC
#0)
Calculate
and add a value
SEC
SBC #$00 or (SBC
#0)
Reverse
calculate and subtract a value
BEQ STATEMENT
Similar BNE, BCC and BCS, but a
bit different. These are mainly used in loops, to defualt values of
pointers.
SEI
SEI turns off an IRQ interrupt
flag, when a loop is inside the program
CLI
Clears registers and allows the
programmer to insert additional commands, which they cannot use inside an IRQ
loop!
PLA
PHA
RTI
These are special
commands.
TAX or TAY
Mainly used to control scrolling
types, initialise everything, for example, music!
LDA #$00
TAX
TAY
JSR $1000 ;Initialise DMC 4
tune
.BYTE (or .BYT)
Data tables for animation,
colours, etc
.TEXT (or .TXT)
Data tables for creating your
own text
There are many other commands,
but the commands (PLA, PHA, RTI, SED, CLD) that I don't use, and they're for
more advanced programmers.
Chapter 4: WRITING YOUR FIRST PROGRAM
We are going to write our first
program, which is just something small and simple. This program shows you how to
create your own flashing border, while asking for the user to press the space
bar, so that then the program exits. So load up your assembler and type in the
following listing. There are two different methods for this phase
;o)
METHOD 1
;===================
;RAINBOW COLOURS
;===================
* = $0900 ;Jump start for code
SEI
;CLEAR IRQ
LOOP INC $D020 ; INCREMENT
BORDER
LDA $DC01 ; CHECK BUFFER
CMP #$EF ; IS SPACE PRESSED?
BNE LOOP ; IF NOT THEN JUMP TO LOOP
RTS ; IF
SPACE IS PRESSED THEN END
Can you see how easy it is to create your own short program? Now all you need to do is assemble the program and run it. Guess what? You'll see a flashing border. The border will continue to flash until you press space. Then the program will finish. Well why does the program continue flashing, before SPACEBAR is pressed? Well, that's easy, because the program is inside a control loop, which continues to loop until the value #$EF is found, and then the C64 stops running the program, as the program tells it to do so. Now why not try deleting LDA $DC01, CMP #$EF and BNE LOOP into:
METHOD 2:
;===================
;RAINBOW COLOURS
;===================
* = $0900 ;Jump start for code
SEI
;CLEAR IRQ
LOOP INC $D020 ; INCREMENT
BORDER
LDA $DC01 ; CHECK SPACEBAR
LSR
; If SPACEBAR IS NOT
LSR
; PRESSED THEN JUMP
LSR
; TO THE LOOP!
LSR
LSR
BCS LOOP
RTS
Not much of a difference there, but this is also checking for a button on joystick port 1. Yes, that's right FIREBUTTON. The spacebar will still work.
I would prefer to use method 1, in order of processing the code. This is because it is shorter compared to method 2. Shorter routines can compress the program, which you write. It also saves the amount of memory that has been used in an assembler.
Chapter 5: USING X & Y LOOPS
In Chapter 4, I gave you an example program,
which allowed you to flash the colour borders, but now, I'm going to show you
how you can EXPAND colour sizes. Here is what we'll do. We shall use an LDX
prompt and also an LDY prompt (for X and Y loops). We shall still use INC $D020
and INC $D021 and the pressing spacebar method, but this is just a little taster
of what we have in store for this section :o)
;==================
;FLASHING BORDERS
;USING X & Y
LOOPS
;==================
*=$0900
<- you should know what this routine does
SEI
<- and this one
MAINLOOP LDX
#$00
;Set 'X' as 0
LOOPX LDY
#$00
;Set 'Y' as 0
LOOPY INC
$D020 ;Flashy
border
INY
;Increment Y
CPY
#$77
; Is 'Y' equal to #$77
BNE LOOPY ; If not then Y=Y+1,
goto LOOPY
INX
; Increment X
CPX
#$77
; Is 'X' equal to #$77
BNE LOOPX ;If not then X=X+1,
goto LOOPX
LDA $DC01 ;Load
Spacebar command
CMP #$EF
;Is spacebar pressed
BNE MAINLOOP ; If not then jump to the MAINLOOP prompt
RTS
; else END program operation
You will notice that there wont be much of a difference in the flashing borders. However, we could try something different. Here is what to do.
Underneath RTS, build your own colour table. Include the label COLOURS. You could try the following:
COLOURS
.BYTE $00,$06,$0E,$03
.BYTE $03,$0E,$06,$00
Now let's try a little experiment shall we?
Where we have INC $D020, replace this with LDA COLOURS,X and then add STA $D020. We're not finished there yet. In order to read the amount of colours that are in the colour table, the next thing for you to do is change CPX #$77 into CPX #$08. Now let's test it ;o)
Different.
Now, why not try and change CPY #$08 and see what happens next ;o) Notice any differences? The border thins down and it scrolls something like those colour bars, which have been used on SEUCK games apart from SEUCK bars go upwards instead of downwards.
Thinning colour bars, etc is plain easy to handle, but when $D012 is involved, things change.
The borders look a mess, as they
are flickering so what should be done now is some minor adjustment to the
flickers. All we do is add NOP, a few times, until the borders are nice and
straight. Let's try it.Erm, no, as not much effort would be put into it. Maybe
using $D012 would help. We'll look at this later on
Chapter 6: Displaying text/characters & their colours on
screens
How can we display text or characters on the screen? Easy, we use loops,
but we need to use screen RAM, which is located in different memory banks. We
shall stick to the normal C64 display bank ($0400 - $07E7), so that then we can
display some text.
For a start off, let us try and something, which is located at $4000 and then pastes it through the whole of the screen area. Remember, this is only an experiment. There are different methods, but we'll use a simple method on displaying a screen, that is located at $4000.
;================================
;DISPLAYING TEXT AT BANK
#$03
;================================
;SET UP PERAMETERS
SCREENLOC1 =
$4000
SCREENLOC2 = $4100
SCREENLOC3 = $4200
SCREENLOC4 =
$42E8
SCREENPOS1 =
$0400
SCREENPOS2 = $0500
SCREENPOS3 = $0600
SCREENPOS4 =
$06E8
* = $0900
SEI
LDX
#$00
;X=0
DISPLAY LDA
SCREENLOC1,X ;READ FROM
SCREENLOC1 'X' TIMES
STA SCREENPOS1,X
;PASTE TO SCREENPOS1 'X' TIMES
LDA SCREENLOC2,X ;READ FROM
SCREENLOC2 'X' TIMES
STA SCREENPOS2,X
;PASTE TO SCREENPOS2 'X' TIMES
LDA SCREENLOC3,X ;READ FROM
SCREENLOC3 'X' TIMES
STA SCREENPOS3,X
;PASTE TO SCREENPOS3 'X' TIMES
LDA SCREENLOC4,X ;READ FROM
SCREENLOC4 'X' TIMES
STA SCREENPOS4,X
;PASTE TO SCREENPOS4 'X' TIMES
INX
; X=X+1 UNTIL X = $FF (256)
BNE
DISPLAY
;IF X <> $FF THEN GOTO DISPLAY
RTS
;END PROGRAM
Compared to using BASIC, this routine is smaller and more compact to display text.
Now that you know how to display the screens, we want to display colours for the text. And here is how we can do this:
The colour RAM is always between $D800 and $DBE7. Therefore, variables can be created for the colours. So create some new variables, which are as follows:
COLOURPOS1 =
$D800
COLOURPOS2 = $D900
COLOURPOS3 = $DA00
COLOURPOS4 =
$DAE8
Then inside your loop (underneath
STA SCREENPOS4,X) enter the following:
LDA #$0A
STA COLOURPOS1,X
STA COLOURPOS2,X
STA COLOURPOS3,X
STA COLOURPOS4,X
You don't just get the screen displaying only text, but you get the text to display painted in pink ;o)
Why not play around with the colours. Here is a small table on which colour does what job :o)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
![]() |
![]() |
;===========================
;COLOUR SPLITTING USING
$D012
;===========================
*=$0810
SEI
MAIN LDA
#$30
LDX #$00 ;BLACK
RASTER1 CMP $D012
BNE RASTER1
STX $D020 ;ASSIGN BLACK TO
STX $D021 ;BORDER AND FRAME
LDA #$A8
LDX #$01 ;WHITE
RASTER2 CMP $D012
BNE RASTER2
STX $D020
STX $D021
JMP MAIN
Now that we have typed in this listing if you run it, just assemble it and run the little program. You will see that the top border and frame is black, and that the bottom border and frame is white. You will also notice that using this routine, there are a few screen flickers. This is because we are not using an IRQ loop, and we're also not using TIMING either :o)
How do we add timing to rasters? There are different ways, but one of the easy ways is by adding the 'NOP' command a few times, before we actually start a process. For example
RASTER1 CMP
$D012
BNE RASTER1
NOP
----- Rest of program
Adding NOPs will move the little flickers further across the screen. Therefore you will need to add a few of these until the split is STRAIGHT and not FLICKERING :o)
There are other methods of timing, which you can use, which can be easier. You could use timing inside an x or y loop. For example
RASTER1 CMP
$D012
BNE RASTER1
LDX #$XX ;Timing Value
TIMER1
DEX
BNE TIMER1
------ Rest of program
You could reverse the timing loop, but if you do, you would need to change the values into the following.
LDX #$00
TIMER1 INX
CPX #$XX ;Timing Value
BNE TIMER1
There is also another method in timing, which is the hardest of them all. Imagine you are doing a raster bar, which uses loads of colours, like some demo groups use. Well a timing table would need to be produced. To find out more about timing, read the disk mag 'Coders World' issue 2.
Chapter 8 - IRQ Raster Interrupts
What is an IRQ Raster Interrupt?
An IRQ Raster Interrupt is a routine, known as the Interrupt Request flag. This is a continuous loop, which can hold more than one control loop. Therefore uses more complicated techniques. Most people use IRQ interrupts to do various effects in their programs. I mainly use IRQ interrupts for my C64 games. A little explanation will be added in a short while. But first copy this routine into your Turbo Assembler before you actually do anything. Below is a listing that shows a nicr and small IRQ raster interrupt routine.
SEI
LDA #<INIT
LDX #>INIT
STA $0314
STX $0315
LDA
#$00
STA $D012
LDA #$7F
STA $DC0D
LDA #$01
STA $D01A
CLI
HOLD JMP HOLD
INIT LDA
#$01
STA $D019
INC $0400
JMP $EA31
Right, looking from the top of the IRQ flag, the values $0314 and $0315 are very special, these call INIT to produce the main IRQ interrupt flag. However you MUST use (as highlighted) the prompts else your IRQ wont work properly. This is because they are vital to use in your program.
What can IRQ be used for? Let us
say for example you are writing a demo, game or utility, you might need to use
IRQ raster interrupt request flags to link various sources, such as the
following:
Okay, press RUN/STOP and restore, load a Demo Tune or a tune of your own into $1000, (JCH, DMC or equivalent), enter sys 36864 and do as follows:
Underneath STA $D01A enter:
LDA
#$00
TAX
TAY
JSR $1000
This is to initialise your music
Now, delete INC $0400 and change to JSR $1003. This is to play your music. Now, assemble and run.
You'll be able to hear some music playing in the background. Later on, we'll be taking a look at preparing a demo.
If you link other routines, be sure to JSR (routine) before JMP $EA31 Let's try something simple, such as flashing the screen. Before JSR $1003, put JSR FLASH and then underneath JMP $EA31, enter the following code:
FLASH INC
$D020
DEC
$D021
RTS
Why do we add an RTS command at the end of this prompt? This is because if we don't use RTS, the program will not respond properly, in fact it will virtually crash and you may lose everything.
Now, let's add another command to the IRQ. After JSR flash, try JSR CHAR, Underneath RTS inset the label CHAR and enter INC $D018 and add another RTS, assemble and run. You'll get some funny effects happening. This is because the C64 is playing with your charset memory.
Basically
that is all for this chapter. We'll be taking a look at a few other chapters
regarding assembly code :)
What is a Sprite?
A sprite is a small object that can be moved around the C64 screen. A sprite is usually used in games and demos. Sprites can be repositioned, moved and also use hi-res or multicolour. Later on we are going to try and make a nice little 2 player game that involves sprites. But that will be in a later chapter. What we are going to do is play around with sprites. Here is what to do.
1. Load a
sprite editor from a PD utilities disk (Or download
one).
2. Draw a sprite (can be
anything)
3. Save to disk
4. Use an
action replay cartridge and load in your own sprite at $2000, using the M/C
prompt: L "(filename),8,2000
5. Load up and enter
turbo assembler
6. Read on.
Right, the first thing, which we are going to do is learn how to turn the sprites on and off. If you remember right, $D020 was for border colour, but what's that to do with sprites? Ehm, nothing.
Turning On/Off Sprites
We use $D015 to turn on sprites. To turn a sprite on we can use LDA #$01, STA $D015, or if you wanted all 8 sprites turned on, we use LDA #$FF, STA $D015. This will be easy to remember.
Setting Sprite Properties
Also, setting up your sprite correctly would be quite tricky. Anyway, because we are using bank $03 on the C64, we will use $07F8 - $07FF for our sprites. However, because our sprite data is loaded at $2000, we will need to use LDA #$80, STA $07F8 (for sprite 1), STA $07F9 (for sprite 2),etc. LDA #$80 reads from the first few lines at $2000 and then pastes it into $07F8, etc to perform a perfect display for your sprites.
Sprite Positioning
To position sprites, we use $D000 - $D00F. Why are there 16 instead of 8 values? Well, the reason for this is because $D000, $D002, $D004, $D006, $D008, $D00A, $D00C, $D00E use the sprite's x-axis, while $D001, $D003, $D005, $D007, $D009, $D00B, $D00D, $D00F all use sprite's y-axis, both of these are according to the sprite number. Here is a simple routine to get you started on how to position, display and turn on sprites. Call out a start (*=xxxx) and SEI then enter the following.
A Practical Example with Sprites
LDA
#$01 ;1 SPRITE
STA $D015 ;TURN ALL
SPRITES ON
LDA #$80
STA
$D018
LDA #$70
STA
$D000
LDA #$89
STA
$D001
RTS
Assemble and run. You will see your sprite sitting on the screen at x = #$70 pixels, and y = #$89 pixels. However, 1 sprite is not enough, so let us make another 7, turn all sprites on and then position them into different places. Refer to the example at the top, then you'll know what you're doing :o)
Sprite Colours
This is something which we have not looked at in this feature. Sprite's colours are simple. We have a hi-res sprite which needs a touch of colour, so here's how it is done. The colour refers from $D027 (sprite 1) to $D02E (sprite 8)
LDA
#$colour
STA $D027
You can even toggle multicolour sprites, using LDA #$FF, STA $D01C (Multi colour)
and to change the 2 multi-colours, we use STA $D025 and STA $D026. $D025 uses multicolour 1, and $D026 uses multicolour 2. To get these to work, we need to set LDA #$colour before STA. The 'colour' has to be between #$00 - #$0F, as these are the main 16 colours. (Please refer to your C64 user guide).
Priorities
Sprites have their own priorities. You can put certain sprites in front or behind the characters on screen. This can be toggled by using $D01B. For example LDA #$00, STA $D01B puts all sprites over the text, and LDA #$FF, STA $D01B puts all sprites under the text. The thing is that you can actually toggle the sprites moving over and under the screen (like in a classic intro screen, which involves a green sprite bar going under and over the logo), however, advanced techniques would be required. We'll be taking a look at this later on in the feature.
Expanding Sprites
Another priority, which sprites have is expanding in two different ways x, and y axis. This transformation can sometimes be a good laugh to try (like I did in a BASIC demo called Biblet Land in 1996), but how do we expand our sprites? We use LDA #$FF (for all sprites), STA $D017, and STA $D01D. $D017 expands 'x' and $D01D expands 'y' for the sprites. You can turn one expansion off and another on.
What to do Next
Simple. Load
up the IRQ player, which you've made. Before the IRQ routine, call up your
sprites, and before JMP $EA31, enter INC $D000 and $DEC $D001. You'll see that
your sprite will move diagonally. Try experimenting with these fun routines. I
am pretty sure you would have fun with this.
This is one of the most simplest tasks. In some demos and other programs on the Commodore 64, you see colours moving from the left hand side - to the right and also vice-versa. How do these simple routines work? Well, this is the easy part - in fact it is the easiest method of them all. Copy this listing below, and all will be revealed straight after the listing.
;Simple
colour washing routine, inside
;an IRQ Raster Interrupt
Player
* = $1000
LDX #$00
SHOWMS LDA
MESSAGE,X
STA $0400,x
INX
CPX #$28
BNE SHOWMS
Now create your own IRQ raster interrupt, make the screen black and set the C64 charset mode to $16 (LDA #$16 STA $D018)
Inside your IRQ raster interrupt routine, call the colour washing routine.
IRQ JSR COLWASH
JMP
$EA31
;======================
;COLOUR WASHING
ROUTINE
;======================
COLWASH LDA COLOUR+$00
STA COLOUR+$28
LDX #$00
CYCLE LDA
COLOUR+$01,X
STA COLOUR+$00,X
LDA COLOUR,X
STA $D800,X
INX
CPX #$28
BNE CYCLE
RTS
;DATA TABLES FOR COLOURS
COLOUR .BYTE
$09,$09,$02,$02,$08
.BYTE $08,$0A,$0A,$0F,$0F
.BYTE $07,$07,$01,$01,$01
.BYTE $01,$01,$01,$01,$01
.BYTE $01,$01,$01,$01,$01
.BYTE $01,$01,$01,$07,$07
.BYTE $0F,$0F,$0A,$0A,$08
.BYTE $08,$02,$02,$09,$09
.BYTE $00,$00,$00,$00,$00
;DATA FOR TEXT MESSAGE
MESSAGE .TEXT
"RICHARD BAYLISS'"
.TEXT " COLOUR
SCROLLER"
.TEXT " ACTIVE......"
.TEXT
"
"
If you take a look at this routine, during the control of the colour washing routine, we take the byte, which is at COLOUR+00 and then we place it at COLOUR+$28, then we call a continuous loop which makes the data table cycle, by subtracting each piece of data in the data table by one, and read the calculations 40 times ($28 times), therefore the data table pulls each byte of data. Also inside our loop, the colours are read from the data table and the positioned on to the C64's colour screen RAM, which is from $D800 until $D828. As for reading the message, you'll see for yourself how that works. It is easy to remember ;o)
There is also a simple way to -reverse- the direction of your colour-washing routine. The listing below shows how you can do this :)
;======================
;COLOUR WASHING ROUTINE
;======================
COLWASH LDA
COLOUR+$28
STA COLOUR+$00
LDX #$28
CYCLE LDA
COLOUR-$01,X
STA COLOUR+$00,X
LDA COLOUR,X
STA $D7FF,X
DEX
BNE CYCLE
RTS
We reverse the process. You'll also notice that $D800,x has been changed into $D7FF,x. Why is this? Well, simply because if you used $D800 instead of $D7FF you would find that the C64 will miss the first character, therefore you will need to subtract 1 from the screen ram location. Pretty easy to understand huh?
Something to try:
Now that you have learned how to do simple colour cycling, try and put BOTH routines on to the screen. Create your own message at the top of the screen, and bottom of the screen and use one cycling routine at the top and a reverse routine at the bottom.
Don't get too excited because it will not be that easy to code your own C64 game :o) There are loads of new routines which you need to learn. To make things a lot easier, I have added a little explanation to each part of the program. You can also download everything in zipped .D64 format so you can read the code off-line and try to understand it a little more.
We are going to create a small 2 player game, where you have two ships. We'll be using three sprites for this tutorial, but in chapter 11, we will enhance the game more. Here is what to do. Using the sprite editor, draw 2 triangles (not in multi-colour) One pointing up, and the other pointing down, then draw 1 small circle. The two triangles will be the two players and the circle will be the player's bullet. Save your sprite data, and rip or compose your own demo tune using any music composer which initialise your tune at $1000 and play at $1003. Save your music to disk. However, If this is too much hassle to get you started then I have attached a .D64 image with the data and code. You'll just need Turbo Assembler. Please read the 2 note files supplied with the code and data. There is also a runnable file for you so you can see the sort of game, we're teaching you to create :). The runnable file was crunched using Time Cruncher V5.0, as I wanted to make quick file compression. While you're coding the game, this is how it should look.
...and now
the code:
;A$$EMBLE IT! - CODING
TUTORIAL
;Creating your first game ;This is an example tutorial for you
to ;Let's setup the perameters for
our plr1Äx = $0340 ;Player 1
x-position ;Our parameters for the player bullets plr1bÄx = $0344 ;Player 1
bullet-xpos ;Collisions parameters plr1col = $0350 ;Value storage for
p1 ;bullet lockup routines plr1lockup = $0360 ;Lockup for
players ;We need to create a jump start for
this *= $2400 start sei ;Set irq flag ;Clear the screen without JSR $E544 ldx
#$00 ;Calls a routine
;You should be familiar with the
next lda
#$00 lda
#$16 lda
#$1b lda
#$ff ;Now here we create the sprite objects lda
#$81 ;This is where we setup the colours
of lda #$02
;Colour red lda #$07
;Colour yellow ;This is a different routine, as now
the lda
$d000 ;This is a method
;Now we reposition the two players
and lda
#$42 ;All this is the
lda
#$00 ;All bullets are
;Setup the scoreboard lda #$30
;We put zero on: ;Now for the main body of this
program lda #<int ;
Call INT values lda #$00
;Initialise music lda
#$01 lda $dc0d
;Copy $DC0D to $DD0D
cli ;Clear IRQ
flag ;Our main interrupt int asl $d019 ;Keep $D019
running ;Call routine to expand and
reconvert jsr expand ;Call routine to read joystick port
2 jsr
read1up ;Call routine for bullet movements jsr bullmove ;Call routine for collision
detection jsr
detect ;And finally play the music jsr $1003 ;Play music pla ; An IRQ
loop routine. ;Expand and reconver the sprite position expand lda plr1Äy ;Copy player
y lda
plr1Äx ;Copy player x ;Read joystick control for player1 read1up lda $dc00 ;Read port
2 fire1 lsr a
;Firebutton ;Read joystick control for Player
2 read2up lda $dc01 ;Read JOY Port
1 ;call bullet routines bullmove ldx plr1bÄy ;The bullet
moves ldx
plr2bÄy ;The bullet moves ;Setup collision detection for player
1 detect lda
plr1Äx
;Calculate lda
plr2Äx ;The
same ;Check player 1 bullet collision
on p2col lda plr1bÄx ;Is
the bullet ;Check player2 bullet on player 1 ship p1col lda plr2bÄx
;Does the victory1
sei
;Stop all IRQs ldx
#$00 ;Call a
routine jmp
space ;Jump to
space victory2
sei
; Look at ldx
#$00 ;This
routine jmp
space ;You know
this space ldx
#$00 ;Another
text hitspace lda #$80
;Create a lda
$dc01 ;Read
SPACEBAR jmp
start ;Restart
game ;Our text display data tables. ;Player 1 victory vic1 .text "player 1 proves
that" ;Player 2 victory vic2 .text "player 2 proves
that" ;Spacebar prompt message spc .text " press the
spacebar" |