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

Got a programming project in mind? Tell everyone about it!
User avatar
kieranhj
Posts: 527
Joined: Sat Sep 19, 2015 10:11 pm
Location: Farnham, Surrey, UK

Re: Starting a Prince of Persia port...

Postby kieranhj » Fri Sep 08, 2017 3:41 pm

Rich Talbot-Watkins wrote:My gut instinct on this is that the only bit which you can probably truly 'port' is the game/animation logic, basically all the high-level stuff. The graphics routines are going to need to get a total rewrite to conform more with the Beeb hardware.

My take on it would be to bite the bullet and go to MODE 2 (or 1). You could keep the tile size the same, and store the sprites in a more native format; so 10 tiles of 14 (or 28) pixels wide, which fits nicely on a byte boundary still, and allows for a 70 column wide screen. Perhaps I haven't grasped quite how low memory is! Obviously doing that would double the size of the sprite data (and it's already doubled the size of the screen), but I suspect it'd be possible to compress the sprites, even with a RLE type method. I would find a way to avoid having to do double-buffering so you can at least use a shadow screen, and keep main RAM for non-graphics related stuff.

Do you have a basic overview of the memory needs for PoP? In honesty, I'm struggling to imagine how it can be so demanding - unless it's just that there are a lot of frames of animation.

I think you might be right Rich. The graphics routines will need a total rewrite but thankfully is a very small part of the overall codebase. There is a massive amount of gameplay code which should stay completely intact. All of this is in Aux (SHADOW) RAM at the moment, with Main RAM being used for the screen buffers and rendering code.

On the sprite front, this is from my notes for what needs to be permanently resident in SWRAM:

Code: Select all

BANK0 = BGTAB1.XXX + BGTAB2.XXX = 9185b + 4593b = 13778b                  <-- Level BG
BANK1 = CHTAB1 + CHTAB3 = 9165b + 5985b = 15150b                          <-- Player
BANK2 = CHTAB2 + CHTAB5 = 9189b + 6134b = 15323b                          <-- Player
BANK3 = CHTAB4.XXX + CHTAB6.X + CHTAB7 = 5281b + 9201b + 1155b = 15637b   <-- Guard + Princess + Boss

Total = 59888b = ~ 58.5KB
Free = 5648b = ~ 5.5KB

This is sprite data in Apple II pixel format. Pretty sure CHTAB6&7 are only required for cutscenes so these could be loaded on demand.
From my brief tests this data gets bloated by minimum 50% in MODE 1 form (2bpp, uncompressed of course.) Not all of the sprites are required, for example some of the larger ones are actually text message boxes!

Current memory usage:

Code: Select all

Core ORG =  &E00
Core lib size =  &39D
Core code size =  &FCF
Core data size =  &E
Core BSS size =  &CE3
Core high watermark =  &2E5D
Core RAM free =  &1A3

Main ORG =  &3000
Main code & data size =  &1237
Main high watermark =  &4237
Screen buffer address =  &65C0 (280x192 MODE 4)
Main RAM free =  &2389

Aux ORG =  &3000
Aux code & data size =  &4030
Aux level blueprint size =  &900
Aux high watermark =  &7A00
Aux RAM free =  &600

Yes, there really is 16KB of just gameplay code in Aux and I haven't finished porting it all yet. Basically the entire game is hand-coded for every player action with lots of (for the time) sophisticated and subtle control behaviours - reminds me a lot of my first N64 game actually. :)

I'm losing a couple of pages to alignment and there are at least 8 pages I can steal from the OS for BSS.

I think I'm going to proceed by trying the approach of converting Apple II into native MODE 4 for now, mostly because I've already written the converter and it keeps all the memory requirements about the same. I can figure out exactly what the expected behaviour of the sprite plotting functions are before worrying about shifting colour format pixels around efficiently.
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 Sep 08, 2017 5:09 pm

Hmm yeah, the graphics data is pretty bulky!

From my best understanding, the scenery tiles are an awkward size on the Apple (28x63), and are rendered in a complicated way. In particular, what intrigues me is the way the floors are rendered:

Image

