Jump to content
IGNORED

My first game in assembler


olix

Recommended Posts

When I had my first Atari 400 in the early 80's, there was one game I always was jealous about VCS owners: Haunted House. I hadn't even played the game in the past, but loved the pictures on the box and the "spooky" story described in the Atari catalog. Is it really possible that there hasn't been a port of it for the Atari 8-bit computers to this day?

 

So I decided to write my own version of this game. But it's not an emulation of the original code, I'm reprogramming the game with my own code. This is actually my first machine language game ever.

 

A beginning has been made: I have my playfield and my main character.
Fine scrolling works and the collision detection with the walls too.

Now it goes on with the treasures and then of course the bad, creepy enemies. So still a lot of work.....

  • Like 34
  • Thanks 4
Link to comment
Share on other sites

1 hour ago, rdefabri said:

That is awesome!  I wish there were an easy way to learn Assembler, I just never "got it".  I'm much more of a C / C++ guy.

 

Great work - keep it coming!  I loved Haunted House, will be a great addition to the games library!

There is "Action!"  It's a lot easier to learn for a C coder.

 

  • Like 2
Link to comment
Share on other sites

4 hours ago, reifsnyderb said:

There is "Action!"  It's a lot easier to learn for a C coder.

 

I'm looking into all options - right now, it's mostly BASIC / Turbo Basic XL / Fast BASIC, since I know Atari BASIC pretty well.  I'd consider Mad Pascal or Action for a future thing, but still trying to re-learn the Atari itself first! :)

Link to comment
Share on other sites

7 minutes ago, rdefabri said:

I have it - but Assembly Language is Greek to me.  I can't get it, I think I'm too old to ever understand it.

It just take a bit of practice, a good way is to use something like MAC/65 and BUG/65

MAC/65 to write an assemble your code and BUG/65 allows you to load and step through

the code instruction by instruction, you can see the effect of your code on the 6502

registers etc.

 

I started with the Assembler Editor cartridge bitd and just played with code to see what happened

and then used assembler code as USR calls in BASIC.

 

I'm no expert, but believe I'm quite proficient at writing 6502 and 68000 machine code.

 

With the Atari, also knowing the hardware and it's registers is essential too.

 

and your never too old to learn 🤩

 

I still write today and think I may be one of the oldest members on this forum

  • Like 3
Link to comment
Share on other sites

A good way to get started understanding assembly is by examining some of the BASIC machine language subroutines.

You can find them in some of the magazine listings in Compute, Antic, Analog, etc.

The good thing about understanding them, too, is that you can manipulate them for your own use in your BASIC

programs, if needed.

 

For instance, here's one for changing some colors in a DLI. It's not a BASIC ML subroutine per se, but it's as simple

as any you'd find, and still very usable within a BASIC program.

 

So, even if you're going to stick with BASIC, or some other higher-level language, it can be quite beneficial to understand a little assembler.

 

