Language…
9 users online: autisticsceptile1993, Batata Douce, DasFueller, DPBOX, Dzing, eltiolavara9, matthwsan, RZRider, Sweetdude - Guests: 262 - Bots: 290
Users: 64,795 (2,377 active)
Latest user: mathew

Advanced Documentation and ASM Code Library

Old threads can be found here:

Sprite/Block/HDMA/ASM Code Library

Advanced documentation

Put any SMW related code or documentation related to the SNES here. I will try to keep this updated, and hopefully more mods can help with that.




Random codes:

Blocks:
Change Map16 Number (load the Map16 tile in X, it can be 8-bit or 16-bit)
Causes a block to disappear
Causes a block to shatter
Causes a block to shatter on sprite contact
Check which side of a block Mario touched
Template block
Get Map16 number given a blocks position

Sprites:
GetDrawInfo
Clipping routines for checking contact between the player and a sprite, or two sprites
Causes the sprite to explode like a Bob-omb
Draw smoke at sprite's position
Stores Mario to the sprite position
Stores sprite to Mario's position
Horizontal proximity check
Vertical proximity check
Spawn a normal sprite
Spawn a custom sprite
Spawn an extended sprite
Set sprite (extended, regular or minor extended) speed based on Mario's speed
Cape collision detection
Fireball Contact Routine
Sprite Interacts With Map16 Tile xxx.
Sprite Aiming Routine

HDMA:
Inverse colors
Translucent color window
Layer scrolling macros
Bright blue to darker blue, background colour gradient. ($2132)
Blue sky gradient
Green sky gradient (Image)
Pink sky gradient (Image)
Night sky gradient (Image)
Sunset gradient (Image)
Window effect (Image)
Wavy HDMA effect
HDMA Brightness gradient
Vertically Scrolling Parallax Scrolling

Misc:
SA-1 base code
VRAM and CGRAM macros
Square root approximation routine
Multiplication routine
Code to get the map16 number of the block at any given position.
Find the number ($13BF format) of the level the current player is on.
Make certain tiles slippery without using custom blocks
Close the VWF dialogue and exit to the overworld
ROM->RAM DMA transfer macro
ExecutePtr macros
Circle routine
Yoshi's Earthquake
Pointer Subroutine
Random Number Generation (Ersanio)
Random Number Generation (1024)
Reset the game
The for() loop in ASM
Lose Yoshi
Convert time to binary
Use JSL with RTS
Hex -> Dec (short)
Hex -> Dec (long)
Show value of a RAM address on the status bar
Layer 3 scroll (left and right codes included)
Stop level at a certain screen
Disable P-switch music when using AMK




Advanced documentation:

HDMA and DMA stuff...
This site has almost everything: ASM, SPC-700, DMA transfer and the Super FX chip, and much more...
Another ASM tutorial
SNES dev. Manual | Version with searchable text layer
Complete listing of opcodes
65c816 ASM opcode matrix
Advanced DMA stuff
Useful information about SNES itself. (visit the links)
In-depth look in SNES registers <-- MUST-HAVE in my opinion
Another document about DMA and HDMA and other stuff...
A VERY detailed ASM tutorial
Another great tutorial about ASM.
A SMWiki category I've mostly worked on, based on ASM
ASM Workshop summary
Ersanio's GENERAL ASM tutorial
Iceguy's SMW ASM tutorial
How to use the opcode MVN $XXXX
Document about DMA and HDMA
ASM workshop 2012 logs: Basic workshop | Intermediate workshop | Intermediate part 2 | Advanced workshop

Other:
SNES INIT <-- Routine to initialize SNES hardware registers (in a homebrew ROM for example)
SNES-SPC700 Sound File Data v0.30 <-- .spc file format
SPC700.log
Someone may find this useful, a routine I made to multiply two numbers. The main benefit of this is that you can multiply two 8-bit numbers, a 16-bit number and a 8-bit number, or two 16-bit numbers.

Code
; Multiplication routine - works with 8-bit and 16-bit numbers.
; It won't however give a 24-bit 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 8-bit or 16-bit 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
Here is a square root approximation routine:
Link

In order to use it, load a 16-bit 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 16-bit 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.
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 16-bit value (shooter_x - target_x), set $02 to be the 16-bit value (shooter_y - target_y), and set A to be the 8-bit 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(dx2+dy2). Thus, we can adjust its speed by multiplying by speed / sqrt(dx2+dy2). This routine calculates the reciprocal 1 / sqrt(dx2+dy2), multiplies by speed, then multiplies by either dx or dy.

erik edit: fixed link because dropbox
added the sa-1 compatible variant (requires a !SA1 detection if you're using spritetool)
Just a small macro for ASM palette changes #w{=)} :
Code
%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).
but you should mention that you can't use that code in sprites or the palette will screw up... (must be done in V-blank)
Originally posted by mzuenni
but you should mention that you can't use that code in sprites or the palette will screw up... (must be done in V-blank)

Air Meter? Ultimate Noob Boss?
Simply put, that code must run in NMI, or you could use something like HDMA to modify the palettes.
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).
Originally posted by wiiqwertyuiop
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 semi-randomly chosen color and ignore what you aim for.
<blm> zsnes users are the flatearthers of emulation
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 #speeds-scanlines+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.
^
Is the HDMA patch necessary for this?
No, you can just plop it in uberASM's level_code.asm. However, it seems like the HDMA is always a frame behind -- not exactly sure why. =\
Maybe that HDMA can't handle running at full frames while the code is in effect? It probably could if the code was small, right?
The SNES isn't that weak that that'd give it problems.
Your layout has been removed.
Originally posted by MarioE
...scanlines needs to add up to $01B0.


It scrolled fine when it was less/more than...
But it did just happen to me that the more scanlines and scrolls, the emulator slows down immediately.

Is that why it needs to add to $01B0?


edit: nvm I'm probably wrong about the emulator thing.