That overlapping bit is a true horror! Given that the Apple sprite data is 1bpp, there doesn't seem to be any way you could infer a sprite mask from that. So does it have a separate sprite mask? If so, that's great news as it means that the data size is no different from a 2bpp or 4bpp native format sprite. It would need a mask when plotting B and A; either that or it's a constant triangle mask which is applied when plotting B (so C is not overwritten), and it's an optional mask applied when plotting A (depending on whether it's mostly wall, or just a floor). Any idea how the masking works?

I guess this diagram is just a rough overview though. I'd assume it's more clever than that, and breaks up the tiles even more so that it can avoid storing and rendering large runs of blank.

Here are some thoughts for clawing back some memory (if expanding out the graphics to 2 or 4bpp):

* If using MODE 2, store the graphics 2bpp, thus giving the same memory footprint as the MODE 4 graphics. Then use the 'Exile' type approach of rendering them in any 4 colours (or 3 + transparent) of your choosing - I don't think the graphical style would make this limiting, and you could still get all 8 colours on screen.

* Use the top bit of each pixel as a foreground/background indicator. I think the top bit could be inferred from which section of the scenery tile it is (section A always foreground, the rest background?), so you wouldn't have to store it either. Then you could have the character plotting routines look at the top screen bits as a mask. Just save the screen data prior to plotting the character (there will be shadow RAM spare for that), and erase the character by restoring the screen data - nice and quick, and no need for double buffering.

* Long shot: LZ77 compress the scenery graphics in an entire block, and expand them out to the screen buffer (blanked) between screens, copying out only the tiles used by that particular screen to a cache. This approach could also work for the NPC graphics which are not all needed simultaneously (I think). I don't think RLE would give big gains. Neither might this approach of course, if the LZ compressed data + required cache is bigger than the unexpanded graphics.

* Break up the scenery tiles into smaller units which allow for some reuse.

* If we have mirrored sprites for the characters, ditch them and use a mirroring table instead to reverse the bytes (and obviously a different routine to plot them backwards).

Not sure how feasible any of that is, but just want to do a brain dump in case anything there sparks any thoughts of your own :D

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

Re: Starting a Prince of Persia port...

Postby kieranhj » Mon Sep 11, 2017 12:38 pm

Rich Talbot-Watkins wrote:Hmm yeah, the graphics data is pretty bulky!

From my best understanding, the scenery tiles are an awkward size on the Apple (28x63), and are rendered in a complicated way. In particular, what intrigues me is the way the floors are rendered:

That overlapping bit is a true horror! Given that the Apple sprite data is 1bpp, there doesn't seem to be any way you could infer a sprite mask from that. So does it have a separate sprite mask? If so, that's great news as it means that the data size is no different from a 2bpp or 4bpp native format sprite. It would need a mask when plotting B and A; either that or it's a constant triangle mask which is applied when plotting B (so C is not overwritten), and it's an optional mask applied when plotting A (depending on whether it's mostly wall, or just a floor). Any idea how the masking works?

I guess this diagram is just a rough overview though. I'd assume it's more clever than that, and breaks up the tiles even more so that it can avoid storing and rendering large runs of blank.

Everything is drawn with painters algorithm, so back to front and overdrawn where necessary. A screen is made up of 10x3 pieces drawn bottom to top and left to right. Where drawing a piece is: (m versions are for the moveable pieces)

Code: Select all

\*-------------------------------
\*
\*  Redraw entire block
\*
\*-------------------------------
.RedBlockSure
{
 jsr drawc ;C-section of piece below & to left
 jsr drawmc

 jsr drawb ;B-section of piece to left
 jsr drawmb

 jsr drawd ;D-section
 jsr drawmd

 jsr drawa ;A-section
 jsr drawma

 jmp drawfrnt ;A-section frontpiece
;(Note: This is necessary in case we do a
;layersave before we get to f.g. plane)
}

Note that this doesn't actually draw the sprites there and then, they are placed into image lists - background, foreground and mid - which are then plotted in later on at the render stage:

Code: Select all

\*-------------------------------
\*
\*  D R A W A L L
\*
\*  Draw everything in image lists
\*
\*  This is the only routine that calls HIRES routines.
\*
\*-------------------------------
.DRAWALL
{
 jsr DOGEN ;Do general stuff like cls

 lda blackflag ;TEMP
 bne label_1 ;

 jsr SNGPEEL ;"Peel off" characters
;(using the peel list we
;set up 2 frames ago)

.label_1 jsr ZEROPEEL ;Zero just-used peel list

 jsr DRAWWIPE ;Draw wipes

 jsr DRAWBACK ;Draw background plane images

 jsr DRAWMID ;Draw middle plane images
;(& save underlayers to now-clear peel list)

 jsr DRAWFORE ;Draw foreground plane images

 jmp DRAWMSG ;Draw messages
}

Each sprite can be plotted at any screen position, with clipping, mirroring and with operand STA, OR, AND (mask) and special (shift & XOR for the "ghost" player character.) As the current plotting is quite slow you can watch it assemble screens in each layer from the SSD's earlier in the thread.

There is no separate sprite mask data. It does infer a mask when required from this table: (note these are Apple II bits so "back to front" with lsb being left-most pixel)

Code: Select all

*-------------------------------
\*
\* MASKTAB
\*
\* Index: byte value w/hibit clr (0-127)
\* Returns mask byte w/hibit set
\*
\*-------------------------------

.MASKTAB
 EQUB $FF,$FC,$F8,$F8,$F1,$F0,$F0,$F0
 EQUB $E3,$E0,$E0,$E0,$E1,$E0,$E0,$E0
 EQUB $C7,$C4,$C0,$C0,$C1,$C0,$C0,$C0
 EQUB $C3,$C0,$C0,$C0,$C1,$C0,$C0,$C0

 EQUB $8F,$8C,$88,$88,$81,$80,$80,$80
 EQUB $83,$80,$80,$80,$81,$80,$80,$80
 EQUB $87,$84,$80,$80,$81,$80,$80,$80
 EQUB $83,$80,$80,$80,$81,$80,$80,$80

 EQUB $9F,$9C,$98,$98,$91,$90,$90,$90
 EQUB $83,$80,$80,$80,$81,$80,$80,$80
 EQUB $87,$84,$80,$80,$81,$80,$80,$80
 EQUB $83,$80,$80,$80,$81,$80,$80,$80

 EQUB $8F,$8C,$88,$88,$81,$80,$80,$80
 EQUB $83,$80,$80,$80,$81,$80,$80,$80
 EQUB $87,$84,$80,$80,$81,$80,$80,$80
 EQUB $83,$80,$80,$80,$81,$80,$80,$80

Rich Talbot-Watkins wrote:Here are some thoughts for clawing back some memory (if expanding out the graphics to 2 or 4bpp):

* If using MODE 2, store the graphics 2bpp, thus giving the same memory footprint as the MODE 4 graphics. Then use the 'Exile' type approach of rendering them in any 4 colours (or 3 + transparent) of your choosing - I don't think the graphical style would make this limiting, and you could still get all 8 colours on screen.

I like this idea a lot and will definitely look into it once I've got the B&W version rendering correctly. The input parameters for the sprite plot routines are well documented so just up to me to write the necessary routines (just quite a few variations and fiddly features to consider, including clipping.) Again the code is well structured so it should be possible to just alter the render function that handles conversion of object X coordinates into plot coordinates without affecting the gameplay for different screen widths. NB. Game objects have a different coordinate system from the background tiles.

Rich Talbot-Watkins wrote:* Use the top bit of each pixel as a foreground/background indicator. I think the top bit could be inferred from which section of the scenery tile it is (section A always foreground, the rest background?), so you wouldn't have to store it either. Then you could have the character plotting routines look at the top screen bits as a mask. Just save the screen data prior to plotting the character (there will be shadow RAM spare for that), and erase the character by restoring the screen data - nice and quick, and no need for double buffering.

PoP actually already saves and restores screen data prior to plotting mid-ground objects. The LAYRSAVE and PEEL functions are designed to do this and copy the data out into (double) buffers using the same format as the sprite tables (so can use the same routines to be put back.) I haven't implemented the Beeb equivalents yet but have earmarked the 4K of MOS RAM at &8000 for this purpose.

Rich Talbot-Watkins wrote:* Long shot: LZ77 compress the scenery graphics in an entire block, and expand them out to the screen buffer (blanked) between screens, copying out only the tiles used by that particular screen to a cache. This approach could also work for the NPC graphics which are not all needed simultaneously (I think). I don't think RLE would give big gains. Neither might this approach of course, if the LZ compressed data + required cache is bigger than the unexpanded graphics.

* Break up the scenery tiles into smaller units which allow for some reuse.

Compression and/or caching could be an option. The game already uses two different sprite banks (Dungeon & Palace) for background tiles & selects one per level (there are actually three in the code so note sure if there is technically a third bank made up of a combination of the other two - I need to investigate further later on.) It can also be noted that from any given screen there are only four possible next screens (L/R/U/D) so in theory we can (pre)calculate all possible next tiles/pieces that we haven't already rendered if caching. (Also those that are no longer reachable.)

There is only one NPC (Guard) type permitted per level and again this is selected & loaded on a per-level basis. The Princess & bad guy (Vizer) are only used in cutscenes (apart from the final boss fight.) The nuclear option would be to halve the number of animation frames for the player but that would be a shame.

Rich Talbot-Watkins wrote:* If we have mirrored sprites for the characters, ditch them and use a mirroring table instead to reverse the bytes (and obviously a different routine to plot them backwards).

Not sure how feasible any of that is, but just want to do a brain dump in case anything there sparks any thoughts of your own :D

Again, PoP already mirrors the sprites in software using a separate set of plot functions in this instance.

There are some great thoughts in here Rich, as ever, thank you! I am continuing to explore just using converted Beeb 1bpp data in MODE4 so I can hopefully get the plotting functionality correct without any additional complications. Once this is working I can explore optimisations and the right approach to colour (MODE1 vs MODE2) and enlist the help of our resident artist if needs be.
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

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

Re: Starting a Prince of Persia port...

Postby kieranhj » Wed Sep 20, 2017 1:02 pm

Apologies all for being a bit quiet of late. I have been plugging away at PoP but reached various impasses / decision-forks so have been exploring (and still exploring them) and found it harder to post concrete updates.

Essentially I implemented ~most~ of the standard sprite plot routine as PoP requires, including per-pixel placement and masking but not clipping or mirroring, in MODE 4 using sprite data converted to 8 pixels per byte format ahead of time and lots of shift & carry tables. I also implemented the sprite save & restore code using MOS 4K RAM as a buffer. The end result, whilst looking good from a level background POV was disheartening - just too damn slow.

FWIW I've attached an SSD image if you want to see it in action (if 1 fps is action.) Please be patient - it takes quite a while to load all of the various data files and will require all 4 banks of swram + shadow (Master only.) Or checkout online: https://bitshifters.github.io/jsbeeb/?disc=https://bitshifters.github.io/content/wip/pop-beeb-slow-sprites-mode4.ssd&autoboot&model=Master. There's no keyboard input implemented so don't try and move!

pop-beeb-slow-sprites-mode4.png
Sprites are now masked

I was starting the implementation of mirrored sprites but the whole thing was getting very complicated and relies on a mountain (about 4k) of tables and requires all sorts of careful masking of bits to get 8 pixels per byte data plotted at 1 pixel alignment but in 7 pixel increments. PoP itself uses lots of masking but now everything needs to be masked twice - once for the sprite data as PoP sees it then again for how the Beeb screen sees it. I also couldn't see how the main sprite plotting loop was going to be optimised using the current approach - saving the odd cycle here & there wasn't going to help.

I stopped for a pause and a rethink and have started to explore Rich's suggestion of using 2bpp sprite data but at half the horizontal resolution, so MODE 5 data effectively, but then expanded out at runtime to plot in MODE 2. Although I liked the hi-res MODE1/4 look there are a number of advantages, not least the possibility of "free" masking using appropriate palette mapping. Given the limitations of the original game, having 3 colours for foreground sprites and 4 colours for backgrounds should be plenty.

I've been trawling through various sprite plot implementations and particularly the Exile code disassembly. I'm essentially now in the process of copying that technique (with ZP optimisation to come later.) I haven't finished the new sprite routine yet but should be soon.

Another important decision has been to try rounding up everything to be in multiples of 8 pixels rather than 7. This just makes everything so much easier to contend with on the Beeb and means that when halving the horizontal resolution I'm not faced with the smallest sprite size being 3 1/2 pixels wide. This implies that the new resolution is 160x192 in MODE 2 which stretches everything horizontally, so will look a bit "fat". Currently I'm just point sampling the original sprites in my simple Apple II image converter but the results don't look too bad in my simple BASIC image checker:

pop-beeb-kid-sprite-mode5.png
Kid sprite sheet in MODE 5

I figure that if I manage to get this project approaching something like completed from a gameplay POV then I will take up DethMunk's kindly offer of artist support for getting all of the sprites redrawn or at least tidied up by hand.

That's it for now. I will post again when I have the background rendering back up & running in MODE 2 and then onwards to a better sprite plot that is good enough for actual animation at runtime. As always your comments & feedback are appreciated.
Attachments
pop-beeb-slow-sprites-mode4.zip
Very slow sprite plotting in MODE 4
(57.8 KiB) Downloaded 18 times
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

User avatar
FourthStone
Posts: 400
Joined: Thu Nov 17, 2016 2:29 am
Location: Melbourne, Australia

Re: Starting a Prince of Persia port...

Postby FourthStone » Wed Sep 20, 2017 8:35 pm

Where's the like button on this thread??

Really enjoying this detailed exploration =D>

User avatar
jbnbeeb
Posts: 368
Joined: Sat Apr 03, 2010 8:16 pm

Re: Starting a Prince of Persia port...

Postby jbnbeeb » Sat Sep 23, 2017 12:05 pm

FourthStone wrote:Where's the like button on this thread??

Really enjoying this detailed exploration =D>


Seconded.
Thanks for continuing to post your detailed updates Kieran; I really enjoy reading them. They're giving me inspiration to resume on my game now that I have some time to pick it up.

Thanks,
Jason
I'm going to ..
ABUG North Halifax June 10-12
Image

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

Re: Starting a Prince of Persia port...

Postby kieranhj » Mon Sep 25, 2017 4:09 pm

FourthStone wrote:Where's the like button on this thread??

Really enjoying this detailed exploration =D>

jbnbeeb wrote:Seconded.
Thanks for continuing to post your detailed updates Kieran; I really enjoy reading them. They're giving me inspiration to resume on my game now that I have some time to pick it up.

Thanks,
Jason

Thanks guys, I really appreciate the support & encouragement and to know that people are following what I'm up to - it's a lot of work and can be a real slog sometimes wading through endless reams of code!

Here is a quick update as to the MODE 2 investigations. There's a very early WIP here: https://bitshifters.github.io/jsbeeb/?disc=https://bitshifters.github.io/content/wip/pop-beeb-exile-sprites-mode2.ssd&autoboot&model=Master which looks terrible but sometimes you have to go backwards to move forwards!

pop-beeb-exile-sprites-mode2.png
PoP in MODE 2 v early

This is using the Exile approach to sprite plotting, albeit nowhere near as sophisticated or optimised yet. Sprites are stored as 2bpp in MODE 5 byte format and then unrolled onto the stack at runtime. With a bit of bit-shifting you can look up a MODE 2 pixel (left or right handed depending on the parity) and plot to the screen. Once this was working it was simple to write a mirrored version which PoP requires, so we are getting somewhere. However there are a number of issues to resolve, not least:

- my automatic sprite converter from the Apple II source data needs some work. I'm converting 7 B&W pixels into 4 colour pixels taking up the same space on screen so obviously some detail will be lost. In time I'll ask Dethmunk to hand finish the sprites to be optimal for this resolution & palette considerations.

- the Apple II sprite data is weird in that it pixels come out different colours depending on the plot parity - this is why the player sprite is sometimes red and sometimes blue! Presumably on a real machine the animation frames are arranged such that parity is constant - I've just realised this is why for moving objects the X coordinates only range from 0-139 and get doubled up to 0-279 on plot. Still doesn't explain why the source data has mixed parity though, hmm.

- I haven't implemented masking yet. I was going to use the EOR method and have 4x background colours + 3x foreground colours by mapping the 16 colour palette but I think I'll need something more sophisticate than this. For instance the flickering torches are in the background sprite set but ideally we'd want these to be drawn in red & yellow whilst the dungeon walls remain blue & cyan. Exile uses a 3 colour palette per sprite so I think I'm going to copy this approach and have a simple way of specifying which palette is used for which sprite in all the image tables. This means we can take full advantage of being in MODE 2 but does mean I need to think a bit more about the masking implementation. Will probably use the top-bit-as-background-signifier approach.

- the player sprite is being plotted in the wrong place for some reason - too far to the right. I've got the layer save & peel functions working and saving areas of the screen to the MOS 4K RAM block but this doesn't correspond to where the sprites are being drawn! Not sure why, need to do some more digging.

- it's all still terribly slow. Some of this is going to be down to the size of the sprites - the player can be typically 16 x 30+ pixels which is a lot in MODE 2. The inner loop of the sprite plot can definitely be improved as well though. There is also a lot going on in the main game loop but I haven't tried profiling this yet.

But this all said I think this is likely to be a good approach for PoP on the Beeb as it keeps the size of the sprite data the same in quite a convenient way and it's easier to plot on a single pixel alignment. So one byte of 2bpp Beeb data (4 pixels) is being used as a direct replacement for 7 pixels per byte Apple II data. This does mean the screen is stretched to 160 (wide) pixels vs 280 but this is clearly what was done on other (similar) platforms and can be overcome with some assistance from a good artist. :)
Attachments
pop-beeb-exile-sprites-mode2.zip
PoP in MODE 2 using Exile style sprites
(51.81 KiB) Downloaded 20 times
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

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

Re: Starting a Prince of Persia port...

Postby tricky » Mon Sep 25, 2017 6:54 pm

Well done for persevering, I know how wading through pages of assembler can "get old quick" as I have had to do it with the "emulators" that I have written. Its great that you have kept going and I love to read your updates.

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

Re: Starting a Prince of Persia port...

Postby kieranhj » Thu Sep 28, 2017 9:55 am

tricky wrote:Well done for persevering, I know how wading through pages of assembler can "get old quick" as I have had to do it with the "emulators" that I have written. Its great that you have kept going and I love to read your updates.

Thanks Tricky! Today I had a big breakthrough on the Tube, of all places. A single digit change now means the game runs at 50Hz... #-o

pop-beeb-full-speed-mode2.png
MODE 2 individual palette per sprite

This turned out to be a couple of bugs, one of which was very subtle, that have taken me the best part of two days to track down.

Firstly, there is a function to return sprite dimensions that is used outside of the plot routines. I'd manage to miss setting up the correct swram bank before accessing the sprite data, so was sometimes returning garbage values. I'd also missed that it needs to preserve the A register on return, so in fact was always returning garbage.

That was the "easy" one. The much harder one was a seeming Heisen-bug - if I made innocuous code changes (NOPs) then I was getting different behaviour - either an actual crash from a corrupted stack or, more weirdly, the code wanted to call a function that I hadn't implemented yet but that I knew shouldn't be called at this point. Anyway, long story short there was a very subtle alignment problem with the collision detection data that is used at runtime, it has to be aligned to &10 (fine - I'd caught that) but all tables have to be contained within a single page. The original Apple code ensure this by using a fixed memory location, I had moved this to a general data block in code space, which of course was moving around depending on the code arrangement.

I also had a nagging concern about the framerate. I had forgotten the first rule of optimisation - never make assumptions, always test what's really going on. I went for a beer with sbadger who commented that the original sprite demo I showed last year was much faster, so why was it so slow now? I realised my answer wasn't sufficiently empirical and after single stepping each frame (a feature I added to the NULA version of b-em BTW) I discovered it was taking approx. 2 frames to draw the sprites and then there were 25 static frames! 25 frames ~= 1 million cycles - even I can't write code that is bad enough to take a million cycles! There was clearly something weird going on.

I'm not sure what the weirdness was but it was clearly associated with the collision detection (seems feasible if it ended up looping thousands of times to resolve) as once I'd fixed the alignment bug - boom! 50Hz.

I now realised that I'd been hasty assuming that my black & white bit twiddling in MODE 4 was impossibly slow (1 million cycles :lol:) so back ported the fix to compare.

You can check out MODE 2 here: https://bitshifters.github.io/jsbeeb/?disc=https://bitshifters.github.io/content/wip/pop-beeb-full-speed-mode2.ssd&autoboot&model=Master and MODE 4 here: https://bitshifters.github.io/jsbeeb/?disc=https://bitshifters.github.io/content/wip/pop-beeb-full-speed-mode4.ssd&autoboot&model=Master. Or grab the ssds from the attached zip.

I now have another decision to make. I have a MODE 2 sprite routine that allows a separate 3 colour palette per sprite ala Exile (actually ripped directly from Exile) and some badly automatically converted MODE 2 "fat" sprites that need some artist love. Alternatively I could continue down the hi-res path in MODE 4 or even think about automatic conversion to MODE 1 as I was doing before. What do my fellow Stardotters think?
Attachments
pop-beeb-full-speed.zip
PoP now running at a decent speed
(109.12 KiB) Downloaded 20 times
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

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

Re: Starting a Prince of Persia port...

Postby kieranhj » Thu Sep 28, 2017 9:57 am

PS. I know I desperately need to hook up the keys now it is running at a playable speed. I will do that asap!
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 » Thu Sep 28, 2017 10:52 am

Awesome work Kieran! Love reading these updates!

I'd also been wondering just how it could be that slow, but assumed there were reasons. Looks lovely now - and even better if you can hack in some rudimentary keyboard control.

For me, it's a no-brainer - MODE 2 wins over MODE 4 or MODE 1, but I've always preferred colours over resolution anyway. Particularly if a Video NuLA palette can be used if the hardware's there. I guess the main issue that can occur with going to MODE 2 (with the stretching of the sprites) is that the movement code might get broken if it's expecting sprites of a different width. The art tidy-up isn't so much of a big deal I don't think - the automatically converted sprites already look pretty good, particularly when they're in constant motion, and they can be tweaked a long way down the line.

If it turns out that you can't really capitalise on the 16 colours (just due to the general graphics design, and the fact that the Apple original is only 4 colours anyway), MODE 1 would give you nice resolution as well as retaining the original colour scheme. But I don't know how you'd compress those sprites, other than essentially using the original Apple data format and expanding it out to 2bpp in real time. I still think it'd be great to emulate the style of the CPC version and make a more colourful port than the original!

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

Re: Starting a Prince of Persia port...

Postby kieranhj » Thu Sep 28, 2017 11:21 am

Rich Talbot-Watkins wrote:Awesome work Kieran! Love reading these updates!

I'd also been wondering just how it could be that slow, but assumed there were reasons. Looks lovely now - and even better if you can hack in some rudimentary keyboard control.

Thanks Rich! It was bizarre to add a single character "ALIGN &100" and suddenly have everything magically appear. Oh well, at least I understand the collision detection code a lot better now. :lol:

Rich Talbot-Watkins wrote:For me, it's a no-brainer - MODE 2 wins over MODE 4 or MODE 1, but I've always preferred colours over resolution anyway. Particularly if a Video NuLA palette can be used if the hardware's there. I guess the main issue that can occur with going to MODE 2 (with the stretching of the sprites) is that the movement code might get broken if it's expecting sprites of a different width. The art tidy-up isn't so much of a big deal I don't think - the automatically converted sprites already look pretty good, particularly when they're in constant motion, and they can be tweaked a long way down the line.

Yes, I think I'm leaning towards MODE 2 now. The sprite routine can be optimised plenty from where it is right now and has the flexibility to specify a 3 colour palette per sprite - this means the torches can be red & yellow whilst the background is blue & cyan etc. I know Dethmunk has done some awesome sprites for other Beeb (and Speccy) games so confident he could make these look really good. The other advantage is that as far as the game engine is concerned, all the sprite sizes and motion calculations have stayed the same. 1 byte of Apple II data (7 pixels) becomes 1 byte of MODE 5 data (4 wide pixels) that's unrolled to MODE 2 at runtime. PoP thinks it's plotting everything in Apple II screen coordinates, it's just getting drawn at the last moment aligned to 4 wide pixels.

Rich Talbot-Watkins wrote:If it turns out that you can't really capitalise on the 16 colours (just due to the general graphics design, and the fact that the Apple original is only 4 colours anyway), MODE 1 would give you nice resolution as well as retaining the original colour scheme. But I don't know how you'd compress those sprites, other than essentially using the original Apple data format and expanding it out to 2bpp in real time. I still think it'd be great to emulate the style of the CPC version and make a more colourful port than the original!

All 16 colours are available for sprites from an engine perspective and a native NULA version would be really special - unlike anything ever seen on the Beeb before! I do have the source sprites from the PC CGA version which might make a better starting point down the line. For now I'll persevere with the auto-converted Apple II -> MODE 5. (Oh, I found the reason for the sprite parity issue with the source data - this is corrected by a flag in the animation frame tables, if the sprite has to be on an odd/even pixel number and isn't then it gets bumped right by one at runtime.)

I do love the idea of making a MODE 1 version, if only because it's my favourite MODE (strange that one should have such a thing) and very few games used it. I might put this on the "to do" list after the MODE 2 version, as more of an "authentic" Apple II port.
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

User avatar
davidb
Posts: 1900
Joined: Sun Nov 11, 2007 10:11 pm
Contact:

Re: Starting a Prince of Persia port...

Postby davidb » Thu Sep 28, 2017 11:27 am

It looks great so far! MODE 2 is so much more Beeb-ish, anyway, so it will make your version stand out. :)

User avatar
sbadger
Posts: 232
Joined: Mon Mar 25, 2013 1:12 pm
Location: Farnham, Surrey

Re: Starting a Prince of Persia port...

Postby sbadger » Thu Sep 28, 2017 12:38 pm

kieranhj wrote: I do have the source sprites from the PC CGA version which might make a better starting point down the line.


if you got that route, go for the VGA, same res, but much better palette starting point for NULA :D
A3020| A3000x3| BBCBx3 | Electrn | Masterx3 |RiscPC| RPix3
A600 | C64 bbin x2|C64C | Toastrack |QL | XB360&1X |GB |GBC |GBA |GBASP | DS | 3DS XL x2| MD | MS
Atari 7600 | PS1-2-3-4| PSP |Vita |SNES |GC |N64 |Wii & U |Switch |JammaCab |Sony PVMx2

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

Re: Starting a Prince of Persia port...

Postby tricky » Thu Sep 28, 2017 12:46 pm

I think you know my preference where mode 1 is concerned, but maybe check with Dethmunk to see if he would be happy making mode 2 graphics.

Did I imagine a NuLA 4 colour mode 4ish that was 1 palette bit + 7 colour bits, maybe I am confusing it with the mode 1ish 4 palettes, 4 colours, 3 pixels; was this the native NuLA mode you were thinking of?

I promise not to be disappointed whatever you choose :D

User avatar
Lardo Boffin
Posts: 670
Joined: Thu Aug 06, 2015 6:47 am

Re: Starting a Prince of Persia port...

Postby Lardo Boffin » Thu Sep 28, 2017 1:15 pm

Reading all this makes me want to get a copy of Prince of Persia for my Apple! I think I have never played the original - just a version done for the original Xbox I think.

The Beeb version looks like it will be awesome and a superb technical achievement. =D>
BBC model B 32k issue 4, 16k sideways RAM, Watford 12 ROM board, Retroclinic Datacentre + HDD, matchbox co-proc, Viglen twin 40/80 5.25" discs, acorn cassette
BBC model B 32k issue 7, turboMMC, Opus Challenger 3 512k, Pi 3 coproc, Acorn 6502 coproc

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

Re: Starting a Prince of Persia port...

Postby kieranhj » Thu Sep 28, 2017 8:41 pm

OK, because I love you guys, try this: https://bitshifters.github.io/jsbeeb/?disc=https://bitshifters.github.io/content/wip/pop-beeb-player-control.ssd&autoboot&model=Master

I ported the keyboard & joystick functions (the keyboard actually "emulates" the joystick) and patched in a call to OSBYTE &81. You can use standard Beeb controls: zx*? to move plus ; and ] for up left and up right. I need to do some work on how the strobing & debounce works because it doesn't seem possible to do a single step or proper running jump etc.

