TL;DW: Memory constrains prevented the inclusion of enemies in the game (due to the space taken by rotoscoped images), so he got the idea of xor-ing frame pixels together to get the outline of the main character, kind of a shadow, and made that the enemy. He also squeezed a bit more memory from an "auxiliary" memory unit to animate guards.
Hi, saw this thread and wanted to jump in. It's a good question not answered in the 20-minute ArsTechnica video: since Shadowman was born out of the necessity of being squeezed for memory on the Apple II, how was I then able to add guards, skeletons, and a Vizier?
To refresh my own memory (which is more than 48K, but often foggy), I checked my journal. Part of the answer is in this entry from 11/20/1988:
"...Put in footsteps, and improved the chomping jaws. But the real breakthrough this week was invisible: I moved a bunch of stuff around so the main game code can use the auxiliary language card. Basically, I've just freed up an extra 12K. That gives me some breathing room I'll sorely need if I'm going to put in all this sword fighting."
And a few months later, on 2/16/89:
"A lot of heavy work, most of it invisible, but which will make it much easier for me to implement the enemy guards in their flowing robes and turbans."
The journal doesn't give more technical detail than that (if I'd imagined anyone would be interested in this stuff 30 years later, I'd have written more!) but the code is on github, so anyone who's motivated enough should be able to reconstruct how the final code uses the auxiliary memory. In my recollection (foggy, as warned -- it's been a while), the "auxiliary language card" was an extra 16K of RAM that Apple had squeezed into the latest generation of Apple II computers, but that was difficult to use because it wasn't contiguous with the rest of RAM. I seem to recall it shared addresses already used by the main memory, so you had to flip between which part you were using. In November '88, seeing how much Shadowman and swordfighting and Shadowman improved the game motivated me to invest the time to rewrite/strategically relocate a bunch of existing code to free up 12K that I could use to implement enemies.
As for the multiple enemies, I'm pretty sure that each level contained exactly one enemy, whose shape table was packaged with the level load. The floppy disk access (very quick, thanks to Roland Gustafsson's magical 18-sector routines) when the level was loaded would swap out the previous level's enemy with the new one. That's why you'll notice that the levels containing the "special enemies" (skeleton, Jaffar, and the Fat Guard) had no normal guards in the rest of the level -- they couldn't.
Such great memories of playing PoP in my teens! I wish I could get as excited about some new game/software as I did back then. In those days there really were some titles that would come along and just knock your socks off. Doesn't happen much anymore...a sign of the times I guess.
I can't reply to the parent anymore, but I just went back to HN after a week of busy work: thanks a lot for the details, jmechner, that's quite interesting :)
I don't have enough time on my hands to dig into the old source code (nor I am particularly interested in the Apple II), but I'm glad to know it's available, should I or some others be suddenly curious to dig in. I much prefer such code to be opened than to be lost to history!
So, it's a bit like register banks [1] or an MMU, where you have to page in and out part of the address space, I guess?
I've seen some people [1] argue that we needed less powerful machines and to break backwards compatibility, for people to get creative again. Maybe there is some truth to that?
It really seems to be a trend these days for new accounts to submit the YouTube videos that were embedded in previously popular HN articles as new HN articles. I've seen this several times in the last week or so.
Didn't change the trend. Does ask for a different call to action. No need to be upset on people submitting auxiliary videos. Would be nice to have a feature linking the video to the article. Is there already metadata to make this discoverable?
Media preferences aside, the article is essentially a watered down commentary on the video. If I came across this while I was at work, I would also prefer to consume the article. But I think the video is where the value is in this content.
I enjoyed the video a lot, but it feels a bit fictionalised. The first fifteen minutes talking about how hard it was to get another character, then immediately after adding shadownman the vizier is added, then unmentioned but shown at 16:21 there's a new skeleton enemy which is clearly a completely different bitmap from any other character.
That's a heck of a lot of space to suddenly find when adding a single extra character was seemingly untenable.
Loved the video, and loved Prince of Persia growing up. It might have been my first PC game, back on our old 286. I'm saying might be, because we also had Monkey Island and Alley Cat!
Now that I'm older, I really appreciate the relentlessness of the vision. "I'm just gonna do rotoscoping! I'm gonna film my karate teacher and my brother!". I have to say it's really rare these days in the tech industry to see this kind of insane vision. It's even more rare to see someone pull off a cohesive product out of it.
I wish the interviewer had asked for more elaboration on the techniques used. It went really quickly from:"I ran out every single byte of memory with this Prince guy, how do I create an antagonist? I know, palette shifting!" to "then I added sword fighting, and enemy guards". Still, really love to hear these tales of optimization.
And he did it on an Apple 2. Those machines were good programming workstations, in the day, fast storage, lots of tools, and so forth, but high resolution graphics were hard to do fast.
And it is not even palette shifting. The Apple has absolute colors. He literally made another draw routine that performed the XOR operation.
For a modern day example of similar dedication, check this out:
Python scripts create in line assembly for the ray caster, PLASMA byte code interpreter, big world, animations, and excellent use of the 6 colors and artifact art.
A game this big would have been epic in the day. The team has been grinding away at it for some years now.
It will end up being an exemplary example of an RPG, and on the Apple, that kind of game is in the sweet spot.
What Jordan did was not really considered possible. PoP amazed many people!
The big complication was 7 pixels per byte. Artifact colors work on even "bit boundaries" aligned with the colorburst.
On pretty much every other computer, the same bit patterns resulted in the dame artifact colors, but the Apple had even and odd byte patterns, because the repeat took two bytes, not one like other machines.
On the other hand, having that high bit shift the pixel clock a little meant 6 colors, plus black and white.
Because of how artifacting works, that is actually enough to do anything. Until the PC and some machines like the color computer 3, artifact colors were limited. Red blue, kinds of things.
The secondary complication was the screen addressing, which cost a table lookup. Had it been linear, overall draw speed would have been a bit faster.
Right, within every even/odd group of seven pixels, the even/odd colors for each of those pixels were reversed. With the high bit switching between different sets of colors. And on top of that the vertical scan line interleaving.
So many levels of owch! And punching through all that with an 8 bit 6502. It's really hard to appreciate how fucking hard any Apple ][ game that uses hires graphics had to work just to put a dot on the screen.
Even more amazing were the text/hires graphics adventure engines that stippled together different colors to get a wider palette. It was so hard for the poor 6502, that part of the visceral pleasure of the game was just sitting there watching it draw each scene.
And all the visible text (IN UPPER CASE OF COURSE) must fit in the characteristic four lines at the bottom. Since it drew the scene so slowly, there was enough time to read the text before it scrolled off the top. Talk about making lemonade out of lemons, due to technical limitations!
Hi-Res Adventure #4: Ulysses and the Golden Fleece for the Apple II
Not to mention that the HGR screen was also interleaved, rather than linear. Also, if you factor in DHGR, you remove the half-pixel shift, but instead you operate like you do in 80 column text mode, with the even columns of 7 pixels being in the normal high-res memory map, and the odd columns being in the auxiliary 80-column memory, on top of the normal HGR interleaving. Certainly a lot to wrap your head around as compared to other video subsystems.
When your only registers are a 8 bits X, Y, and A, the hires screen memory was practically encrypted!
It felt so fucking amazing to finally have a computer with a normal 1 pixel : 1 byte memory mapped display.
But before that, I played around with the Sun CG1 graphics board (on a Sun 2: I mmap'ed /dev/cgone0, but maybe it was actually a cgtwo card, not sure), which was kinda but not really memory mapped.
It had 8 bit color mapped pixels, and it had an implicit read position and write position, such that you could address a row and column of pixels at a time, one pair for reading and one for writing ("rop mode memory").
When you accessed a column of the row block of memory, that set which column you could address in the other column block of memory. When you accessed a row of the the column block of memory, that set which row you could address in the other row block of memory!
As it turned out, that just happened to be useful for drawing lines and filling trapazons and performing raster operations, but it made random access quite inefficient, and was a huge pain in the ass for anything else.
(Although nowhere near as painful as Apple ][ graphics, but a lot more expensive!)
I think the early X10 and X11 servers actually supported it (SunView [SunTools at the time] certainly did), but it was really really slow.
I learned later than John Gilmore had written weird union structs the .h file to describe the memory mapped registers, when he was at Sun in its early days:
Here's some Forth and 68K code I wrote to play around with that card (notice how register offsets gr_x_select / gr_y_select, 68k code xsel / ysel, and Forth words lineaddr / coladdr work together -- yes Forth can mmap device registers, and that is RPN 68k assembly code, with opcodes at the end of the line!):
Did it use double hires graphics? That was even harder to do correctly. Half the graphics memory was in the first 64K of memory ($2000-$4000) and the other half was stored in the second bank switched 64K of memory.
It's possible that Mechner did go into further detail and it was cut for this video. Keep an eye on this channel; recent videos in this series (Rand Miller and Lorne Lanning) had the full un-cut interviews posted, which go on for hours and are well worth it if you're into this stuff.
Along the same lines, there's a wonderful series of forum posts detailing the progress (right through to completion) of a fan-made Prince of Persia port to the BBC Master here: https://stardot.org.uk/forums/viewtopic.php?f=53&t=13079
This War Stories series from Ars is really great. The episodes are generally geared for the gaming audience and not necessarily a technical audience, but they often touch on a wide range of topics involved in producing video games that also end up being applicable in wider software development.
Yeah it's really good, though one minor issue is that they seem to be keen on fitting a certain structure (cutting in with "The Problem", "The Solution" when it doesn't really fit well) when really it's just entertaining hearing people like Jordan Mechner, Sid Meier and Lucas Pope talk for a while about an interesting mechanic or issue.
Download a copy of the original Apple II disk for an emulator https://archive.org/details/wozaday_Prince_of_Persia You can kinda play it in the browser but the sound was a little odd and I couldn't figure out the controls.
The the Apple II version the game is actually very playable with the keyboard (easier than using a joystick) but it would be hard to figure out without some guidance.
At the title screen, hit the space bar to start the game.
After the game starts, hit Control+K to enable keyboard controls.
It uses the standard I,J,K,L + U,O layout for up, down, left, right and jumping. Note that you can't press two of these keys at the same time, but you can hold one of them down.
The Option/Alt key modifies the behavior of these keys, and you will use it often:
- Option+J/L: step slowly rather than run. Use this to safely walk up to the edge of a ledge.
- Option+I: Jump up and hang on to a ledge. Hold 'I' to climb up the ledge.
- Option+K: Drop down and hang on to a ledge. Release Option to let yourself drop.
Use 'U' and 'O' to leap left or right over a ledge. This can be done while running or from a standstill.
Use 'Option' to pick up objects and drink potions.
Use the space bar to see how much time you have left.
There is a lot of trial and error at first, as you discover what things can kill you. When you die you can back to the start of the current level. Some tips:
- You can only safely fall one story. Falling two stories will reduce your life. Falling more will kill you.
- You can safely step into spikes that have popped out of the ground. If you run into them you will die.
- You can jump straight up to see which floor and roof tiles are loose. Run over floor tiles that are loose. Jump up underneath a loose ceiling tile to reveal hidden areas.
Why wasn't the "auxiliary" memory the actual solution? Most of the video was about not having enough memory to add guards/monster for combat but guards were added anyway after finding extra memory and yet that fact was largely glossed over.
Path of least resistance. Also, if he would have used that part for the "evil self" there would have been no guards because that memory would be in use now.
The evil self was suppose to be (according the video) the "genius" work around to not having guards and combat in the game due to memory constrains. Guards and combat being added anyway really undercuts the narrative of the video.
One point that Jordan Mechner makes is the limitations made the game better. The whole idea of the mirror guy as an antagonist was inspired by these limitations. Here's someone who is actually in the game world (not just in cutscenes or a final boss battle) that would manipulate the environment to frustrate your efforts to escape.
And then some extra memory was found so guards were added, and the ports had even less limitations and could reach a larger audience. But the original limitation inspired creativity that might otherwise never have been.
Not so long ago I shared a small video of his young brother doing the jumps and walks that he uses to create the animations for his game. Awesome work, awesome video. Inspiring.
The answer would likely be along the lines of torches using a minimal amount of memory, while combat would involve adding multiple large sprites for the player in combat as well as many large sprites for the the combatants's combat and motion. Given that the game was already pushing the limits of computer graphics with it's art style, it was likely desirable to differentiate the appearance of at least some of the combatants, pushing the memory requirements even higher.
Then there was the author's lack of desire to make another game focused upon combat.
Which is the beauty of the shadow character. Since it is based upon a computational trick, it added a minimum to the resources required. At the same time, it afforded a twist in the plot that allowed the author to accept and integrate combat into the game. It changed the nature of the combat and of the player's decisions, permitted the antagonist to exist long enough to have it's own story, and got rid of the cheap feeling of a clone army (i.e. reused sprites).
I would like to see Jordan getting out there and making stuff again. From this outsider's perspective, he's been in a largely quiescent state for 15+ years. I'm sure he's got more good stuff inside his brain and I want him to set it free.
Their video on Crash Bandicoot has some more technical trick to squeeze performance out of a finite resource, where I think this one was mostly conceptual. Both enjoyable though.
For some reason I initially read this as "Prince Charles." And thought that I was totally ignorant of Prince Charles' programming exploits, as though he were a Lee Hsien Loong.
I always wanted to play "Prince of Persia" but I was too busy writing code for a living. Is it possible to play this game in a current platform, may be in Ubuntu ?
Which links to the transcript: https://cdn.arstechnica.net/wp-content/uploads/2020/03/princ...
And his journals from the time, which are now being published: http://jordanmechner.com/journals