Banner
Views: 773,058,471
Time:
21 users online: Adryel,  bebn legg, earthmeLon, eltiolavara9, Evernn, GreenHammerBro, Kiatus,  Maarfy, marathonx, Maxodex, NikSik1, pakkie, placeholdertest,  RPG Hacker, slothrop, The X, TooMuchToby, umjammercammy, WhiteYoshiEgg, Yoshin, Zandro - Guests: 50 - Bots: 209Users: 40,602 (1,831 active)
Latest: Overcrow
Tip: Check this thread to find extremely useful diagrams and data.Not logged in.
Advanced Documentation and ASM Code Library
Forum Index - SMW Hacking - SMW Hacking Help - ASM & Related Topics - Advanced Documentation and ASM Code Library
Pages: « 1 2 3 4 5 6 7 8 »
.. Yes, that's what I said.
It's not the center, it's the sprite position. The ones in RAM.

--------------------
Your layout has been removed.
Thats why I put them in quotes, they move relatively to each other.

--------------------
Give thanks to RPG hacker for working on Asar.
I realized, that mine is "glitch proof", meaning that there is a bug on smw's clipping routine when a sprite's hitbox is past the left edge of the level (mainly, the banzai bill). Since Mine is signed position but not smw, this is better (minus the 16-bit width and height).

E: I was wrong, it uses a different collision routine that had a bug.

--------------------
Give thanks to RPG hacker for working on Asar.

Because the Hex -> Dec (long) was very complicated to use when you want it to display 4 (or rarely 5) digits. I made a simple subroutine that does all the work for you. It works by dividing the value by 10 repeatedly and taking the remainder for each digits starting at “low digit”, here is an example:

Code
$1234 is 4660 in decimal:

$1234/$A = Q:$1D2 R:$0 (ones place)

$1D2/$A = Q:$2E R:$6 (tens place)

$2E/$A = Q:$4 R:$6 (hundreds place)

$4/$A = Q:0 R:$4 (thousands place)


Obviously, this converts a binary integer into unpacked Binary coded decimal due to each digit placed in each byte.

Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;16-bit hex to 4 (or 5)-digit decimal subroutine
;Input:
; $00-$01 = the value you want to display
;Output:
; !HexDecDigitTable to !HexDecDigitTable+4 = a digit 0-9 per byte table
; (used for 1-digit per 8x8 tile):
; +$00 = ten thousands
; +$01 = thousands
; +$02 = hundreds
; +$03 = tens
; +$04 = ones
;
;!HexDecDigitTable is address $02 for normal ROM and $04 for SA-1.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if read1($00FFD5) == $23	;\can be omitted if pre-included
	!sa1 = 1
	sa1rom
else
	!sa1 = 0
endif				;/

!HexDecDigitTable = $02
if !sa1 != 0
	!HexDecDigitTable = $04
endif
	
ConvertToDigits:
	if !sa1 == 0
		PHX
		PHY

		LDX #$04	;>5 bytes to write 5 digits.

		.Loop
		REP #$20	;\Dividend (in 16-bit)
		LDA $00		;|
		STA $4204	;|
		SEP #$20	;/
		LDA.b #10	;\base 10 Divisor
		STA $4206	;/
		JSR .Wait	;>wait
		REP #$20	;\quotient so that next loop would output
		LDA $4214	;|the next digit properly, so basically the value
		STA $00		;|in question gets divided by 10 repeatedly. [Value/(10^x)]
		SEP #$20	;/
		LDA $4216	;>Remainder (mod 10 to stay within 0-9 per digit)
		STA $02,x	;>Store tile

		DEX
		BPL .Loop

		PLY
		PLX
		RTL

		.Wait
		JSR ..Done		;>Waste cycles until the calculation is done
		..Done
		RTS
	else
		PHX
		PHY

		LDX #$04

		.Loop
		REP #$20			;>16-bit XY
		LDA.w #10			;>Base 10
		STA $02				;>Divisor (10)
		SEP #$20			;>8-bit XY
		JSL MathDiv			;>divide
		LDA $02				;>Remainder (mod 10 to stay within 0-9 per digit)
		STA.b !HexDecDigitTable,x	;>Store tile

		DEX
		BPL .Loop

		PLY
		PLX
		RTL
	endif

if !sa1 != 0
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; unsigned 16bit / 16bit Division
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; Arguments
	; $00-$01 : Dividend
	; $02-$03 : Divisor
	; Return values
	; $00-$01 : Quotient
	; $02-$03 : Remainder
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	MathDiv:	REP #$20
			ASL $00
			LDY #$0F
			LDA.w #$0000
	-		ROL A
			CMP $02
			BCC +
			SBC $02
	+		ROL $00
			DEY
			BPL -
			STA $02
			SEP #$20
			RTL