It's also not possible to leave the screen as I haven't implemented the destructible floor plates! The game will (deliberately) crash on a BRK if it calls an unimplemented function (of which there are many) - this will happen eventually if you hit the wrong bit of the screen.

I reckon we're about 50% complete at this point but very happy with the progress so far. Another bonus - our Bitshifters musician friend is a big Apple II fan and has offered to write SN versions of the tunes for the game. With a custom NULA version this could look and sound like no other Beeb game ever made! :D
Attachments
pop-beeb-player-control.zip
Hacked in player controls!
(52.2 KiB) Downloaded 19 times
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

SteveF
Posts: 439
Joined: Fri Aug 28, 2015 8:34 pm

Re: Starting a Prince of Persia port...

Postby SteveF » Thu Sep 28, 2017 10:33 pm

That looks great! Really enjoying this write up, and amazed if you really think you're at 50% completion. Of course, everyone knows the last 10% takes 90% of the time. :-)

Do you have a feel for whether memory is going to be a big problem or not yet?

steve3000
Posts: 1711
Joined: Sun Nov 25, 2012 12:43 am

Re: Starting a Prince of Persia port...

Postby steve3000 » Thu Sep 28, 2017 10:50 pm

Great to see the progress you've made on this Kieran. I was expecting to prefer MODE 4 version, but the MODE 2 graphics really do look good and the potential for using exile-type colour dithering (and/or NULA) would make a really unique conversion.

