Going great guns on a Prince of Persia port...

Got a programming project in mind? Tell everyone about it!
sirbod
Posts: 739
Joined: Mon Apr 09, 2012 8:44 am
Location: Essex
Contact:

Re: Starting a Prince of Persia port...

Postby sirbod » Sun Oct 01, 2017 12:18 pm

Begging for a NuLA colour map, looks awesome so far.

Just the sort of thing to show of in the Games Arcade at the London Show. I have room for a few more machines if anyone has the hardware ;)

User avatar
kieranhj
Posts: 528
Joined: Sat Sep 19, 2015 10:11 pm
Location: Farnham, Surrey, UK

Re: Starting a Prince of Persia port...

Postby kieranhj » Sun Oct 01, 2017 1:05 pm

Thanks for the kind words everyone and thanks trixster for making a quick video - I didn't even check that you could open the exit door! Certainly seems to have caused a bit of splash on Facebook. Much as I'd love to be able to squeeze the game onto a vanilla Model B, I don't think even Kevin Edwards would be able to manage that. :lol:

As for NULA, when I get round to redoing the graphics, or at least asking Dethmunk nicely :), I'll work on a specific NULA sprite set with custom palette because we'll be able to use all 16 colours rather than just remapping 8 colours from the vanilla version.

I'm going to carry on the port during my commute time but will be on holiday for two weeks across the London Show. We have the November ABUG meet up which is a great target for me to see where I can get to by then. :D
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

User avatar
kieranhj
Posts: 528
Joined: Sat Sep 19, 2015 10:11 pm
Location: Farnham, Surrey, UK

Re: Starting a Prince of Persia port...

Postby kieranhj » Fri Oct 06, 2017 10:43 pm

I thought you would all like another weekend treat. This is the first level of the game fully playable including all secret areas! I ported the guard & AI functions, along with the ability to pick up objects including the sword. I also re-implemented the keyboard handler, so the game is actually controllable - it used to do weird things before - and have re-written the sprite routines to correctly handle clipping and fixed other gfx glitches.

https://bitshifters.github.io/jsbeeb/?disc=https://bitshifters.github.io/content/wip/pop-beeb-play-level1-mode2.ssd&autoboot&model=Master

(Note: Return is the "action" key including grab & step, for timed jumps you'll need up-left & up-right which are mapped to the two keys either side of up '*'.)

Consider this a "teaser" :D and probably the last image I will upload here until the game is complete. I don't want you all getting bored and would like the final version to be fresh for everyone to play through and enjoy. :)

There is still plenty of work to do. I need to implement cutscenes and remaining gameplay features plus attract mode, save game etc. All the graphics need to be revamped for MODE 2 resolution and good palettes chosen (including NULA palettes.) Then I need SN music and sfx from our musician friend, Inverse Phase. Finally the whole lot needs to come together on a double-sided disc and any remaining Beeb specific support.

I'm also still not happy with the flickering and frame-rate. The good news is that there is plenty of memory free now - at least 6K - but not enough to double-buffer in MODE 2 (need around 13K.) The frame-rate gets quite bad when many sprites are being redrawn - I need to do some profiling (not jump to conclusions this time!) and have a good think about the best way to speed it up.

I'm still looking for an alpha tester to join our Slack channel and do playtesting with regular builds. Ideally someone who has played & completed the game on Apple II or PC and doesn't mind ruining their enjoyment of the finished Beeb version somewhat - it will mean replaying a lot of the same levels over again but at least you get some input into the development process. :wink: If you're interested please PM me!
Attachments
pop-beeb-play-level1-mode2.zip
PoP Level 1 fully playable
(55.57 KiB) Downloaded 41 times
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

User avatar
lazarusr
Posts: 620
Joined: Thu Sep 10, 2015 8:56 pm
Location: London

Re: Starting a Prince of Persia port...

Postby lazarusr » Fri Oct 06, 2017 10:55 pm

This truly remarkable. Who'd have thought this was possible on a Beeb. =D> =D> =D>

User avatar
billcarr2005
Posts: 1102
Joined: Fri Sep 09, 2005 3:01 pm
Location: UK
Contact:

Re: Starting a Prince of Persia port...

Postby billcarr2005 » Fri Oct 06, 2017 11:24 pm

Just played the level through. Fantastic achievement. :)
Can't wait for the finished game! =D>