endif

Remove leading zeroes:
Code
	RemoveLeadingZeroes:
	LDX #$00
	
	.Loop
	LDA !DigitTable,x	;\if current digit non-zero, don't omit trailing zeros
	BNE .NonZero		;/
	LDA #$FC		;\blank tile to replace leading zero
	STA !DigitTable,x	;/
	INX			;>next digit
	CPX #$04		;>last digit to check (tens place). So that it can display a single 0.
	BCC .Loop		;>if not done yet, continue looping.
	
	.NonZero
	RTL


2/23/2018 edit: improved the loop code for the hexdec routine so that after writing the last digit, doesn't do unnecessary division once again before breaking out the loop. Also you can now go above 32,767 for both versions without issues.

4/20/2018 edit: renamed the !Sa1 to !sa1 to fit with many patches (and tools) that nowdays uses the “ all lowercase” defines.

3/24/2019 edit: rename the define.

--------------------
Give thanks to RPG hacker for working on Asar.
I happen to have needed a similar function for some VLDC shenanigans. If anyone cares, this is the code I used:
Possible advantages: It works in non mirrored RAM, use of pointer for where to store decimal value, works for full range 0...65535 (#$0000-#$FFFF)
Possible disadvantages: Worst case (dec value 59999) the loop is executed 41 times each costing some 48 cycles.

Code
;A   = 16 bit value to convert
;$00 = long pointer to where decimal should be stored
PrintCounter:
	LDY #$04
	LDX #$06
-
	CMP.l .decimal,x	; \ branch if value is less than 10^(x/2+1)
	BCC +			; /
	PHA			; \
	SEP #$20		; |
	LDA [$00],y		; |
	INC			; | increase current position
	STA [$00],y		; |
	REP #$20		; |
	PLA			; /
	SEC			; \
	SBC.l .decimal,x	; | subtract 10^(x/2+1)
	BRA -			; / and repeat loop
+
	DEY			; set pointer to next (previous) position
	DEX : DEX		; get to next decimal digit
	BPL -			; loop while x is positive (or 0)
	RTS			; return

.decimal:
	dw $000A	;    10
	dw $0064 	;   100
	dw $03E8	; 1.000
	dw $2710	;10.000


--------------------
Anime statistic on MyAnimeList:
400 animes completed ✓
6000 episodes completed ✓
100 Days completed ✓
... what even am I doing with my life?
signed sine and signed cosine:
Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;GreenHammerBro's signed sine routine.
;Input:
;$00-$01 : The degree value (#$0000-#$01FF)
;Output:
;$02-$03 : Signed sine result.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SignedSine:
	PHX
	REP #$30
	LDA $00			;>Input
	AND #$00FF		;>Remove high byte (since index is 0-255)
	ASL			;>Each value holds 2 bytes.
	TAX			;>Transfer to index.
	LDA $07F7DB,x		;>Load sine
	STA $02			;>The unsigned result stored.
	SEP #$30

	.FlipIfNegative
	LDA $01			;\If degree value is >= #$0100 (180 in real-word
	BEQ ..Positive		;/degrees), then don't flip the end result
	REP #$20		;\Flip
	LDA $02			;|
	EOR #$FFFF		;|
	INC			;|
	STA $02			;|
	SEP #$20		;/

	..Positive
	PLX
	RTS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;GreenHammerBro's signed cosine routine.
;Input:
;$00-$01 : The degree value (#$0000-#$01FF)
;Output:
;$02-$03 : Signed cosine result.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SignedCosine:
	PHX
	REP #$30
	LDA $00			;\Shift by 90 real world degrees
	CLC			;|(since cosine is sine+90)
	ADC #$0080		;/
	CMP #$0100		;\If bigger than 180 (real world) degrees,
	BCC .FirstHalf		;/loop back to index 0 with the 2nd half.
	CMP #$0200		;\If approaching final quadrant, don't invert
	BCS .FirstHalf		;/

	.SecondHalf		;>#$0100 to #$01FF = 2nd half (negative X)
	AND #$00FF		;>Modulo by 256 (#$0100, because smw only have half-wave)
	ASL			;>Each value holds 2 bytes.
	TAX			;>Transfer to index.
	LDA $07F7DB,x		;>Load table
	EOR #$FFFF		;\Invert
	INC A			;/
	STA $02			;>And get negative X value.
	SEP #$30
	BRA .Done

	.FirstHalf	;>#$0000-#$00FF or #$0200-#$02FF (positive X)
	AND #$00FF	;>Remove high byte (if final quadrant)
	ASL		;>Each value holds 2 bytes.
	TAX		;>Transfer to index.
	LDA $07F7DB,x	;>Load table
	STA $02
	SEP #$30

	.Done
	PLX
	RTS

Made this from scratch. Things to note:
  • Smw's "unit circle" is multiplied by 256 to allow fractional units, since values are regarded as integers.
  • To convert smw <-> real world degrees, here is the formula: Real world to smw's: SMWDegrees = RealWorldDegrees*512/360.
    To convert to real world: RealWorldDegrees = SMWDegrees*360/512


--------------------
Give thanks to RPG hacker for working on Asar.


Doesn't that already exist at $01CB20? The only difference is that it's not inverted when negative, but you can determine that from $1866/$1867.

Professional frame-by-frame time wizard. YouTube - Twitter - SMW Glitch List - SMW Randomizer
Due to some bugs found with changing multiple map16 blocks, I found a glitch with the behavor as well as interacting with 2 blocks at the same time should they delete (by standing on 2 blocks). If you place them in the vertical level's top-left sub-screen boundary. So here is a fix for the $99/$9B fix:

Code
;this routine fixes vertical level block-positioning issues after you change map16.
	LDA $5B				;\Check if vertical level = true
	AND #$01			;|
	BEQ +				;/
	LDA $99				;\Prevent strange behavor on top-left subscreen of vertical level.
	BNE ++				;|(such as interact with the wrong blocks; 2 blocks at same time)
	LDA $9B				;|
	BNE ++				;|
	BRA +				;/
++
	PHY
	LDA $99				;\Fix the $99 and $9B from glitching up if placed
	LDY $9B				;|other than top-left subscreen boundaries of vertical
	STY $99				;|levels!!!!! (barrowed from the map16 change routine of GPS).
	STA $9B				;|(this switch values $99 <-> $9B, since the subscreen boundaries are sideways).
	PLY
+					;/
	RTL


Use this after every time you use the map16 change or the erase block.

--------------------
Give thanks to RPG hacker for working on Asar.
Sprite template

--------------------
Give thanks to RPG hacker for working on Asar.
Just like custom sprites and blocks, custom objects are also possible with this patch (come to think of it, it might not be a bad idea to update that with some additional routines and stuff), but not many people actually seem to use custom objects, especially non-extended ones. I figure that part of that is Lunar Magic not displaying them properly, but it probably doesn't help that there aren't a bunch of pre-existing resources for them like there are for sprites and blocks. So here are a few base codes that can be used for your own custom objects. They do take a slight bit of ASM knowledge, but nothing too complicated.

Code
Objects16x16:
	ASL
	TAX
	LDY $57
	LDA.w Obj16x16Tiles,x
	STA [$6B],y
	LDA.w Obj16x16Tiles+1,x
	STA [$6E],y
	RTS

Objects16x32:
	ASL #2
	TAX
	LDY $57
	LDA.w Obj16x32Tiles,x
	STA [$6B],y
	LDA.w Obj16x32Tiles+1,x
	STA [$6E],y
	INX : INX
	JSR ShiftObjDown
	LDA.w Obj16x32Tiles,x
	STA [$6B],y
	LDA.w Obj16x32Tiles+1,x
	STA [$6E],y
	RTS

Objects32x16:
	ASL #2
	TAX
	LDY $57
	LDA.w Obj32x16Tiles,x
	STA [$6B],y
	LDA.w Obj32x16Tiles+1,x
	STA [$6E],y
	INX : INX
	JSR ShiftObjRight
	LDA.w Obj32x16Tiles,x
	STA [$6B],y
	LDA.w Obj32x16Tiles+1,x
	STA [$6E],y
	RTS

Objects32x32:
	ASL #3
	TAX
	JSR BackUpPtrs
	LDY $57
	LDA.w Obj32x32Tiles,x
	STA [$6B],y
	LDA.w Obj32x32Tiles+1,x
	STA [$6E],y
	INX : INX
	JSR ShiftObjRight
	LDA.w Obj32x32Tiles,x
	STA [$6B],y
	LDA.w Obj32x32Tiles+1,x
	STA [$6E],y
	JSR RestorePtrs
	JSR ShiftObjDown
	INX : INX
	LDA.w Obj32x32Tiles,x
	STA [$6B],y
	LDA.w Obj32x32Tiles+1,x
	STA [$6E],y
	INX : INX
	JSR ShiftObjRight
	LDA.w Obj32x32Tiles,x
	STA [$6B],y
	LDA.w Obj32x32Tiles+1,x
	STA [$6E],y
	RTS

Obj16x16Tiles:
;	dw $0000	; index 00
;...

Obj16x32Tiles:
;	dw $0000,$0000	; index 00
;...

Obj32x16Tiles:
;	dw $0000,$0000	; index 00
;...

Obj32x32Tiles:
;	dw $0000,$0000,$0000,$0000	; index 00
;...

These routines will make an extended object consisting of a 1x1, 1x2, 2x1, or 2x2 array of blocks. The tables should consist of one 16-bit value per block for each entry, as you see here. Load the index you want into A before calling the routine. (These may seem pointless given that Direct Map16 exists, but keep in mind that you can also have them load variable values depending on a specified factor, such as item memory or switch palace flags.) Note that it is currently not possible to go beyond index $7F for the 16x16, $3F for the 16x32 and 32x16, and $1F for the 32x32 ones, because the index to the tables is only 8-bit. If I end up needing more for my own objects, I will probably add 16-bit indexing to the routines and add them to this post.


Code
SquareObjects:
	REP #$20					;
	AND.w #$00FF				;
	ORA #$0900				;
	STA $4202				;
	JSR .Return				;
	LDA $4216				;
	STA $0C					;
	SEP #$20					;
	JSR StoreNybbles			;
	LDY $57					;
	LDA $08					;
	STA $00					;
	STA $02					;
	LDA $09					;
	STA $01					;
	JSR BackUpPtrs				;
.StartObjLoop					;	
	REP #$10					;
	LDX $0C					;
	LDA $01					;
	CMP $09					;
	BEQ .NoInc1				;
	INX #3					;
	CMP #$00				;
	BNE .NoInc1				;
	INX #3					;
.NoInc1						;
	LDA $02					;
	CMP $08					;
	BEQ .SetTileIndex			;
	INX						;
	CMP #$00				;
	BNE .SetTileIndex			;
	INX						;
.SetTileIndex					;
	REP #$20					;
	TXA						;
	ASL						;
	TAX						;
	LDA.w SquareObjTiles,x		;
	SEP #$30					;
	STA [$6B],y				;
	XBA						;
	STA [$6E],y				;
	JSR ShiftObjRight			; shift the tile position right one tile
.DecAndLoop					;
	DEC $02					; if there are more tiles to draw on this line...
	BPL .StartObjLoop			; loop the routine
	JSR RestorePtrs			; if not, restore the base tile position...
	JSR ShiftObjDown			; and move on to the next line
	LDA $00					;
	STA $02					; also reset the X position counter
	DEC $01					; decrement the Y position (line) counter
	BMI .EndObjLoop			; if still positive...
	JMP .StartObjLoop			; loop the routine
.EndObjLoop					;
.Return						;
	RTS						;

SquareObjects2:
	REP #$20					;
	AND.w #$00FF				;
	ORA #$0900				;
	STA $4202				;
	JSR .Return				;
	LDA $4216				;
	STA $0C					;
	SEP #$20					;
	JSR StoreNybbles			;
	LDY $57					;
	LDA $08					;
	STA $00					;
	STA $02					;
	LDA $09					;
	STA $01					;
	JSR BackUpPtrs				;
.StartObjLoop					;	
	REP #$10					;
	LDX $0C					;
	LDA $01					;
	CMP $09					;
	BEQ .NoInc1				;
	INX #3					;
	CMP #$00				;
	BNE .NoInc1				;
	INX #3					;
.NoInc1						;
	LDA $02					;
	CMP $08					;
	BEQ .SetTileIndex			;
	INX						;
	CMP #$00				;
	BNE .SetTileIndex			;
	INX						;
.SetTileIndex					;
	LDA [$6E],y				;
	XBA						;
	LDA [$6B],y				;
	REP #$20					;
	CLC						;
	ADC #$7FDA				; #$0025 + #$7FDA = #$7FFF
	REP #$41					; make sure V and C are clear
	ADC #$0001				; this should set overflow if and only if the tile number was 25
	TXA						;
	ASL						;
	TAX						;
	LDA.w SquareObjTiles2A,x	;
	BVS .NoAlt				;
	LDA.w SquareObjTiles2B,x	;
.NoAlt						;
	SEP #$30					;
	STA [$6B],y				;
	XBA						;
	STA [$6E],y				;
	JSR ShiftObjRight			; shift the tile position right one tile
.DecAndLoop					;
	DEC $02					; if there are more tiles to draw on this line...
	BPL .StartObjLoop			; loop the routine
	JSR RestorePtrs			; if not, restore the base tile position...
	JSR ShiftObjDown			; and move on to the next line
	LDA $00					;
	STA $02					; also reset the X position counter
	DEC $01					; decrement the Y position (line) counter
	BMI .EndObjLoop			; if still positive...
	JMP .StartObjLoop			; loop the routine
.EndObjLoop					;
.Return						;
	RTS						;

SquareObjTiles:
;	dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000	; index 00

SquareObjTiles2A:
;	dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000	; index 00
SquareObjTiles2B:
;	dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000	; index 00

These are for normal objects that have an array of 9 tiles, with the middle ones stretchable (think the SMB3 metal blocks, or any 4-sided ground object). The block number tables use 9 values in the order you'd expect (top-left corner, top-middle, top-right, middle-left edge, middle, middle-right, bottom-left, bottom-middle, bottom-right). They can also be used for ledges if you set the middle and bottom rows to the same numbers. There are two routines here, and the second one is for objects that change when placed over something else, as ledges do (with the corners becoming filled in). For that one, the first table is for when that part of the object is over a blank tile, and the second table is for when it is over a non-blank tile. Like the previous set, the value in A before calling the routine determines which list of blocks will be used, though it can go all the way up to $FF this time since the index becomes 16-bit. You should also JSR to the "StoreNybbles" subroutine before using these.


Code
ClusterExObjRt:
	TAY
	LDA ClusterExObjSize,y
	PHA
	AND #$0F
	STA $00
	STA $02
	PLA
	LSR #4
	STA $01
	TYA
	ASL
	TAY
	REP #$20
	LDA ClusterExObjPtrs,y
	STA $0A
	SEP #$20
	LDY $57
	JSR BackUpPtrs
.Loop
	REP #$20
	LDA ($0A)
	CMP #$FFFF
	SEP #$20
	BEQ .SkipTile
	STA [$6B],y
	XBA
	STA [$6E],y
.SkipTile
	JSR ShiftObjRight
	REP #$20
	INC $0A
	INC $0A
	SEP #$20
	DEC $02
	BPL .Loop
	JSR RestorePtrs
	JSR ShiftObjDown
	LDA $00
	STA $02
	DEC $01
	BPL .Loop
	RTS

ClusterExObjSize:
;	db $42

; pointers to the tilemaps of extended objects consisting of a large group of tiles
ClusterExObjPtrs:
;	dw TileArray00

TileArray00:
;	dw $0000,$0000,$0000
;	dw $0000,$0000,$0000
;	dw $0000,$0000,$0000
;	dw $0000,$0000,$0000
;	dw $0000,$0000,$0000

This is for non-stretchable objects of variable dimensions. (This is a simplified version; the one I use has a couple extra behavior checks that I felt most people might not need and might simply get tripped up by.) The input is the same as it is for the others, just the index you want to use. The tables are a bit different here. The first is for the size, first digit for Y and second for X (minus 1, so $11 would create a 2x2 object); the second is a list of pointers to the block data; and the third is the block data itself. (Example data is shown.) The block data consists of Map16 numbers as usual, but putting $FFFF in for any number will skip that particular block. (This is not the same as drawing an empty block, or Map16 tile 25, which would overwrite anything already placed in that area by another object with empty space.) You can use this subroutine for things like the large bushes.
Updated sa-1/superfx check:
Code
	!dp = $0000
	!addr = $0000
	!sa1 = 0
	!gsu = 0

if read1($00FFD6) == $15
	sfxrom
	!dp = $6000
	!addr = !dp
	!gsu = 1
elseif read1($00FFD5) == $23
	sa1rom
	!dp = $3000
	!addr = $6000
	!sa1 = 1
endif


In case if users don't have to go to the patch section.

--------------------
Give thanks to RPG hacker for working on Asar.
sfxrom is broken. Stick to sa1rom.

--------------------
I'm sure I'll find it
Wasn't sfxrom fixed with Raiden's update?
I use the latest version and I'm pretty sure it still doesn't work.

--------------------
I'm sure I'll find it
You are using the asar version in the waiting tools, right?

--------------------
Give thanks to RPG hacker for working on Asar.
You shouldn't build any standards requiring "unverified" tools.

--------------------
Anime statistic on MyAnimeList:
400 animes completed ✓
6000 episodes completed ✓
100 Days completed ✓
... what even am I doing with my life?
Removing the RNG from Footballs:

Code
!MiscTable = $1594

org $03800E  
db $A0,$C0,$D0,$D0	;data table for the bounce speed of footballs

org $03805C

autoclean JSL NewFootBall

freecode

NewFootBall:
LDA !MiscTable,x
BNE IsSet
LDA #$A6
IsSet:
ROR
STA !MiscTable,x
RTL
Insertion sort algorithm: (sorts in increasing order, unsigned)

8-bit:
Code
!Freeram_BufferSort = $7FA000
;^Format: nnnnnnnn (1 byte each). Number of items equal to how
;many bytes consume this freeram.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Input:
;; *!Freeram_BufferSort: Write any numbers (1-byte each) here.
;;
;; *$00: Number of items to sort.
;;
;;Output:
;; *!Freeram_BufferSort: Numbers already sorted
;;
;;Destroyed values:
;; *$01: A memory index position needed so when moving multiple
;;   items foward, does continue back after placing the item-in-hand back.
;; *$02: A holder used to place the number at the correct spot.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

InsertionSort:
	PHX
	LDX #$01			;>Start at the 2nd item ("grabber")
	STX $01				;>Start memory position

	.Loop
	LDA !Freeram_BufferSort,x	;\Grab value to compare (about to drop it).
	STA $02				;/

	..ShiftElementAgain
	CPX #$00			;\Prevent searching and dropping value in invalid indexes.
	BEQ ..DropValueToFirst		;/This also means that the item grabbed is the smallest number possible.
	LDA $02				;>This is so that when the loops comes around, still compares with the number grabbed.
	DEX				;>Check previous to find correct spot.
	CMP !Freeram_BufferSort,x	;>Compare with previous value
	BCC ..MovePrev			;>If grabbed value is smaller, move larger number over and execute move item loop
	BRA ..DropValue			;>If not "put it back", needed if it finally finds the correct place to drop.

	..MovePrev
	LDA !Freeram_BufferSort,x	;>Load previous item
	INX				;>Move previous item index into a space where the item is "grabbed"
	STA !Freeram_BufferSort,x	;>Move item 1 space foward.
	DEX				;>Place index back (index doesn't move/change after this).
	BRA ..ShiftElementAgain		;>Loop again to see if needed to shift again or drop.

	..DropValue
	INX				;>go back and drop larger index positioned after the smaller number (place 2 after 1).

	..DropValueToFirst
	LDA $02
	STA !Freeram_BufferSort,x

	..CheckNextValue
	INC $01				;\Continue where left off since it started grabbing a number
	LDX $01				;/
	CPX $00				;\Loop until all numbers sorted
	BCC .Loop			;/

	.SuboutineDone
	PLX
	RTL

16-bit:
Code
!Freeram_BufferSort = $7FA000
;^Format: nnnnnnnn NNNNNNNN (each item is 2 bytes). Number of
;items *2 equal to how many bytes consume this freeram. Should
;not be higher than 128.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Input:
;; *!Freeram_BufferSort: Write any numbers (2-bytes each) here.
;;
;; *$00: Number of items *2 to sort (4 items, you would write 8). Does not
;;  work if >128 (#$80), since index is 8-bit.
;;
;;Output:
;; *!Freeram_BufferSort: Numbers already sorted.
;;
;;Destroyed values:
;; *$01: A memory index position needed so when moving multiple
;;   items foward, does continue back after placing the item-in-hand back.
;; *$02-$03: A holder used to place the number at the correct spot.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

InsertionSort:
	PHX
	REP #$20
	LDX #$02			;>Start at the 2nd item ("grabber")
	STX $01				;>Start memory position

	.Loop
	LDA !Freeram_BufferSort,x	;\Grab value to compare (about to drop it).
	STA $02				;/

	..ShiftElementAgain
	CPX #$00			;\Prevent searching and dropping value in invalid indexes.
	BEQ ..DropValueToFirst		;/This also means that the item grabbed is the smallest number possible.
	LDA $02				;>This is so that when the loops comes around, still compares with the number grabbed.
	DEX #2				;>Check previous to find correct spot.
	CMP !Freeram_BufferSort,x	;>Compare with previous value
	BCC ..MovePrev			;>If grabbed value is smaller, move larger number over and execute move item loop
	BRA ..DropValue			;>If not "put it back", needed if it finally finds the correct place to drop.

	..MovePrev
	LDA !Freeram_BufferSort,x	;>Load previous item
	INX #2				;>Move previous item index into a space where the item is "grabbed"
	STA !Freeram_BufferSort,x	;>Move item 1 space foward.
	DEX #2				;>Place index back (index doesn't move/change after this).
	BRA ..ShiftElementAgain		;>Loop again to see if needed to shift again or drop.

	..DropValue
	INX #2				;>go back and drop larger index positioned after the smaller number (place 2 after 1).

	..DropValueToFirst
	LDA $02
	STA !Freeram_BufferSort,x

	..CheckNextValue
	SEP #$20			;>8-bit mode
	INC $01				;\Continue where left off since it started grabbing a number.
	INC $01				;/(INC $xx twice takes less space than having LDA and STA around it).
	REP #$20			;>16-bit mode
	LDX $01				;>set index to where left off.
	CPX $00				;\Loop until all numbers sorted
	BCC .Loop			;/

	.SuboutineDone
	SEP #$20
	PLX
	RTL


Not really useful for smw, but for advanced ASM'ers that have a “record” gimmick, such as showing “top 3 quickest level completion” (simply by comparing minutes, then seconds, and finally frames). Make sure you edit to not only sort the numbers in the tables themselves, but also the “id” (in a new table) of the item everytime there is LDA and STA for !Freeram_BufferSort (so if you're going to make a high score mechanic, that not only stores the score, but also things like names of something (3000 GreenHammerBro), you would need to move the ID (GreenHammerBro) and not just the score number), otherwise you end up mixing up the score number and the ID. Of course if there are 3+ things per item (3000 GreenHammerBro 50), the ID can be used to store multiple items (the “GreenHammerBro” and the “50&rdquo to be moved). This will make it so that it will move all the items together.

--------------------
Give thanks to RPG hacker for working on Asar.
Originally posted by MarioE
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.


This is why you should not use temporally storage to share your files, it will not last for long term (error 404)

Thank god I use this subroutine on one of my stuff.

Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Aiming routine, by MarioE.
;Input:
;$00 = (shooter_x - target_x), 16-bit
;$02 = (shooter_y - target_y), 16-bit
;A = projectile speed
;Output:
;$00 = X speed
;$02 = Y speed
;NOTE: distance more than $0100 (256 in decimal) will glitch, unless you divide them by
;the same number (like both by 4) to go under 256 and it still works.
;
;MarioE's 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.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
recip_sqrt_lookup:
		dw $0000,$FFFF,$B505,$93CD,$8000,$727D,$6883,$60C2
		dw $5A82,$5555,$50F4,$4D30,$49E7,$4700,$446B,$4219
		dw $4000,$3E17,$3C57,$3ABB,$393E,$37DD,$3694,$3561
		dw $3441,$3333,$3235,$3144,$3061,$2F8A,$2EBD,$2DFB
		dw $2D41,$2C90,$2BE7,$2B46,$2AAB,$2A16,$2987,$28FE
		dw $287A,$27FB,$2780,$270A,$2698,$262A,$25BF,$2557
		dw $24F3,$2492,$2434,$23D9,$2380,$232A,$22D6,$2285
		dw $2236,$21E8,$219D,$2154,$210D,$20C7,$2083,$2041
		dw $2000,$1FC1,$1F83,$1F46,$1F0B,$1ED2,$1E99,$1E62
		dw $1E2B,$1DF6,$1DC2,$1D8F,$1D5D,$1D2D,$1CFC,$1CCD
		dw $1C9F,$1C72,$1C45,$1C1A,$1BEF,$1BC4,$1B9B,$1B72
		dw $1B4A,$1B23,$1AFC,$1AD6,$1AB1,$1A8C,$1A68,$1A44
		dw $1A21,$19FE,$19DC,$19BB,$199A,$1979,$1959,$1939
		dw $191A,$18FC,$18DD,$18C0,$18A2,$1885,$1869,$184C
		dw $1831,$1815,$17FA,$17DF,$17C5,$17AB,$1791,$1778
		dw $175F,$1746,$172D,$1715,$16FD,$16E6,$16CE,$16B7
		dw $16A1,$168A,$1674,$165E,$1648,$1633,$161D,$1608
		dw $15F4,$15DF,$15CB,$15B7,$15A3,$158F,$157C,$1568
		dw $1555,$1542,$1530,$151D,$150B,$14F9,$14E7,$14D5
		dw $14C4,$14B2,$14A1,$1490,$147F,$146E,$145E,$144D
		dw $143D,$142D,$141D,$140D,$13FE,$13EE,$13DF,$13CF
		dw $13C0,$13B1,$13A2,$1394,$1385,$1377,$1368,$135A
		dw $134C,$133E,$1330,$1322,$1315,$1307,$12FA,$12ED
		dw $12DF,$12D2,$12C5,$12B8,$12AC,$129F,$1292,$1286
		dw $127A,$126D,$1261,$1255,$1249,$123D,$1231,$1226
		dw $121A,$120F,$1203,$11F8,$11EC,$11E1,$11D6,$11CB
		dw $11C0,$11B5,$11AA,$11A0,$1195,$118A,$1180,$1176
		dw $116B,$1161,$1157,$114D,$1142,$1138,$112E,$1125
		dw $111B,$1111,$1107,$10FE,$10F4,$10EB,$10E1,$10D8
		dw $10CF,$10C5,$10BC,$10B3,$10AA,$10A1,$1098,$108F
		dw $1086,$107E,$1075,$106C,$1064,$105B,$1052,$104A
		dw $1042,$1039,$1031,$1029,$1020,$1018,$1010,$1008
		
aiming:		PHX
		PHY
		PHP
		SEP #$30
		STA $0F
		
		LDX #$00
		REP #$20
		LDA $00
		BPL .pos_dx
		EOR #$FFFF
		INC
		INX
		INX
		STA $00
	.pos_dx	SEP #$20
		STA $4202
		STA $4203
		
		NOP
		NOP
		NOP
		REP #$20
		LDA $4216
		STA $04
		LDA $02
		BPL .pos_dy
		EOR #$FFFF
		INC
		INX
		STA $02
	.pos_dy	SEP #$20
		STA $4202
		STA $4203
		STX $0E
		
		REP #$30
		LDA $04
		CLC
		ADC $4216
		LDY #$0000
		BCC .loop
		INY
		ROR
		LSR
	.loop	CMP #$0100
		BCC +
		INY
		LSR
		LSR
		BRA .loop
	+	CLC
		ASL
		TAX
		LDA recip_sqrt_lookup,x
	-	DEY
		BMI +
		LSR
		BRA -
	+	SEP #$30
		
		STA $4202
		LDA $0F
		STA $4203
		NOP
		STZ $05
		STZ $07
		LDA $4217
		STA $04
		XBA
		STA $4202
		LDA $0F
		STA $4203
		
		REP #$20
		LDA $04
		CLC
		ADC $4216
		STA $04
		SEP #$20
		
		LDX #$02
	-	LDA $04
		STA $4202
		LDA $00,x
		STA $4203
		
		NOP
		NOP
		NOP
		NOP
		
		LDA $4217
		STA $06
		LDA $05
		STA $4202
		LDA $00,x
		STA $4203

		REP #$20
		LDA $06
		CLC
		ADC $4216
		SEP #$20
		
		LSR $0E
		BCS +
		EOR #$FF
		INC
	+	STA $00,x
		DEX
		DEX
		BPL -
		
		PLP
		PLY
		PLX
		RTL


There should be a rule against uploading it in places that it doesn't guarantee it would stay there, otherwise stuff would "rot" and nobody could find it.

Edit: unlimited distance.

--------------------
Give thanks to RPG hacker for working on Asar.
This is updated to be more valid even to the human eye, No freespace required!

This should be considered the final edition of this patch, unless someone finds a problem, of which there should be none.

Code
;Attributes for the Misc. Switch Palace Sprites
;By Hamtaro126, No Credit necessary!

org $05B29B
	;;;;;;;;;;;;;;;;;;;;;;
	;Tiles and Attributes;
	;;;;;;;;;;;;;;;;;;;;;;
	dw $35AD,$75AD,$B5AD,$F5AD ;\ Yellow Dotted Line Block
	dw $35A7,$75A7,$35B7,$75B7 ;/ Yellow Exclamation Block
	dw $37BD,$77BD,$B7BD,$F7BD ;\ Blue Dotted Line Block
	dw $37A7,$77A7,$37B7,$77B7 ;/ Blue Exclamation Block
	dw $39AD,$79AD,$B9AD,$F9AD ;\ Red Dotted Line Block
	dw $39A7,$79A7,$39B7,$79B7 ;/ Red Exclamation Block
	dw $3BBD,$7BBD,$BBBD,$FBBD ;\ Green Dotted Line Block
	dw $3BA7,$7BA7,$3BB7,$7BB7 ;/ Green Exclamation Block

org $02CD55
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	;Flat Palace Switch colors (Green, Yellow, Blue, Red);
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	db $0A,$04,$06,$08

org $02CD4D
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	;The Bottom of the Flat Palace Switch, Use it if changing the palette and map16;
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	db $31,$31,$71,$71,$31,$31,$71,$71
Pages: « 1 2 3 4 5 6 7 8 »
Forum Index - SMW Hacking - SMW Hacking Help - ASM & Related Topics - Advanced Documentation and ASM Code Library

The purpose of this site is not to distribute copyrighted material, but to honor one of our favourite games.

Copyright © 2005 - 2019 - SMW Central
Legal Information - Privacy Policy - Link To Us


Total queries: 9

Menu

Follow Us On

  • YouTube
  • Twitch
  • Twitter

Affiliates

  • Talkhaus
  • SMBX Community
  • GTx0
  • Super Luigi Bros
  • ROMhacking.net
  • MFGG
  • Gaming Reinvented