Brilliant work!

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 Sep 29, 2017 9:07 am

Great work Kieran, and so fast arriving at this point! Looks great... and I was able to navigate a few screens before it finally gave up.

How easy was it to transplant the Exile sprite routine by the way? It has some very specific needs regarding sprite format, screen dimensions, and ZP usage.

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

Re: Starting a Prince of Persia port...

Postby kieranhj » Fri Sep 29, 2017 9:10 am

Thanks for the feedback everyone!

SteveF wrote:That looks great! Really enjoying this write up, and amazed if you really think you're at 50% completion. Of course, everyone knows the last 10% takes 90% of the time. :-)

Do you have a feel for whether memory is going to be a big problem or not yet?

Haha, yes I think might have been a bit giddy with excitement yesterday. I estimate I have ported approximately 50% of the functions but that certainly doesn't mean it's 50% complete. I've made enough games professionally to know that if you want something to be really polished & high quality then that last 10% absolutely does take a crazy amount of time.

On the topic of memory, I started porting some moveable object code to try and get the loose floors working and immediately hit the AUX memory guard point. #-o Back to earth with a bump. :) There's still quite a bit of swram left but that's not very helpful. The sprite system has a nice clean interface so it's easy to page in a swram bank for sprite plot. Many other data sections are accessed liberally through the gameplay code so it's not as easy to intercept these. I can get 2K back by moving 8x pages of runtime data down below &E00 but I fear that will still not be enough...

