Language…
14 users online: Batata Douce, BlueSheep123, CalHal, crocodileman94,  Deeke, Ekimnoid,  Fernap, Gamet2004, GiraffeKiller, Green, Housemeister, ppp9q, sugarfish456, WalrusLife - Guests: 266 - Bots: 289
Users: 64,795 (2,376 active)
Latest user: mathew

Advanced Documentation and ASM Code Library

Here is the explanation how this works when you use JSL -> RTS:

Code
	PHK                       ;\This will push the 24-bit address location
	PEA.w .jslrtsreturn-1     ;/after the JML (below) into the stack*
	PEA $yyyy-1               ;>This modifies the RTS in the pointed routine (below) to jump to an RTL in same bank.*
                                  ;^This RTL then pulls the stack (which is the 24-bit address) to jump to a location after the JML
	JML $xxxxxx               ;>The desired routine that ends with RTS

	.jslrtsreturn

*Means that when the PC (program counter) "returns" (weather RTS or RTL), it pulls the stack + 1. I've learned it from Ersanio's ASM tutorial (not the SMW version).
Originally posted by Ersanio
About JSR and JSL, and RTS and RTL:
Imagine that there is a JSR opcode located at $8000, and there is an LDA at $8003, and RTS at $B000. A JSR instruction is 3 bytes long (JSR $xxxx). So we have this:
Code
$8000 JSR $B000
$8003 LDA #$01
…
$B000 RTS

Now, what JSR does is, pushing the next instruction’s location - $0001 onto the stack. This means, that the value $8002 is pushed on the stack. Then JSR jumps to the specified address. What RTS does, is pulling that $8002 from the stack and adding $0001 to it, and storing it into the program counter register, causing the program to jump back to the instruction after that JSR.
JSL and RTL work the same way, except these push and pull 24-bit addresses. JSL pushes the long address - 1 onto the stack and jumps to the specified address, and RTL pulls the long address +1 onto the stack and jump to it.

Give thanks to RPG hacker for working on Asar.
Count how many bits are set in a specified range of address:
Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Counts how many bits are set in a specified address range.
;
;Input:
; $00-$01 = the starting address to count bits, low endian.
;  ($AABB -> $BB $AA)
;
; $02-$03 = the ending address to count bits, same format
;  as above.
;
; $04 = the bank byte of the address. The range of bytes to
;  check must be in the same bank. if not, try calling this
;  subroutine twice or more but with
;  "JSL ContinueCountBits" instead.
;
;Output:
;*$05-$06 = the number of bits being set.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CountSetBitsAtStart:
	STZ $05			;\Reset counter
	STZ $06			;/
ContinueCountBits:
	PHB			;>Just in case
	LDA $04			;\Adjust bank.
	PHA			;|
	PLB			;/

	.LoopBytes
	LDY #$07		;>Check each bit in a byte
	LDA ($00)		;>Load address stored in $00, A should have a value inside the pointed value

	..LoopThroughBits
	LSR			;>Shift bit right
	BCC ...NextBit		;>If bit moved into carry is clear, don't count.
	REP #$20		;\Increment bit counter
	INC $05			;|
	SEP #$20		;/

	...NextBit
	DEY			;>Next bit
	BPL ..LoopThroughBits	;>Keep until full byte has been checked.

	.NextByte
	REP #$20		;>16bit A
	INC $00			;>Next address to read
	LDA $00			;>This is so that the branches below works.
	CMP $02			;>The last byte
	SEP #$20		;>8bit A
	BEQ .LoopBytes		;\If not past the final byte, loop
	BCC .LoopBytes		;/
	PLB			;>Restore bank
	RTL

This is useful for hacks that have things stored in as bits and you want to count how many. For example, counting how many star coins collected total without having a separate RAM that increments each time you collect (since how levels remember that each star coins being collected and was stored as bits).
Here is how to use:
Code
;Example, checks how many set bits from $7E0060 to $7E0063
	REP #$20
	LDA #$0060	;>Start Address
	STA $00
	LDA #$0063	;>End address
	STA $02
	SEP #$20
	
	LDA #$7E	;>Bank address
	STA $04
	JSL CountSetBits
	RTL

