Ozmoo - A Z-machine interpreter for the Commodore 64

I’ll do it. I don’t familiar with the 64’s keyboard, especially the typing sequence of the special characters. I’ll look at what’s been done for the other languages.

There are some different ways to go here.

For Swedish, we have used the same Swedish keyboard layout that a lot of C64s were sold with back in the day. I think the company importing them made the modification.

For Italian, we have placed accented characters so that you get them by pressing the Commodore key and the base character. So Commodore-e types an é. And you get the capital version by hitting the Commodore key and the key just below the character on the keyboard.

Unless there was a common French keyboard produced for the C64, with accented characters, I would recommend we do something like what we did for Italian.

Yes, it’s easy for the user if you only have one accent per letter. But for a single “e”, we have four: “é è ê ë”. If they are not displayed on the keyboard, how will the user memorize the position of the keys? Anyway, I’ll see what I can do.
Can you give me all the possible combinations for a single keyboard key? e.g. for the e.
e
shift-e => E
Commodore-e = >
And other? (control-e?)

(I realize that we could move this discussion to a private channel, but maybe there’s someone here who cares and has something wise to say about it.)

I think we should be able to use CTRL-e as well, but this maps to PETSCII code 5, which is not a printable character (none of the CTRL-combinations are). This means we can map it to the accented character of our choice, but that character will have to be placed elsewhere in the PETSCII table and thus will also be accessible through some other key combination. So we could put è on CTRL-e but it would also be on say Commodore-M or some other combination.

Do French C64s have AZERTY keyboards?
– Update: Have received several replies from French C64 users saying French C64s had the same keyboard as US C64s.

I’ll do it again for a QWERTY keyboard.
As there are many accented characters in upper case, I could also, instead of displaying them, display a single “Caps Lock On” character, to inform the user that he is in upper case mode: CapsLockOn, and that it doesn’t work for accented upper case letters !?

Ozmoo Release 3 is now out: Ozmoo Release 3

(Support for French has been implemented, among other things)

1 Like

I have GOT to figure out how to get some room to set up my childhood C64…

2 Likes

Thank you for the French translation, it will please some people.
I didn’t have a C64 as a child, but I only remember that it had a reputation for being difficult to program.

Thanks for the help in sorting out the details for characters and keyboard for the French version!

Would be great to hear if you hear of anyone distributing French games with Ozmoo.

Hi, thanks a lot for the great work!

I’m trying to convert Lost Pig to a c64. The online tool ozmoo online spits out an error message (see below). The error message appears regardless of Build Mode.

I don’t really know enough to make much sense of it. Is there a way to get Lost Pig running?

Thanks & Best, Conrad

Reading file lostpig.z8…
Dynmem blocks: 88
$zmachine_memory_size = 317552
$story_size = 317952
acme/acme --setpc 2049 -DCACHE_PAGES=4 -DSTACK_PAGES=4 -DZ8=1 -DCONF_TRK=1 --cpu 6510 --format cbm -DBGCOL=2 -DFGCOL=9 -DBORDERCOL=0 -DBGCOLDM=2 -DFGCOLDM=4 -DBORDERCOLDM=0 -DSMALLBLOCK=1 -DVMEM=1 -DALLRAM=1 -l “ozmoo/temp/acme_labels.txt” --outfile “ozmoo/temp/ozmoo” ozmoo.asm
Interpreter size: 11242 bytes.
ERROR: Dynamic memory is too big (45056 bytes), would pass $D000. Maximum dynmem size is 37888 bytes.

“Lost Pig” uses too much dynamic memory to fit into a C64.

Simple answer: The game is too big.

A story file has two parts - dynamic memory and static memory. Ozmoo will always keep the entire contents of dynamic memory in RAM. For reasons of speed and not making save/restore overly complicated, we decided not to let dynamic memory extend past the address $D000. This means dynamic memory can’t be larger than ~35 KB. This isn’t a very serious limitation, since a typical game which uses more dynamic memory than that will be so slow on a C64 that it won’t be enjoyable anyway.

So, what would happen if we redesigned Ozmoo and removed this limitation? Whatever RAM is left after loading dynamic memory is used for loading as much of static memory as possible, swapping in new parts as they are needed. In the case of Lost Pig, this would mean 5 KB of RAM is used to keep the most recently used parts of the ~260 KB of static memory in that story file. In an Inform 6 game, so much code is needed each turn, that the game would be constantly swapping and would be terribly sluggish.

