So let's disassemble Stellar 7's cos and sin multiplication routine and write it to a file with the dasm command.
dasm d00_multiplication_dasm.txt,d00,f6
This will dissassemble from d00-df5.
As input, it takes the number to be multiplied in $00, the angle in A.
As output, the COS(A) * $00 goes in $22-23 and the SIN A goes in $24-25. The high byte of the output will always be zero. The multiplication generates 16 bits, we're only interested in the high byte, the remainder goes in $02 but it is just ignored.
Another thing to note is that the cos table values are 7 bits with the high bit used as a sign bit.
The cos table represent fractions from 0 to 80.
0x0 represents 0.0 and 0x80 represents 1.0.
But we only have 7 bits, from 0 to 0x7F, we can't actually get 1.0. That's why we've got the special case handling of the angles at 0,90,180 and 270 degrees.
0x7f divided by 128 gets pretty close to 1.0, about 99.2%.
print (0x7f/0x80)
0.9921875
The multiplication routine multiplies by the 7 bits of the lookup table value and then multiplies that by 2.
Therefore our multiplication routine can only get up to multiplying by 0x7f * 2 = 0xfe or 254.
===============================
Example: multiplying by 0x7f or (.992)
So for example, let's take a number, say 0x19 and multiply it by 0x7F and then multiply it by 2. We get
print (string.format("%x",0x7f*0x19*2))
18ce
We take the result of 0x18CE, throw away the low byte of the result 0xCE and we get 0x18 which is 99% of 0x19.
Example: multiplying by 0x40 or (0.5)
So for another example, let's take our same number, say 0x19 and multiply it by 0x40 and then multiply it by 2. We get
print (string.format("%x",0x40*0x19*2))
c80
We take the result of 0xC80, throw away the low byte of the result 0x80 and we get 0xC which is 0.5 * 0x19 or 0xC. 0x19=25 0xC=12.
Basically what we're doing is multiplying by our cos value fraction (0 to 255) and then shifting that result by 8 bits (dividing by 256 by throwing away the low byte).
result = (multiplicand * ((cosvalue AND 0x7f) * 2) / 256
The sign bit is handled specially, we just negate the result by EOR #$FF and ADC #$00 (with the sign bit set, effectively adds by 1).
==================================
Special cases:
First thing we do is to look and see if the number is zero. If so, then we can just put #$00 in $22-23 and $24-25 and rts.
At 0d0d, there's a TAY make a copy of the angle and store it in Y.
We and it with #$3f to check to see if it's any of the special angle cases, 0,0x40,0x80,0xc0 or 0,90,128,192 degrees. If A is zero after anding with #$3f, then we know it's a special case and we jmp to $0db3.
The special cases are pretty straightforward, if the angle is 0, cos 0 = 1, sin 0 = 0. Therefore at $0db6 we copy $00 to $22, put #$00 in $23,$24 and $25.
If the angle is 90, cos 90=0, sin 90=1.
If the angle is 180, cos 180=-1, sin 180=0. So return negative $00 in $22-23, #$00 in $24-25.
If the angle is 270, cos 90=0, sin 90=-1, at $0de6 we put #$00 in $22-23 and we do a subtraction of $00 from #$00 and put that in $24 (ldx #$00,txa,sec,sbc $00,sta $25) and put #$FF in $25 (ldx #$00,dex and stx $25).
0D00: A6 00 ldx $00 0D02: D0 09 bne $0d0d 0D04: 86 22 stx $22 0D06: 86 23 stx $23 0D08: 86 24 stx $24 0D0A: 86 25 stx $25 0D0C: 60 rts 0D0D: A8 tay copy the angle into y 0D0E: 29 3F and #$3f 0D10: D0 03 bne $0d15 0D12: 4C B3 0D jmp $0db3 jmp to 0db3, one of our special cases 00,40,80,c0. 0D15: B9 00 0F lda $0f00, y get our lookup table value 0D18: CA dex decrement x (because when we do the adds, the carry bit will be set) 0D19: 86 01 stx $01 store x in $01 (multiplicand minus 1 goes in $01) 0D1B: 4A lsr a shift a right 0D1C: 85 02 sta $02 store a in $02 (will shift bits in and out of $02 with ror, when done $02=low byte of result) 0D1E: A9 00 lda #$00 0D20: 90 02 bcc $0d24 0D22: 65 01 adc $01 0D24: 6A ror a 0D25: 66 02 ror $02 0D27: 90 02 bcc $0d2b 0D29: 65 01 adc $01 0D2B: 6A ror a 0D2C: 66 02 ror $02 0D2E: 90 02 bcc $0d32 0D30: 65 01 adc $01 0D32: 6A ror a 0D33: 66 02 ror $02 0D35: 90 02 bcc $0d39 0D37: 65 01 adc $01 0D39: 6A ror a 0D3A: 66 02 ror $02 0D3C: 90 02 bcc $0d40 0D3E: 65 01 adc $01 0D40: 6A ror a 0D41: 66 02 ror $02 0D43: 90 02 bcc $0d47 0D45: 65 01 adc $01 0D47: 6A ror a 0D48: 66 02 ror $02 0D4A: 90 02 bcc $0d4e 0D4C: 65 01 adc $01 0D4E: 6A ror a 0D4F: 66 02 ror $02 0D51: A2 00 ldx #$00 0D53: 90 07 bcc $0d5c no sign bit, so let's branch to d5c 0D55: 49 FF eor #$ff sign bit is set, so negate our result A by EOR #$FF, and ADC #$00 (carry is set) 0D57: 69 00 adc #$00 0D59: F0 01 beq $0d5c need this branch here, because if A was 0, we don't want -0 to come back as FF00 (-256). 0D5B: CA dex decrement x so x will be #$FF 0D5C: 85 22 sta $22 0D5E: 86 23 stx $23 0D60: A6 00 ldx $00 0D62: 98 tya Multiply by SIN value, first get the angle from the Y register 0D63: 18 clc 0D64: 69 C0 adc #$c0 add #$c0 (add 192) since sin A is cos(A-0x40)=(A+0x100-0x40), addition wraps around 0-255 0D66: A8 tay put our new angle (+192) back into Y 0D67: B9 00 0F lda $0f00, y get the value from the cos table 0D6A: CA dex 0D6B: 86 01 stx $01 0D6D: 4A lsr a 0D6E: 85 02 sta $02 0D70: A9 00 lda #$00 0D72: 90 02 bcc $0d76 0D74: 65 01 adc $01 0D76: 6A ror a 0D77: 66 02 ror $02 0D79: 90 02 bcc $0d7d 0D7B: 65 01 adc $01 0D7D: 6A ror a 0D7E: 66 02 ror $02 0D80: 90 02 bcc $0d84 0D82: 65 01 adc $01 0D84: 6A ror a 0D85: 66 02 ror $02 0D87: 90 02 bcc $0d8b 0D89: 65 01 adc $01 0D8B: 6A ror a 0D8C: 66 02 ror $02 0D8E: 90 02 bcc $0d92 0D90: 65 01 adc $01 0D92: 6A ror a 0D93: 66 02 ror $02 0D95: 90 02 bcc $0d99 0D97: 65 01 adc $01 0D99: 6A ror a 0D9A: 66 02 ror $02 0D9C: 90 02 bcc $0da0 0D9E: 65 01 adc $01 0DA0: 6A ror a 0DA1: 66 02 ror $02 0DA3: A2 00 ldx #$00 0DA5: 90 07 bcc $0dae 0DA7: 49 FF eor #$ff 0DA9: 69 00 adc #$00 0DAB: F0 01 beq $0dae 0DAD: CA dex 0DAE: 85 24 sta $24 0DB0: 86 25 stx $25 0DB2: 60 rts 0DB3: 98 tya we copied the angle to the Y register before, so copy angle back to A 0DB4: D0 0D bne $0dc3 0DB6: A2 00 ldx #$00 angle = 0 or #$00, cos = 1, sin = 0 0DB8: 86 24 stx $24 0DBA: 86 25 stx $25 0DBC: A5 00 lda $00 0DBE: 85 22 sta $22 0DC0: 86 23 stx $23 0DC2: 60 rts 0DC3: 30 0D bmi $0dd2 0DC5: A2 00 ldx #$00 angle = 90 or #$40, cos = 0, sin = 1 0DC7: 86 22 stx $22 0DC9: 86 23 stx $23 0DCB: A5 00 lda $00 0DCD: 85 24 sta $24 0DCF: 86 25 stx $25 0DD1: 60 rts 0DD2: 29 40 and #$40 0DD4: D0 10 bne $0de6 0DD6: A2 00 ldx #$00 angle = 180 or #$80, cos = -1, sin = 0 0DD8: 86 24 stx $24 0DDA: 86 25 stx $25 0DDC: 38 sec 0DDD: 8A txa 0DDE: E5 00 sbc $00 0DE0: 85 22 sta $22 0DE2: CA dex 0DE3: 86 23 stx $23 0DE5: 60 rts 0DE6: A2 00 ldx #$00 angle = 270 or #$C0, cos = 0, sin = -1 0DE8: 86 22 stx $22 0DEA: 86 23 stx $23 0DEC: 38 sec 0DED: 8A txa 0DEE: E5 00 sbc $00 0DF0: 85 24 sta $24 0DF2: CA dex 0DF3: 86 25 stx $25 0DF5: 60 rts
Best Casinos for UK players at legal US casino sites 2021
ReplyDeleteWith over 15 years in business and 평택 출장마사지 a strong reputation for quality 양주 출장안마 online 아산 출장샵 casino games 속초 출장안마 in the UK, we're confident you'll 부천 출장마사지 find a lot of