Be careful not to have a possibility of having more than 65535 bits set, as the counter is 16-bit. Here is an example on how to call.
Give thanks to RPG hacker for working on Asar.
Honestly think you'd have an easier time passing the length instead of the end address. Like:
(untested code written in 5 minutes, don't kill me if it's actually nonsense.)
Code
;$00 = 3 byte pointer
;A   = length - 1
;X   = 16 bit output counter

Count:
	PHP
	REP #$30	; all 16 bit.
	TAY		; length in Y
	SEP #$20	; A back to 8 bit
	LDX #$0000	; reset counter

	PHB
	LDA $02
	PHA : PLB

.loop
	LDA ($0000),y	; load value
	BEQ +		; skip altogether if already empty
-	LSR		; shift LSB into carry
	BCC ++		; skip increment if carry clear
	INX		; increment
++	CMP #$00	; \ end once A is 0
	BNE -		; /

+	DEY		; more to go?
	BPL .loop

	PLB
	PLP
	RTL


Alternatively you could make Y the input for the length and not bother with the TAY thing at all.
Plus, I'm not too sure if TAY doesn't transfer all 16 bits regardless of process flag, so you could potentially skip the REP #$30 : SEP #$20 with just a REP #$10
Anime statistic on MyAnimeList:
400 animes completed ✓
6000 episodes completed ✓
100 Days completed ✓
... what even am I doing with my life?


Originally posted by JackTheSpades
(untested code written in 5 minutes, don't kill me if it's actually nonsense.)

