SDLPoP; David's open-source port of PoP

Open-source port of PoP that runs natively on Windows, Linux, etc.
David
The Prince of Persia
The Prince of Persia
Posts: 2880
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: SDLPoP; David's open-source port of PoP (pre-release)

Post by David »

David wrote:
segra wrote:- Apple / Amiga data support?
Amiga graphics is identical to the DOS, so why?
Apple: It makes sense, but is it worth?
Um... by "Apple", did you mean Apple II or Macintosh?
User avatar
segra
Efendi
Efendi
Posts: 5
Joined: May 29th, 2015, 7:45 am
Contact:

Re: SDLPoP; David's open-source port of PoP (pre-release)

Post by segra »

David wrote:
David wrote:
segra wrote:- Apple / Amiga data support?
Amiga graphics is identical to the DOS, so why?
Apple: It makes sense, but is it worth?
Um... by "Apple", did you mean Apple II or Macintosh?
Apple 2, I havn't seen the Mac version... come to think of it though, SNES graphics would be pretty cool tho ;)
Falcury
Calif
Calif
Posts: 568
Joined: June 25th, 2009, 10:01 pm

Re: SDLPoP; David's open-source port of PoP (pre-release)

Post by Falcury »

David wrote: So is it time to release 1.15 officially?

Maybe I play it through to see if there are no showstopper bugs like that one with the exit door on level 4. :)
Have you tested the game yet?
I did a playthrough and had no problems.

The way the quicksave system handles the remaining time is one remaining issue though, that we will probably want to fix in 1.16.
Simply restoring the quicksaved time when quickloading is not ideal, because getting the best possible time then becomes very reliant on overuse of the quicksave system (this is probably not a lot of fun).
A flat penalty for quickloading might be a solution: i.e. quickloading always jumps to, for example, one minute later than the quicksaved time. (Except perhaps when the remaining time is already very low (say, below 5 minutes or so) because then the penalty becomes rather harsh; and speedrunners are unlikely to ever reach such a threshold anyway.)

The sequence table deobfuscation is over halfway done now. It may be good to have a human readable seqtable to it will be easier to fix some annoyances (like the quirk that makes trick 25 necessary). Sadly, inserting new stuff into the seqtable might get a bit tricky, because the table offsets will get messed up by doing this. Some C macros may be of some help, although this will probably not be as convenient as the original assembler code.

Edit: I finished the deobfuscation of the sequence table. I moved it into its own file because it became quite large (see attachment).
Here is the pull request on GitHub.
Attachments
seqtbl.c
(51.38 KiB) Downloaded 263 times
Falcury
Calif
Calif
Posts: 568
Joined: June 25th, 2009, 10:01 pm

Re: SDLPoP; David's open-source port of PoP (pre-release)

Post by Falcury »

I added some optional fixes for a couple of gameplay quirks (pull request):

Fix for falling off the ledge when turning around and jumping up after climbing two floors:
See Trick 25. With this fix the kid automatically moves one pixel backward before jumping up (only when the kid is exactly three pixels from the edge). The trick still works but it is unnecessary now.
In seg005.c, jump_up():

Code: Select all

	distance = get_edge_distance();
	if (distance < 4 && edge_type == 1) {
		Char.x = char_dx_forward(distance - 3);
	}
	#ifdef FIX_JUMP_DISTANCE_AT_EDGE
	// When climbing up two floors, turning around and jumping upward, the kid falls down.
	// This fix makes the workaround of Trick 25 unnecessary.
	if (distance == 3 && edge_type == 0) {
		Char.x = char_dx_forward(-1);
	}
	#endif
Fix "teleporting" four pixels further than necessary when climbing up from firm ground while not in front of a wall
Removes an edge distance check. The game checks whether the distance to the nearest edge below is <4 pixels, but this is only relevant if there's a wall right in front of the kid (because the kid might bump into the wall then) and the game already checks for the presence of a wall: edge_type != 1
In seg005.c, grab_up_with_floor_behind():

Code: Select all

	distance = distance_to_edge_weight();

	#ifdef FIX_EDGE_DISTANCE_CHECK_WHEN_CLIMBING
	// When climbing to a higher floor, the game unnecessarily checks how far away the edge below is;
	// This contributes to sometimes "teleporting" considerable distances when climbing from firm ground
	#define JUMP_STRAIGHT_CONDITION distance < 4 /* && get_edge_distance() < 4 */ && edge_type != 1
	#else
	#define JUMP_STRAIGHT_CONDITION distance < 4 && get_edge_distance() < 4 && edge_type != 1
	#endif

	if (JUMP_STRAIGHT_CONDITION) {
		Char.x = char_dx_forward(distance);
		seqtbl_offset_char(seq_8_jump_up_and_grab_straight); // jump up and grab (when?)
	} else {
		Char.x = char_dx_forward(distance - 4);
		seqtbl_offset_char(seq_24_jump_up_and_grab_forward); // jump up and grab (with floor behind)
	}
Fix being able to survive lethal falls by jumping on top of a guard
See Trick 11.
In seg003.c, bump_into_opponent():

