News:

Don't forget to visit the main site! There's lots of helpful docs, patches, and more!

Main Menu

[SM] The: "I have a dumb question about ASM hijacking" thread

Started by monktroid, April 13, 2017, 02:13:36 PM

Previous topic - Next topic

monktroid

Yo,

I've been studying my little socks off; gotten to grips with ASM and I get how a lot of the SNES works.  Now I wanna start striding into some actual dev.  Basically, my first task is I wanna design some fades using HDMA (a bit like, for example, the ones in ceres).  I've been beginning with similar stuff to the fades demonstrated in this https://www.smwcentral.net/?p=viewthread&t=27054.  Here's the thing though, all the stuff I've read thus far hasn't really helped me get my head around hijack points with xkas.

say I have something like the following as the start of my RAM

LoRom

org $88A61B ;points to the unusued FX1 space between scrolling sky and fireflea.

JSR someCode


I know I'm missing a bunch of stuff but I don't really know what!

I've gotta find some free space right?  How do I assign my asm to that free space?
I've gotta have the whole thing return such that the program carries on running as normal but with the additional code.  trouble is I don't really know how to get xkas to do that.  How do I inject my code so that it works against an unused FX1 space? Or is there some other way I can have my fades appear in specific rooms?

Apologies if this is well trodden ground, I've been struggling to find similar posts on this issue!

PHOSPHOTiDYL

QuoteI've gotta find some free space right?  How do I assign my asm to that free space?

LoROM

org $88A61B ;hijack point
JSR Freespace

org $88EE32 ;$11CE bytes free space
Freespace:
your
code
here

monktroid

Quote from: PHOSPHOTiDYL on April 13, 2017, 04:25:38 PM
QuoteI've gotta find some free space right?  How do I assign my asm to that free space?

LoROM

org $88A61B ;hijack point
JSR Freespace

org $88EE32 ;$11CE bytes free space
Freespace:
your
code
here
OOOOH,

I think I get it now, so the second 'org $88EE32' is telling the compiler where the actual free space for your code goes.  Is that right?

so in effect, are you saying: any code written after 'org $88EE32' is gonna be stored at that location?


squishy_ichigo

Just a quick mention, just in case, if you are hijacking code, then that means you are overwriting something and redirecting to free space, which means you will likely want to reinsert the code you are overwriting at the end of your custom code before doing a return jump.

You may also want to dive into the xkas documentation that explains some of the other features xkas has, could make your job a lot easier.

PHOSPHOTiDYL

Also be careful with labels.

Anything YourLabel,x & YourLabel,y will not compile properly.
Anything YourLabel, x & YourLabel, y with a space will compile as a long address.

So if I wanted to LDA MyLabel,x I'd have to have the exact address, ie. LDA $B257,x.
With a space the compiler thinks its LDA $82B257,x.
Without a space it compiles with the wrong opcode.

monktroid

thanks all, HDMA in Super Metroid is... not fun. I'm currently very very slowly reading through 888435 (the area where all the HDMA stuff is set up for fx1 stuff.)  Getting there! Brother, if only there was some kind of API for C++ :P

Scyzer

Quote from: PHOSPHOTiDYL on April 14, 2017, 02:12:43 PM
Also be careful with labels.

Anything YourLabel,x & YourLabel,y will not compile properly.
Anything YourLabel, x & YourLabel, y with a space will compile as a long address.

So if I wanted to LDA MyLabel,x I'd have to have the exact address, ie. LDA $B257,x.
With a space the compiler thinks its LDA $82B257,x.
Without a space it compiles with the wrong opcode.


I would like to point out how very incorrect this is. Spacing within address indexing is irrelevant and has no effect on the final compiled ASM.

Assuming MyLabel is at a location $82F230:
LDA MyLabel = LDA $82F230
LDA MyLabel,X = LDA $82F230,X
LDA MyLabel, X = LDA $82F230,X
LDA MyLabel,Y = LDA $F230,Y
LDA MyLabel, Y = LDA $F230,Y

You can also force a word/long address like so:
LDA.w MyLabel = LDA $F230
LDA.w MyLabel,X = LDA $F230,X
LDA.w MyLabel,Y = LDA $F230,Y
LDA.l MyLabel = LDA $82F230
LDA.l MyLabel,X = LDA $82F230,X
LDA.l MyLabel,Y = *Error* (There is no opcode for LDA Long,Y)

Basically, anytime xkas sees a label, it replaces that label with the LONG address of wherever that label is. Then it will shorten the final instruction to a word if (and only if) the opcode requires it. If a certain opcode (such as LDA) has both a word and long address, then it will use the long address by default.

LDA MyLabel will be a long address, because LDA long exists.
LDA MyLabel,Y only exists as a word address, which is why it is compiled as LDA $F230,Y, and you cannot force it to be a long address.

JSR MyLabel will be a word address. It is replaced as JSR $82F230 before being compiled, but then shortened to JSR $F230 as JSR only uses 2 bytes. Note that while JSL is a long address version of JSR, xkas will NOT replace a JSR with JSL or vice versa.

As far as I've found, there is only 1 instruction that xkas cannot compile correctly with a label, and that is PER.
PER MyLabel = *Error* (it should compile as PER $F230)
You can always manually put PER $F230, but with variable code that becomes a problem. The easiest solution for this is to use PEI, which is very similar, but uses an immediate address rather than absolute address.
The actual value written out will depend on the location of the instruction. For eg, if the instruction is located at $82F220, PEI MyLabel = PEI $0010. PEI will push an address that is equal to the current instruction's address + the value.

PHOSPHOTiDYL

Well xkas hasn't shortened the final instruction for me.
So much time wasted on product placement.

Those "force" instructions should be well noted.