Tip: Entering a door or pipe, activating a P-Switch or grabbing a star, completing the level, hitting a message block, and dying will cause issues on the title screen, such as causing musical glitches, or trapping the player in an endlessly-looping level.
I'm pretty sure that this can be optimized even more. But seeing that I hit my limit, I have no idea how. I'd prefer advanced ASM hackers to contribute to this optimization. But other people can try too.
With optimizing I mean faster code, even if it costs ROM space. This means that the code should use minimal amount of cycles. It's all for the sake of decreasing level loading times and what not. It would be awesome if we actually saw some visible faster loading time.
I just added in a little piece of code that stores the Y value (which contains the size of the decompressed ExGFX file) to $8D/$8E before the high byte gets destroyed by the SEP #$10 at $00B8EA.
This is useful for patches that need to upload arbitrary-sized ExGFX files without having to include a full copy of this routine in their code just to get the decompressed size.
$8D/$8E is already overwritten many times in the decompression routine and doesn't contain any useful information afterwards, so it's a good address to use.
EDIT: I'm also still leaning towards coding a GZIP decompression routine for SMW and implementing it into LM - not necessarily for faster decompression speeds, but because GZIP can compress to decently smaller sizes than LC_LZ2 in some cases.
GZIP is a pretty standardized compression format, and I've already found quite a few documents on it, I just haven't gotten around to coding a 65c816-version of the decompressor.
!Freespace = $1D8000
+ STX $8A
STY $8D ; store size to $8D
+ LDA $8F
.Label2 INC A
.LoopEnd0 SEP #$20
.NextUp ASL A
- STA ($00),y
- STA ($00),y
- STA ($00),y
.LoopEnd SEP #$20
+ STA ($00),y
If [$00] points to $12:FFFF for example it will read upper byte from $13:0000 instead of $13:8000.
SEP #$20 ;is $03 used for anything? can save a cycle without the SEP
XBA ;it's the high byte that got affected
didn't test that so point out anything that doesn't look quite right, ofcourse =)
edit: since push/pull is actually slower than STA dp/LDA dp, some savings can be made by placing them in unused DP space for that routine.
@ersanio: the unrollable stuff will be good to convert to DMA, except word fill that would be pretty awkward. The copy/fill(byte) loops are suitable though.
@Min: Self modifying code with MVN is better than load/store, but DMA WRAM->SRAM->WRAM is 2 cycle/byte not counting setup. A few days ago there was a chat about just using DMA (would also work for byte copy).
@ersanio/others: For byte fill you can just use DMA and set DMA to not increment the address so it reads the same byte every time. 1 cycle per byte transferred like that to $2180. Just have to store it to some byte in SRAM because WRAM->WRAM transfer not allowed.
Copy can do $2180->$70xxxx->$2180 but some SRAM must be reserved. Much faster, but more akward to use. MVN is easy so it depends on what we decide. If we ever have to copy like 200 bytes or something (large monocolored area, repeating tile sequence etc) then DMA will be massively faster than MVN. For small quantities, MVN is OK due to DMA setup time.
By the end when everyone has put in their contribution it should be much, much faster than the original.
@Japan guys: if there is anyone else to bring please bring them since the communities are kind of divided for whatever reason. Even if the English is not too good it is still very easy to contribute to projects like these.
Seeing as the JSL/RTL only gets called about 20 times max per level, you only lose about 1 microsecond give or take. Also, because there is potential for a hacker to need the decompression routine for whatever reason, I argue that it should stay as an RTL. I hate to keep going back to SMAS, but I do intend on using this routine in more than one spot. Point is, it can happen in SMW too, so I'd say the beneficiary comfort of keeping an RTL for convenience outweighs the additional microsecond we save in time.
Just my opinion. Anyone can rebut. ----------
Interested in MushROMs? View its progress, source code, and make contributions here.
Seeing as the JSL/RTL only gets called about 20 times max per level, you only lose about 1 microsecond give or take. Also, because there is potential for a hacker to need the decompression routine for whatever reason, I argue that it should stay as an RTL.
Agreeing with this. It's literally impossible to notice the difference and just causes inconvenience, so there's little reason to keep it. The focus should be on optimizing the loop content.
for some reason the DMA version is screwing up the new (yet-to-be-released) Layer3ExGFX that reloads GFX on submap change (including FG slots) w/o fblank. It causes layer 1 and sprites to "flicker" above the windowing effects. I think it might have something to do with the DMA transfer that uses channel 6, because when I comment out the STA $420B it stops flickering (of course messes up the GFX load too though), but when I change the channel it doesn't help at all.
I'm looking into a solution right now, because I really think this should be addressed.
EDIT: I just tested it in SNES9x, and the problem isn't exactly the same but it is there. the whole screen flickers black as if entering fblank every other frame.
I guess the routine has a problem running outside of blank, which is a problem for any "OW ExGraFix" patches that reload GFX on submap change without fblank
EDIT2: BSNES does the same
EDIT3: I'm not even sure if the DMA version is faster. And if it is slightly faster, I think we should continue to use the non-DMA version because compatibility > tiny speed increases.
@edit: It writes to CH5/CH6 registers, any possibility CH5 is messing things up for whatever you are doing? The registers themselves are readable so maybe push them before entering the routine and see if it helps.