If you're not familiar with math operations in 8-bit and want to hack 8-bit games (or even 16-bit, as the rules are similar), then you may find this page useful. Some of these you may yourself already know, but if you're like me, you're learning everything from Ground Zero.
When you look through ASM, it's confusing enough already. When you stumble across something that is purely arithmetic and goes beyond basic 8-bit addition/subtraction, it can be daunting to make sense of what you see. It doesn't help that each programmer has his own style of coding the same operations. This reference article should help you at least recognize common arithmetic operations; your trusty old calculator and deductive reasoning will help with the rest.
As always, make sure your calculator is set to work in 32-bit HEX.
Adding
8bit $01+$02=$03
- CLC ; always clear Carry
- LDA $01
- ADC $02
- STA $03
- CLC ; always clear Carry before smaller value
- LDA $01
- ADC $02
- STA $04
- LDA $03
- ADC #00
- STA $05
- CLC ; always clear Carry
- LDA $01
- ADC $03
- STA $05
- LDA $02
- ADC $04
- STA $06
Subtraction
8bit $01-$02=$03
- SEC ; always set Carry
- LDA $01
- SBC $02
- STA $03
- CLC ; always clear Carry for addition
- LDA $01
- ADC #FF
- STA $02
- SEC ; always set Carry before larger value
- LDA $01
- SBC $03
- STA $04
- LDA $02
- SBC #00
- STA $05
- SEC ; always set Carry before larger value
- LDA $01
- SBC $03
- STA $04
- LDA $02
- ADC #FF
- STA $05
Multiplication
8bit*3 $01*3=$02
- LDA $01
- ASL
- CLC
- ADC $01
- STA $02
- ASL $01
- STA $02 ; save the value
- ASL $01
- ASL $01
- CLC
- ADC $02
- STA $02
- ASL $01
- ROL $02
I have seen a couple variations on this, so I will just try to explain what I have seen happen. This is what I witnessed in Castlevania III:
You take your first number and save it as a 16bit value (so across two bytes). You save how many bits beyond the first byte you want to go (typically register X or Y). Save your low byte and clear the next two subsequent bytes so you're working with, up to 24 bits. Here's where it can be confusing - you shift and rotate the values right when multiplying. You would think left, but nope. If the Carry flag is set after shifting the lowest byte (i.e., the lowest byte was odd), you add the other number to your upper two bytes; either way, you then rotate the other two bytes and decrease the bit counter until it zeroes.
To illustrate, here's the CV3 code abridged $01*$04=$01$02
- LDY #08
- LDA #00
- STA $02
- STA $03
- STA $05
- LSR $01
- BCC >loop ; >enter
- CLC
- LDA $04
- ADC $02
- STA $02
- LDA $05
- ADC $03
- STA $03
- ROR $03 ; >loop
- ROR $02
- ROR $01
- DEY
- BNE >enter
- RTS
Division
Division is essentially the same as multiplication, except you switch ASL with LSR and ROL with ROR. You also start your operations with the higher byte.
Consider the 16bit*2 code. The lower byte $01 is shifted left and then the upper byte $02 is rotated left. Now look at the 8bit*N code. The upper byte is shifted (rotated in that situation) right and then the lower byte is rotated right.
Further Reading
The following link has some articles on various arithmetic operations on 8bit machines. Currently, I will admit, it's beyond my tired brain. It's easier for me to see a code in a running game and figure out what the code does using hard numbers instead of ambiguous variables. If you're interested, by all means read through the articles. There's even one or two by Apple co-founder Steve Wozniak.
http://codebase64.org/doku.php?id=base:6502_6510_maths
No comments:
Post a Comment