Has Parchment left Infocom behind? EDIT: No

I should clarify that these ‘repeated statusline’ bugs are not literally repeated statuslines, they are about six or seven inverse blocks repeated every other line down the page, starting on the statusline, and they seem to correspond in position to a blank part of the statusline, so I interpreted that as an errant status line blanking algorithm. But it just occurred to me that it could be one of those opening quotation blocks gone badly wrong. I don’t particularly remember there being an opening quotation block Planetfall or Sherlock. Or it could just be something unrelated to either function I suppose.

I did not expect you to take this up at all, so it’s all gravy at this point. Take your time. And thanks!

Paul.

The status line remnants bug is an old one that I thought had been fixed, but maybe Infocom is causing it for different reasons than Inform. Can you please email me the file?

Check your PMs.

It’s hitting an infinite loop when you try to enter a command. I can’t tell what’s wrong with it though.

Why is it printing this to the status line? And why doesn’t it show up on any other interpreter?

\r          \r          \r          \r          \r          \r          \r          \r          

Ooohh… It’s using @print_table. Perhaps my implementation of it is incorrect. Could anyone take a look at it: github.com/curiousdannii/ifvms. … me.js#L405
Perhaps the newline should only be printed between lines if there are actually multiple lines?

[edit] Fixed that bug. I still don’t know what’s the cause of the infinite loop.

Glad that one got fixed at least, thanks. I wonder why it’s only the two games I have with the weird status line printing that also experienced the infinite loop. I had kind of assumed the bugs were related in some way. Wish I could help with the code.

What’s the other game? The common factor is probably that they’re not written in Inform. Zilch and Inform use the Z-Machine in different ways. The statusline bug was because it used @print_table, which I don’t think Inform ever does. Perhaps the infinite loop is caused by another buggy opcode that hasn’t been noticed because Inform doesn’t use it.

The other game is Sherlock.z5 — the behaviour of it when launched in latest Parchment is exactly identical to that of Planetfall.z5.

Even more curious: Sherlock is trying to use a non-existent opcode! Probably this means something else is buggy and it’s branching to the wrong place.

A question for Z-Machine experts: should @read lowercase the buffer in versions 5/8? ZVM currently does, but I just noticed that the spec looks like that’s only for <5.

Yes, 5/8 does that too.

Thanks Zarf!

I still can’t find the cause of the bugs yet. The opcodes involved in Planetfall’s infinite loop all look okay, but maybe the bug is before the loop starts. Sherlock is trying to call address 0 which is obviously wrong. There are about 5 indirect calls in the segment though which makes it a bit trickier.

I’m posting this in case anyone has any ideas. I’m stumped.

Here is the generated code involved in Planetfall’s infinite loop. I’ve included the opcode names.

[code]function JIT_79829(e) {
var l = e.l, m = e.m, s = e.s;
/* 79829/5/@inc_chk / if (e.U2S(e.incdec(1, 1)) > 7) { e.pc = 79841; return };
/
79833/225/@storew / m.setUint16(e.S2U((m[1052] << 8 | m[1052 + 1]) + 2 * ((l[0]) << 16 >> 16)), 0);
/
79838/140/@jump */ e.pc = -10 + 79839
}

