WIP Battle Pong- Questions, Comments, Snide Remarks Welcome

63 replies to this topic

#26 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Sun Aug 28, 2016 1:02 PM

```Affects Flags: S V Z C

MODE           SYNTAX       HEX LEN TIM
Immediate     ADC #\$44      \$69  2   2
Zero Page     ADC \$44       \$65  2   3
Zero Page,X   ADC \$44,X     \$75  2   4
Absolute      ADC \$4400     \$6D  3   4
Absolute,X    ADC \$4400,X   \$7D  3   4+
Absolute,Y    ADC \$4400,Y   \$79  3   4+
Indirect,X    ADC (\$44,X)   \$61  2   6
Indirect,Y    ADC (\$44),Y   \$71  2   5+
```

You'll notice there's a Zero Page,X but not a Zero Page,Y. dasm knows this, so it will use Absolute,Y instead. Likewise Indirect,X and Indirect,Y look different in the SYTNAX in order to help you remember that they work differently.  I don't think I've ever used Indirect,X

I think I get it though not sure on this one.  Is (\$44,x) a 16 bit address and (\$44),Y an indexed zero page address?

Also, funny you mentioned Draconian.  I got a Harmony Encore last week and last night I added Draconian to it and played it.

#27 OmegamatrixOFFLINE

Omegamatrix

• 6,098 posts

Posted Sun Aug 28, 2016 2:06 PM

I think I get it though not sure on this one.  Is (\$44,x) a 16 bit address and (\$44),Y an indexed zero page address?

Both those instructions use a 16 bit address. This is why when you set up the pointer you have to store a high byte of the address and a low byte of the address.

The actual instruction only takes one byte for the operand, which is the ram location of the low address of the pointer.

Example:

```    SEG.U RIOT_RAM
ORG \$80

colorPtr   ds 2      ; designates 2 bytes of ram (\$80-\$81) for a 16 bit address, which is stored little endian
; zero page (zp) ram location \$80 is the low byte of the address
; zero page (zp) ram location \$81 is the high byte of the address

SEG CODE
ORG \$F000

;.....

lda #<ColorP0     ; get low address
sta colorPtr      ; store to zero page ram location \$80
lda #>ColorP0     ; get high address
sta colorPtr+1    ; store to zero page ram location \$80+1 = \$81

;usage
lda (colorPtr),Y  ; in Stella's debugger (or the list file) this will be \$B1 \$80 (just 2 bytes, not 3)
; \$B1 is the opcode for lda (indirect),Y ; \$80 is the operand for lda (indirect),Y
; - For lda (indirect),Y the operand is the zp ram location which holds the low address of our pointer.
; - It is required that the high part of the address be stored in ram immediately after the low address,
; which in this case would be zp ram location \$81. This requirement allows lda (indirect),Y to only use
; 2 bytes of code instead of 3.```

For (indirect,X) you probably will never use it, so I'm not going to explain it.

#28 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Tue Aug 30, 2016 5:58 PM

Now for jumps:

It's branches could only move forward or backward half a page. Jumps can go anywhere in the current bank. The state table doesn't have to be close as you are using absolute indexed addressing to look up the values.

Ah..  OK.  Got it.  Thanks!

#29 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Tue Aug 30, 2016 6:06 PM

For (indirect,X) you probably will never use it, so I'm not going to explain it.

Fair enough

#30 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Wed Aug 31, 2016 6:49 PM

OK.. I made the score changes and to my surprise, implemented the state machine.  I think I have a pretty complete understanding of it now..

Thanks everyone for the help!

#31 tschak909OFFLINE

tschak909

Stargunner

• 1,481 posts
• Location:USA

Posted Wed Aug 31, 2016 8:01 PM

STATIC AND COLOR BARS IN A GAME?!? bwahahaha... I'm laughing my ass off, in a good way... that's one hell of a sense of humour in a game Hats off to you, man

-Thom

(in other words, Great job!)

Edited by tschak909, Wed Aug 31, 2016 8:01 PM.

#32 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Thu Sep 1, 2016 3:33 AM

Thanks!  Did you notice that the game keeps resetting?  The score always starts over from zero every time it comes up.  I didn't realize until after I posted.  I'm certain I need to change the JumboState mask:

```FrameCount:
inc FrameCounter
lda FrameCounter
cmp #255
beq IncDisplay
jmp EndIncDisplay

IncDisplay:
inc JumboState
lda JumboState
and #%00001111
sta JumboState
EndIncDisplay:

```

#33 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Thu Sep 1, 2016 3:52 AM

There we go, I masked it at 4 and added an extra trip on the score loop to bring it up to 4 states.

#34 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Sat Sep 3, 2016 6:03 AM