(it's a bit nonsense)
LDA (addr),y doesn't exist, for one thing

Something like this would probably work instead:

Code
; Input:
; $00 = 24-bit pointer to start address.
;   A = number of bytes to count (16-bit)

Count:
	PHX
	PHY
	PHP

	REP #$10
	TAY
	SEP #$20
	LDX #$0000	; reset counter

.loop
	LDA [$00],y	; load value
	BEQ ++		; skip altogether if already empty
-	LSR		; shift LSB into carry
	BCC +		; skip increment if carry clear
	INX		; increment
+	CMP #$00	; \ end once A is 0
	BNE -		; /

++	DEY		; more to go?
	BPL .loop

	PLP
	PLY
	PLX
	RTL


Professional frame-by-frame time wizard. YouTube - Twitter - SMW Glitch List - SMW Randomizer
When are we need that code?
I'm created many sprites, blocks, and patches so far, but I didn't need that.

Stupid solution (untested)
Code
; Input:
; $00 = 24-bit pointer to start address.
;   A = number of bytes to count (16-bit)
;
; Output:
; $03-$04 = number of bits being set

Count:	PHX
	PHY
	PHP
	
	REP #$31
	TAY
	STZ $03
	
-	LDA [$00],y
	AND.w #$00FF
	TAX
	LDA.l .BitTable,x
	AND.w #$00FF
	ADC $03
	STA $03
	DEY
	BPL -
	
	PLP
	PLY
	PLX
	RTL
	
.BitTable
db $00,$01,$01,$02,$01,$02,$02,$03,$01,$02,$02,$03,$02,$03,$03,$04
db $01,$02,$02,$03,$02,$03,$03,$04,$02,$03,$03,$04,$03,$04,$04,$05
db $01,$02,$02,$03,$02,$03,$03,$04,$02,$03,$03,$04,$03,$04,$04,$05
db $02,$03,$03,$04,$03,$04,$04,$05,$03,$04,$04,$05,$04,$05,$05,$06
db $01,$02,$02,$03,$02,$03,$03,$04,$02,$03,$03,$04,$03,$04,$04,$05
db $02,$03,$03,$04,$03,$04,$04,$05,$03,$04,$04,$05,$04,$05,$05,$06
db $02,$03,$03,$04,$03,$04,$04,$05,$03,$04,$04,$05,$04,$05,$05,$06
db $03,$04,$04,$05,$04,$05,$05,$06,$04,$05,$05,$06,$05,$06,$06,$07
db $01,$02,$02,$03,$02,$03,$03,$04,$02,$03,$03,$04,$03,$04,$04,$05
db $02,$03,$03,$04,$03,$04,$04,$05,$03,$04,$04,$05,$04,$05,$05,$06
db $02,$03,$03,$04,$03,$04,$04,$05,$03,$04,$04,$05,$04,$05,$05,$06
db $03,$04,$04,$05,$04,$05,$05,$06,$04,$05,$05,$06,$05,$06,$06,$07
db $02,$03,$03,$04,$03,$04,$04,$05,$03,$04,$04,$05,$04,$05,$05,$06
db $03,$04,$04,$05,$04,$05,$05,$06,$04,$05,$05,$06,$05,$06,$06,$07
db $03,$04,$04,$05,$04,$05,$05,$06,$04,$05,$05,$06,$05,$06,$06,$07
db $04,$05,$05,$06,$05,$06,$06,$07,$05,$06,$06,$07,$06,$07,$07,$08
Simple increment/decrement counter effect. Useful if you want to show to the player that something has decreased or increased.

Code
!RAM_Record = $xxxx	;>The value shown that slowly increases/decreases
!RAM_RealVal = $yyyy	;>The real value that isn't shown, but shown "slowly follows" this value.

	LDA !RAM_Record
	CMP !RAM_RealVal
	BEQ .Done
	BMI .Increment			;>Feel free to change to BCC if unsigned.

	.Decrement
	LDA $13				;>Frame counter
	AND #$03			;>choose any value that is base2 minus 1 (modulo)
	BNE .Done			;>If any remainder bits set, don't change.
	LDA !RAM_Record
	DEC 
	STA !RAM_Record
	BRA .Done

	.Increment
	LDA $13				;>Frame counter
	AND #$03			;>choose any value that is base2 minus 1 (modulo)
	BNE ..Done			;>If any remainder bits set, don't change.
	LDA !RAM_Record
	INC 
	STA !RAM_Record

	.Done
	[...]

16-bit version:
Code
!RAM_Record = $xxxx	;>The value shown that slowly increases/decreases
!RAM_RealVal = $yyyy	;>The real value that isn't shown, but shown "slowly follows" this value.
	REP #$20
	LDA !RAM_Record
	CMP !RAM_RealVal
	SEP #$20
	BEQ .Done
	BMI .Increment			;>Feel free to change to BCC if unsigned.

	.Decrement
	LDA $13				;>Frame counter
	AND #$03			;>choose any value that is base2 minus 1 (modulo)
	BNE .Done			;>If any remainder bits set, don't change.
	REP #$20
	LDA !RAM_Record
	DEC 
	STA !RAM_Record
	SEP #$20
	BRA .Done

	.Increment
	LDA $13				;>Frame counter
	AND #$03			;>choose any value that is base2 minus 1 (modulo)
	BNE ..Done			;>If any remainder bits set, don't change.
	REP #$20
	LDA !RAM_Record
	INC 
	STA !RAM_Record
	SEP #$20

	.Done
	[...]

Give thanks to RPG hacker for working on Asar.
Originally posted by Akaginite
I had implemented another RNG routine at about 6 years ago.

Code
; 8bit Twisted-GFSR generator
; Period : 2^32-1
; 4 Bytes used

!Random =	$148B

TGFSR:		PHY
		LDA.w !Random+$01
		LSR A
		BCS +
		EOR #$95		; maximum tap values: 0x8E,0x95,0x9F,0xA6,0xB2
+		EOR.w !Random+$02
		EOR.w !Random+$00
		LDY.w !Random+$02
		STA.w !Random+$02
		LDA.w !Random+$03
		STY.w !Random+$03
		LDY.w !Random+$00
		STA.w !Random+$00
		STY.w !Random+$01
		PLY
		RTL

8bit Mersenne-Twister generator
I think this RNG has over-engineering for use in SMW.


Code
!MT_N =		160
!MT_M =		31
!MT_MATRIX =	$B2


What does those mean?
Give thanks to RPG hacker for working on Asar.


Originally posted by GreenHammerBro
Code
!MT_N =		160
!MT_M =		31
!MT_MATRIX =	$B2


What does those mean?

Those are just some parameters for the Merseene Twister's algorithm. N is the degree of recurrence, which can be calculated as desired Mersenne prime (1279) divided by the number of bits in each RNG value (8), rounded up; this value plus 1 also indicates how many values need to be in the SeedData table. M is somewhat freely chosen, just with M < N. Lastly, the MATRIX value is a series of bitwise matrix coefficents, which has a formula that I can't really explain briefly (Wikipedia kinda does).

Professional frame-by-frame time wizard. YouTube - Twitter - SMW Glitch List - SMW Randomizer
SA-1 Unsigned 16bit * 16bit multiplication routine

SA-1's arithmetic operations are calculated by signed.
for that reason, this routine doing signed to unsigned conversion.

Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 16bit * 16bit Multiplication SA-1 version
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Argusment
; $00-$01 : Multiplicand
; $02-$03 : Multiplier
; Return values
; $04-$07 : Product
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

MathMul16_16:	STZ $2250
		REP #$20
		LDA $00
		STA $2251
		ASL A
		LDA $02
		STA $2253
		BCS +
		LDA.w #$0000
+		BIT $02
		BPL +
		CLC
		ADC $00
+		CLC
		ADC $2308
		STA $06
		LDA $2306
		STA $04
		SEP #$20
		RTS
This is interesting. But don't the result will come messed up if you don't remove the sign bit in $2251 bit 15 and $2253 bit 15?... How you did the "to unsigned" logic there?

That routine reminds me of... I never managed to make a 32 bit by 16 bit divider (or even 24 bit by 16 bit) using 16 bit by 16 bit divider. But that probably is not possible unfortunately.
GitHub - Twitter - YouTube - SnesLab Discord
Originally posted by Vitor Vilela
This is interesting. But don't the result will come messed up if you don't remove the sign bit in $2251 bit 15 and $2253 bit 15?... How you did the "to unsigned" logic there?

That routine reminds me of... I never managed to make a 32 bit by 16 bit divider (or even 24 bit by 16 bit) using 16 bit by 16 bit divider. But that probably is not possible unfortunately.


this code is implemented by my experience, but I can't prove mathematically why it works fine. I'm silly.

verification of calculate:
Code
1) 0x004C * 0x9A63
Signed   : 0xFFE1 D564
Unsigned : 0x002D D564
Signed to Unsigned : 0xFFE1 D564 + 0x004C 0000 -> 0x002D D564

