Someone may find this useful, a routine I made to multiply two numbers. The main benefit of this is that you can multiply two 8bit numbers, a 16bit number and a 8bit number, or two 16bit numbers.
Code
; Multiplication routine  works with 8bit and 16bit numbers.
; It won't however give a 24bit number (it could probably be edited to do so).
;
; Input:
; A should be 00(00) when entering (unless you want to add the multiplied number to what is already in A)
; $00 should be the number you want to multiply and $02 is what you are multiplying it by. $00 * $02
; You can enter in either 8bit or 16bit mode A
;
; Ouput:
; Result will go in A
; $00 and $02 will no longer hold their original values
;
Multiply:

LSR $02
BEQ .end
BCC +
CLC
ADC $00
+
ASL $00
BRA 
.end
CLC
ADC $00
RTS
MarioE
Posts: 391/751
Since:
Location: Cambridge, MA
In order to use it, load a 16bit value into A, with the carry bit acting as a 17th bit and call it. It will return the approximation to the square root as a 16bit value in A, with the carry bit acting as a 17th bit. The return value should be interpreted as 9.8 fixed point.
For example, a return value of $45A0 (C) should be interpreted as $0145.A0.
MarioE
Posts: 396/751
Since:
Location: Cambridge, MA
Using an inlined reciprocal square root routine, I've created a pretty accurate aiming routine. Link
In order to use it, set $00 to be the 16bit value (shooter_x  target_x), set $02 to be the 16bit value (shooter_y  target_y), and set A to be the 8bit projectile speed. It will return the projectile's X speed in $00 and the projectile's Y speed in $02. Note that distances over $0100 pixels are not allowed.
Explanation: Suppose one fired the projectile with X speed dx, and Y speed dy. Then its speed would be sqrt(dx^{2}+dy^{2}). Thus, we can adjust its speed by multiplying by speed / sqrt(dx^{2}+dy^{2}). This routine calculates the reciprocal 1 / sqrt(dx^{2}+dy^{2}), multiplies by speed, then multiplies by either dx or dy.
erik edit: fixed link because dropbox
added the sa1 compatible variant (requires a !SA1 detection if you're using spritetool)
%palette(!destination, #$XX, #$XX)
macro palette(destination, lowbyte, highbyte)
LDA <Destination>
STA $2121
LDA <lowbyte> ; Yes, you need a high byte too
STA $2122
LDA <highbyte>
STA $2122 ; Remember: $2122 is a ‘write twice’ register (you must store again into the address).
endmacro
But it can slow down a bit if you're using it to much (I didn't used it).
If you use an acurate emulator not ZSNES than the palette will screw up when you change the palette with that code in a sprite...
thats the reasen why all SMW sprites which modify the palette use the table at $0682
Oh right, ZSNES is inaccurat. And not only with the palette, every adress in the SNES regrister must have a mirror to not screw up the other things (with esception of [like MarioEdit has written] [H]DMA).
And not only with the palette, every adress in the SNES regrister must have a mirror to not screw up the other things (with esception of [like MarioEdit has written] [H]DMA).
Not really true. Some only can be written during a blank yes, but, most registers can not be read, so having mirrors allows you to read what will be put in that register. Direct writes to registers should with no problems.
Direct writes to registers should with no problems.
Dear lord, some of your advise is horrible.
The following code in levelasm/uberasm
Code
level105:
REP #$20
LDA #$2000
.x
DEC A ; waste some time so we're not in vblank
BNE .x
SEP #$20
LDA $14
LSR #3
AND #$07
ASL
TAX
LDA #$24
STA $2121
LDA $00B61C,x
STA $2122
LDA $00B61D,x
STA $2122
RTS
(clean ROM, not even LM) intends to create the following results (bsnes092c+ZMZ)
but on real hardware, it creates the following instead (bsnes092a+ZMZ)
Therefore, it is safe to concluce that writing to CGRAM outside of a blank will glitch up. It will go to a semirandomly chosen color and ignore what you aim for.
 <blm> zsnes users are the flatearthers of emulation
I wrote that late at night and I meant to say most direct writes to registers should work with no problems, I already knew things like CGRAM/VRAM/etc. couldn't be written to outside of a blank, but I meant things like the H/V scroll registers, screen brightness, screen settings, window settings, etc. They are just easier to work with with mirrors.
MarioE
Posts: 527/751
Since:
Location: Cambridge, MA
Here's some code for parallax scrolling that scrolls vertically:
Code
parallax:
LDA #$7F
STA $4334
REP #$20
LDA #$0F02
STA $4330
LDA #$8600
STA $4332
STZ $00
TAX
TAY
.loop LDA scanlines,y
CLC
ADC $00
STA $00
SBC $20
BMI .next
CMP scanlines,y
BCC +
LDA scanlines,y
+ SEP #$20
STA $7F8600,x
LDA $1E
STA $211B
LDA $1F
STA $211B
LDA speeds,y
STA $211C
REP #$20
LDA $2134
LSR #4
STA $7F8601,x
INX #3
.next INY #2
CPY.b #speedsscanlines+2
BNE .loop
SEP #$20
LDA #$08
TSB $0D9F
RTS
scanlines:
dw $0030,$0030,$0030,$0030,$0030,$0030,$0030,$0030
dw $0030
speeds:
dw $0010,$0018,$0020,$0028,$0030,$0038,$0040,$0048
dw $0050
scanlines should add up to greater than $01B0 in a horizontal level. speeds is divided by $10 to get the true scrolling value; the speed ranges from $0000 to $007F.
Note: The parallax appears to flicker for a single frame when scrolling up sometimes  I have no idea why.
Follow Us On