On the to-do list: porting all the remaining functions and gameplay code, so that includes fighting, guards, moveable objects, triggers, doors, spikes etc. Also the cutscenes, intro, attract mode, game timer etc. Plus lower level stuff like save game and on-screen messages.

On the Beeb specific side I've still got to revisit the sprite engine for optimisation and to fix up the plot routines to properly draw everything in MODE 2, remove the flicker (means timing against the raster as there's not enough memory for double buffering), get the sprites all redrawn including palette selection, implement music & sound routines for the SN chip, figure out the memory configuration when loading cutscenes, get the disk system to handle double-sided discs.

Just a little bit left to do then. Oh, and there are bound to be some crazy, head-messing bugs that crop up which will take several days to track down. :D
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

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

Re: Starting a Prince of Persia port...

Postby kieranhj » Fri Sep 29, 2017 9:50 am

Rich Talbot-Watkins wrote:Great work Kieran, and so fast arriving at this point! Looks great... and I was able to navigate a few screens before it finally gave up.

How easy was it to transplant the Exile sprite routine by the way? It has some very specific needs regarding sprite format, screen dimensions, and ZP usage.

Thanks Rich! How did you change screen BTW?!

I actually ended up adapting the Exile sprite routine quite a lot and there is still a ton of optimisation possible. Whilst unrolling the 2bpp data Exile uses X as temporary storage to save cycles and then self-mod code to read out of an array in ZP. I used this method at first but with the array located in main memory (hence the smPIXEL labels.) For various reasons along the way I changed this to store the temp data in ZP and then use X as an index. I will look at putting this back later on when I revisit. Exile also magically precomputes exactly where the stack pointer will be ahead of time. I'm just reading the stack pointer after unrolling then self-modding the loop that reads this back so it gets the data from the right place.

