Autosplitter for SNES and Apple II
Autosplitter for SNES and Apple II
David, is it known the offsets for each of the 20-21 levels of this game? On the speedrun discord, we want to have an autosplitter for this version and the Apple II as well, and we're adapting the splitter from the DOS version, but the offsets of the levels on the DOS version are different from the Apple II and SNES and we don't know them.
NEW UPDATE! Prince Of Persia: 30th Anniversary Port v1.1.5. Download it today!: viewtopic.php?p=29053#p29053
NEW UPDATE! Prince Of Persia: The Queen Of Light v2.6. Download it today! viewtopic.php?p=33174#p33174
NEW UPDATE! Prince Of Persia: The Queen Of Light v2.6. Download it today! viewtopic.php?p=33174#p33174
Re: Disassembly of PoP1 SNES
Do you mean the memory location in RAM where the number of the current level is stored?Shauing wrote: ↑August 14th, 2021, 9:20 am David, is it known the offsets for each of the 20-21 levels of this game?
On the speedrun discord, we want to have an autosplitter for this version and the Apple II as well, and we're adapting the splitter from the DOS version,
but the offsets of the levels on the DOS version are different from the Apple II and SNES and we don't know them.
In SNES PoP that is 7E:0579. -- The number stored here is one less than the displayed level number.
7E is the bank number and I guess that within an emulated RAM the offset will be simply 0x0579.
In Apple II PoP it's 0x03F4.
(I think the authors of splitters already know the following, but I mention it for the sake of completeness.)
Both addresses refer to the address on real hardware, or within the emulated RAM.
To find the address in an emulator you need to add the base address (where the emulated RAM starts) which depends on the emulator and its version.
Re: Disassembly of PoP1 SNES
I see, I'll figure out the address for the SNES9X 1.60 one.David wrote: ↑August 14th, 2021, 7:04 pm Do you mean the memory location in RAM where the number of the current level is stored?
In SNES PoP that is 7E:0579. -- The number stored here is one less than the displayed level number.
7E is the bank number and I guess that within an emulated RAM the offset will be simply 0x0579.
In Apple II PoP it's 0x03F4.
(I think the authors of splitters already know the following, but I mention it for the sake of completeness.)
Both addresses refer to the address on real hardware, or within the emulated RAM.
To find the address in an emulator you need to add the base address (where the emulated RAM starts) which depends on the emulator and its version.
There's a few other offsets that might be needed, if we're adapting it from the DOS version. Some additions or removals might have to be done to the SNES one. Here's the Autosplitter for the DOS PoP 1.4 (under the state 'DOSBOX' section, there's several addresses/bytes that are used for this autosplitter):
https://raw.githubusercontent.com/Winte ... sia1.4.asl
NEW UPDATE! Prince Of Persia: 30th Anniversary Port v1.1.5. Download it today!: viewtopic.php?p=29053#p29053
NEW UPDATE! Prince Of Persia: The Queen Of Light v2.6. Download it today! viewtopic.php?p=33174#p33174
NEW UPDATE! Prince Of Persia: The Queen Of Light v2.6. Download it today! viewtopic.php?p=33174#p33174
Re: Disassembly of PoP1 SNES
To see what variable does each offset access, I converted the number in the .asl file to the offset within the data segment (DOS PoP 1.4 disassembly), by subtracting 0x19410.Shauing wrote: ↑August 15th, 2021, 7:08 am There's a few other offsets that might be needed, if we're adapting it from the DOS version.
Some additions or removals might have to be done to the SNES one.
Here's the Autosplitter for the DOS PoP 1.4 (under the state 'DOSBOX' section, there's several addresses/bytes that are used for this autosplitter):
Then I tried to find a variable with the same purpose in the other two versions.
Code: Select all
byte Level : "DOSBox.exe", 0x193C370, 0x1D0F4; // shows level 1-14 changes as door is entered
SNES: 7E:0544 (byte) = next level
Apple II: 031C (byte) = NextLevel
Code: Select all
byte Scene : "DOSBox.exe", 0x193C370, 0x1A4BA; // shows level 1-14 changes as scenes end
SNES: 7E:0579 (byte) = current level
Apple II: 03F4 (byte) = level
Code: Select all
byte EndGame : "DOSBox.exe", 0x193C370, 0x1D74A; // 0 before endgame, 255 at endgame cutscene
This is also set to 255 when the intro cutscene starts. Then it's set to 0 when the hourglass appears.
If the player interrupts the intro between the two then it remains 255 until a cutscene is shown.
This means that this variable is not a perfect indicator of whether the game ended.
Instead you could use disable_keys = data:5850 = 0x1EC60.
SNES: 7E:0629 (byte) = hourglass present -- 2 if the hourglass is present, otherwise 0.
This has a similar problem: If you interrupt the intro before the hourglass appears then it stays 0 until the next cutscene.
7E:0A84 (byte) = current cutscene -- This becomes 06 for the bad ending and 07 for the good ending.
It stays so even after the cutscene ends.
Apple II: E14A (byte) = psandcount -- Works like in the DOS version, with the same problems.
There is no equivalent of disable_keys because this version does not disable keys during the ending scene.
(The animation skips if you press a key then.)
Code: Select all
byte Start : "DOSBox.exe", 0x193C370, 0x1D694; // the level you start the game at
SNES: 7E:0E5D (byte) = decoded level -- This is the level number decoded from an entered password.
It stays 00 if you start the training so it's not exactly the same as the DOS variable.
Apple II: There is B6F0 = SavLevel, but it's updated when loading or saving a game.
Code: Select all
byte GameRunning : "DOSBox.exe", 0x19175EA; // 0 if game isn't running
Is this supposed to check if the player has quit PoP?
Code: Select all
byte MinutesLeft : "DOSBox.exe", 0x193C370, 0x1E350; // Minutes
int Count : "DOSBox.exe", 0x193C370, 0x1E354; // Frames
short FrameSeconds : "DOSBox.exe", 0x193C370, 0x1E356; // Frames in second part of time (720-0)
* data:4F40 = rem_min
* data:4F44 = pickup_obj_type -- "Count" accesses two 16-bit integers, pickup_obj_type *and* the following rem_tick, as a single 32-bit integer!
* data:4F46 = rem_tick
SNES: 7E:052D (ushort) = FrameCount -- This is the number of elapsed ticks.
1 minute = 0x1A9 (425) ticks, 1 second = 7 ticks.
Apple II: 0306 (ushort) = FrameCount -- This is the number of elapsed ticks.
1 minute = 725 ticks, 1 second = 12 ticks.
Code: Select all
byte Sound : "DOSBox.exe", 0x193C370, 0x2F233; // 0 if sound is on, 1 if sound is off
SNES: Sound cannot be turned off in this version.
Apple II: 031A (byte) = musicon, 0203 (byte) = soundon
Code: Select all
byte Room : "DOSBox.exe", 0x193C370, 0x1D107; // shows current room ID
SNES: 7E:0462 (byte) = CharScrn
Apple II: 004B (byte) = CharScrn
Code: Select all
byte IsRestartLevel : "DOSBox.exe", 0x193C370, 0x1E16A; // the is_restart_level (Ctrl+A) flag
is_restart_level would be data:429C = 0x1D6AC
SNES: You can't restart the level in this version.
Apple II: 00A3 (byte) = cutplan (the equivalent of different_room)
Code: Select all
byte LevelTextTime : "DOSBox.exe", 0x193C370, 0x1F35E; // frames left for showing the "Level N" text
SNES: 7E:0518 (byte) = msgtimer
Apple II: 00DB (byte) = msgtimer
Code: Select all
byte Level3CP : "DOSBox.exe", 0x193C370, 0x1E050; // Level 3 checkpoint flag (changes from 0-1)
SNES: 7E:0627 (byte) = checkpoint on/off -- Here it's not limited to level 3, of course.
Apple II: 0212 (byte) = milestone
Code: Select all
int RestartFlag0 : "DOSBox.exe", 0x193C370, 0x1D0E2; // eien86's flag for restart detection
int RestartFlag1 : "DOSBox.exe", 0x193C370, 0x1D0E6; // eien86's flag for restart detection
short RestartFlag2 : "DOSBox.exe", 0x193C370, 0x1D0EA; // eien86's flag for restart detection
data:3CD2 = below_row_coll_room[0]
data:3CD6 = below_row_coll_room[4]
data:3CDA = below_row_coll_room[8]
SNES:
7E:0605 (int) = SNbelow
7E:0609 (int) = SNbelow+4
7E:060D (short) = SNbelow+8
Apple II:
0380 (int) = SNbelow
0384 (int) = SNbelow+4
0388 (short) = SNbelow+8
Re: Autosplitter for SNES and Apple II
I moved the posts about the autosplitter from the SNES Disassembly thread to this new thread.
Re: Autosplitter for SNES and Apple II
Getting back to you with this but for the Apple II one, Mattcubing (who is trying to make the autosplitter for the Apple II), said that although he found the variables for the Apple II, it seems that they're different from computer to computer even if all of them were using the same emulator. Is there any solution for this?
NEW UPDATE! Prince Of Persia: 30th Anniversary Port v1.1.5. Download it today!: viewtopic.php?p=29053#p29053
NEW UPDATE! Prince Of Persia: The Queen Of Light v2.6. Download it today! viewtopic.php?p=33174#p33174
NEW UPDATE! Prince Of Persia: The Queen Of Light v2.6. Download it today! viewtopic.php?p=33174#p33174
Re: Autosplitter for SNES and Apple II
What happens:Shauing wrote: ↑August 21st, 2021, 6:25 am Getting back to you with this but for the Apple II one, Mattcubing (who is trying to make the autosplitter for the Apple II), said that although he found the variables for the Apple II, it seems that they're different from computer to computer even if all of them were using the same emulator.
Is there any solution for this?
The array which holds the emulated RAM is allocated dynamically, and it ends up at a different address every time the emulator is started (even on the same computer).
We need to find where does the emulator store the address of that array.
How to solve it:
Here is how to find the correct address in Cheat Engine.
(I used Cheat Engine because it's recommended in the docs of LiveSplit.)
After you added the variable to the list of cheats, click on it with the right mouse button, then choose "Pointer scan for this address".
In the window that opens, you can lower the Max level. You can go down to 1, at least if the emulator is AppleWin.
But the default 7 will probably find too many results in any case.
You can also enable this option to lessen the number of results: Show advanced options -> Stop traversing a path when a static has been found.
After you press OK, Cheat Engine will want to save a file. I'm not sure what is it good for. Anyway, save it somewhere.
There will be multiple results.
To find out which is the "real" one, consider only the results with the fewest offsets (i.e. the fewest levels of indirection).
(If every result has only one offset then consider all of them.)
Add them to the cheats list, then on each of them, right click -> Find out what accesses this address -> Find out what accesses this pointer.
If there are some results then it's the pointer used by the emulator, keep it.
If the result is empty then it's a wrong one, delete it.
After you found out the correct pointer for the first variable:
Double-click its Address and copy out the base address from the bottom textbox.
You can later pick the same base in the Pointer scan results window for the other variables.
With AppleWin 1.26.2.1 (32-bit), the "real" base address is "AppleWin.exe"+0023B8EC.
How to convert the addresses into the format expected by LiveSplit:
In the list of cheats, double-click the Address of the variable.
Copy the contents of the text boxes under the Pointer checkbox, from bottom to top.
For example the current level variable has these addresses for me:
• "AppleWin.exe"+0023B8EC
• 3F4
Then combine them like this:
Code: Select all
byte CurrLevel : "AppleWin.exe", 0x0023B8EC, 0x03F4;
I hope this helps.
Re: Autosplitter for SNES and Apple II
Will this also work to find the base address for the SNES emulator I'm writing the autosplitter (in this case snes9x-1.60-win32-x64)?
I'm having a hard time finding the base address for it.
EDIT: I tried to get the base address, but it seems that every time the emulator is reopened, it changes. I've had as base addresses in the times I tested this: 022ABFD0, 03CCAFD0, 03E4AFD0 and 03E0AFD0.
I'm having a hard time finding the base address for it.
EDIT: I tried to get the base address, but it seems that every time the emulator is reopened, it changes. I've had as base addresses in the times I tested this: 022ABFD0, 03CCAFD0, 03E4AFD0 and 03E0AFD0.
NEW UPDATE! Prince Of Persia: 30th Anniversary Port v1.1.5. Download it today!: viewtopic.php?p=29053#p29053
NEW UPDATE! Prince Of Persia: The Queen Of Light v2.6. Download it today! viewtopic.php?p=33174#p33174
NEW UPDATE! Prince Of Persia: The Queen Of Light v2.6. Download it today! viewtopic.php?p=33174#p33174
Re: Autosplitter for SNES and Apple II
I think you're looking at the wrong number.Shauing wrote: ↑August 21st, 2021, 10:14 pm Will this also work to find the base address for the SNES emulator I'm writing the autosplitter (in this case snes9x-1.60-win32-x64)?
I'm having a hard time finding the base address for it.
EDIT: I tried to get the base address, but it seems that every time the emulator is reopened, it changes. I've had as base addresses in the times I tested this: 022ABFD0, 03CCAFD0, 03E4AFD0 and 03E0AFD0.
Look at the screenshot below.
What we need is the "snes9x-x64.exe"+008D8C38, not the 041CAFD0.
Re: Autosplitter for SNES and Apple II
So it's always going to be "snes9x-x64.exe"+008D8C38, only the pointer changes depending of what are we looking for.
There still some stuff later that I have to change/delete as well it seems, seeing that there's no level skip/individual level stuff. For example there's a calculation that goes something like 60*720 ; I assume it has to do with the 60 seconds multiplied for the frames that elapse on DOS - in this case - 12?
NEW UPDATE! Prince Of Persia: 30th Anniversary Port v1.1.5. Download it today!: viewtopic.php?p=29053#p29053
NEW UPDATE! Prince Of Persia: The Queen Of Light v2.6. Download it today! viewtopic.php?p=33174#p33174
NEW UPDATE! Prince Of Persia: The Queen Of Light v2.6. Download it today! viewtopic.php?p=33174#p33174
Re: Autosplitter for SNES and Apple II
Yes.
Yes, it's 60 minutes * 60 seconds/minute * 12 frames/second.
It's always used like this:
Code: Select all
vars.levelRestartTimestamp = 60*720;
It's reset to 60*720 when the game is restarted, i.e. when the timer resets to 60 minutes left.
Don't forget that while DOS PoP stores the remaining time, SNES PoP and Apple II PoP store the elapsed time.
Which means that in the latter versions, 60*720 should be replaced with 0.
That is, unless you want to calculate with the remaining time in these versions as well.
The minutesLeft, totalFramesLeft, and adjustedFramesLeft variables have to be calculated differently as well, since the time is not split into minutes and frames in these versions.
Re: Autosplitter for SNES and Apple II
David, do you have a disassembly for the Apple II? I know there's the source code, but things aren't labeled over there. It could be useful to fine-tune the Apple II autosplitter.
Also, do you know what the C11E-C3EE section in memory does? For what the guys at discord tell me, that section could be useful for the autosplitter.
Also, do you know what the C11E-C3EE section in memory does? For what the guys at discord tell me, that section could be useful for the autosplitter.
NEW UPDATE! Prince Of Persia: 30th Anniversary Port v1.1.5. Download it today!: viewtopic.php?p=29053#p29053
NEW UPDATE! Prince Of Persia: The Queen Of Light v2.6. Download it today! viewtopic.php?p=33174#p33174
NEW UPDATE! Prince Of Persia: The Queen Of Light v2.6. Download it today! viewtopic.php?p=33174#p33174
Re: Autosplitter for SNES and Apple II
The author of the C64 port of PoP made one: http://popc64.blogspot.com/2012/03/part ... -push.html
Alternatively, there is a copy of the source together with build tools here: https://github.com/adamgreen/Prince-of- ... uick-start
The build process creates an obj/ folder, and within that, *.LST files will contain the source lines together with their offsets and byte values.
On the Apple II, the CPU sees I/O and ROM at the C000-CFFF range.
Emulators probably use the C000-CFFF range of their RAM buffer for one of the RAM banks which can be paged into D000-DFFF (where the CPU sees it).
The part in the spoiler is probably irrelevant, but I noticed that only after I wrote it...
Spoiler: show
base+C000 contains these bytes: FE 02 20 48 5A 96 DA 1E 60 78 D6 00 24 3E 76 9A
These are from MUSIC.SET2 (from the build repo I linked above).
The contents of that file end at base+C3F0.
This means the C11E-C3EE area contains only music data.
The only way it could be useful for autosplitting is if loading a different music set can signal something.