The Z-Machine Standard 1.2 (draft)

If the 1.2 spec isn’t the appropriate place to revise the 1.1 spec, then what is? It seems quite strange to me to propose that 1.0/1.1 be revised independently of 1.2, and that those revisions be announced through some means other than the version number.

You have a proposal for one new feature here, but labeling that as a new version of the Z-Machine Standard seems premature.

It’s one feature as well as an incrementing of the standard revision header. I honestly don’t really care what this spec is called, but having it match the revision header makes the most sense to me. Further clarifications could be made by a 1.1.1 spec, or even a 1.3 spec (whether or not that would entail incrementing the revision header again.)

How strongly do people feel the need for a further set of clarifications? It might be helpful to collect a list of issues, even if there isn’t consensus on all of them, I’d even be willing to help with this.

What I don’t want is to tie them all to my spec. I’d like to be able to introduce some function acceleration to Parchment in time for the next I7 release and would prefer the spec to be finalised by then.

Well, that header field is there to indicate which version of the Z-Machine Standard the interpreter implements, so if you increment that number, you’re making a new revision of that standard. My objection is not that this proposal is called “The Z-Machine Standard 1.2” – that’s what it should be called – but that it isn’t addressing the things that a standard revision ought to address.

(I’m also not sure what the purpose of selector $01 is, since the standard revision number is already stored in the header, and any game that uses @gestalt will have read it from there.)

It would have to be 1.3, since the header field only has room to store two parts of the version number.

Have you had any luck with pattern matching?

I think the revision header is like an API version: it describes what functionality is available. The description of that API can be updated without updating the API itself though. Similarly the 1.0 standard had a few revisions, and the 1.1 standard had clarifications for 1.0 that should be implemented by all 1.0 terps, even if they didn’t implement the 1.1 “API”. So there’s no reason another document couldn’t do the same, and if it only had clarifications it wouldn’t need to increment the revision header.

Now maybe instead of having multiple documents we should instead work on a new unified 1.0-1.1 standard. This is like the HTML5 standard, which instead of just describing the additions it makes, redescribes the entire language. Perhaps we could do the same. I could edit it if others would help with the technical minutiae.

Both options are possible, and they wouldn’t need to stop this 1.2 spec from being finalised either.

As to pattern matching, the Gnusto architecture doesn’t lend itself well to that. I’ve started rewriting Gnusto from scratch so I could add pattern matching later. Having an acceleration opcode though would be possible with the current architecture, and feasible to implement in time for the next I7 release.

I disagree: the standard revision number doesn’t only describe the set of opcodes that are available, but also the behavior of those opcodes. The game has to assume that an interpreter claiming to support 1.0 only supports 1.0 as it was first published, because there’s no way for it to know whether or not the interpreter incorporates clarifications that weren’t published until years after the original 1.0 spec.

Again, I think attempting to change the old specs retroactively is a mistake. Games can’t distinguish between “old 1.0” and “new 1.0”.

What do you suggest I do? Has consensus been reached on some issues which need specifying? Even if there has been no consensus we could still add a selector for each issue to show which reading of the standard a terp has taken, so that at least games could then detect and account for different implementations. That’s the approach I’d like to take… so if you can identify which issues need specifying I’ll add them in.

Well, from this thread we have:

  • @set_font 0
  • output streams 3 and 4 available in V3/V4
  • maximum of 7 routine arguments in V4

The first may require some more discussion – is there consensus on what @set_font 0 should do? – but the latter two are contradictions in the current specs and just need to be re-specified.

I’ve updated the spec again. I’ve added selectors which allow for those issues to be identified, but which don’t dictate which is the correct interpretation. Comments?

Any comments? I’d appreciate if someone would check I understood the spec conflict issues.

If not I’d like to finalise this now. I’ll keep updating the list of selectors as needed, so if further spec conflicts were identified it will be easy to add them in. Note that those selectors are all core selectors, so compliant implementations must support all of them. Which reminds me, I should include them in praxix…

Sorry, but I really dislike the idea of the specification just listing selectors for the outstanding issues. This is just pushing work onto game authors: you’ve got to check for all these possible cases, and do something sensible in each case. The 1.2 spec should simply state definitively what a compliant interpreter should do in each case.

If authors were having problems, if these issues needed to be definitively sort out, then they would have been by now. It’s been years. I doubt there’ll ever be problems caused by issues. Now at least those possibly existent authors could check for these problems and deal with them accordingly.

Now that Vorple is being used I think it’s time to finish this up and submit it to the archive. Any last gripes?

Agreed. For example, why is there a selector for “clarification for how many arguments are allowed in V4 for @call_vs2”? The very purpose of @call_vs2 is to support more than 3 arguments. It’s been doing that since the Infocom days, and some Inform 6 action syntax currently in development is going to rely on it. Adding a selector means granting interpreter authors a pass for getting it wrong.

(hansprestige.com/inform/zmachine_versions.html is a handy overview of the differences between Z-machine versions that notes this problem in the original spec; feel free to reference it.)

So for the V4 streams and @call_vs2 is it really only the specs that are at fault? Do all the interpreters agree?

The @set_font 0 issue seems different as different interpreters are already in disagreement on it.

Perhaps it would be a good idea to wait until the pending Inform6 things are worked out.

What pending things?

Without being able to speak for all interpreters, I can confidently say that these are both errors in the specification.

There are V3 Infocom games which make use of stream 4 and V4 games which make use of stream 3 (easily checked by looking at a disassembly). This is something that 1.0 got right but 1.1 incorrectly “corrected”.

The fact that @call_vs2 is used with more than three arguments can be verified by disassembly as well: Nord and Bert (at 0xe346, for example) calls a routine and passes 7 arguments.

I don’t have every published Infocom story, so I can only speak for those I have, but in disassembling them I see calls to @set_font with values of 1, 3, and 4 only. There is a lone call (in Journey) to @set_font with a variable as the first argument; the code is essentially this:

SET_FONT #04 -> L02
SET_FONT L02 -> -(SP)

So it will call @set_font with the result of a previous @set_font call. According to the standard,

If this quote is right, then L02 would never be 0, so @set_font 0 would never happen.

As such, I think we simply need to choose a behavior for @set_font 0. Unless there are story files which make use of it (and/or Inform can produce it), then we can have it do anything. Since nothing would be affected, it would hardly matter what the consensus is, so long as there is one. I’d be in favor of @set_font 0 being a no-op, since it’d simplify code that is never used anyway, but I don’t really care one way or the other.

As I was bringing the Inform6 library up to speed, I came across some additions to the Inform6 compiler that seem to do things legally, but a bit different from how the specs seemed to say.

Now putting on my Frotz hat, David Kinder and I need to get together and have a discussion about the Frotz core and how the 1.2 spec will affect it.

I’m strongly considering writing a combined spec now, which is what vaporware has been after I think. So we can fix anything there, as long we don’t break anything.

What things?

What is the status of the “Standard 1.1” spec, while I’m asking? Did that get universally adopted?