There's a load of stuff in here that can be pre-calculated, made simpler and optimised, counting in reverse for example. I wanted to make sure it was working "correctly" first. (There are still some things I need to sort out with respect to PoP's plotting needs.) I love the cunning use of the stack pointer as a "free" index register and the fact that a stack can easily accommodate the pixel parity.

Code: Select all

    TSX
    STX beeb_stack_ptr          ; use this to reset stack

.plot_lines_loop

    LDY WIDTH
    DEY                     ; bytes_per_line_in_sprite

\ Decode a line of sprite data using Exile method!

\ Push a zero on the end in case of parity

    LDA #0
    PHA

    .line_loop

    .sprite_addr
    LDA &FFFF, Y
    STA beeb_data
    AND #&11
    TAX
.smPIXELD
    LDA map_2bpp_to_mode2_pixel,X         ; could be in ZP ala Exile to save 2cx4=8c per sprite byte
    PHA                                 ; [3c]
    LDA beeb_data
    AND #&22
    TAX
.smPIXELC
    LDA map_2bpp_to_mode2_pixel,X
    PHA
    LDA beeb_data
    LSR A
    LSR A
    STA beeb_data
    AND #&11
    TAX
.smPIXELB
    LDA map_2bpp_to_mode2_pixel,X
    PHA
    LDA beeb_data
    AND #&22
    TAX