Now for another big one I've been ignoring... The coins.  I want the coins to disappear one at time when a player is running over them.  To accomplish this, I'm thinking of doing something like this:

1. The coins are stored in RAM using 12 bytes per player.  (There has got to be a better way to do this.) Each byte is a PF2 line.

2. Detect playfield collisions

3. Get x and y coordinates of player.

4. Apply a mask that corresponds to each stack. Currently, the coins in PF2 are the D5, D3, and D1 bits. So something like:

```
;------------------------------------------------------------------------------
; Decrement Coins
;----------------

; The stacks of coins are displayed using PF2 register. Three stacks of coins.
; Before the jsr, upon collision, the accumulator will have been loaded with either %00100000,
; 00001000, or 00000010 which correspond to one of the stacks.

CoinCollision:			;
ldx #11			; The stacks of coins are potentially 12 high

CoinTest:
and PillRAMGfx,x	; Check to see if there is a match on this line
bpl RemoveCoin		; Branch if we've hit a coin
dex
bne CoinTest		; Repeat if there was not match

RemoveCoin:
eor #%11111111		; Change 00100000 to 11011111 for example
and PillRAMGfx,x	; Remove a coin from the first stack for this example
sta PillRAMGfx,x	; Then store it back from where it came.
rts

```

Funny, while trying to show an example of the code I was going to write, I ended up writing the code.  I'll have to remember that technique. How does it look?

Edited by BNE Jeff, Sat Sep 3, 2016 6:18 AM.

#35 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Sat Sep 3, 2016 11:31 AM

Hmm..  It doesn't work yet.  I added the player/playfield collisions but the score loop was causing player/playfield collisions on every loop.  Also I didn't account for PF2 being reversed so I had to change the initial LDA.  I fixed those but I guess BPL also branches on zero?

#36 tschak909OFFLINE

tschak909

Stargunner

• 1,481 posts
• Location:USA

Posted Sat Sep 3, 2016 12:03 PM

BPL branches when the sign bit is clear after an operation. This means that since 0 doesn't flip the sign bit, it will still take the branch. It will fall through however, when the counter wraps around to \$FF, since the sign bit is set.

-Thom

#37 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Sat Sep 3, 2016 2:58 PM

BPL branches when the sign bit is clear after an operation. This means that since 0 doesn't flip the sign bit, it will still take the branch. It will fall through however, when the counter wraps around to \$FF, since the sign bit is set.

-Thom

Thanks..  I got rid of the BPL and used BEQ instead. Its a couple more steps but its working! (By which I mean, if player 0 touches the playfield anywhere, one stack of coins will disappear one at a time, but really fast.)

```;------------------------------------------------------------------------------
; Decrement Coins
;----------------

; The stacks of coins are displayed using PF2 register. Three stacks of coins.
; Before the jsr, the y register will have been loaded with either %00000100,
; %00010000, or %01000000 which correspond to one of the stacks.

CoinCollision:
ldx #12			; The stacks of coins are potentially 12 high

CoinTest:
tya			; y has to be transferred each time through
dex			; go to next coin location
beq EndCoinCheck	; End if we're at the bottom of the coin stack.
and PillRAMGfx,x	; Check to see if there is a match on this line
beq CoinTest		; If zero matches, go back up

RemoveCoin:
eor #%11111111		; Change 00000100 to 111111011 for example
and PillRAMGfx,x	; Remove a coin from the first stack for this example
sta PillRAMGfx,x	; Then store it back from where it came.

EndCoinCheck
rts

```

#38 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Thu Sep 8, 2016 4:47 PM

Greetings!

The coins can now be collected by the players- at the cost of 24 bytes of RAM

Added some collision stuff and software control of ball speed.  You can really get the ball moving. (Or stopped if you time it right.)

To stabilize the screen, I set a timer inside the top wall and I only re-position the two players within it.  If you turn on debug colors (ALT+ comma)and move the players around the right side of the screen, you'll see the comb line bounce around, but not anything else.

Attached Files

Edited by BNE Jeff, Thu Sep 8, 2016 4:49 PM.

#39 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Sun Feb 12, 2017 3:10 PM

Hi!...

So I have a state machine question..  I have this state state machine:

```    ldy    JumboState
lda    JumboLo,Y
sta    jumbo_JumpInd
lda    JumboHi,Y
sta    jumbo_JumpInd+1
jmp.ind (jumbo_JumpInd)   ; indirect jump into code segment

and...

JumboLo:
.byte <ShowFireballsLogo
.byte <TestPattern
.byte <TwoScore
.byte <TwoScore
JumboHi:
.byte >ShowFireballsLogo
.byte >TestPattern
.byte >TwoScore
.byte >TwoScore

```