[Note: This just shows the mnemonics, their decimal values, and the decimal values of the data being loaded/stored or the memory addresses being referenced. The decimal values are what you'd see in data statements (for instance) in your BASIC program for loading the routine into memory.]

 

[Edit]

In a nutshell, all this program does is load color values in the Accumulator, X-Register, and Y-Register; and then store them into the hardware registers for the background, foreground, and border. Everything else is just housekeeping required for a DLI. 

 

STEP I: Save the accumulator, the X-register and the Y-register onto the stack.  
PHA    72     save accumulator
TXA    138    transfer X to accumulator
PHA    72     save accumulator
TYA    152    transfer Y to accumulator
PHA    72     save accumulator

 

STEP II: load register.
LDA    169,42     load accumulator with yellow
LDX    162,192    load X with dark green
LDY    160,92     load Y with pink

 

STEP III: Wait for horizontal blank. Store colors.
STA WYSNC    141,10,212    wait for horizontal blank
STA COLOR1   141,24,208    yellow to background register
STX COLOR2   142,23,208    dark green to foreground
STY COLOR3   140,26,208    pink to border register

 

STEP IV: Restore the accumulator, X and Y registers.
PLA    104    recall top value on stack into accumulator
TAY    168    transfer it to Y register
PLA    104    recall next value on stack
TAX    170    transfer it to X register
PLA    104    recall original accumulator value

 

STEP V: Return from interrupt.
RTI    64    return
 

  • Like 1
Link to comment
Share on other sites

1 hour ago, TGB1718 said:

It just take a bit of practice, a good way is to use something like MAC/65 and BUG/65

MAC/65 to write an assemble your code and BUG/65 allows you to load and step through

the code instruction by instruction, you can see the effect of your code on the 6502

registers etc.

 

I started with the Assembler Editor cartridge bitd and just played with code to see what happened

and then used assembler code as USR calls in BASIC.

 

I'm no expert, but believe I'm quite proficient at writing 6502 and 68000 machine code.

 

With the Atari, also knowing the hardware and it's registers is essential too.

 

and your never too old to learn 🤩

 

I still write today and think I may be one of the oldest members on this forum

I can (sort of) understand the USR calls more than the mnemonics in Assembler.  Maybe I need to just sit down and read it, although I'm not suffering from insomnia, so it may take me a while :)

Link to comment
Share on other sites

1 hour ago, MrFish said:

A good way to get started understanding assembly is examine some of the BASIC machine language subroutines.

You can find them in some of the magazine listings in Compute, Antic, Analog, etc.

The good thing about understanding them, too, is that you can manipulate them for your own use in your BASIC

programs, if needed.

 

For instance, here's one for changing some colors in a DLI. It's not a BASIC ML subroutine per se, but it's as simple

as any one you'd find, and still very usable within a BASIC program.

 

So, even if you're going to stick with BASIC, or some other higher-level language, it can be quite beneficial to understand a little assembler.

 

[Note: This just shows the mnemonics, their decimal values, and the decimal values of the data being loaded/stored or the memory addresses being referenced. The decimal values are what you'd see in data statements (for instance) in your BASIC program for loading the routine into memory.]

 

[Edit]

In a nutshell, all this program does is load color values in the Accumulator, X-Register, and Y-Register; and then stores them into the hardware registers for the background, foreground, and border. Everything else is just housekeeping required for a DLI. 

 

STEP I: Save the accumulator, the X-register and the Y-register onto the stack.  
PHA    72     save accumulator
TXA    138    transfer X to accumulator
PHA    72     save accumulator
TYA    152    transfer Y to accumulator
PHA    72     save accumulator

 

STEP II: load register.
LDA    169,42     load accumulator with yellow
LDX    162,192    load X with dark green
LDY    160,92     load Y with pink

 

STEP III: Wait for horizontal blank. Store colors.
STA WYSNC    141,10,212    wait for horizontal blank
STA COLOR1   141,24,208    yellow to background register
STX COLOR2   142,23,208    dark green to foreground
STY COLOR3   140,26,208    pink to border register

 

STEP IV: Restore the accumulator, X and Y registers.
PLA    104    recall top value on stack into accumulator
TAY    168    transfer it to Y register
PLA    104    recall next value on stack
TAX    170    transfer it to X register
PLA    104    recall original accumulator value

 

STEP V: Return from interrupt.
RTI    64    return
 

Some of it makes sense - what I don't know is the syntax after the mnemonics "WSYNC" for example.  Is there a list of the decimal values and what they relate to specifically for the Atari?  I've figured some of it out through BASIC, but at a very primary level.

Link to comment
Share on other sites

50 minutes ago, rdefabri said:

Some of it makes sense - what I don't know is the syntax after the mnemonics "WSYNC" for example.  Is there a list of the decimal values and what they relate to specifically for the Atari?  I've figured some of it out through BASIC, but at a very primary level.

What follows, in that particular line, is 141, which is the decimal value for an STA command to the 6502, and then 10 & 212, which are the lsb & msb for the address of the WYSNC register. So, WYSNC is not a mnemonic here, it is just an equate for the register location in memory, which is 54282 (decimal) and $D40A (hex).

 

What you're asking for would be a listing that had decimal values for all the 6502 instructions, of which there are many out there (this is not specific to the Atari); and then something containing hardware register locations, which would be something like "Mapping the Atari".

 

Link to comment
Share on other sites

10 hours ago, rdefabri said:

I have it - but Assembly Language is Greek to me.  I can't get it, I think I'm too old to ever understand it.

It‘s a bit like assembling (no pun intended) your car before actually driving. You do the same things you‘d do in C (or any other language): loops, branches, manipulation of variables, input, output, etc. but you do it in minuscule steps taking care of everything yourself. 
 

IMHO what you need most is a very good description of the Atari‘s memory map and workings of the various graphics and sound gizmos to know what to store where to get something visible on the screen. Therefore it‘s better to learn with an Atari specific book rather than general 6502 assembly language tutorials as visible results learning more interesting than just looking at a few changes memory locations. 
 

The actual workings of assembler code are rather banal except for maybe the carry flag. There’s a bit more to wrap your head round if you try to write very fast and/or tight code but even iconic game programmers of the 80‘s sometimes used code that was superfluous (I assume because they had not discovered easier ways yet). 
 

Be sure to comment copiously. Even for the small stuff I’ve done so far I don‘t get what my own code does if I don‘t.

 

I found ML coding on a PC using WUDSN and an Emulator much easier than on real hardware as the debugging facilities are vastly superior. 

  • Like 3
Link to comment
Share on other sites

15 hours ago, rdefabri said:

Is there a list of the decimal values and what they relate to specifically for the Atari?

 

14 hours ago, MrFish said:

What you're asking for would be a listing that had decimal values for all the 6502 instructions, of which there are many out there (this is not specific to the Atari);

 

Apparently it isn't so common for 6502 instruction set listings to include decimal values; they're most often given in hex only. Here's one that does give the decimal values. However, it doesn't include descriptions; but you can get one here that does: 6502 Instruction Set (with descriptions)

 

[Note: In both listings, that a given instruction can have different decimal/hex values depending on which addressing mode is being used. For instance, in the example above, where STA has a decimal value of 141, that this is only for absolute addressing mode -- which is how WYSYNC is being addressed in that case.]

 

NMOS 6502 Opcodes

opcode mode octal decimal hex bytes cycles
brk implied 0000 0 0x00 1 7
ora (ind,x) 0001 1 0x01 2 6
ora zp 0005 5 0x05 2 3
asl zp 0006 6 0x06 2 5
php implied 0010 8 0x08 1 3
ora imm 0011 9 0x09 2 2
asl accum 0012 10 0x0a 1 2
ora abs 0015 13 0x0d 3 4
asl abs 0016 14 0x0e 3 6
bpl relative 0020 16 0x10 2 2∗
ora (ind),y 0021 17 0x11 2 5•
ora zp,x 0025 21 0x15 2 4
asl zp,x 0026 22 0x16 2 6
clc implied 0030 24 0x18 1 2
ora abs,y 0031 25 0x19 3 4•
ora abs,x 0035 29 0x1d 3 4•
asl abs,x 0036 30 0x1e 3 7
jsr abs 0040 32 0x20 3 6
and (ind,x) 0041 33 0x21 2 6
bit zp 0044 36 0x24 2 3
and zp 0045 37 0x25 2 3
rol zp 0046 38 0x26 2 5
plp implied 0050 40 0x28 1 4
and imm 0051 41 0x29 2 2
rol accum 0052 42 0x2a 1 2
bit abs 0054 44 0x2c 3 4
and abs 0055 45 0x2d 3 4
rol abs 0056 46 0x2e 3 6
bmi relative 0060 48 0x30 2 2∗
and (ind),y 0061 49 0x31 2 5•
and zp,x 0065 53 0x35 2 4
rol zp,x 0066 54 0x36 2 6
sec implied 0070 56 0x38 1 2
and abs,y 0071 57 0x39 3 4•
and abs,x 0075 61 0x3d 3 4•
rol abs,x 0076 62 0x3e 3 7
rti implied 0100 64 0x40 1 6
eor (ind,x) 0101 65 0x41 2 6
eor zp 0105 69 0x45 2 3
lsr zp 0106 70 0x46 2 5
pha implied 0110 72 0x48 1 3
eor imm 0111 73 0x49 2 2
lsr accum 0112 74 0x4a 1 2
jmp abs 0114 76 0x4c 3 3
eor abs 0115 77 0x4d 3 4
lsr abs 0116 78 0x4e 3 6
bvc relative 0120 80 0x50 2 2∗
eor (ind),y 0121 81 0x51 2 5•
eor zp,x 0125 85 0x55 2 4
lsr zp,x 0126 86 0x56 2 6
cli implied 0130 88 0x58 1 2
eor abs,y 0131 89 0x59 3 4•
eor abs,x 0135 93 0x5d 3 4•
lsr abs,x 0136 94 0x5e 3 7
rts implied 0140 96 0x60 1 6
adc (ind,x) 0141 97 0x61 2 6†
adc zp 0145 101 0x65 2 3†
ror zp 0146 102 0x66 2 5
pla implied 0150 104 0x68 1 4
adc imm 0151 105 0x69 2 2†
ror accum 0152 106 0x6a 1 2
jmp (abs) 0154 108 0x6c 3 6
adc abs 0155 109 0x6d 3 4†
ror abs 0156 110 0x6e 3 6
bvs relative 0160 112 0x70 2 2∗
adc (ind),y 0161 113 0x71 2 5•†
adc zp,x 0165 117 0x75 2 4†
ror zp,x 0166 118 0x76 2 6
sei implied 0170 120 0x78 1 2
adc abs,y 0171 121 0x79 3 4•†
adc abs,x 0175 125 0x7d 3 4•†
ror abs,x 0176 126 0x7e 3 7
sta (ind,x) 0201 129 0x81 2 6
sty zp 0204 132 0x84 2 3
sta zp 0205 133 0x85 2 3
stx zp 0206 134 0x86 2 3
dey implied 0210 136 0x88 1 2
txa implied 0212 138 0x8a 1 2
sty abs 0214 140 0x8c 3 4
sta abs 0215 141 0x8d 3 4
stx abs 0216 142 0x8e 3 4
bcc relative 0220 144 0x90 2 2∗
sta (ind),y 0221 145 0x91 2 6
sty zp,x 0224 148 0x94 2 4
sta zp,x 0225 149 0x95 2 4
stx zp,y 0226 150 0x96 2 4
tya implied 0230 152 0x98 1 2
sta abs,y 0231 153 0x99 3 5
txs implied 0232 154 0x9a 1 2
sta abs,x 0235 157 0x9d 3 5
ldy imm 0240 160 0xa0 2 2
lda (ind,x) 0241 161 0xa1 2 6
ldx imm 0242 162 0xa2 2 2
ldy zp 0244 164 0xa4 2 3
lda zp 0245 165 0xa5 2 3
ldx zp 0246 166 0xa6 2 3
tay implied 0250 168 0xa8 1 2
lda imm 0251 169 0xa9 2 2
tax implied 0252 170 0xaa 1 2
ldy abs 0254 172 0xac 3 4
lda abs 0255 173 0xad 3 4
ldx abs 0256 174 0xae 3 4
bcs relative 0260 176 0xb0 2 2∗
lda (ind),y 0261 177 0xb1 2 5•
ldy zp,x 0264 180 0xb4 2 4
lda zp,x 0265 181 0xb5 2 4
ldx zp,y 0266 182 0xb6 2 4
clv implied 0270 184 0xb8 1 2
lda abs,y 0271 185 0xb9 3 4•
tsx implied 0272 186 0xba 1 2
ldy abs,x 0274 188 0xbc 3 4•
lda abs,x 0275 189 0xbd 3 4•
ldx abs,y 0276 190 0xbe 3 4•
cpy imm 0300 192 0xc0 2 2
cmp (ind,x) 0301 193 0xc1 2 6
cpy zp 0304 196 0xc4 2 3
cmp zp 0305 197 0xc5 2 3
dec zp 0306 198 0xc6 2 5
iny implied 0310 200 0xc8 1 2
cmp imm 0311 201 0xc9 2 2
dex implied 0312 202 0xca 1 2
cpy abs 0314 204 0xcc 3 4
cmp abs 0315 205 0xcd 3 4
dec abs 0316 206 0xce 3 6
bne relative 0320 208 0xd0 2 2∗
cmp (ind),y 0321 209 0xd1 2 5•
cmp zp,x 0325 213 0xd5 2 4
dec zp,x 0326 214 0xd6 2 6
cld implied 0330 216 0xd8 1 2
cmp abs,y 0331 217 0xd9 3 4•
cmp abs,x 0335 221 0xdd 3 4•
dec abs,x 0336 222 0xde 3 7
cpx imm 0340 224 0xe0 2 2
sbc (ind,x) 0341 225 0xe1 2 6†
cpx zp 0344 228 0xe4 2 3
sbc zp 0345 229 0xe5 2 3†
inc zp 0346 230 0xe6 2 5
inx implied 0350 232 0xe8 1 2
sbc imm 0351 233 0xe9 2 2†
nop implied 0352 234 0xea 1 2
cpx abs 0354 236 0xec 3 4
sbc abs 0355 237 0xed 3 4†
inc abs 0356 238 0xee 3 6
beq relative 0360 240 0xf0 2 2∗
sbc (ind),y 0361 241 0xf1 2 5•†
sbc zp,x 0365 245 0xf5 2 4†
inc zp,x 0366 246 0xf6 2 6
sed implied 0370 248 0xf8 1 2
sbc abs,y 0371 249 0xf9 3 4•†
sbc abs,x 0375 253 0xfd 3 4•†
inc abs,x 0376 254 0xfe 3 7

 

• - Add 1 to N if page boundary is crossed

∗ - Add 1 to N if branch occurs to same page, add 2 to N if branch occurs to different page

† - Add 1 to N if in decimal mode

 

 

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

13 minutes ago, TGB1718 said:

See my attachment earlier in this thread

Yeah, I did see that before. I'm quite familiar with it too; it's on my website. The descriptions there are rather sparse (expected, as it's a reference card) compared to what I'm linking to, though. The one I linked to is also a pretty handy/clickable (color-coded, etc.), webpage reference.

 

  • Like 1
Link to comment
Share on other sites

15 hours ago, rdefabri said:

Some of it makes sense - what I don't know is the syntax after the mnemonics "WSYNC" for example.

To be clear, the lines shown in each of those steps aren't from an assembly program listing. They're basically part of a breakdown and description of the decimal values that were packed into the DATA statements from an Atari BASIC program.

 

Link to comment
Share on other sites

At least for me, the main struggle with assembler is related with the implementation of "functions" and more generally, the structure of the "main loop", like should I do math and process game logic in the main section (outside ISRs) or during the VBI?, or both? what about instructions executed during DLI?, maybe I should add more there. Of course, the answers to those questions are almost always "It depends". My take on this is basically, I will learn that by doing, by getting experience, by "copying and stealing with pride"(TM) from experienced Atari game programmers. Anyway, in that sense the book "Atari graphics & arcade game design" by Stanton and Pinal is great.

 

 

 

 

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...