User avatar
vanekp
Posts: 337
Joined: Thu Nov 30, 2000 7:09 am
Location: The Netherlands

Re: Starting a Prince of Persia port...

Postby vanekp » Sat Oct 07, 2017 7:52 am

Indeed looking good, never expected to see this game runnig on a BBC, graphics has a few glitches but then its not the final version.

User avatar
trixster
Posts: 527
Joined: Wed May 06, 2015 11:45 am
Location: York

Re: Starting a Prince of Persia port...

Postby trixster » Sat Oct 07, 2017 4:06 pm

It's stunning. Amazing work! I've popped another vid on the FB group.
A3020 | A3000 | BBC B + 128K RAM/ROM + 20K Shadow + Pi0 + VideoNuLA
BBC Master Turbo + DC | Atom | A1200 060 | A500 | Jaguar | A420/1
A4000/040 060 | Atari Falcon 060 | Saturn | PS1 | SNES | CPC6128 | C64 | 3DO | MD

User avatar
tricky
Posts: 1917
Joined: Tue Jun 21, 2011 8:25 am
Contact:

Re: Starting a Prince of Persia port...

Postby tricky » Sat Oct 07, 2017 4:32 pm

Kieran, do you think you might have room to double buffer just the bit where the player is, or at least build it off-screen?

RobC
Posts: 1820
Joined: Sat Sep 01, 2007 9:41 pm

Re: Starting a Prince of Persia port...

Postby RobC » Sat Oct 07, 2017 4:45 pm

This is amazing - great work Kieran =D> =D> :D

User avatar
Matt Godbolt
Posts: 163
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: Starting a Prince of Persia port...

Postby Matt Godbolt » Sat Oct 07, 2017 7:13 pm

Wow, this is totally *awesome* - great job Kieran!

User avatar
kieranhj
Posts: 528
Joined: Sat Sep 19, 2015 10:11 pm
Location: Farnham, Surrey, UK

Re: Starting a Prince of Persia port...

Postby kieranhj » Wed Oct 11, 2017 9:32 am

As always, thanks for the kind words everyone! Helps me keep up the motivation to get things finished.

tricky wrote:Kieran, do you think you might have room to double buffer just the bit where the player is, or at least build it off-screen?

I've been doing some profiling to take a look at how the screen draw works and take some rough raster timings. For a start the gameplay code overhead (without moving so limited collision detection and no AI) is around 1/2 frame. The draw order is:

1. erase mid-ground objects (copy back layrsaved screen buffers) - aka "peel"
2. clear solid rectangles (used to blank "transitional" background sprites, e.g. spikes, before next frame is plotted) - aka "wipes"
3. draw background sprites marked for redraw (can also be masked) - aka "fastlay" (byte aligned, no clipping, no mirroring)
4. copy existing screen buffer before drawing mid-ground objects - aka "layrsave" (restored with "peel")
5. draw mid-ground moving objects: player, guard, falling floor (masked) - aka "lay" (pixel aligned, can be mirrored, full clipping)
5. draw foreground objects in front of player: pillars etc. - aka "fastlay"

I didn't realise how much of the background gets (potentially) redrawn each frame and was still using the full-fat pixel aligned function for this. I rewrote the "fastlay" sprite functions to skip using the stack and just lookup MODE 2 pixel pairs directly from the packed MODE 5 data and achieved a substantial frame-rate increase. The game is much more playable now in the general case, although still slows down more than I'd like in places.

I'm not sure that I can assemble the player image off-screen - the background already gets saved out before being overdrawn by mid-ground and foreground sprites. I don't want to have to copy it back another time.

I have an idea to reduce sprite flicker - since the game uses image lists (containing all of the above) I could use a crude sorting method (top bit of Y coordinate) to make two passes over the lists for plot operations in the top and bottom half of the screen. I'd like to get the wipe closer to the background sprite redraw, for instance, so there is less flicker on things like the spikes etc.