Code: Select all

		if (ABS(distance) <= 15) {

			#ifdef FIX_PAINLESS_FALL_ON_GUARD
			if (Char.fall_y >= 33) return; // don't bump; dead
			else if (Char.fall_y >= 22) { // medium land
				take_hp(1);
				play_sound(sound_16_medium_land);
			}
			#endif

			Char.y = y_land[Char.curr_row + 1];
			Char.fall_y = 0;
			seqtbl_offset_char(seq_47_bump); // bump into opponent
			play_seq();
		}
Fix triggering loose floors by bumping into the wall above
See Trick 18. The fix modifies the sequence table: in the "bumpwall" sequence, I changed actions_5_bumped to actions_3_in_midair.
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5808
Joined: April 9th, 2009, 10:58 pm

Re: SDLPoP; David's open-source port of PoP (pre-release)

Post by Norbert »

Man, you've really been an active contributor to the SDLPoP project, Falcury. Nice.
Funny how you suddenly appeared with contributions, even though you already had a forum account. ;)
David
The Prince of Persia
The Prince of Persia
Posts: 2880
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: SDLPoP; David's open-source port of PoP (pre-release)

Post by David »

Falcury wrote: Have you tested the game yet?
I did a playthrough and had no problems.
I also played it through and found no problems either.
Falcury wrote: Sadly, inserting new stuff into the seqtable might get a bit tricky, because the table offsets will get messed up by doing this. Some C macros may be of some help, although this will probably not be as convenient as the original assembler code.
Ideally, seqtbl[] (and jump commands) would contain pointers into seqtbl_offsets[].
But I'm afraid that requires assembly, or dirty macro tricks. (*)
(I wonder how was this solved in the DOS port?)

By the way, seqtbl_offsets[] in seg005.c should also be moved to the new file.

(*) A dirty macro trick would be to cut seqtbl[] where you would put a label, like this:
(I did not try this yet!)

Code: Select all

#define LABEL(label) }; const byte label[] = {
#define OFFSET(label) (&label-&seqtbl+SEQTBL_BASE) // or: (&label-SEQTBL_0)

