Anybody here with Apple ][ experience?

Almost — there are three failures related to pull (sp—).

Although I just ran Czech through my home-grown emulator and it failed early because jumps don’t work, so I should probably start with that.

Thank you for reminding me about Czech. I figured I had SBC implemented incorrectly in my old 6502 emulator and some internet research said SBC is really just ADC ~value, so I tried that, and lo and behold, it worked.

I’m not sure if decimal mode is correct but I’m not using that.

Thanks again Fredrik!

-Dave

2 Likes

Good call; that way it can also run on a Ricoh 2A07, for people who don’t have a real 6502.

1 Like

Clearly I need to port this to the original NES once I’m done debugging it. Wonder what mapper would give me enough dynamic RAM to be usable (well, and enough ROM to store the story).

-Dave

1 Like

Hey guess what, LSR doesn’t force the carry flag to be cleared. At all.

In fact, the LSB of the result sets the carry flag.

Because of this, any properties larger than 15 would measure one byte longer than they really were. Derp.

2 Likes

Wow… just played through it again from memory, everything… worked. Damn. Saved the world, even.

Guess I get to try the other stories now!

Well, Zork I seems to work. Got the leaflet and made it up the tree so far at least.

Escape from the Troll’s Cave worked too!

So did Babysitter!

It’s late, I’ll try Calypso in the morning. I suspect I’m also ready to try any z3 story larger than 44k now. I should be able to handle anything up 88k with the code as it stands now, and another 8k past that without too much fuss. Beyond that though I’ll need to implement proper virtual memory — the interpreter is in the upper 12k of main memory so I can’t easily get to memory in aux upper memory.

-Dave

3 Likes

Retro hobbyists absolutely do still use real media, though a lot of day-to-day stuff is from things that work off SD cards and USB drives. I have a The C64 sitting on my desk, with a USB drive stuck into it, and a real C128 from back in the day on the other desk, with both a SD2IEC SD card reader and a real Commodore 1571 drive with real disks.

The growth of retrocomputing has finally burned through most of the leftover supply of disks, so some publishers now only offer cartridges or tapes for their physical media releases, since a whole product’s worth of diskettes in good condition is a harder thing to source now.

3 Likes

I wonder if the retro market will eventually grow strong enough for someone to start producing disks again (in far smaller quantities than before)? It’s one of those things where (I imagine) you really need economies of scale for it to work, but after that point they must cost pennies to make.

1 Like

A while ago I wrote a 6502 core of my own, and I found GitHub - Klaus2m5/6502_65C02_functional_tests: Tests for all valid opcodes of the 6502 and 65C02 processor · GitHub to be an excellent and exhaustive test of available opcodes. There’s even exhaustive tests for all the weird corner-cases of decimal arithmetic, including decimal operations on non-decimal numbers, if you want to be excruciatingly thorough.

2 Likes

I guess the hard part is identifying the lowest common denominator. Is there a 5.25" floppy format that will work on an Apple 2, C64, Atari 400/800, BBC Whatever, etc? (ie will accept formatting from any of those drives)

-Dave

Darn, I just disassembled the 1998 version of Anchorhead and static memory starts at 0xA00D. Wait-- that’s 40k, I’m safe (I support up to 44k of dynamic memory).

As it stands, I currently require both dynamic and static memory to end before 44k. But the only things that use static memory are:

  • Tokenization (dictionary parsing)
  • @loadb/@loadw

Am I forgetting anything? Practically speaking, I probably don’t want to page static memory or parsing (dictionary lookup) might cause a LOT of page misses though, right?

For Anchorhead: Just noticed that of the roughly 2200 words in the dictionary, 1958 of them have zero’s in the last two bytes of the dictionary word. And all of them have a zero in the last byte of the dictionary word. So that could have freed up some static memory.

-Dave

I did some (simplistic) analysis awhile back; about 97% of Inform 6 games on IFArchive have <44 KB of dynamic memory, and 89% have <44 KB of static memory. Unfortunately a number of great classics (like Anchorhead) exceed one or both of these, mainly the static memory limit.

Zym II pages all memory above >48 KB. In practice lexing seems to work fine; it’s slower, but only needs to be run a few times per turn, so isn’t the main bottleneck. The bigger issue is that Inform 6 tends to compile the globals table at the end of dynamic memory, so paging to access globals can waste a huge amount of time. Zym solves this by copying globals to an offline buffer, which is non-Standard in theory but seems to work fine in practice.

Bank-switching is cheap on Apple II, though, so a better solution would probably store the upper 20 KB in aux memory and use direct banked access for @loadb/@loadw and lexing. These operations could bypass the usual paging system entirely.

1 Like

I do the same thing - shadow globals inside my interpreter code alongside the Z machine stack, and it’s worked fine for everything I’ve tried.

I guess I have two options:

  1. Limit dynamic memory to 44k (as it is now) but static can go up to 64k, and uses 20k of the 44k of aux memory available
  2. Limit dynamic memory to 44k, and static memory is paged like everything else. The 44k of aux memory is used for paging (and is always read-only)

No matter what I do, I’ll have to deal with the possibility of the dictionary straddling the 44k dynamic memory boundary. What I could do I suppose is make multiple versions of the interpreter (similar to how Ozmoo does it, I think) that are tailored for different story setups. Certainly the case where dynamic and static memory is below 44k will be fastest.

So, in increasing order of complexity and “slowness”

  • Entire game fits in 44k. No paging code or banking code necessary.
  • Entire dynamic+static fits in 44k, entire game fits in 88k. That’s where I’m at now; only routines are currently banked.
  • Entire dynamic+static fits in 44k, entire game larger than 88k; aux memory (and any leftover in the original 44k) is used as VM backing store
  • Entire dynamic fits in 44k. All remaining memory is used as VM backing store for both static memory and routines.

Only the last one is likely to be useful for any V5/V8 games.

(Just checked, Anchorhead has static memory starting at 0xA00D, which is below my 0xB000 hard limit, and Muldoon starts at 0xAEC2, which is also – barely – below the hard limit. I’m guessing the saving grace here is that any big game has a big dictionary, and that’s going limit how big dynamic memory can get. Are there any Z8 stories “bigger” than those?)

(I think to keep things simple, I’ll load the first 44k of the story in main RAM, full stop, and then if the rest of the story is larger than 88k, I’ll use the entire 44k of aux memory as VM backing store. The debug version of my interpreter is larger than 8k now, although the “retail” version is about 512 bytes short of 8k, so the A/B banks of language card memory aren’t available to me then)

Inform6 don’t use the last byte on each entry in the dictionary. Older versions keept the size so it is the same as Infocom’s. Newer versions of the compiler can drop this byte and save a couple of kb (depending on size of dictionary). Second to last byte is the verb number, if I remember correctly.

1 Like

New question - if I want games larger than 140k to be playable on real hardware, what does that look like?

V5 games are capped at 256k, so the game could ship on two disks (or, practically two virtual disks).

If I wanted to support V8 games, I’m not sure how that could be played on real hardware since I currently don’t use any ROM routines or DOS 3.3 or ProDOS.

Are there common modern storage devices that somehow emulate a bigger disk drive or something? Or simulate having more tracks on the drive, or something like that? Currently the only thing my code knows how to do is move the Disk ][ drive head and read 1-16 sectors into memory.

Thanks,

-Dave

Pretty much all larger volume solutions involve ProDOS volumes, whether real ProDOS hard drives (don’t know if I’ve ever seen one for real) or hardware simulations (e.g FloppyEmu, CFFA3000) which you connect to real hardware.

The Apple IIGS, IIc+ (and nobody has a IIc+…) can use 800kb 3.5-inch floppies. Other Apples (IIe etc.) need a card to attach such a drive. Those floppies are ProDOS formatted.

I don’t think there’s anything that can create, or be, a bigger-than-140kb 5.25-inch floppy, real or virtual.

So when you say ‘games larger than 140k to be playable on real hardware’, I don’t understand your interpreter enough to know whether using more than two 5.25 floppies or images is logistically practical. (Would you have to swap during play? Is such a thing possible? Or just once at the start? Or halfway through?)

I assume the 800kb 3.5-inch floppies and ProDOS-formatted volumes are out of the question with your Disk II code.

-Wade

1 Like

The way the Z machine works, you pretty much have to have the entire story available on secondary storage. Having to exchange disks potentially multiple times when taking a turn seems unviable.

You do bring up a good point… there’s nothing preventing me from “requiring” four floppy drives (S5/S6 D1/D2) although I doubt many people would have setups that supported that.

But otherwise… if there’s hardware out there that you can “read” arbitrary sectors from with a call into slot 4 or something (trying to have my interpreter play nice with ProDOS seems like a nonstarter) that could work too.

(I never went past DOS 3.3 in my Apple days)

-Dave

Calypso works fine too. Also got my home-grown emulator to support reading the keyboard so that I could play the entire game and get final cycle counts. (This does NOT currently include reading the story into memory from disk, my emulator infrastructure reads the story data manually).

I took the walkthrough from Ozmoo but it quits after “say cintra” because the weathervane never seems to move because my RNG is crap.

The total cycle count in 80 column mode is 123,170,253 cycles.

The total cycle count in 40 column mode is 107,376,315 cycles. If I disable banked memory entirely (the interpreter would only work on a 44k or smaller game) it dropped to 106,380,139 cycles)

The difference is pretty much down to scrolling the screen taking twice as long (which in turn tells you the overhead of scrolling is about 15 million cycles even in 40 column mode).

-Dave

1 Like

Ozmoo for C64 takes 173s to play through z3 Calypso from first prompt to last, see Calypso, a PunyInform benchmark - #10 by RobertSzacki

This is using REU for caching. Building without virtual memory is probably a bit faster.

1 Like

in a word, no.

For a starter, some FD drive’s read/write technique use MFM, other GCR, and few even FM. (the latter used in the CP/M “common denominator”, the 256Kb 8" SSSD) then there’s a staggering diversity of formats from the ~90k of the atari 8 bit to the 1Mb of the 8" DDDS.

lastly, the filesystem is very varied, some accept only 6 char+2ext filenames, other up to 32 character, and there was also fixed file types (Apple filesystem know only Integer, Applesoft, Binary and Text) &c. &c. and the directories are absent or crude (e.g. the USER in the CP/M)

Best regards from Italy,
dott. Piergiorgio.