Obviously the player is the most important sprite to get smooth. I also thought that I could potentially combine the background "layrsave" operation with the sprite plot, since these are directly correlated, so save out the screen buffer immediately before writing the masked sprite data. It would make the inner loop of the sprite routine more complicated as more pointers to keep track of, but might result in an overall speed up.

There is clearly going to be a lot of coherency between what gets "layrsaved" and "peeled" each frame because the player can't move ~that~ far per tick, but not sure how to exploit that.

Whilst writing the "fastlay" function that's all conveniently byte aligned, I realised that the Exile sprite routine is optimised to use as little RAM as possible because they were targeting vanilla Beeb with 16K SWRAM max. So one sprite plot routine handles every possible operation (mirroring, clipping, wraparound etc.) and the palette to pixel mapping is designed to use just 7 bytes. Since I'm targeting a 128K Master I have a "lot" (relatively speaking) more RAM to play with. For absolutely critical sprite plot routines I am happy to burn a page or several for lookup tables.

I'm also wondering whether using the top palette bit as a "background" flag helps me at all. Perhaps if the foreground objects had this bit set I could modify the mid-ground plot routine to not overwrite these pixels (ala Exile) and potentially save having to redraw the foreground objects at all.

Ideally, I would very much like to keep the 3 colours per sprite palette approach as I think this will make the eventual 16 colour NULA version truly stunning.

However, I have been pondering whether I will have to relent and adopt the 4 background / 3 foreground EOR palette mapped approach. I could plot the player sprite EOR with the background which would save the "layrsave" copy operation (still need to erase the sprite before the next frame so the "peel" operation would be replaced by another EOR plot.) There are foreground objects drawn on top of the player, but at least these are explicitly held in an image list. I would have to think about where any mid-ground objects intersect with each other, likely the AI guards and any collectibles. Some background objects, like the torches, would likely have to be special-cased as the background palette wouldn't have the right colours - they can't be foreground objects as the player has to walk in front of them.

Anyway, all thoughts and suggestions welcome as always! :)
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

User avatar
tricky
Posts: 1917
Joined: Tue Jun 21, 2011 8:25 am
Contact:

Re: Starting a Prince of Persia port...

Postby tricky » Wed Oct 11, 2017 11:27 am

I was thinking of constructing part of the screen of-screen and then copying it to the screen. No copy/peel, just draw opaque back to front, it may just be to wasteful.

User avatar
Arcadian
Posts: 2798
Joined: Fri Nov 24, 2000 12:16 pm
Contact:

Re: Starting a Prince of Persia port...

Postby Arcadian » Wed Oct 11, 2017 12:06 pm

Hi, sorry it's taken me so long to pipe up in this thread, I can assure you I've been excitedly reading every update, trying out every test version as soon as they've been posted! Am simply amazed at how smooth/fast it's looking already and can barely believe how in an instant it went from mere concept sprite routines into a responsive, playable game!

Can't wait to hear the how the tunes sound once native Beeb music tracks have been composed. And do you think there could be mileage in adding options for BeebSID (using the C64 conversions?) and BeebOPL (using the PC/adlib tracks?) too?
For a "Complete BBC Games Archive" visit www.bbcmicro.co.uk

Image
ABug NORTH (Manchester) (19-21 January 2018)
ABug SOUTH (Hampshire) (1-3 June 2018)

User avatar
kieranhj
Posts: 528
Joined: Sat Sep 19, 2015 10:11 pm
Location: Farnham, Surrey, UK

Re: Starting a Prince of Persia port...

Postby kieranhj » Wed Oct 11, 2017 12:15 pm

Arcadian wrote:Hi, sorry it's taken me so long to pipe up in this thread, I can assure you I've been excitedly reading every update, trying out every test version as soon as they've been posted! Am simply amazed at how smooth/fast it's looking already and can barely believe how in an instant it went from mere concept sprite routines into a responsive, playable game!

