Jump to content
IGNORED

16-bit math on the 2600


johnnywc

Recommended Posts

Hello all,

 

I'm working away on my hockey game and I'm trying to come up with a way to simulate the puck hitting the boards and reversing direction, but I think my 6502 arithmetic knowledge is a little weak...

 

I'm trying to use fractional math for the X and Y coordnates, as well as the horizontal and vertical components:

 

Puck_X ds 2

Puck_Y ds 2

Puck_H ds 2

Puck_V ds 2

 

In each case, the lower byte is storing the "fractional" part and the higher byte is storing the integer part (very much like Kirk Israel's method in JoustPong).

 

To move the puck (let's focus on the X coord and the H component), I'm doing standard 16-bit math:

 

CLC

LDA Puck_X

ADC Puck_H

STA Puck_X

LDA Puck_X+1

ADC Puck_H+1

STA Puck_X+1

 

I can then position the puck using the high byte (Puck_X+1).

 

This works fine for the situation where the H component is positive.

 

When the puck hits the wall, I reverse the H direction by calculating it's 2's complement:

 

LDA Puck_H

EOR #$FF

TAY

INY

STY Puck_H

LDA Puck_H+1

EOR #$FF

TAY

INY

STY Puck_H+1

 

(is there a better way to compute the 2's complement of a number???)

 

The behavior I see is:

 

- the integral part seems to work fine (that is, if it's to "1", the object moves right, hits the boundary, the value is converted to -1, and the object starts moving left

- the fractional part doesn't seem to be working in the negative direction. In my example, I set the fractional part to 127 (to simulate a 1.5 pixel motion). It doesn't seem to have any impact on the speed of the object in the negative direction.

 

Does anybody have any ideas or a possible solution to this? I'm thinking I might have to subtract with negative values, but I would think there should be a way to just "add" a negative number to achieve the same result.

 

Thanks for any suggestions,

Link to comment
Share on other sites

Hmmm...

 

The more I think about this:

 

Would it make more sense to store a bit that determines what direction the puck is moving (one each for the H and V components)? With this method, I would either add (for positive values) or subtract (for negative values). To "reverse" a direction, I would just invert the bit. To apply friction, I would be able to just decrease the H component using subtraction.

 

Does this sound feasible?

 

The pros are:

 

- "reverse" code becomes very simple

- friction becomes more simple (only have to subtract from one value)

- it might actually work, as opposed to the way I'm doing it now

 

Cons:

 

- I need to add a check for the direction bit and jmp to either subtraction or addition code based on the value instead of always just adding unconditionally

 

Any ideas are welcomed!

 

Thanks,

Link to comment
Share on other sites

UPDATE:

 

I implemented the solution as described above and it works very well, but seems pretty convoluted. I was even able to implement friction so the puck will slow down naturually on the ice and slow down even more when it hits the boards (I actually half the H and V components when it hits the boards by doing a LSR from the high byte to the low byte).

 

If anyone else has a better solution, I'd love to hear it!

 

Thanks for letting me ramble... :)

Link to comment
Share on other sites

The way you're moving the puck should work fine with + and -

 

You have to be a bit careful on your 2's complements though:

 

your code whilst pretty neat by saving a couple of bytes, doesn't deal with any carry generated by the low byte, which means that when puck_h=0 and negated, the high byte will be out by 1. Not sure, but depending how accurate you want things, that might not be a major issue? I'm sure someone else can clarify that though. This code for 16 bit 2's complement should work ok though:

 

clc

lda puck_h

eor #$ff

adc #1

sta puck_h

lda puck_h+1

eor #$ff

adc #1

sta puck_h+1

 

 

-128=11111111 01111111

 

when you're testing the -128 don't forget that that high byte must be 255 not 0, as well as the low byte being set to 127. hopefully the darn puck will move the other way then :twisted:

Link to comment
Share on other sites

For Marble Craze I just used a velocity table instead of fractional positioning, so the math was trivial. I don't think the table needs to be very large either. Not sure if this would work for you, but MC has pretty much the same physics you need for hockey (including friction and bouncing off walls).

 

-paul

Link to comment
Share on other sites

The way you're moving the puck should work fine with + and -

 

You have to be a bit careful on your 2's complements though:

 

your code whilst pretty neat by saving a couple of bytes, doesn't deal with any carry generated by the low byte, which means that when puck_h=0 and negated, the high byte will be out by 1. Not sure, but depending how accurate you want things, that might not be a major issue? I'm sure someone else can clarify that though. This code for 16 bit 2's complement should work ok though:

 

clc

lda puck_h

eor #$ff

adc #1

sta puck_h

lda puck_h+1

eor #$ff

adc #1

sta puck_h+1

 

 

-128=11111111 01111111

 

when you're testing the -128 don't forget that that high byte must be 255 not 0, as well as the low byte being set to 127. hopefully the darn puck will move the other way then  :twisted:

 

:!: oops -128 =11111111 10000000 :ponder:

-0.5

Link to comment
Share on other sites

Chris -

 

Thanks for the info. Unfortunately, it doesn't seem to work. Again, it works in the positive direction, but when it reverses the fractional part doesn't seem to have an effect on the speed. What's even more strange is that the speed seems the same if I compute the 2's complement of the fractional part or not!

 

On the other hand, by just using positive values for H and V and having a bit to determine the direction and switching to ADC or SBC works well, and also reduces the code to reflect (since I just need to invert one bit) and for friction (since I always decrement or shift to the right). In the end, I think it will take less ROM space and cycles to do it this way.

 

Paul - thanks for the idea of a velocity table. Unforuntately, I'm not exactly sure what you mean. :( Can you elaborate???

 

Thanks again for all the help!!

Link to comment
Share on other sites

Here is the binary with the 2nd method employed (H always positive, bit deciding whether to add or subtract).

 

Joystick Up will increase the H component

Joystick Down will decrease the H component (it doesn't check for 0 so unpredictable results happen when it goes negative!)

 

The V component is constant.

 

Be kind - this is my first attempt at 2600 programming... :)

hockey3.zip

Link to comment
Share on other sites

Thanks guys - that second way made a big difference (and it works!). I'm not sure which way I'll keep it - I'll see how the rest of the implementation goes.

 

To be clear - should the first AND second ADC be ADC #0? Or is the SEC taking care of adding one to the inverse?

 

Thanks again! This was a HUGE help and very insprirational!!

 

:)

Link to comment
Share on other sites

(is there a better way to compute the 2's complement of a number???)

 

You mean how to negate a two complements value (number=-number)?

Substrack the number from zero.

 

LDA #0

SCF

SBC PUCK_H

STA puck_H

LDA #0

SBC PUCK_H+1

STA PUCK_H+1

 

should do the trick

Link to comment
Share on other sites

To be clear - should the first AND second ADC be ADC #0?  Or is the SEC taking care of adding one to the inverse?

 

Yes, it adds 1 by setting the carry first. Sorry, that wasn't the best way to go about it anyway.

 

sec

lda #$00

sbc puck_h

sta puck_h

lda #$00

sbc puck_h+1

sta puck_h+1

 

Much better!

 

Alex

Link to comment
Share on other sites

(is there a better way to compute the 2's complement of a number???)

 

You mean how to negate a two complements value (number=-number)?

Substrack the number from zero.

 

LDA #0

SCF

SBC PUCK_H

STA puck_H

LDA #0

SBC PUCK_H+1

STA PUCK_H+1

 

should do the trick

 

Argh, got there before me. I just don't think sometimes. :dunce:

Link to comment
Share on other sites

I'm not sure if this is any help (I didn't read the Stella thread on this subject), but I used a table to determines how the integeter X and Y velocity values affect the position for each of N number of frames. I believe it ends up with the same effect as fractional positioning. Takes up a little space for the table, but it makes the code extremely simple, especially if you include negetive velocities in the table.

 

And you can easily tweak the speed of gameplay very precisely (which is especially helpful in PAL/NTSC conversion). I think I ended up adding a bit of a curve to Marble Craze table to get the gameplay just how I wanted it. ;)

 

;4 frame velocity table

;frame1 2 3 4

byte 0,0,0,0 ; vel=0 | standing still

byte 1,0,0,0 ; vel=1 | move 1 pixel per 4 frames

byte 1,0,1,0 ; vel=2 | move 2 pixels per 4 frames

byte 1,1,1,0 ; vel=3 | move 3 pixels per 4 frames

byte 1,1,1,1 ; vel=4 etc.

byte 2,1,1,1 ; vel=5

byte 2,1,2,1 ; vel=6

Link to comment
Share on other sites

Paul,

 

Thanks for the explanation. That's very similar to the way I used to do "fractional" positioning in my CHAMP games:

 

if (!(FRAME%4)) - once every 4 frames

if (FRAME%2) - twice every 4 frames

if (FRAME%4) - 3 times every 4 frames

 

The table seems pretty cool and definitely makes the math trivial compared to fractional math (and saves some bytes in RAM too!)...

 

I'll have to experiment with both methods and see which suits my needs the best.

 

Thanks again for all the help!

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...