.smPIXELA
    LDA map_2bpp_to_mode2_pixel,X
    PHA
    DEY
    BPL line_loop

\ How many bytes to plot?

    LDA VISWIDTH
    ASL A           ; bytes_per_line_on_screen - can precompute
    STA beeb_width

\ If parity push an extra blank

    LDA beeb_rem
    BEQ no_extra
    LDA #0
    PHA
    INC beeb_width  ; and extra byte
    .no_extra

\ Not sure how Exile does this?

    TSX
    STX smSTACK1+1
    STX smSTACK2+1

\ None of this needs to happen each loop!

\ Sort out where to start in the stack lookup

    LDA OFFLEFT
    ASL A
    TAX

    LDA OPACITY
    BPL not_reversed
    LDA beeb_width
    SEC
    SBC OFFRIGHT
    ASL A
    INC A
    TAX
    .not_reversed

\ Now plot that data to the screen

    LDY beeb_yoffset
    CLC

.plot_screen_loop

    .smSTACKdir1
    INX
.smSTACK1
    LDA &100,X

    .smSTACKdir2
    INX
.smSTACK2
    ORA &100,X

\ Plotting mode here

    .smod
    STA (beeb_writeptr), Y

\ Write to screen

    STA (beeb_writeptr), Y

\ Next screen byte across

    TYA
    ADC #8
    TAY

    DEC beeb_width
    BNE plot_screen_loop

    LDX beeb_stack_ptr
    TXS