const word seqtbl_offsets[] = {
0x0000, OFFSET(startrun), OFFSET(stand), ......
......

const byte seqtbl[] = {
	LABEL(running)
		SEQ_ACTION, actions_1_run_jump, SEQ_JMP, DW(OFFSET(running_frame_7)), // goto running: frame 7
	LABEL(startrun)
		SEQ_ACTION, actions_1_run_jump, frame_1_start_run,
......
(And maybe change the SEQ_JMP, SEQ_ACTION etc. macros to take parameters? But we need the values in play_seq().)
And then hope that the parts remain in order after compiling and linking. :)
Although that might not even be required if every label is preceded by a jump.
(But that's not the case with "goto running: frame 7", and there are more!)
Falcury wrote: Edit: I finished the deobfuscation of the sequence table.
Thank you!
Falcury
Calif
Calif
Posts: 568
Joined: June 25th, 2009, 10:01 pm

Re: SDLPoP; David's open-source port of PoP (pre-release)

Post by Falcury »

Norbert wrote:Man, you've really been an active contributor to the SDLPoP project, Falcury. Nice.
Funny how you suddenly appeared with contributions, even though you already had a forum account. ;)
Thanks! Well, I only recently developed my coding skills to the extent where I could do something useful... It also helps that I finally have some free time to spare lately. It's a very nice project to work on (so many ideas!)
David wrote:By the way, seqtbl_offsets[] in seg005.c should also be moved to the new file.
Yes, that makes sense!
David wrote:A dirty macro trick would be to cut seqtbl[] where you would put a label, like this:

Code: Select all

#define LABEL(label) }; const byte label[] = {
That is absolutely brilliant. I shall try this out!

Edit:
Apparently, the gcc compiler adds some padding bytes between subsequent declarations. However, forcing the compiler to use an alignment of 1 byte seems to work for me:

Code: Select all

#define LABEL(label) }; const byte label[] __attribute__ ((aligned(1))) = {
Edit2:
Progress so far (pull request):
seqtbl.c
(48.2 KiB) Downloaded 240 times
David wrote:(And maybe change the SEQ_JMP, SEQ_ACTION etc. macros to take parameters? But we need the values in play_seq().)
We could perhaps leave the enum in place for global access to the values, but in seqtbl.c add macros without the "SEQ_" prefix that take parameters.
David
The Prince of Persia
The Prince of Persia
Posts: 2880
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: SDLPoP; David's open-source port of PoP (pre-release)

Post by David »

Falcury wrote: The eventual memory addresses are only available at runtime, and C won't let me do something like the offsetof(type, member) macro because apparently that only works for structs...
Yes, I get errors like this:

Code: Select all

pointer_into_array.c:18: error: initializer element is not computable at load time
It compiles if I place seqtbl within a function, but then the pieces are in reverse order!

If I put only seqptr inside a function, then that part compiles, but jumps still can't be used in seqtbl.

Interestingly, something similar works with labels: https://gcc.gnu.org/onlinedocs/gcc/Labe ... alues.html (the last example)
Falcury
Calif
Calif
Posts: 568
Joined: June 25th, 2009, 10:01 pm

Re: SDLPoP; David's open-source port of PoP (pre-release)

Post by Falcury »

I gave up on the seqtbl labels... couldn't get it to work. Ended up doing a gaint macro chain, so inserting and deleting is at least possible now (are there better solutions?)
seqtbl.c
(65.89 KiB) Downloaded 238 times
Edit: I added some new gameplay fixes:

Temporarily standing on thin air when standing up on a falling loose tile:
Added a check in check_action() (seg006.c) whether the kid is actually standing on a floor tile during the standing up animation. Side effect: it became easier to fall off ledges by standing up. I think this is because the kid gets moved a little bit forward (and then back again) during the animation - after reducing this by one pixel in the sequence table however, it is much less an issue.

Being able to press buttons through closed gates (Trick 1):
Adds a call to determine_col() in check_press() (seg006.c) to check that the kid is actually on the tile's column (and not bumped backward!) before the tile is pressed.

Being able to grab ledges two stories down by bumping into a wall first:
Reduces the max falling speed cutoff for grabbing to <30 in check_grab() (seg006.c).
The trick can be done with a standing jump slightly more than two tiles from a wall. The kid can than grab the ledge with a Char.fall_y of 30 (the game's original cutoff is <32; but under normal conditions the falling speed for "legal" grabs always seems to be 27 or less).

Blood appearing on chompers when a skeleton is chomped:
Before adding blood, check that the victim is not a skeleton in chomped() (seg004.c)

Controls not being released during the drinking animation, causing unintended movement:
During the drinking animation, use release_arrows() in control() (seg005.c).

Add a way to crouch after climbing up (instead of climbing down again) by pressing down + forward:
It's annoying not to be able to crouch-hop under gates that are near ledges (because when you are too close to a gate and forward is pressed, you will safe_step() instead of run + slide).
To execute this maneuver, press down and forward at exactly the same time.

Here is an experimental build. Hopefully this does not introduce too many strange new bugs.
Attachments
SDLPoP_v1.16b1.zip
(4.72 MiB) Downloaded 272 times
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5808
Joined: April 9th, 2009, 10:58 pm

Re: SDLPoP; David's open-source port of PoP (pre-release)

Post by Norbert »

David, will you create a 1.15 package?
Falcury
Calif
Calif
Posts: 568
Joined: June 25th, 2009, 10:01 pm

Re: SDLPoP; David's open-source port of PoP (pre-release)

Post by Falcury »

I finally managed to finish my mod: see here. Phew.
Well... actually it's only eight levels. Oh well.
It requires SDLPoP; I diverged a bit from the main branch to add some "special events" and the like.
It may be good to have some sort of "customization" API or "scripting framework" for modders in the future? Of course I do not want to not want to "pollute" the original code just for the sake of my own levelset...
David
The Prince of Persia
The Prince of Persia
Posts: 2880
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: SDLPoP; David's open-source port of PoP (pre-release)

Post by David »

Norbert wrote:David, will you create a 1.15 package?
Umm... I should have already made it earlier.
Now the ChangeLog needs updating.

I also merged the new pull requests.
Falcury wrote:Ended up doing a gaint macro chain, so inserting and deleting is at least possible now
I looked at those series of #defines.
I tried replacing it with const, but it won't work.

A smaller example:
This code results in the error "initializer element is not constant".

Code: Select all

const int i=1;
const int j=i+1;
It compiles as C++, though.
It seems C and C++ have different ideas about what is a constant.
David
The Prince of Persia
The Prince of Persia
Posts: 2880
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: SDLPoP; David's open-source port of PoP (pre-release)

Post by David »

David wrote:Now the ChangeLog needs updating.
Done.
Can I make a ZIP now, or does someone have more additions? :)
Falcury
Calif
Calif
Posts: 568
Joined: June 25th, 2009, 10:01 pm

Re: SDLPoP; David's open-source port of PoP (pre-release)

Post by Falcury »

There are some additions that I haven't made pull requests for yet. Do you want me to do that now, or do you want to wait for the next update?
Edit: pull requests submitted.
David
The Prince of Persia
The Prince of Persia
Posts: 2880
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: SDLPoP; David's open-source port of PoP (pre-release)

Post by David »

From https://github.com/NagyD/SDLPoP/pull/20
Falcury wrote:A drawing bug occurs when a loose tile is placed to the left of a potion.
[...]
Unfortunately, the bug still occurs when the loose tile wobbles.
Interestingly, the bug disappears in the original game in exactly that case.
I'm trying to figure out why.

Update: I just figured it out: An else was missing in redraw_needed().
Looks like I overlooked a jmp in the disassembly. (Even though it's followed by a separator line as wide as the screen.)
Who would have thunk there were still some of these?... :D

From https://github.com/NagyD/SDLPoP/pull/21/files
I'm not sure what FIX_GUARD_FOLLOWING_THROUGH_CLOSED_GATES does.
Also, that "Kid.curr_row * 10 + 9" looks strange. get_tile() expects a column there, so it should be just 9?
Post Reply