function JIT_79841(e) {
var l = e.l, m = e.m, s = e.s;
/* 79841/13/@store / l[0] = 0;
/
79844/5/inc_chk / if (e.U2S(e.incdec(1, 1)) > 7) { e.ret(1); return };
/
79848/231/@random / l[1] = e.random(7);
/
79852/15/@loadw / l[3] = m.getUint16(e.S2U((m[1052] << 8 | m[1052 + 1]) + 2 * 1));
/
79856/15/@loadw / l[2] = m.getUint16(e.S2U((m[1052] << 8 | m[1052 + 1]) + 2 * 2));
/
79860/15/@loadw / s.push( m.getUint16(e.S2U((m[1052] << 8 | m[1052 + 1]) + 2 * 3)));
/
79864/1/@je / if (e.jeq(l[1], l[3], l[2], s.pop())) { e.pc = 79898; return };
/
79871/15/@loadw / l[3] = m.getUint16(e.S2U((m[1052] << 8 | m[1052 + 1]) + 2 * 4));
/
79875/15/@loadw / l[2] = m.getUint16(e.S2U((m[1052] << 8 | m[1052 + 1]) + 2 * 5));
/
79879/15/@loadw / s.push( m.getUint16(e.S2U((m[1052] << 8 | m[1052 + 1]) + 2 * 6)));
/
79883/1/@je / if (e.jeq(l[1], l[3], l[2], s.pop())) { e.pc = 79898; return };
/
79890/15/@loadw / s.push( m.getUint16(e.S2U((m[1052] << 8 | m[1052 + 1]) + 2 * 7)));
/
79894/1/@je / if (!(l[1] === s.pop())) { e.pc = 79903; return };
/
79898/134/@dec / e.l[0] = ((e.l[0] + -1) & 65535);
/
79900/140/@jump */ e.pc = -57 + 79901
}

function JIT_79903(e) {
var l = e.l, m = e.m, s = e.s;
/* 79903/225/storew / m.setUint16(e.S2U((m[1052] << 8 | m[1052 + 1]) + 2 * ((l[0]) << 16 >> 16)), l[1]);
/
79908/140/@jump */ e.pc = -65 + 79909
}[/code]

I believe that 79829 is the beginning of a routine.
The main loop is from 79844 to 79900, though sometimes it goes on to 79903 but then back to 79844.
@inc_chk is incrementing the local #0, which is then @dec’d later on. That seems suspicious, but if it was the problem then surely the disassembler would be disassembling lots of other wrong opcodes for other programs?

When I get a chance I will try to see if Frotz ever executes that code when running Planetfall. What path does Parchment take through the opcodes you posted (i.e. what are the PC values in the infinite loop)?

Thanks David. There would be a routine call to 79828. The main loop would be like this: 79844->79898->79844 or 79844->79903->79844. (Those are the addresses where branches/jumps end up. The individual addresses are listed above.) The only exit is at 79844 when @inc_chk can return from the routine, but it never does.

The opcodes looks right: txd diassembles the relevant code as

[code]Routine r0453, 4 locals

l0001: inc_chk local0 #07 l0002
storew gab local0 #00
jump l0001
l0002: store local0 #00
l0003: inc_chk local0 #07 rtrue
random #07 -> local1
loadw gab #01 -> local3
loadw gab #02 -> local2
loadw gab #03 -> sp
je local1 local3 local2 sp l0004
loadw gab #04 -> local3
loadw gab #05 -> local2
loadw gab #06 -> sp
je local1 local3 local2 sp l0004
loadw gab #07 -> sp
je local1 sp ~l0005
l0004: dec local0
jump l0003
l0005: storew gab local0 local1
jump l0003
[/code]
That code is pretty hard to fathom. One thing that leaps out at me is the use of “random” - here it should produce random numbers between 1 and 7. One thing to check is that Parchment really is doing that, possibly the code is relying on random eventually producing a specific value that will cause the loop to exit.

(I should really run this through Frotz, but haven’t the time right now.)

txd is great, I should’ve thought to use that to check my disassembler was accurate. Thanks! I’ll check that @random is behaving as it should too.

Haha oh dear. So @random was giving answers in the correct range, but only odd numbers. Planetfall is working now. Two bugs down, one(?) to go!

Awesome news.

Hmm, so I think the last bug is actually the one mentioned in the standard: “Infocom’s ‘Sherlock’ contains a bug making it try to set and clear attribute 48.”

Any advice on what to do? I’ll take a look at Frotz and Bocfel to see what they do…

[edit] Actually that’s not the problem, I got the same bug in Planetfall too. Though advice on what to do about the attribute bug would still be good.

Is there a list of opcodes which Inform doesn’t use? That would help focus my search…

Frotz detects Sherlock by looking at the serial and release numbers. For Sherlock only, @set_attr and @clear_attr for attribute 48 just silently return without doing anything.

I’m not clear from the above what your last remaining bug actually is …