2) 0x8765 * 0x4321
Signed   : 0xE05F E305
Unsigned : 0x2380 E305
Signed to Unsigned : 0xE05F E305 + 0x4321 0000 -> 0x2380 E305

3) 0x8000 * 0xABCD
Signed   : 0x2A19 8000
Unsigned : 0x55E6 8000
Signed to Unsigned : 0x2A19 8000 + 0x8000 0000 + 0xABCD 0000 -> 55E6 8000
I have made a test program that did all multiplication possibles and indeed it works perfectly. This is pretty amazing!

I really wanted if it was possible to do an unsigned 16 bit division, but then the division does not have any similar property.

The divisor in SA-1 is unsigned, which is less bad (or more bad, I don't know). It's a quite bizarre to SA-1 division be signed by unsigned but lol.

Excellent work for finding this, though.
GitHub - Twitter - YouTube - SnesLab Discord
Opcode database.
Give thanks to RPG hacker for working on Asar.
Update that comes along with my 4-5 hex-> dec subroutine: the leading zeroes remover.
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.

erik edit: fixed link because dropbox
added the sa-1 compatible variant (requires a !SA1 detection if you're using spritetool)


optimized for cycle count and tweaked to unlimited distance.
Aligned number display (the “X” symbol was meant to be the “/” graphic symbol, but SMW does not have that):


This code displays numbers left or right-aligned with leading zeroes suppressed (no leading zeroes nor spaces). This is useful if you don't want your hack to have a hint on the maximum number of digits the number can have. Very useful for compact display since the “characters” are positioned to the left or right as possible.

Notes:
  • Prior to writing the numbers to the status bar/overworld border (Overworld Border plus patch), you must have clear the tiles that would be overwritten by the digits so that if they got changed (“10” becomes a “9”), the tile that “disappeared” doesn't end up staying there and be duplicated (“10” becomes “90”, where the “0” tile wasn't cleared)


See the code here. In the event the work gets (falsely taken down (I mean, this have shown how easy to abuse takedown notices, therefore no post is safe)), I've posted a copy here:

Defines:


Routines:


Example:



Note that this is tested using uberasm tool, so they call via JSL FileNameWithoutExtension_Label
Give thanks to RPG hacker for working on Asar.
My 32-bit frame counter to “hours:minutes:seconds.centiseconds” (centiseconds is actually a frame counter from 0 to 59; converted to 0 to 99). Give credit to Akaginite for the division routine.

If you input a value #$0004F1A0 (324000 decimal frames: 1 hour and 30 minutes), it outputs:
Code
-!Scratchram_Frames2TimeOutput is 1, the hour
-!Scratchram_Frames2TimeOutput+1 is 30 (#$1E in hex) the minutes
-!Scratchram_Frames2TimeOutput+2 is 00, this is the seconds
-!Scratchram_Frames2TimeOutput+3 is 00, this is the approximate centiseconds.


Not to be confused with the old timer generators found on the sprite section (actually rejected due to smwc updating sections when UberasmTool hit the scene), this one is different:

  • The value representing the amount of time is a single value stored in 32-bit (low endian; like the SNES would do) indicating a frame counter. The other codes that tries to replicate the real world timer stores 3 units of time in each byte: minutes:seconds:frames, where each value are handled individually rather than one, so if a value were to go past a certain threshold, say if frames reaches 60, it increases the seconds byte, and of course if it was a countdown, (frames goes down past 00), it would decrease the seconds byte (remember that the game runs at 60FPS).

    Using my method, it makes it easier if you are manipulating time using math operators, such as adding a minute to the countdown, you simply use this code:
    Code
    REP #$20
    LDA !Freeram_TimeFrames
    CLC
    ADC.w #3600		;>3600 frames = 1 minute (60frames/seconds times 60)
    STA !Freeram_TimeFrames
    LDA !Freeram_TimeFrames+2
    ADC #$0000
    STA !Freeram_TimeFrames+2
    SEP #$20

  • Because this is an input/output based subroutine, you can have multiple different timers use this without any issues, other timers that had its value stores it units separately uses the freeram directly and you had to rewrite the code with different RAM to store the time amount


To have a timer the increments/decrements, use this code:
Code
!Freeram_Time = $60
;^[4 bytes] frame counter

REP #$20
LDA !Freeram_Time
CLC			;\not to use INC because it doesn't set carry
ADC #$0001		;/when the value overflows a 16-bit boundary (#$FFFF)
STA !Freeram_Time
LDA !Freeram_Time+2	;\high word
ADC #$0000		;|
STA !Freeram_Time+2	;/
SEP #$20

For decrements (countdown), simply replace the CLC and 2 ADCs (not the number next to the opcode) with SEC and 2 SBCs.

Unit conversion to frames (as “frms”) template:
Code
                   1 sec =     60 frms
        1 min =   60 sec =   3600 frms
1 hr = 60 min = 3600 sec = 216000 frms

Formula:

Frames = (Hours*216000)+(Minutes*3600)+(Seconds*60)



Code to set (write) the timer value:

Code
!Freeram_Timer = $60
!StartTimerHour = 0
!StartTimerMinute = 3
!StartTimerSeconds = 30
	REP #$20
	LDA.w #(!StartTimerHour*216000)+(!StartTimerMinute*3600)+(!StartTimerSeconds*60)
	STA !Freeram_Timer
	LDA.w #(!StartTimerHour*216000)+(!StartTimerMinute*3600)+(!StartTimerSeconds*60)>>16
	STA !Freeram_Timer+2
	SEP #$20


Code to compare the time with another value (greater than/equal to and less than):

Code
!CompareTimerHour = 0
!CompareTimerMinute = 1
!CompareTimerSeconds = 0

!CompareFramesLowWord = (!CompareTimerHour*216000)+(!CompareTimerMinute*3600)+(!CompareTimerSeconds*60)
!CompareFramesHighWord = (!CompareTimerHour*216000)+(!CompareTimerMinute*3600)+(!CompareTimerSeconds*60)>>16
;^Placed like this because table stretched if the whole formula was applied in the code

	REP #$20
	LDA !Freeram_Timer				;\CMP sets the carry should A >= compare value (CMP is like SBC)
	CMP.w #!CompareFramesLowWord			;/following SBC would subtract an additional 1 if carry is clear (borrowing)
	LDA !Freeram_Timer+2				;\SBC would set the carry should A subtract by subtrahend
	SBC #!CompareFramesHighWord			;/if subtrahend was smaller than A (clear carry if underflow occurs)
	SEP #$20

	;Carry (BCC/BCS) = set should timer is above or equal to a value.


Compare if equal or not (best for executing events for 1 frame):
Code
!CompareTimerHour = 0
!CompareTimerMinute = 1
!CompareTimerSeconds = 0

!CompareFramesLowWord = (!CompareTimerHour*216000)+(!CompareTimerMinute*3600)+(!CompareTimerSeconds*60)
!CompareFramesHighWord = (!CompareTimerHour*216000)+(!CompareTimerMinute*3600)+(!CompareTimerSeconds*60)>>16

	REP #$20
	LDA !Freeram_Timer
	CMP.w #!CompareFramesLowWord
	BNE .NotEqual
	LDA !Freeram_Timer+2
	CMP #!CompareFramesHighWord
	BNE .NotEqual
	SEP #$20
	
	.Equal
	
	.NotEqual
	SEP #$20	;>remove this if you continue 16-bit A


2/24/2018 Edit: improved the division loop routine in the frames -> Hours:Minutes:Seconds:Centiseconds, it no longer holds a duplicate code, and the format stores the units from hours to frames instead the other way around, thus making loops to write to the status bar/HUD more easier to work with.

2019-10-10 EDIT: Fixed a bug that the minute is not displaying properly and also fixed the hours also.
Give thanks to RPG hacker for working on Asar.
32-bit unsigned hex-dec, great for numbers greater than 65535:
Code
!NumOfDigits = 6
;^Number of digits to be stored. Up to 10 because maximum
; 32-bit unsigned integer is 4,294,967,295.

!Scratchram_32bitHexDecOutput = $7F844E
;^[bytes_used = !NumOfDigits] The output
; formatted each byte is each digit 0-9.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;32-bit hex-dec converter
;input:
;-$00-$03 = the 32-bit number, in little endian.
;output:
;-!Scratchram_32bitHexDecOutput to (!Scratchram_32bitHexDecOutput+!NumOfDigits)-1:
; Contains value 0-9 on every byte, in big endian digits. Formula to get what RAM of a given digit:
;
; !Scratchram_32bitHexDecOutput+(!NumOfDigits-1)-(DigitIndex)
;
; Where DigitIndex is an integer ranging from 0 to !NumOfDigits-1, representing what digit with 0
; being the ones, 2 being 10s, and so on:
; DigitValue = 0: 1s place (ex. w/ 6 digits: $7F8453)
; DigitValue = 1: 10s place (ex. w/ 6 digits: $7F8452)
; DigitValue = 2: 100s place (ex. w/ 6 digits: $7F8451)
; DigitValue = 3: 1000s place (ex. w/ 6 digits: $7F8450)
; [...]
; DigitValue = 5: 100000s place (ex. w/ 6 digits: $7F844E)
;
;Overwritten
;-$04 to $05: because remainder of the division.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	Convert32bitIntegerToDecDigits:
	LDX.b #!NumOfDigits-1
	
	.Loop
	LDA.b #10				;\divide by 10 (the radix)
	STA $04					;|
	STZ $05					;/
	JSL MathDiv32_16			;>divide.
	LDA $04					;\write remainder digit (obviously shouldn't exceed 255)
	STA !Scratchram_32bitHexDecOutput,x	;/
	
	..Next
	DEX					;\loop until all digits are written
	BPL .Loop				;/
	RTL

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Unsigned 32bit / 16bit Division
; By Akaginite (ID:8691), fixed the overflow
; bitshift by GreenHammerBro (ID:18802)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Arguments
; $00-$03 : Dividend
; $04-$05 : Divisor
; Return values
; $00-$03 : Quotient
; $04-$05 : Remainder
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

MathDiv32_16:	REP #$20
		ASL $00
		ROL $02
		LDY #$1F
		LDA.w #$0000
-		ROL A
		BCS +
		CMP $04
		BCC ++
+		SBC $04
		SEC
++		ROL $00
		ROL $02
		DEY
		BPL -
		STA $04
		SEP #$20
		RTL


Remove leading zeroes (same as my 4-5 hexdec, but changeable with how many digits you are going to use):
Code
RemoveLeadingZeroes:
	LDX #$00
	
	.Loop
	LDA !Scratchram_32bitHexDecOutput,x	;\if current digit non-zero, don't omit trailing zeros
	BNE .NonZero				;/
	LDA #$FC				;\blank tile to replace leading zero
	STA !Scratchram_32bitHexDecOutput,x	;/
	INX					;>next digit
	CPX.b #!NumOfDigits-1			;>last digit to check (tens place). So that it can display a single 0.
	BCC .Loop				;>if not done yet, continue looping.
	
	.NonZero
	RTL

Give thanks to RPG hacker for working on Asar.
Originally posted by Akaginite
this code is implemented by my experience, but I can't prove mathematically why it works fine. I'm silly.

You're adding (operand) x 0x10000, and since n + (-n) is 0x10000 (we just ignore the carry normally), there's why it works.
I've noticed that Akaginite's 32-bit/16-bit division routine have a bug on it where the bitshift overflow can happen and outputs the wrong values. This happens when the value in A (up to 16-bits can be processed at a time) gets ASL A'ed when A holds a value $8000+, which ends up with bit 15 transferred to the carry without being checked (discarded), then compares this broken value to $04 (which can assume that this large value is less than $04) and incorrectly flags this value as less than and screws up the result. I've added a carry check and SEC (because it's expected that after the SBC operation, carry is ALWAYS set) and this bug is fixed.

This bug can easily happen if you were to have the (unsigned) 32bit integer #$80000000 or more (in binary, that is a 1 on the leftmost digit and 31 zeroes after or more), as the glitch triggers right away on the first loop on ASL A.
Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Unsigned 32bit / 16bit Division
; By Akaginite (ID:8691), fixed the overflow
; bitshift by GreenHammerBro (ID:18802)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Arguments
; $00-$03 : Dividend
; $04-$05 : Divisor
; Return values
; $00-$03 : Quotient
; $04-$05 : Remainder
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

MathDiv32_16:	REP #$20
		ASL $00
		ROL $02
		LDY #$1F
		LDA.w #$0000
-		ROL A
		BCS +
		CMP $04
		BCC ++
+		SBC $04
		SEC
++		ROL $00
		ROL $02
		DEY
		BPL -
		STA $04
		SEP #$20
		RTL

Give thanks to RPG hacker for working on Asar.