Can't wait to hear the how the tunes sound once native Beeb music tracks have been composed. And do you think there could be mileage in adding options for BeebSID (using the C64 conversions?) and BeebOPL (using the PC/adlib tracks?) too?

Thanks Dave! I hadn't thought about BeebSID or BeebOPL music; I guess this would fall into the same category as the NULA version. Look forward to chatting to everyone and showing more progress at ABUG in November. :)
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

User avatar
kieranhj
Posts: 528
Joined: Sat Sep 19, 2015 10:11 pm
Location: Farnham, Surrey, UK

Re: Starting a Prince of Persia port...

Postby kieranhj » Fri Oct 20, 2017 11:58 am

Hey folks, thought I'd post a quick update since I'll be on holiday for a couple of weeks from Sunday. I have been continuing development, mostly focused on optimising the sprite plot and trying to get the game running as fast as possible. I've had a good bit of success unrolling the various sprite plot loops although there are a large number of combinations. The widest player sprite is 9x35 Apple II bytes across which translates into 18x35 MODE 2 bytes which is a fair old chunk to move around.

I had the biggest speed ups by changing the way that the background layrsave & peel functions work; it now stores the screen data in the same CRTC byte arrangement - so with an 8 byte stride between adjacent bytes. This means I can use the same index over the data and the loop unrolls much more nicely.

There isn't really enough memory to unroll every possible combination of sprite plot and even if I did this I'm never doing to be able to update the screen in a single 50Hz frame with some of the more complex screens. For example, having two falling floor pieces plus an enemy on screen requires an awful lot of the screen buffer to be saved & restored and 4x large, masked sprites to be plotted.