You can play the game on Zeugma. Zeugma requires an REU, and save/restore isn’t supported, but it can handle any story file and it’s faster than Ozmoo - requiring an REU means the terp can use a lot more memory, which allows for all sorts of optimizations for speed.

1 Like

Thanks for the quick and detailed reply! In lieu of a physical machine, I’ll try and get it to run on VICE.

Obviously the difference between how much dynmem the game is using and the ceiling is pretty far in this situation, but in cases like this where the author is around with access to their source (presumably), is there any general “here’s how you reduce dynmem usage in your I6 code” advice you can provide?

2 Likes

I haven’t done serious optimization work in a while, but I’d imagine the main thing is moving your tables into static memory. Inform 6 puts all tables and arrays into dynamic memory, and has no way to change that.

So if you want to move your constant data tables into ROM, the main way to do that in I6 is to turn each array into a routine with a big switch statement, that takes an index parameter and returns the relevent entry. Routines are always stored in “high memory” (the part of ROM that (usually) can’t be addressed directly), so this can help with both dynamic memory limitations and address-space limitations.

(Alternately, modifying I6 to let you store arrays in static memory. Which is a pretty significant change for a fairly niche benefit, since the main limitation nowadays is usually addressable space, not dynamic memory. But if there’s a lot of demand for I6 games on the C64, and someone who knows the I6 compiler better than me were willing to put in the time, it could be worth it.)

1 Like

I filed http://inform7.com/mantis/view.php?id=1354 years and years ago, just to have somewhere to collect my thoughts on the issue. As you say, the benefit is niche.

2 Likes

The question of how to work around the hard limitation of 64 KB dynmem for Z-code story files was the subject of some debate many years ago, when a z9 format was discussed on the Z-machine mailing list. Unfortunately, there was no proposal which wouldn’t also necessitate Inform code to be written quite differently for z9 compared to z5 and z8, making large changes to the library necessary, making many library extensions useless and break code for games which someone started to make for z5 or z8 and then found that it got too big and needed z9.

Anyway, if you want a large game to run smoothly on a machine with 64 KB of RAM in total, you will need to have the target platform in mind when writing the game. Not only do you want to keep dynamic memory usage low, you also want to make sure there is not so much code that is run every turn or almost every turn. Much of the parser is code that is run every turn, and so you need a library that is a lot more compact and preferably more performance-oriented than the regular Inform 6 library.

Also you need to mind what kind of content you’re trying to squeeze into the game. If you want long descriptions of locations and items, and have the items respond in clever ways to many actions, that’s probably fine - it doesn’t use much dynamic memory, and the code is only needed when you interact with that object. If you have an extensive before-routine for a statue in the garden, that code can be paged out once you enter the house or leave the garden in some other way, to make room for other code. However, if you have ten NPCs which all have their own clever routines to try to accomplish goals of their own, seek out their own paths through the map etc, that will probably bog down the machine.

If you have a look at Infocom’s games, they always designed their games in a way that made the game fast enough on the target machine. If a puzzle turned out too big or needed too much CPU, it had to be reworked or scrapped.

Cloak of Darkness currently compiles to a z5 file weighing in at 50 KB using I6 lib 6/12. The very same game can be built as a z3 file with Metrocenter’84 (not yet released) and take up 21 KB, or PunyInform (not yet ready for production use) and take up 17.5 KB. I think these libraries will be the way to go for anyone who is serious about writing I6 games for 8-bit platforms.

Or to put it another way - there’s no reason to act surpised that a game that was developed and tested on a machine with a 3 GHz CPU and 8 GB of RAM turns out to be slow on a machine with a 0.001 GHz CPU and 0.00006 GB of RAM.

3 Likes

(may it please the court, it was meant as a friendly question)

1 Like

I never doubted it was a friendly question. I just saw this as a good opportunity to share what I’ve learnt about making Z-code games run on 8-bit computers. There seems to be an increasing interest in this now, and I’m glad to see and help promote that surge in interest.

2 Likes

I’ve been looking at what would be required for I6 to support static memory arrays. It’s doable, but it’s not a trivial hack.

My experiment doesn’t fully work yet, but it’s getting closer. I’ll post against when I have something demostratable.

4 Likes