Language…
16 users online: bradcomp, BUX88, DanMario24YT, deported,  DeppySlide, Domokun007, ForthRightMC, Heitor Porfirio, hhuxy, Knight of Time, mtheordinarygamer,  Ringo, Sammmoo,  StayAtHomeStegosaurus, The_Uber_Camper, Tomi P - Guests: 297 - Bots: 267
Users: 64,795 (2,375 active)
Latest user: mathew

RTS/RTL

I'm having trouble trying to JSL to a routine that requires a JSR. The trick i'm trying can be found here number 6. The code looks like:
Code
PHK
PER $0006
PEA $yyyy
JML $xxxxxx

In my context, i'd like to call the glitter routine from bank 0. So this is what I can interpret from the code:
- Push the program bank.
- I think this is push relative to the PC. This is one of the sources of confusion as you'll see later.
- Push an address in bank 0 that has RTL next ($84CE).
- Jump to the subroutine ($00FD5A).
- Routine finishes, return to $84CE + 1, which is an RTL.
- RTL to whatever was pushed in the opcode PER $0006.
This is where i'm stuck. Could someone please explain what happens from here and what PER $0006 actually does?
Thanks

EDIT: Logically it makes sense for the RTL at $84CF to return one line after the jump, so what was the point of PHK. Wouldn't it still be on the stack?
PER $0000 pushes the 16-bit location of the first byte AFTER the PER instruction. So PER $0000 at 008000 pushes "80" then "03" onto the stack. PER $0006 pushes the location of the next opcode after the JML - 1, so the RTL jumps to that opcode. The PHK is needed since RTL needs a 24-bit return address but PER only pushes a 16-bit one. After this the code just keeps running after your JML, as if it's a JSL.
I'm getting the reason for PHK now, but still a bit confused about PER and what it does.
Originally posted by Medic
So PER $0000 at 008000 pushes "80" then "03" onto the stack.

I'm not exactly sure where the 80 and 03 are coming from.

Originally posted by Medic
PER $0006 pushes the location of the next opcode after the JML - 1, so the RTL jumps to that opcode.

Why does $0006 signify a jump to the JML?
As Medic said PER pushes the current pc + value of PER so if PER is located at $008000 then PER $0000 would push 80 and 03 onto the stack because that's what the current pc address is.

Look at the code in terms of bytes in memory:

Code
org $008000
db $62,$00,$00,$F4,$yy,$yy,$5C,$xx,$xx,$xx

The first 62 is the hex number for PER and located at $008000 the 2 bytes after that are the operands (the $0000) which are located at $008001 and $008002 therefore the pc address is now $008003 (The $F4)
However you don't want to return to the first $yy (Because it always returns to address on the stack + 1) but to after the last $xx so you have to do PER $0006 (Because the last $xx where you want to return to is located 6 bytes after the PER instruction)

On a side note: AlcaRobot has a neat feature to get this kind of code


For reference, the PER abbreviation comes from Push Effective Relative, with relative meaning "from the current location", like with branch commands. Just like BRA $00 just goes to the next opcode, PEA $0000 pushes the location of the next opcode.

PEA, on the other hand, comes from Push Effective Absolute, with absolute meaning "this address specifically". So you'd use that to push an actual ROM location; PEA $8000, for instance, pushes $8000 directly instead of adding it to the current code position.

On that note, PER is... well, pretty much useless, since PEA can accomplish everything it can do except PEA is actually faster (5 cycles vs 6), plus it's just easier to do absolute addressing instead of relative.

Professional frame-by-frame time wizard. YouTube - Twitter - SMW Glitch List - SMW Randomizer
PER is most useful with dynamically placed code (IE, in RAM). I suppose it might be useful in bad development practices if they manually move around pre-complied code.
The only time I've ever seen pre-compiled code move around is jonwil's blocktool. And even that one had its reloc offsets, so PER still wasn't useful.

PER is probably useful for multitasking 65816 OSes, but it's completely useless on SNES.

(On a mostly related note, still a bit surprised we went so long without shared routines, when jonwil had it all along. But on the other hand, TRASM, lag, and closed-source blocks.)
<blm> zsnes users are the flatearthers of emulation
Well, I was using shared subroutines before they were cool.

Also, wasn't PER used in the past because some assemblers had trouble with PEA? I think xkas required a .w after it (because hey, why wouldn't it make sense to have to specify the operand size of an opcode that literally only has one possible operand size?), and TRASM outright didn't support it unless you wrote it as hex code. Though I guess I'm not sure if TRASM supported PER either.

----------------

I'm working on a hack! Check it out here. Progress: 64/95 levels.
xkas 0.06 doesn't support PEA label. Romi's modified version of it does, but I don't know if the .w stuff is needed.