Tip: Bad things to do in the title demo: Enter a door or a pipe, activate a P-switch or a star, complete the level, hit a message block, or die. These will either glitch the music, or force the player into an endlessly looping title level until they reset the game.
Well, what did you expect from programming?
Mersenne Numbers aren't that hard to understand as the the formula is "2^n - 1" (and most people in computer sciense will know the formula before the name). What makes them special in base 2 (and therefore programming) is that consecutive bits from zero to a specific bit are set (i.e. 0x01 has bit 0, 0x03 has bits 0 and 1, 0x07 has bits 0, 1 and 2, etc. set). The advantage of using these values is that performing a modulo in base 2 is pretty easy with these numbers since you just have to perform an "AND #$MN" (with MN being the Mersenne Number).
That being said, 0x7F should work as normal as that's 0b01111111 or 2^7 - 1.
I tested the values previously given (1F and 3F) it works as intented.
I looked at a list of mersenne numbers, but I can't find anything in hexadecimal. In decimal 7F=127 which id one of the lowest mersenne number. The equivalent of 3F in decimal isn't in the list, yet works, which makes me think it's different in hex and dec.
The equivalent of 3F in decimal isn't in the list, yet works, which makes me think it's different in hex and dec.
It is, actually, as 63.
Basically, the hex version of the Mercenne numbers are 00, 01, 03, 07, 0F, 1F, 3F, 7F, FF. You'll notice a repeating pattern of "1-3-7-F"; this continues for any additional digits too, like 1FF, 3FF, 7FF, FFF, etc. The reason Mercenne numbers are useful for hex is because they represent a "full binary"; if you convert each of those numbers to binary, you'll see that they fill in all bits below the top one, i.e. 00000001, 00000011, 00000111, 0000111, 00011111, 00111111, 01111111, 11111111. Professional frame-by-frame time wizard. YouTube - Twitter - SMW Glitch List - SMW Randomizer
Indeed these values work as intended. It doesn't give me a lot of options though.
Why is that in mersenne numbers, when tons of other coding is not? Is there an easy way to make it not in mersenne?
Like the speed of the projectile, I pick any number between 00 and 7F and each one is different. Gives a lot more room to work.
In a nutshell: AND-ing with Mersenne numbers is a particularly nice way to decrease the range of the frame counter. It lets you easily make counters that go from 0 to 1, from 0 to 2, from 0 to 4, from 0 to 8, from 0 to 16, and so on, but nothing inbetween. By checking when such a counter is zero, you can make things happen every second frame, or every fourth frame, or every 8th frame, or every 16th frame, and so on.
However, this method can't give you timers that go from, say, 0 to 12, so you can't make things happen every 12th frame this way. It's possible to do of course, but it's less elegant and requires more code, so people often willingly limit themselves to Mersenne numbers to be able to write elegant code.
In order to use other numbers, you need to set up an actual timer using a RAM address. Thankfully, SMW has a bunch of RAM tables already allocated for sprites which you can use, and some of those are already set up to be used as timers. It looks like the noob boss has $1558 unused, so try that one.
Basically, take this part of the code:
And replace it with:
LDA #$xx ; how long you want to wait between spawns
Well, as I said, you can imitate it using ExAnimation. It's not messing with any actual graphics; it's just animating the palette.
The way the actual game does it is a bit more complicated, as it randomly performs the flashes. It uses a palette handler table at $0682 for updating the colors. Professional frame-by-frame time wizard. YouTube - Twitter - SMW Glitch List - SMW Randomizer
Is this Pixi's %get_map16() routine? Because that should handle dealing with $9A/$98 already, as well as accessing the Map16 tables at $40C800/$41C800. (also, you can write multiple LSR/ASL opcodes like "LSR #4". Doesn't save space though, it's just for readability)
Otherwise, though, yeah that's the only way to shift a value down a nibble. It looks wasteful, but LSR/ASL are actually very fast opcodes at only 2 cycles per shift (comparatively, a JSL takes 8 cycles, meaning four LSR/ASL opcodes can run in the same time as one JSL). Professional frame-by-frame time wizard. YouTube - Twitter - SMW Glitch List - SMW Randomizer
LSR #4 at least makes the code more readable so thanks a ton for that.
GPS is what it's for. I don't think it handles getting block coords, so that would mean I did it right!
On a related note:
I'm trying to implement a %next_map16() as per my asm request thread entry (dunno how I missed %get_map16() already existing when I requested them... :/)
; call %get_map16() to prep input. then call the following:
LDA $41C800,x ; Get Map16 Tile into A
STA $41C800,x ; Get Map16 Tile into A
; JML $00C0FB|!bank ;pulled from %change_map16(), I *know* it needs more before it.
;Just not understanding what yet, seeing something about layers?
Any quick suggestions on this to get me pointed in the right direction/solve this?
(Trying to next_map16 so that I don't have to have 16+ copies of the same block asm, the usual use case I guess).
Not even sure if $00C0FB works the way I think it does.
Thanks as always by the way Thomas! I've gotten a couple cool blocks made already thanks to your help!
(If there's a more streamlined way of doing it you can think of that would be welcome feedback too!)
If it's *super* involved I'll probably just cheat and call get16,INC,change16...
EDIT: ended up doing just that. Looked like understanding the layer code would only save me about 16 instructions afaik, which just wasn't worth the optimization effort. (and fixed table stretch...)
Context: Know next to nothing about SPC. Or which/whatever does the music thingies! X3
Was the only idea I had just now to increase decrease loading time of music besides global music.
Question: Is it possible to cache a projected "next song" into RAM somewhere and DMA/"redirect via pointer (multibuffer)" to quickly load it when asked? Or is that RAM completely isolated/other technical difficulty (no actual speed gains, etc.)? If so, anyone have any pointers? Docs/wikis/RAM addresses/co-dev recommendations/gimme free code/pseudo code/write my will and testament?
Use Case: Eventual fleshing out of the Jukebox Block I posted in ASM Request. Waaaay down the road, but figured it wouldn't hurt to ask for help! Especially since learning an entire topic just for a (I would assume) few lines of code is... daunting (TT^TT)
Fringe Idea: Make 2 global songs that are just a "calloc()" of the largest song essentially and load next song into that ram via DMA then load that global song. This would be the multibuffer approach pseudo-concept.
Edit: Was bitten by the urge to poke and I'm now a little scared to touch this project. I was wrong. Very wrong. I see that now. Not a patch for the faint of heart. Seems I'd need to apply a patch maybe even hijack NMI to ignore SPC I/O when flagged and probably learn SPC-asm and SA1-asm so I can upload a byte at a time in a remotely fast manner. That about the gist of it? Or did I careen off course? *shivers*
Not sure if this is tool-related (ASAR) or asm-related...
Anywho, I'm making a patch and currently it's setup like so:
I'd like to replace that with:
or similar. Only problem is, I need to access that location from outside the patch (shared-subroutine essentially, and I could do it that way if needed). Is there a way to get the generated address (I assume I can lock it in place with the static keyword? Maybe a define file?) Not really sure the best way to set this up. Any help with this? Or is this not possible?
Edit: This has been tried a couple times before it seems. For those who follow: yes you can get it by writing external tools, no you can't using just ASAR. Afaik, from what I found anyway.
I am looking for something that as soon as you press a button on the title screen, makes a small sound effect and lead directly to level C5. Any ideas?
One file, One player
No Overworld Apply UberASM (game modes 07 and 08):
"Press start" sign
Inside the "Press Start" sign UberASM replace:
!sfx_number = $29
!sfx_port = $1DFC
if read1($00FFD5) == $23 ;sa-1 compatibility
!addr = $6000
!addr = $0000
BEQ .no_press ; check start, a, & b for press
Ideally you'd want to disable controller input on game modes 04/05/06 (didn't test how far back you'd need to go but at least 6) and disable a/b/start for whichever ones you don't want to use (and edit the controller detect code accordingly)
Unfortunately, UberASM runs after the normal code though and I couldn't find the hijacks after 50 minutes :/
Edit: Not *thoroughly* tested. May break with saves. Didn't get that far in testing.