-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document the differences between GlkAPI and the C API #13
Comments
The C API and the JS API are not arg-for-arg identical. Where the C API has an array and length, it is generally translated into a JS array with the length already set. In this case, buf should be a JS array of length maxlen. If initlen is nonzero, the first initlen entries should be set to the character codes of the preloaded string. On return, buf will contain the line input. (It will still have length maxlen; the number of characters actually there is returned in the event structure.) |
Hmm, I don't think I like that. If anyone was to make new a JS implementation of Glk they would probably more closely follow the spec (I would). At the very least these changes should be more clearly documented. Can buf be an array of undefineds? Can it be a typed array (probably a Uint32Array)? The current result is very strange: the text box is limited to 1 character, but it stays active when you press enter, and more presses of enter result in multiple console logs saying "Input event had wrong generation number: got 1, currently at 2". But maybe they will be fixed when I call it correctly. |
When I set this up, typed arrays weren't universally available. I've never gotten around to converting to them. However, I think everything will work fine if you use them. The contents of the buffer on entry don't matter if initlen is zero. You could copy the Z-machine memory array in anyway. (That would cover the cases of initlen being zero or nonzero.) The text box entry limit should be buf.length. Getting the generation number correct is important, but not specific to this call. It works the same for any kind of input event. |
Thanks for the explanations. Good point about copying the Z-Machine memory array in case initlen is nonzero - that will probably be simpler (though I will need to convert ZSCII to unicode first...) The generation number was fixed when I started calling glk_select before glk.update() |
If you use glk_request_line_event, all array values (in and out) should be 0..255. If you use glk_request_line_event_uni, they may be any Unicode code value. Not sure which you want to go with. |
Hi @erkyrath, how are we to use glk_fileref_create_by_prompt()? It looks like it sends control out through GlkOte, and then gli_fileref_create_by_prompt_callback() will call VM.resume() again. How is our resume function to distinguish between calls from glk_select and glk_fileref_create_by_prompt? And once control is passed to resume(), how do we access the fref object? |
For glk_fileref_create_by_prompt, the update goes out with a |
Are you suggesting that I try to handle the event manually before gli_fileref_create_by_prompt_callback runs? Currently I've just been using glkapi.js. gli_fileref_create_by_prompt_callback creates the fref and passes it to GiDispa.prepare_resume() but not to VM.resume(). In order to use glk_fileref_create_by_prompt do I really need to start using GiDispa too? [Edit] Okay, from looking at GiDispa, for prepare_resume() to work I would need to set blocked_selector, but neither it or set_blocked_selector are exposed. But even if I got that working, prepare_resume would only return an id to the VM, not the object which glk_stream_open_file etc need. Unless I've missed something I can't see any way to get this working as is, glk_fileref_create_by_prompt is just not designed to work outside a dispatch system. To get this to work glk_fileref_create_by_prompt would need to be extended and be passed a RefStruct like glk_select (or an additional function should be created, perhaps named glk_fileref_create_by_prompt_boxed. Or gli_fileref_create_by_prompt_boxed if gli indicates that it is outside the glk api). gli_fileref_create_by_prompt_callback will need to be extended to set the RefStruct details. Would you consider a pull request doing this? |
So the solution I worked out ended up being much simpler: if glk_select() is called after glk_fileref_create_by_prompt() then gli_fileref_create_by_prompt_callback() will return fref via the RefStruct. I added a fake event so the whole system can go through my normal resume(). I haven't made a pull request, but I can if you like. |
I have not had a chance to look over this in detail. The brief answer is "the entire glkapi library was meant to be used with the dispatch layer". I envisioned other VMs using glkote alone. (This is how I set up inkjs, for example.) But I see that glkapi does some things that are generally useful. (Accumulating window content data is the biggie.) So I will look at that use case in when I tackle updating the remglk/glkote pair, per erkyrath/remglk#6 . However, arrays will still be handled as single arguments. :) That follows from the way array arguments are handled in the dispatch layer. The dispatch layer also fixes the argument representation for fileref_create_by_prompt. The general solution has to cope with that. |
Yeah straight Glkote would probably work really well for many applications. I thought I'd try glkapi because it's an API I already know, and it just matches the Z-Machine so closely (by design of course). But even thought it may not have been planned to be used in this way, it still worked really well. It's very well implemented! I'll be keeping watch over this repository, and I'm happy to adjust ZVM to any changes you make. |
I've started documenting these at https://github.com/erkyrath/glkote/wiki/Differences-between-GlkApi-and-the-C-Glk-API If I find any more I'll just add them there rather than posting here, unless I can't figure out how to get them to work. |
glk_stream_open_file() throws an error if in read mode and the file doesn't exist, whereas the spec says: "If the filemode requires the file to exist, but the file does not exist, glk_stream_open_file() returns NULL." Is this intentional (in which case I'll add it to the wiki page) or should it be considered a bug? |
That's a good question. My C libraries treat this as an error, or a "strict warning" (which in practice is an error although it doesn't kill the game). So by the spec all the implementations are wrong. But they've all been wrong since day one, and no game which relied on the spec has ever worked. So the sensible course is to say that it's a mistake in the spec. |
Ah. When we ran into this problem with Counterfeit Monkey you said it was safe, so I've just kept on doing it. It's very easy to work around so not a problem. Edit: But even the Inform 7 template function RESTORE_THE_GAME_R doesn't check for existence before trying to open the stream... |
I think this can be closed now. If I find anything else I'll add it to the wiki page. |
The spec says
But glkapi.js has
(glk_request_line_event_uni is also missing maxlen.)
Where is maxlen? How are we meant to call it?
This is how I'm currently trying: https://github.com/curiousdannii/ifvms.js/blob/e8fd78e377/src/zvm/io.js#L314
The text was updated successfully, but these errors were encountered: