Log In  

Cart #tookbooks-5 | 2023-12-30 | Code ▽ | Embed ▽ | No License

It's just before Christmas, and Santa needs to know...


This is the sequel game to WHO STOLE THE COAL? - a Pico-8 holiday game from Dec 2020.



There was a video game crash, with tons of unsold/unreleased cartridges for the ATOMI 3600 console being buried in the desert in 1983.

Years later in 2014, they were excavated. Amongst the cartridges was a finished sequel to WHO STOLE THE COAL?, which was the original immensely popular game when released. But by the time WHO TOOK THE BOOKS? was finished, the market has collapsed, and it never saw the light of day.

But ATOMI rose from the ashes, recently releasing the ATOMI 3600+, and on it, WHO TOOK THE BOOKS? finally got released to the public. Game players and historians rejoiced!

Primitive now, it was a technological feat for its day. But puzzle game fans and secret-finders will still love it!


Arrows move.

Z/X: Swing canemaul. Santa's not happy till he has his canemaul!

To move across ice, you must find the FASKATES, which are, not surprisingly, fast skates. You can't steer skating across ice, but they let you cross it! You may have to BUY them at the SHOPPE. (New FASKATES cost five DIAMONDS!) WORTH IT!

You also run across SHAKY BRIDGES cuz they might collapse! Approaching from the side, you can walk UNDER bridges...


Santa recovered his coal from the Abominable Snowbeast in the past. But this year, he woke to find his NAUGHTY AND NICE BOOKS stolen! Plus his REINDEER and coveted COOKIES!

Sneak into the Snowbeasts lair while it's asleep! Recover the BOOKS. Rescue the REINDEER. And grab them COOKIES!

Winning means you find at least four books, so Christmas isn't totally a loss. Once you can "win", your sleigh will appear where you started. You can just go do that, or, you can try for the...


Find all nine books, rescue nine reindeer, and find all eighty cookies! Also don't be naughty!

Buckle up, Santa! Can you SAVE CHRISTMAS?

Naughty Hint:

Don't canemaul snowpeople, reindeer, or elves, ya meanie!

Cartridge Cover Art: Father Christmas Skating on Duddingston Loch by Carol Lawson

Intro art: Toby Hefflin (mangled by me to add beard)

Music: Gruber

Label dithered with DEPICT.

Testing: Bikibird (thanks!) and Squirrel!

UPDATE 12/30/23: fixed two softlocks, made leaving easier to evade.

P#139114 2023-12-24 14:44 ( Edited 2023-12-30 18:44)


Super fun game and huge! Still working on getting my skates. I'm only half way done.

P#139309 2023-12-28 18:02 ( Edited 2023-12-28 18:04)

Thanks @bikibird!

P#139310 2023-12-28 18:04

This feels like a very early Amstrad CPC game in mode 0 with graphics handled in basic with print statements and redefined characters. Even the font in the status bar feels amstrady.
Gameplay wise, it reminded me of "le secret du tombeau".

Even the screen size in tiles is similar (9x11) vs 15x8
With a similar griddy feel where each cell has low number of colours.
Finished the game by mistake when exiting the lair.
I swear I was naughty by mistake, I was aiming for a rock...

P#139342 2023-12-29 08:39 ( Edited 2023-12-29 08:40)

nice to see a to who stole the coal!

P#139348 2023-12-29 13:39

Nicely done, @RealShadowCaster !

Yeah I was gonna add an end confirmation, but ran outta time, tokens. Will try to minify a little and add that. And thanks for the game reference!

P#139351 2023-12-29 14:59

Thanks @Toblerone ! It was fun to make the sequel.

P#139352 2023-12-29 15:00

@thattomhall, if you don’t have the tokens, you could maybe move the sleigh to the side so you don’t run into it when exiting the lair.

P#139362 2023-12-29 15:52

Yeah, may look at that as well, @RealShadowCaster .

P#139363 2023-12-29 16:22

It's possible to soft lock yourself. If you take the key that you're supposed to open the mountain pass with and open the locked door to the south before you have the skates, you'll be stuck.

Unless I'm missing another key somewhere.

P#139371 2023-12-29 18:38

Ooh, thanks @joealarson ! Will add another key to prevent that!

Just 2-3 testers tested for just a few hours heh.

P#139372 2023-12-29 18:46

Just make sure the last book/cookie is acquired in the lair, or you may be locked out :(

P#139411 2023-12-30 15:54

@ChakAttack Gah will fix that so the trophies are in the fenceline. Thanks for the knowledge and sorry for that trophy trouble!

P#139412 2023-12-30 16:00

@ChakAttack and @joealarson - fixed your softlocks!

@RealShadowCaster - Moved sleigh outta the way. Changed word to GO <<< so people don't think you are flying to another place as part of the game.

P#139421 2023-12-30 18:35


Did you know that the ATOMI hadrware actually has 32 colors support ? No game ever used it to my knowledge.
I found an alpha dev tape in my imaginary attic containing a debug version where the black tiles are replaced by a darker version of the tiles that use the secret 16 colors. This feature was likely cut later because it made the game too easy and removing it also allowed the addition of an extra room in the game.(row zero column one) that was needed.

Cart #rujihisaju-0 | 2024-01-03 | Code ▽ | Embed ▽ | No License

P#139583 2024-01-03 17:05 ( Edited 2024-01-03 17:11)

More seriously, in theory, wide pixels allow for pixel level use of all 32 colours, but the native functions (spr,sspr, map, print, line, and the like) are not compatible with it.
There is also no 32 colors wide pixels editor...
If you think you want to use 32 colours wide pixels for your next Xmas game, I'm willing to build the tools in the next 6 month :
a set of functions to handle 32 colours sprites like normal Wspr, Wmap, Wline... And a sprite editor.
Because Pixels take 5 bits instead of 4, the sprite map would be organized by rows of 16 :
12 sprites whose indexes would be used normally by the W functions, then 3 reserved unusable sprites containing the 5th bits of the 12 sprites, and finally a single 4bit sprite.
instead of 256 4bit sprites, you'd have 16x12=192 5bits sprites and 16 4 bits sprites.
Because of the lines of 16 organization, the usual map/sprite tradeoffs would still be possible.

P#139585 2024-01-03 17:49

Haha amazing @RealShadowCaster ! :D

P#139586 2024-01-03 18:12

@RealShadowCaster Interesting... so you can draw with 32 colors in the SAME SPRITE?

Also I am JAMMED for sprite space, but could get some back theoretically by doing a custom font instead, though that eliminates the Ultima-like "words in the map".... hmm...

Would be interesting -- maybe that is the ATOMI 2600+'s advanced rendering mode...

I can have my art bud do some sprites with all the colors he wants to compare/contrast....

P#139587 2024-01-03 18:17

32 colors in the same sprite... I think a picture is worth 1000 words.

On the left you have the video memory displayed once back to standard resolution and 16 colors default palette.
The left half of the screen contains the data for the 4 lower bits of the wide pixels, and the right half encodes a single bit per pixel, the bit is 0 if the pixel nibble is 0, and 1 otherwise.
The four bits from the left side define a palette index between 0 and 15.
The bit from the right side defines what palette to use : palette 1 if the bit is 0 and palette 2 if bit is 1.
By default palettes 1 and 2 are 0123456789ABCDEF, witch is why that video mode stayed unknown for so long.
I have no idea how it was even discovered.
You can do a lot of things with this, and by setting the palette 2 with all the secret colors,

for i=0,15 do pal(i,i+128,2) end

You can set every wide pixel to any of the 32 colors.

But to do this with the standard library, you have to change two square pixels,one on each half of the screen, for each corresponding wide pixel.
What I was proposing was to write a family of functions to re-implement the standard library in a 32 wide pixels context.
For example, the logical 32 colors sprite 0 would have the first four bits of its pixel data in the real sprite zero, and the fifth bit in a part of sprite 12. When calling WSpr, Spr would be called with sprite 0 on the left half of the screen (with some clip to protect the right half) and then Spr would be called again with sprite 12 on the right half. To only write the data of sprite 12 relevant to logical 32colors sprite 0, some palette and/or bitplanes shenanigans would be needed.
But assuming all of that is implemented, then yes, logical sprite 0 would be an 8x8 wide pixels sprite of arbitrary pixels, all 32 colors in the same logical sprite if you wished.
I think the hardest part of the implementation will be transparency. Wpalt and it's impact on all the rest of the library will probably be tricky.

Regarding shortage of sprites, there's a lot you can do :
You can activate the hidden memory with a poke and then move sprite data in and out of the sprite sheet.
Each line of 16 sprites is in a contiguous memory segment, so can be copied around with a single memcpy statement.
You can group sprites in categories, for example every sprite needed for the intro can be moved out to make room for the in game sprites once the game starts...
Even the in-game sprites can have area specific subsets that you can shuffle around.
That unfortunately doesn't work nicely with the sprite/map editor. (Lots of cart shuffling).

P#139595 2024-01-03 23:10

Ah I see, @RealShadowCaster (from your image which shows real shadow casting).

Yeah, might be a mess for palt stuff, but could adjust to that pretty easily. But this takes over the whole drawing mode? So sprite fonts would have to move out/be done differently?

Still, that would be a great upgrade for the next chonky game I make. I was also considering a Santa platformer with an XOR sprites. This could have lots more room for sprites, heh:

It obeys the one color per scanline sprite rule of old games.

P#139597 2024-01-03 23:44

I didn't understand your question about drawing mode/sprite fonts.

About XOR sprites, I find it funny that you're adding XOR sprites artifacts to your game, when hiding them has been the goal of the developers of the 80s that didn't have nearly enough CPU for a full screen redraw per frame.
For example, on the amstrad, the technique was perfectly used in ghosts n goblins :

This is mode 0, so 16 color palette with wide pixels, and big (for the machine) sprites with transparency, but in reality it's just XOR sprites :
every moving sprite uses white, blue and orange, and the background uses black and three other colors that depend on the level, for a total of only 7 onscreen colors.
by using cleverly placed duplicate entries in the palette, each pixel contains the info of the foreground sprite (2 bits) and of the background (2 bits) but only shows the foreground color if it's not transparent.
By reducing the 16 colors to 3 foreground and 4 background, you get sprites with transparency and no artifacts, with a single routine for sprite display and removal that just XORs sprite data with the background...

You could use a similar trick with palette duplicates to reduce the artefacts... But that kind of defeats the purpose of adding them in the first place I guess...

P#139599 2024-01-04 02:04

Yeah, I played a number of games that did that from CPU slowdown, so it is funny to simulate it, heh.

I meant, does your PAL(x,2) change thw draw mode for the draw frame, or just for the current SPR right after?

P#139603 2024-01-04 03:38

pal(X,2) is the same as pal(X,2,0) , the color of index X now writes color 2, and X is in the range 0-15.
Wpal(X,2) would do something similar, except X is in the range -16..15
the most significant bit, or sign bit, would be the one that will be written in the right half of the screen.

P#139604 2024-01-04 04:05

Ah k then. Those would really be cool!

P#139632 2024-01-04 15:25

I’ve started playing with 32 Colors sprites, and I’m wondering what you’d like best, since you’d be my first library user :
ATM I see 3 possible organisations for the inner storing of 32 colors sprites :
The one I already proposed : logical sprites are 8x8, the last four sprites of each line are reserved.

Option 2 : each 32 Color 8x8 sprite uses two full entries : first four bits in sprite N and the 5th bit in sprite N+8.
This is a bit wasteful in sprite space but would be the fastest and the least consuming in tokens.
3rd possibility that is the most in line with standard library :
Each sprite is 8 pixels tall and four wide pixels wide.
What I really like with option three is that games with tokens and CPU to spare would only need graphics redesigns to be ported to wide pixels. (But might arguably look worse)
On the down side, you don’t get the double map size effect any more. It’s roughly as wasteful as option 2 in sprite space, except you get 256 4x8 instead of 128 8x8.

P#139744 2024-01-07 15:16

How does option 3 get the 5th bit for color? Does it just hide in other half of the sprite?

Hmm, just thinking STOLECOAL/TOOKBOOKS-wise, the first two options would allow dev in wide sprites and then could do a final color pass.

Option 3 is cool but it its own thing, and loses the easy dev version, but could provide a cool 32-color text mode? So something like Brogue would be more possible.

Option 1 seems best for making an ATOMI-puzzlevania. Slower but more sprites.

Option 2 seems best for making an arcade game like the GIF I posted. (Faster, less sprites)

Option 3 should be its own 32-color library as it night have it's own vibe? If I was converting this game, I'd wind up just drawing two sprites to get, say, Santa detail.

Is there an option 4 -- store the hi-bits in a sister cart, and at the start, load that data part of the cart and whoop it in user memory? So the main cart would be kinda similar to how it is NOW, but the sister cart would enhance the colors. (This is not really true, as the colors without the extra bit would be the wrong ones, really.)

But ACTIVE32 or whatever can be FALSE or TRUE, as to whether to need the data. So you can finish coding a game, then do a 32-color art pass, run a tool, and now it's a 32-color game?

P#139753 2024-01-07 19:13

A lovely sequel! I didn’t have an ATOMI as a kid - we could only afford that 2600 knock-off. 😉

P#139761 2024-01-07 21:14

Thanks @Trog!

Aw haha

P#139762 2024-01-07 21:16

Hey @thattomhall (hey to avoid the BBS bug)

>How does option 3 get the 5th bit for color? Does it just hide in other half of the sprite?

The left half of the sprite is the the data that is written to the left half of the screen (4bits per pixels) and the right half is written to the right half of the screen (black and white)

>Option 3 is cool but it its own thing, and loses the easy dev version, but could provide a cool 32-color text mode?

No need, Wprint can use the standard font in 32 colors with wide pixels.
For text only, I think resolution is more important so I'd rather use the 1 palette/scanline 128x128 trick instead for more the 16 colours text.If you put black in both palettes, you get black and 30 colors
but have constrains on what color can be used simultaneously on each line.
What is Brogue ?

>Is there an option 4
Interesting idea, it's true that none of the options 1,2 or 3 allow to adapt the current game to 32 colors due to lack of sprite space...
Is your pixel artist willing to redo all the tiles in 32 colors ?
If so, I'll build your version 4 instead of what I had planned so far.
As for the ACTIVE32 flag, no, you'll have to manually replace the function calls with their W counterparts.
Just to know what I'm working with, how may tokens roughly do you think you could leave to me for the W library ?
I'll probably just implement what you are using.
Could you please list what W functions you need.
Spr, pal, palt, line, print, sspr, ...

About the sprite sheets ? Do you need me to built tools or will you make them yourself ?

P#139823 2024-01-08 17:11

Whoops forgot about wprint! :D

Option 4: Well we could do it in stages. SPR first, draw some core sprites for this or say, the larger Toy Box Jam sprites enhanced.

Then move on from there? Will be pretty busy through the end of January, but...

Also, the artist could convert the current TOOKBOOKS, but might be better to do its own new graphics for a game that is not so, say, holiday-locked?

P#139828 2024-01-08 18:50 ( Edited 2024-01-08 19:01)

Loved it!
Wasn't able to find the SECRET ICELAB on my own, though...

(I guess the trick to find it would be to draw a map?)

P#139837 2024-01-08 20:22 ( Edited 2024-01-08 20:24)

@thisismypassword... Yay! Thanks!

Yeah, that can help, or just really thoroughly check each room. I could add a rough map template to this page so you sort of "know where you are". So it doesn't ruin the exploration totally....

P#139843 2024-01-08 20:48

Hey @thattomhall,
There's a crazy combination of secret functions and poke that will probably greatly help with option 4 !


To enable the extended memory

  • memcpy to copy the sprite sheet (the 4 1st bits) to the 1st 8K of extended memory

  • load to run the real game cart that contains the game logic. I have to check that the extended memory stays untouched, still WIP

  • another memcopy to move the 2nd cart's sprite sheet (that contains the black&white 5th bit of the 32 colors sprites) to the 2nd block of extended memory

  • poke(0x5f54,0x60,0X00)

This one is crazy, we are switching the mapping of the screen and the sprite sheet.

After that, we are using the former sprite sheet as the screen,
and we can switch between the 4bit sprite sheet and the 1bit sprite sheet with a single call to

Any pokes like your animated tiles will likely do weird things and will need to be rewritten.

P#139876 2024-01-09 11:19

Oh okay -- I will have to do the scrolling some other way if we use this for a Santa-themed puzzlevania-style game.

So much trickery! But seeing 32-color sprites could be kinda magical. I saw that post of the double-pixel 32-color image, but....

P#139888 2024-01-09 14:14 ( Edited 2024-01-09 14:20)

Hey @thattomhall
You can still do your pokes to scroll the tile, it's just that your pokes have to be run twice :
YOUR POXES AGAIN (to roll the 5th bits)

No need to change the poked adresses, you just need to have the correct screen (that is in fact a sprite sheet... due to previous poking) active.

P#139889 2024-01-09 14:54

Ohhh okay, makes sense. This will really make the third in the trilogy look awesome! :D

Can try to do a Remaster of the first two if I have enough room. It is rush-coded so reeeeeeeeally inefficient, heh.

P#139892 2024-01-09 15:14

5th bit is really just 2kb of data. Using an extra cart feels a bit overkill. Maybe compressed string instead ? But that would add to the size and token counts when the 2 cart solution just gives you extra data for free.

P#139899 2024-01-09 17:30

Well the final data format solution can wait, wanna test it out first. But yeah that could work....


TOKENS: 7860/8192
CHARS: 43009/65535
COMPRESSED: 11371/15616

So compressed,with more complex colors, might get worse?

P#139900 2024-01-09 17:34 ( Edited 2024-01-09 17:34)

300 tokens is not enough for a clean implementation of transparency, but I could probably do it if only colors in the -15..-1 range are allowed to be transparent
Size and compressed size shouldn’t be a problem in a 2 carts context

P#139904 2024-01-09 18:17 ( Edited 2024-01-09 18:18)

Yeah that transparency limit is fine.

Yes, of course.

Also note my code is super inefficient so a lot of space can be recovered for sure. Though the next sequel would likely add a mechanic or two, so....

P#139906 2024-01-09 18:33

First thing I am doing is just a "nicely drawn" TOOKBOOKS just to see if that looks okay. Sometimes "sorta good" can look worse.

P#139918 2024-01-09 21:03

Okay, the artist is getting SOME time to work on sprites, may be a bit of time before the full sheet.

P#140126 2024-01-14 22:17

And the "sorta good" gfx looked fine, so the artist feels they can do the cool ones up over time.

P#140127 2024-01-14 22:18

Hey @thattomhall
Cool, I'm rewriting the whole WSpr,Wmap,Wpal,Wpalt functions to take less tokens AND have full transparency support AND have an extra "color" (number 16) that is always transparent, so you can have 32 opaque colors and transparency at the same time in a 8x8 sprite.
The downsides are

  • memory, I'm using the entirety of the unlocked high memory for the W lib.
  • CPU :
    Previously a call to Wspr generated 2 calls to Spr, now it generates 6.
    Previously a call to Wmap generated 2 calls to map, now it generates 6.
  • pokes : now you have 3 sprites to modify when you want to poke a tile.

The new sprite organization is as follows :
There are 3 sprite sheets in memory : Wide sprite N uses sprite N of each sheet.
In the 1st sheet, Values between 0 and 14 indicate the color -16..-2 and 15 indicates "not in range -16..-2"
In the 2nd sheet, values between 0 and 14 indicate color -1..13 and 15 indicates "not in the range -1..13"
In the 3rd sheet, value 0-2 means color 14-16, and 15 indicates "not in the range 14-16" (out of context it sounds completely crazy)

P#140133 2024-01-15 00:00

@RealShadowCaster Haha, okay cool! The artist is starting on some sprites tonight!

Should look pretty awesome when it's done.

P#140142 2024-01-15 02:34

Hey @thattomhall, I'll soon (2-3 days) post a demo of the W lib. If your artist has a 256x256 32colors sprite map that I could use (with credits of course) that would be helpful for the demo.
One of the missing functions atm is Wcamera that I completely forgot about because you don't use camera in your game ;)
Forgetting about it is a big mistake on my part as it affects coordinate computations everywhere...
Other missing one is Wclip.
Another one that breaks a lot is print, when things like scrolling or P8SCII are involved. I'd also love to support things like '\fj' to have access to all 32 color changes inside a single print statement for example... But I suspect I'll drop support as it involves complex parsing and lots of token usage... Just use the color parameter of Wprint for monochrome print, I guess...

P#140488 2024-01-23 14:18

@RealShadowCaster Okay will ask him, he is kinda getting slammed at work. So double the size in both dirs of the sprite sheet?

He may be able to squeak out a run cycle and bricks to scroll, or the sprites used in one screen of WHO TOOK THE BOOKS... but otherwise may have to wait a bit... but def want to get you cool art.

P#140489 2024-01-23 14:27

A sprite sheet will internally use all 10K of sprites and map data of a cart. So the logical data is 128x128 wide pixels. This can be in a 128 lines and 256 columns png for accurate proportions, or a 128x128 for a "logical" representation. 256x256 is just what I'm using for my tests, but the format doesn't matter much, it could be a text file like in 32 colors thumbnails of .p8 files, for example...

P#140490 2024-01-23 14:48

Okay, so if he just 32-colored the TOOKBOOKS sprites in place, you can munge it the way you need the data... yeah?

P#140492 2024-01-23 15:07

Yup, I can tweak data but can't create even half decent pixel art. Since the whole point of using the W lib is to get a new display mode without learning a completely new API, having a decent looking sprite sheet as demo is a needed selling point, otherwise it's just a needless sacrifice of tokens, memory, screen resolution, CPU and user-friendliness.

P#140494 2024-01-23 16:25

[Please log in to post a comment]