
How Prince of Persia Defeated Apple II's Memory Limitations [video] - weare138
https://www.youtube.com/watch?v=sw0VfmXKq54
======
ChrisSD
Accompanying article is here: [https://arstechnica.com/gaming/2020/03/war-
stories-how-princ...](https://arstechnica.com/gaming/2020/03/war-stories-how-
prince-of-persia-slew-the-apple-iis-memory-limitations/)

Which links to the transcript: [https://cdn.arstechnica.net/wp-
content/uploads/2020/03/princ...](https://cdn.arstechnica.net/wp-
content/uploads/2020/03/prince.txt)

And his journals from the time, which are now being published:
[http://jordanmechner.com/journals](http://jordanmechner.com/journals)

~~~
MayeulC
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.

Kind of light on details, though :)

~~~
jmechner
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.

Hope this helps. Thanks for your interest!

~~~
luckman212
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.

Thanks for taking time to share!

~~~
MayeulC
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?

[1]:
[http://www.keil.com/support/man/docs/c51/c51_le_regbankspec....](http://www.keil.com/support/man/docs/c51/c51_le_regbankspec.htm)

[2]:
[https://fosdem.org/2020/schedule/event/generation_gaps/](https://fosdem.org/2020/schedule/event/generation_gaps/)

------
wyattpeak
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.

~~~
Morizero
It's because the video is an ad for his book, "The Making of Prince of
Persia".

------
leshokunin
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.

~~~
ddingus
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:

[https://m.facebook.com/LawlessLegends/](https://m.facebook.com/LawlessLegends/)

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!

~~~
DonHopkins
Not just absolute colors, but absolutely bizarre Rube-Goldbergesque colors!

[https://en.wikipedia.org/wiki/Apple_II_graphics](https://en.wikipedia.org/wiki/Apple_II_graphics)

~~~
ddingus
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.

~~~
DonHopkins
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.

[https://en.wikipedia.org/wiki/Composite_artifact_colors#Appl...](https://en.wikipedia.org/wiki/Composite_artifact_colors#Apple_II)

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

[https://www.youtube.com/watch?v=QTFNKbkxeY8](https://www.youtube.com/watch?v=QTFNKbkxeY8)

~~~
LocalH
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.

[http://www.appleoldies.ca/graphics/dhgr/dhgrtechnote.txt](http://www.appleoldies.ca/graphics/dhgr/dhgrtechnote.txt)

~~~
DonHopkins
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.

[http://www.sunhelp.org/faq/FrameBufferHistory.html](http://www.sunhelp.org/faq/FrameBufferHistory.html)

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:

[https://donhopkins.com/home/archive/forth/cg/cg2reg.h](https://donhopkins.com/home/archive/forth/cg/cg2reg.h)

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!):

[https://donhopkins.com/home/archive/forth/cg/cgone.f](https://donhopkins.com/home/archive/forth/cg/cgone.f)

    
    
        : getfb
          0 bytes/fb [""] /dev/cgone0 mapin  >fb !
        ;
    

[https://donhopkins.com/home/archive/forth/cg/cg.f](https://donhopkins.com/home/archive/forth/cg/cg.f)

    
    
        code xsel ( x --- addr )
          >fb l#) d0 long move
          gr_x_select gr_update + l# d0 long add
          d0 sp ) add
          next
        c;
    
        code ysel ( y --- addr )
          >fb l#) d0 long move
          gr_y_select gr_update + l# d0 long add
          d0 sp ) add
          next
        c;
    

[https://donhopkins.com/home/archive/forth/cg/fline.f](https://donhopkins.com/home/archive/forth/cg/fline.f)

[https://donhopkins.com/home/archive/forth/cg/iline.f](https://donhopkins.com/home/archive/forth/cg/iline.f)

------
chris_overseas
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](https://stardot.org.uk/forums/viewtopic.php?f=53&t=13079)

~~~
buckminster
It's very good. Official page here:

[https://bitshifters.github.io/posts/prods/bs-pop-
beeb.html](https://bitshifters.github.io/posts/prods/bs-pop-beeb.html)

Click the "Emulate" button at the bottom to play in your browser.

------
slg
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.

~~~
smcl
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.

------
sp332
Download a copy of the original Apple II disk for an emulator
[https://archive.org/details/wozaday_Prince_of_Persia](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.

~~~
thought_alarm
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.

~~~
ngold
You da real documentation mvp. Thank's, I've tried playing this in the past,
but got lost on how the controls work.

------
wnevets
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.

~~~
bootloop
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.

~~~
wnevets
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.

------
Waterluvian
It was such a let down to hear that after all that work, apparently the ports
are what made PoP successful.

~~~
ChrisSD
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.

------
atum47
combat, combat, combat.

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.

~~~
hinkley
I'm trying to imagine his coworker, telling him this every time he was
bragging about some feature he managed to squeeze into the game.

Torches on the wall. Super. Why didn't you use that surplus for, and I'm just
spitballing here, say... combat?

~~~
II2II
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).

------
nodesocket
Related, the video How Myst Almost Couldn't Run on CD-ROM[1] is actually more
fascinating and entertaining in my opinion.

[1]
[https://www.youtube.com/watch?v=EWX5B6cD4_4](https://www.youtube.com/watch?v=EWX5B6cD4_4)

------
jgalt212
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.

~~~
scarface74
He designed a completely re-imagined Karateka in 2013. The iOS version died
during the great 32 bit apocalypse.

~~~
arn
He posted some "making of" videos when he remade the iOS version of Karateka.

I really enjoyed this video explaining how he got around making the gameplay
easier (not just 1 life) but also made it make sense to the story.

You have 3 lives... but 3 different lives:

[https://www.youtube.com/watch?v=Vq31IwKZkt0](https://www.youtube.com/watch?v=Vq31IwKZkt0)

------
bootlooped
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.

------
hinkley
Is "Shadow Man" the origin story of Nega Scott?

'Nega Scott is a reference to the "Shadow Doppelganger" stock character
present in many games and anime & manga.'

~~~
djmips
Maybe, but I feel there's a great chance it inspired Shadow Mario, the main
antagonist in Super Mario Sunshine.

------
corysama
[https://www.reddit.com/r/TheMakingOfGames/](https://www.reddit.com/r/TheMakingOfGames/)

------
u801e
There's a related set of blog posts[1] that go into some details of the memory
limitation problems when making the C64 port.

[1] [http://popc64.blogspot.com/2011/10/part-one-why-hell-
would-a...](http://popc64.blogspot.com/2011/10/part-one-why-hell-would-anyone-
want-to.html)

------
anbop
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.

------
corpMaverick
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 ?

~~~
paines
The PC version is available via abandonware. You can play it in dosbox.

~~~
petepete
Or here, right in the browser (via Dosbox)

[https://archive.org/details/msdos_Prince_of_Persia_1990](https://archive.org/details/msdos_Prince_of_Persia_1990)

~~~
corpMaverick
This was awesome. Thanks!!