It works great, but when I tried to call ShowFireballsLogo from elsewhere with a JSR, I realized I cannot because the routines end with a JMP since they were set up with the state machine using the above jmp.ind, they therefore do not have an RTS.

Does anybody have any tips on how to be able to call routines in a state machine but using a JSR?

Thanks!

Edited by BNE Jeff, Sun Feb 12, 2017 3:30 PM.

#40 gauauuOFFLINE

gauauu

Chopper Commander

• 217 posts
• Location:Illinois

Posted Sun Feb 12, 2017 9:56 PM

You can just push manually an address onto the stack (ie the address of where you want to return to) using PHA, then do your indirect jump like you're currently doing it.

When you hit the RTS at the end of your subroutine, it will pop an address off the stack and jump to it.  It doesn't matter how that address got there -- it doesn't care whether you actually did a JSR, or what, just as long as there's an address to pop off and jump to.

(To be technical, I think you have to push the address - 1, it doesn't return to the exact address that's on the stack)

#41 carlssonOFFLINE

carlsson

River Patroller

• 3,838 posts
• Location:Västerås, Sweden

Posted Mon Feb 13, 2017 5:29 AM

Couldn't you break out the code into a mostly pointless subroutine?

ShowFireballsLogo:

jsr ShowFireballsLogo1

[.. rest of code ..]

and in your other routine, call ShowFireballsLogo1 instead, which is designed to return with a RTS?

#42 RevEngOFFLINE

RevEng

River Patroller

• 4,386 posts
• Bitnik

Posted Mon Feb 13, 2017 7:05 AM

Does anybody have any tips on how to be able to call routines in a state machine but using a JSR?

Stick this bit of "state machine" code out of the regular program path, and JSR to it.

#43 gauauuOFFLINE

gauauu

Chopper Commander

• 217 posts
• Location:Illinois

Posted Mon Feb 13, 2017 10:43 AM

Stick this bit of "state machine" code out of the regular program path, and JSR to it.

This really is the easiest way to deal with it, despite what I said above

#44 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Mon Feb 13, 2017 8:08 PM

Thanks..

As I recall, I set up the state machine to avoid having to do a jumbled bunch of compares and JSRs so I don't think I can easily break it out into its own..  I definitely like the idea of using PHA- mainly because I've never used any stack instructions before.  I always wondered what the point of some of those instructions was so it will be a valuable learning experience.

ShowFireballsLogo currently does not have an RTS at the end of it, just a JMP- which I'll need to change.  And I guess I'll have to work in another PHA in the other location as well.

Thanks again for all the advice!

#45 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Sun Feb 19, 2017 3:22 PM

I spent a little time trying to wrap my head around this..  I need a 16 bit address- right? And I don't think DASM has any magic trick for it so would it be something like this?

```StartSreenLo:

StartScreenHi:

lda    StartScreenLo,Y
pha
lda    StartScreenHi,Y
pha
```

#46 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Sat Feb 25, 2017 1:48 PM

Before I proceed, should this code work?:

```lda <StartScreenReturn
pha
lda >StartScreenReturn
pha
jmp ShowFireballsLogo

StartScreenReturn:
```

And my ShowFireballsLogo routine would end with an rts

#47 SpiceWareONLINE

SpiceWare

• 10,745 posts
• Medieval Mayhem
• Location:Planet Houston

Posted Sat Feb 25, 2017 1:58 PM

close - you left off the #, and the address is off by 1 due to how RTS works.

RTS pulls the top two bytes off the stack (low byte first) and transfers program control to that address+1.

So subtract 1 from the address to compensate.

```  lda #<(StartScreenReturn-1)
pha
lda #>(StartScreenReturn-1)
pha
jmp ShowFireballsLogo

StartScreenReturn:
```

#48 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Sat Feb 25, 2017 4:05 PM

Thanks!

I read up on rts and made the change, but it never returns.  Looking the debugger, it puts \$FACE in the stack and when it comes to the rts, it restarts the program completely.  I don't see that address (\$FACE) in the debugger either.  Any ideas?

#49 SpiceWareONLINE

SpiceWare

• 10,745 posts
• Medieval Mayhem
• Location:Planet Houston

Posted Sat Feb 25, 2017 4:25 PM

Looking at the example with the specs for RTS, the high byte should be done first. Swap the > and < to fix that.

#50 BNE JeffOFFLINE

BNE Jeff

Chopper Commander

• Topic Starter
• 233 posts
• Location:Virginia, USA

Posted Sat Feb 25, 2017 5:06 PM

Ahh..  I see it now.  It works.. Thanks!

0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users