pop-beeb.png
Now in green (don't ask!)

I believe the game is generally now fast enough to be considered playable, even if there are slow downs when it is busy. However I think I have to accept that to make the game look as good as it should then it needs to be double-buffered, as it was in the original. Doing this with 2x 15K MODE 2 screens is immensely challenging given the memory constraints.

I think I have a plan to maybe, possibly just about squeeze this in but I still haven't finished porting all the gameplay code and would like room for music etc. My plan is to use the 8K of HAZEL RAM at &C000 but just ignore the claims on the ROM workspace, of course. This still doesn't quite get me there but I'm hoping I can shrink / remove some lookup tables or rearrange the lower memory to find the 5 pages I'm still missing according to my calculations.

The more drastic approach would be to switch down to MODE 5 which would be fine from a memory POV, although it would complicate the sprite plot again. I have been clinging on to the 3 colour palette per sprite from 8/16 colours in MODE 2 (even though it doesn't look that colourful at the moment) as my ultimate goal, but the flickering is a big detraction in my opinion.

I guess I'll throw it open to you folks again - would you rather have a flickery MODE 2 or a rock-solid MODE 5 version of the game?!

You can test out the latest faster WIP (still just level 1) here: https://bitshifters.github.io/jsbeeb/?disc=https://bitshifters.github.io/content/wip/pop-beeb-faster-level1-mode2.ssd&autoboot&model=Master. Yes, it's gone green!
Attachments
pop-beeb-faster-level1-mode2.zip
Level 1 again but faster
(56.15 KiB) Downloaded 18 times
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

User avatar
Rich Talbot-Watkins
Posts: 1117
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca

Re: Starting a Prince of Persia port...

Postby Rich Talbot-Watkins » Fri Oct 20, 2017 1:47 pm

Nice work Kieran, it's really coming on well!

Just to be clear, how is the sprite erasing currently working? Are you storing screen bytes before plotting the sprites, and then just copying them back over the top to erase? (i.e. a direct store, rather than the Exile type routine).

I feel there must be some other trick to reduce the flicker. In the most common case, where the character is stationary, with nothing in the foreground, there is still a lot of flicker (some due to not syncing with VSync, but still...). The player, in a standing position, is not that big (looks like 3 characters wide by about 32 high) - I would expect, even with a slow plot routine, to be able to flickerlessly draw that, provided the erase were fast. Have you tried profiling the plot routines (even just with changes to palette 0 to be able to get a vague idea of scanline count)?

cmorley
Posts: 260
Joined: Sat Jul 30, 2016 7:11 pm
Location: Oxford

Re: Starting a Prince of Persia port...

Postby cmorley » Fri Oct 20, 2017 3:43 pm

Perhaps you've considered this but if not..

Do all the sprites need to be redrawn every frame? Perhaps you could interleve non player sprites on odd & even frame redraws, like the torches? Can you cull plots which would put the same sprite & animation frame in the same location as the previous frame - like the player standing still? Then there would be no flicker on static actors even if there is some flicker on motion.

+1 like for the development 'blog' posts. I enjoy reading them. =D>

User avatar
kieranhj
Posts: 528
Joined: Sat Sep 19, 2015 10:11 pm
Location: Farnham, Surrey, UK

Re: Starting a Prince of Persia port...

Postby kieranhj » Fri Oct 20, 2017 5:14 pm

Rich Talbot-Watkins wrote:Nice work Kieran, it's really coming on well!

Just to be clear, how is the sprite erasing currently working? Are you storing screen bytes before plotting the sprites, and then just copying them back over the top to erase? (i.e. a direct store, rather than the Exile type routine).

I feel there must be some other trick to reduce the flicker. In the most common case, where the character is stationary, with nothing in the foreground, there is still a lot of flicker (some due to not syncing with VSync, but still...). The player, in a standing position, is not that big (looks like 3 characters wide by about 32 high) - I would expect, even with a slow plot routine, to be able to flickerlessly draw that, provided the erase were fast. Have you tried profiling the plot routines (even just with changes to palette 0 to be able to get a vague idea of scanline count)?

The main problem is that the render loop is set up for double-buffering and for an extremely variable render time. Because it assumes the buffer is not being displayed the process is:

- write back all stored screen bytes
- clear solid rectangles (where background animates, e.g. spikes)
- draw background objects (e.g. flames)
- copy screen buffer beneath masked sprites
- draw masked sprites (player)
- draw foreground objects (pillars)

So, yes, it is copying screen bytes as a direct store before plotting masked sprites then copying them all back to erase. I can tune the vsync timer to stop flickering whilst standing at the start but because there could be a number of masked sprites on screen (e.g. 4 or more if enemy + 2x falling floor), it takes a variable amount of time before we get around to drawing them, so very easy to catch a refresh where everything has been erased but nothing has been drawn back yet.

PoP actually sorts all masked objects so they are plotted in the correct order. One answer would be to restore the screen area immediately before plotting the new sprite, rather than in batches, but I imagine this might not work with overlapped sprites. I could also attempt to spread the draw operations across two frames but timed differently vs the raster (top half vs bottom half) but this would essentially lock to 12.5Hz.

I have tried profiling the various routines crudely, using palette changes. Just standing till there is at least half a frame (~128 scanlines) of gameplay logic running (a lot I know) which I'm not going to be able to crunch. Before the unrolling experiments the screen buffer save & restore was taking another 128 scanlines and the various sprite plots another 128 scanlines, so a solid 25Hz but highly variable under motion. This would basically double when an enemy character was on screen or any sort of moving objects, like the falling floors.

I haven't done any empirical measurements of the framerate or function timings since then - I guess that's my next step before deciding on any memory / performance trade-offs.
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

User avatar
Matt Godbolt
Posts: 163
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: Starting a Prince of Persia port...

Postby Matt Godbolt » Fri Oct 20, 2017 5:15 pm

Re: profiling...what do folks use for profiling? I just realised there's a golden opportunity to add something cool to jsbeeb for profiling purposes, and wondered if other emulators already have this?

User avatar
kieranhj
Posts: 528
Joined: Sat Sep 19, 2015 10:11 pm
Location: Farnham, Surrey, UK

Re: Starting a Prince of Persia port...

Postby kieranhj » Fri Oct 20, 2017 5:21 pm

Matt Godbolt wrote:Re: profiling...what do folks use for profiling? I just realised there's a golden opportunity to add something cool to jsbeeb for profiling purposes, and wondered if other emulators already have this?

Nothing, just a good old fashioned macro for setting the background colour. :( I was pondering extending b-em in some way but not thought much about it. I'm not aware of any decent profiling tools for the Beeb. If you fancy returning to jsbeeb for a bit that would be awesome. :)
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

User avatar
tricky
Posts: 1917
Joined: Tue Jun 21, 2011 8:25 am
Contact:

Re: Starting a Prince of Persia port...

Postby tricky » Fri Oct 20, 2017 5:47 pm

Macro changing palette for me too.
It might be a good sanity check to produce a table of addresses executed per frame. Summarised in ranges would be good just to see where all the time is going, but I probably won't be using it ;)

User avatar
Matt Godbolt
Posts: 163
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: Starting a Prince of Persia port...

Postby Matt Godbolt » Fri Oct 20, 2017 6:04 pm

Well, the world's cheesiest profiler is but a few JS console steps away. Load up the game, hit ctrl-home to pause it. then open JS console and type:

Code: Select all

hits={};
processor.debugInstruction.add(function(pc){hits[pc] = (hits[pc]||0)+1;});


Then run....and "hits" will contain an array of counts of hits per PC:

Code: Select all

hits
Object {56348: 4156, 56350: 4155, 56351: 4156, 56352: 4156, 56354: 4155, 56356: 4155, 56467: 4156, 56468: 4156, 56470: 4156, 56471: 4156, 56472: 4156, 56473: 4156, 56474: 4156, 56475: 4156, 56477: 4156, 56478: 4156, 56480: 4156, 56481: 4156, 56482: 5825, 56485: 5825, 56487: 4156, 56489: 1670, 56491: 1670, 56492: 1670, 56541: 1670, 56542: 1670, 56545: 1670, 56546: 1670, 56555: ...


Then you can do something crappy like:

Code: Select all

_.last(_.sortBy(_.pairs(hits), _.last), 20).reverse()


To get the top 20 hotspots :)

User avatar
Matt Godbolt
Posts: 163
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: Starting a Prince of Persia port...

Postby Matt Godbolt » Fri Oct 20, 2017 7:26 pm

This is what I got for PoP on the idle screen:

Code: Select all

> utils = require('utils')
> _.each(_.last(_.sortBy(_.pairs(hits), _.last), 20).reverse(), function(x) { console.log(utils.hexword(parseInt(x[0])), x[1]); });
12bf 385525
12bd 385503
40dc 11480
40db 11480
40d6 11480
40cd 11480
40cb 11480
40c8 11480
40c5 11480
40bc 11480
40b9 11480
40b6 11480
40de 11479
40d7 11479
40d4 11479
40d1 11479
40ce 11479
40c9 11479
40c2 11479
40c0 11479


...I suspect batching by 8-byte blocks or similar might be better (or more likely some actual visualisation...)

I'll see what I can knock up!

User avatar
tricky
Posts: 1917
Joined: Tue Jun 21, 2011 8:25 am
Contact:

Re: Starting a Prince of Persia port...

Postby tricky » Fri Oct 20, 2017 7:29 pm

Thanks, I knew it would be something like that, but I have still never written a line of JS, other than copy and pasting yours.
Now, what do I type in to get TMS speech support :lol:

User avatar
kieranhj
Posts: 528
Joined: Sat Sep 19, 2015 10:11 pm
Location: Farnham, Surrey, UK

Re: Starting a Prince of Persia port...

Postby kieranhj » Fri Oct 20, 2017 9:07 pm

cmorley wrote:Perhaps you've considered this but if not..

Do all the sprites need to be redrawn every frame? Perhaps you could interleve non player sprites on odd & even frame redraws, like the torches? Can you cull plots which would put the same sprite & animation frame in the same location as the previous frame - like the player standing still? Then there would be no flicker on static actors even if there is some flicker on motion.

+1 like for the development 'blog' posts. I enjoy reading them. =D>

Hey Chris, I wasn’t ignoring your comment - I wrote a reply and my dodgy train WiFi lost it. :(

The background sprites are all handled with custom code so it might be possible to come up with a way to interleave them or reduce the overhead relatively easily. Could certainly cycle through the torches for instance.

Even when the player is standing still there could be a torch or animated gate behind so there’s not really such a thing as a static actor.

PoP actually does a good job of marking which background pieces have been dirtied by the different animated objects, including the player and enemies etc. That code is quite complicated already so not sure there’s much mileage in it.

I think I need to focus on the constant worst case which is the large player sprite which has to be plotted pixel aligned + mask + mirror + crop.
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

User avatar
kieranhj
Posts: 528
Joined: Sat Sep 19, 2015 10:11 pm
Location: Farnham, Surrey, UK

Re: Starting a Prince of Persia port...

Postby kieranhj » Fri Oct 20, 2017 9:28 pm

Matt Godbolt wrote:This is what I got for PoP on the idle screen:

...I suspect batching by 8-byte blocks or similar might be better (or more likely some actual visualisation...)

I'll see what I can knock up!

Thanks Matt! I will cross reference against the assembly in err, two weeks. I expect you to have a full 6502 profiling toolkit written by then. :D

I did a tiny bit of raster profiling on the latest build on the train home. Saving & restoring the screen around the player takes approx 40 scanlines each. Drawing the player takes a whopping 150 scanlines!! Even my slightly unrolled version takes 140 scanlines. There a good 10 lines of setup because of clipping etc but the rest is all a couple of scanlines to decode the 2bpp data and a couple of scanlines plotting masked to the screen. This is then x30 for the height of the sprite. This seems roughly tally ~10 + ~4 x 30 = ~130 scanlines.

Going to have to find a way to speed this up...
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

User avatar
kieranhj
Posts: 528
Joined: Sat Sep 19, 2015 10:11 pm
Location: Farnham, Surrey, UK

Re: Starting a Prince of Persia port...

Postby kieranhj » Tue Nov 14, 2017 10:52 am

OK folks. I'm long overdue an update for you all. There is good news and bad news. :D

The good news is that I managed to refactor the memory usage to remove all the gameplay code from SHADOW RAM (not a trivial task) and implement screen double-buffering for MODE 2. Without wanting to sound too pleased with myself, it looks flipping awesome! I am going to be mean and hold onto this until ABUG at the weekend so I can show everyone in person and on real hardware (my Master has been in storage since I moved house in August so I've still never seen PoP running on a real machine.) Of course I will post a new WIP for everyone on the forum on Saturday as well.

The bad news is that I am seriously, seriously completely out of memory to finish the port. :( I have scraped every nook & cranny to get this far - including stealing most of HAZEL, hacking out unused sprites from the sprite banks, splitting up the background sprite banks to maximise SWRAM bank usage, halved the size of the image lists / display buffers (with debug traps in case of overrun), pruned unused code, replaced large lookup tables with code, temporarily commented out animation data tables which can "in theory" be loaded as an overlay during the cutscenes. I estimate there is ~2K of RAM left in the system but this is spread in pockets of < 2 pages each across the various banks. I believe I need a minimum of 8K more RAM to finish the port. To do:

IN-GAME
    - meters (energy bars)
    - hit fx
    - flash screen fx - needs bespoke Beeb implementation, probably set palette directly
    - game timer (60 minutes)
    - potion fx - upside down screen requires bespoke Beeb implementation :?
    - level specific gameplay (unholy, reflection, bonesrise, mouse)
    - messages (time left, continue) - needs bespoke Beeb implementation, where does font come from?!
PRE-GAME
    - cutscenes (princess, epilogue)
    - princess room gfx (flame, post, hourglass, star twinkle)
    - attract mode (intro sequence & music)
    - demo level
SYSTEM
    - load cutscene overlays
    - multiple keypress support & ctrl keys
    - sound effects
    - music
    - cheats
    - joystick support?
BEEB EXTRAS
    - ask Dethmunk to redraw all sprites for MODE 2 resolution
    - pick palettes for all sprites
    - NULA implementation
    - disk layout optimisation
Having implemented double-buffering there is no going back - because of the variable frame-rate it is the only way to get the game smooth and solid. I honestly don't think it will be possible to eke the RAM out bit by bit any further, so I will need some fairly drastic change to get the port finished. The two main options I can think of are:

    1. Drop down to MODE 5
    2. Reduce the sprite data budget (currently 48K)
I don't believe it is possible to refactor the code to make substantial enough use of overlays that would provide enough RAM needed, the bank switching (MAIN, SHADOW, SWRAM, ANDY, HAZEL) is complicated enough and I'm already loading all data on a per-level basis from disc.

I really don't want to drop down to MODE 5, although this would instantly solve my memory issues (albeit complicate my sprite plotting issues.) The Beeb version is already at half the horizontal resolution of the original (I had originally hoped to have the game running in MODE 1) and without the colour depth it is not going to be competitive with the other 8-bit ports like C64 and CPC. At the moment the game runs fast enough to keep the plot routines to 3 colours per sprite from palette of 16 - this could look unbelievable with NULA!

In terms of reducing the sprite budget, the options I can think of are:

    1. Halve number of animation frames
    2. Custom compression scheme for some / all sprites
    3. Halve vertical resolution for some sprites
Although other platforms have used fewer animation frames, I am reluctant to do this because if not done correctly then it will interfere with the gameplay and change the timings / behaviour of the player's moves. I tried hacking a quick version in and it looks very jerky.

In terms of custom compression - the sprite plot is already very expensive as it is converting 2bpp to 3bpp on a per-pixel basis for relatively large sprites (some frames up to 32x28 pixels.) The background sprites might be more approachable (a simple Exomiser test reduces the data to 30% of original size) but whilst most of the background is static the system can mark any piece on screen as dirty and require a redraw at any time. Whilst it would be great to have some sort of cache for decompressed sprites, this sounds like a lot of work and I don't know what the worst case RAM requirements might be.

So, my current proposal is to halve the vertical resolution of the player sprites only which would net me up to 14K worth of RAM back (albeit in another SWRAM bank, so still bank juggling to figure out.) Whilst it sounds like a drastic move my logic is that the player has the largest number of animation frames and is generally always moving so will still look nice and fluid (particularly at 25Hz.) We've already halved the horizontal resolution and I've not yet had chance to ask Dethmunk to bring his professional art skills to bear on the player sprites to improve their quality. At least this way the pixels will be a bit more square. :wink:

What do you all think? Looking forward to sharing the latest progress on Saturday. :P
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

RobC
Posts: 1820
Joined: Sat Sep 01, 2007 9:41 pm

Re: Starting a Prince of Persia port...

Postby RobC » Tue Nov 14, 2017 12:27 pm

Looking forward to seeing this :D

Given that it's already Master-only, is it worth thinking about just requiring an extra 16K of sideways RAM? I'm guessing that many Master owners have a cartridge that gives RAM in slot 0/1 or 2/3.

dp11
Posts: 707
Joined: Sun Aug 12, 2012 8:47 pm

Re: Starting a Prince of Persia port...

Postby dp11 » Tue Nov 14, 2017 1:35 pm

Another option is to use the Tube.

User avatar
kieranhj
Posts: 528
Joined: Sat Sep 19, 2015 10:11 pm
Location: Farnham, Surrey, UK

Re: Starting a Prince of Persia port...

Postby kieranhj » Tue Nov 14, 2017 1:36 pm

RobC wrote:Looking forward to seeing this :D

Given that it's already Master-only, is it worth thinking about just requiring an extra 16K of sideways RAM? I'm guessing that many Master owners have a cartridge that gives RAM in slot 0/1 or 2/3.

Since the original game runs on an Apple II, and there have been C64 + CPC ports already, I'm loathed to require more than standard 128K (or require a cartridge / ROM like the C64 does.) I guess I could do an "enhanced" version if there was an extra 16K SWRAM available, since we're getting into custom build territory with a NULA version anyway. 6502 copro doesn't help either because it's so hard to get (good amounts of) data down the Tube.

I think I will show folks a version with & without the half (vertical) resolution player and see who can notice the difference. :)
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/


Return to “projects”

Who is online

Users browsing this forum: No registered users and 1 guest