I stole the Exile palette code wholesale as this seemed quite sensible and was immediately compatible with the pixel lookup array (&00,&01,&02,&10,&11,&20,&22) approach.
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

User avatar
jbnbeeb
Posts: 368
Joined: Sat Apr 03, 2010 8:16 pm

Re: Starting a Prince of Persia port...

Postby jbnbeeb » Fri Sep 29, 2017 9:55 am

Kieran - just ran your latest cut of this. Very well done ! I know there's a lot more work to do but it's a real milestone to see that familiar sprite animation, with the control feeling just like it did when I played on PC back in the day!

I was able to move left in to another room as well.

D'you think you'll be able to keep all the frames of animation without double buffering?
I'm going to ..
ABUG North Halifax June 10-12
Image

User avatar
FourthStone
Posts: 400
Joined: Thu Nov 17, 2016 2:29 am
Location: Melbourne, Australia

Re: Starting a Prince of Persia port...

Postby FourthStone » Fri Sep 29, 2017 9:57 am

Fantastic progress, super fast at 50fps and can't wait to experience it all when sunc'd to the raster, expecting it to be smooth as butter [-o<

I think the game will work for any mode really so will be great if you end up doing multiple releases, saying that I would be super stoked with a mode 2 chunky style beeb classic conversion / port of a childhood favourite, well done for taking on this project :mrgreen:

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 Sep 29, 2017 10:56 am

Exile's sprite routine is ingenious isn't it? Using the stack as per-pixel scratch space is an idea I'd never thought of, and the fact that it makes recolouring, offsetting and mirroring the sprite so simple is brilliant in its inventiveness. If you can reserve those zp locations for holding the colours of sprite pixels, it'll definitely help your performance.

It's nice that you don't have to worry about scrolling, and particularly the screen wraparound at &8000, as this makes the Exile code even more complicated.

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

Re: Starting a Prince of Persia port...

Postby kieranhj » Fri Sep 29, 2017 10:41 pm

A very quick Friday night treat for you. I ported some more gameplay functions, including gate, loose floor, spikes and press plates. You can explore a bit more now but the controls are still wonky so it's very easy to die. :D Also there are various sprite plotting glitches that are very obvious. Oh, and if you die you have to shift-break to start again! It's early days. :)

I also completely ran out of memory so going to have to think a bit more about how I handle this. I might have to assign a SWRAM bank to gameplay coded and page this in alongside the SHADOW RAM. This means more loading of sprites etc. during cutscenes, but pretty sure that's what the original did anyway.

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

A separate question to think about - would anyone like to be a "proper" gameplay tester when I get a bit further along? Ideally someone that knows the game really well and has completed it before on a different platform. Be warned that being a tester tends to ruin your enjoyment of a game, certainly in my professional experience - you'll be sick of it after repeating the same handful of screens over & over again. :P
Attachments
pop-beeb-moar-gameplay.zip
PoP with MOAR gameplay
(53.83 KiB) Downloaded 25 times
Bitshifters Collective | Retro Code & Demos for BBC Micro & Acorn computers | https://bitshifters.github.io/

User avatar
lurkio
Posts: 1285
Joined: Tue Apr 09, 2013 11:30 pm
Location: Doomawangara
Contact:

Re: Starting a Prince of Persia port...

Postby lurkio » Fri Sep 29, 2017 10:47 pm

kieranhj wrote:A very quick Friday night treat for you.

:shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: :shock: =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D> =D>

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 Sep 30, 2017 9:38 am

This is incredible, amazing work!

I made a quick video of the playable version.

https://youtu.be/7W0c3qeaY3I
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

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

Re: Starting a Prince of Persia port...

Postby RobC » Sat Sep 30, 2017 11:07 am

This is looking really good! Amazing to see so much progress =D> =D> :D

User avatar
marcusjambler
Posts: 122
Joined: Mon May 22, 2017 11:20 am
Location: Bradford
Contact:

Re: Starting a Prince of Persia port...

Postby marcusjambler » Sat Sep 30, 2017 11:20 am

=D> :shock: =D> :shock: WOW!!


Return to “projects”

Who is online

Users browsing this forum: No registered users and 1 guest