Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[I7] Bugs with creation of Glulx sound channels

1 view
Skip to first unread message

Eliuk Blau

unread,
Oct 25, 2008, 10:01:34 AM10/25/08
to
Hello. I am Eliuk Blau. Some time ago I found a major error in I7,
related to the audio channel opens by default. I publish here the
report of Bugs that has been sent to Graham, in case anyone is
interested in learning about the mistake and would like to benefit
from the corrections.

Thank you very much to Aaron A. Reed for his great work with the
English translation of this message.

------------------------------------------------------------------------------------

Hello, this is Eliuk Blau: -) I want to report a pair of bugs of
medium importance that I have found in the present version of I7
(5U92), which date back to the first version that implemented audio
features in the system.

In testing my Damusix extension, I have found a bug related to the 2
channels of audio that Inform7 creates automatically in any Glulx
game. Be advised that this error cannot be verified in the versions of
I7 for Mac OS X (and I'm not sure if they can be tested in Linux,
either) since, at the moment, sound support is not implemented in
that version of the IDE. I have verified that the error exists, by the
way, using the Windows version of I7 (5U92).

Basically, what happens is that these 2 channels of audio are created
(with rocks 410 and 411), but their references are not appropriately
recovered by the system, nor are the sounds stopped, when doing
RESTART/LOAD/UNDO, etc., in the game.

In order to correct this error, none of the common Glk entry points
can be used (because it does not make sense at this point of the
execution); one must correct the routines VM_Initialise() and
GGRecoverObjects() in the file "Glulx.i6t". In addition, after
recovering the references of these channels, any sound currently being
played must always be stopped: imagine that a quite long sound is
being played and suddenly the player types "UNDO". If the channel is
reclaimed, but its sound does not pause, the player will be able to
continue listening to it, although within the new context of the game
that sound should no longer exist. For this reason these channels must
*always* be stopped. This error can be verified quickly (in the IDE
for Windows), by creating a new minimum game. Ex:

-------------------------------
"I7 Default Soundchannels Bug"
Test is a room.
-------------------------------

… in the same IDE, the game should be executed with "debug" (pressing
the button "Go!") in order to have access to the command GLKLIST. If
GLKLIST is typed on the first move, a list of the created Glk objects
appears, in which will be the pair of automatically created sound
channels (410 and 411). If RESTART is typed and then GLKLIST again,
now 4 channels of sound exist, even with their repeated values Rock (2
channels with rock 410 and 2 channels with rock 411). If you keep
restarting, more sound channels are created, which is a serious and
ugly bug. Certainly this will not create too many problems, almost no
one will notice, but in any case it is still something that *should
not happen*, because to leave Glk objects with recovered references is
an important Glulx programming error.

I have corrected this bug and in addition I accidentally found another
potential error related to the order in which VM_Initialise() is
written. First of all, the creation of the sound channels is done
after calling InitGlkWindow(0). This does not produce any strange
behavior until the programmer tries to create Glk windows by himself.
If in his personal implementation, InitGlkWindow(0) returns a value
other than zero (which can happen if the Glk windows are created by
hand), then the code that creates the audio channels will never
execute. The same things happens with what seems to be a "fix for the
random number generator" (FIX_RNG). As this piece of code also is
after the call to InitGlkWindow(0), if this routine returns something
other than zero, the code of "Fix" will never execute (independent of
the fact that it is a conditional compilation).

As I said, I have corrected the sound channel recovery bug and have
correctly ordered the VM_Initialise() routine. The correction at the
moment affects VM_Initialise() and GGRecoverObjects(). I copy here the
corrected (and isolated) code for both routines. All the changes and
corrections are noted with comments with the text "ELIUK BLAU".

--------------------------------------------------------------------------------------
[ VM_Initialise res sty;
@gestalt 4 2 res; ! Test if this interpreter has Glk...
if (res == 0) quit; ! ...without which there would be nothing we
could do

unicode_gestalt_ok = false;
if (glk_gestalt(gestalt_Unicode, 0))
unicode_gestalt_ok = true;

! Set the VM's I/O system to be Glk.
@setiosys 2 0;

! First, we must go through all the Glk objects that exist, and
see
! if we created any of them. One might think this strange, since
the
! program has just started running, but remember that the player
might
! have just typed "restart".

GGRecoverObjects();

!
===============================================================================
! ELIUK BLAU: (CORRECTION) THE CORRECT POSITION FOR THIS CODE IS
! ALWAYS BEFORE THE CALL TO InitGlkWindow(0) [FARTHER DOWN IN THE
! SAME ROUTINE] (SEE THE COMMENTS AT THE END OF THIS ROUTINE)
!
===============================================================================
if (glk_gestalt(gestalt_Sound, 0)) {
if (gg_foregroundchan == 0)
gg_foregroundchan =
glk_schannel_create(GG_FOREGROUNDCHAN_ROCK);
if (gg_backgroundchan == 0)
gg_backgroundchan =
glk_schannel_create(GG_BACKGROUNDCHAN_ROCK);
}

#ifdef FIX_RNG;
@random 10000 i;
i = -i-2000;
print "[Random number generator seed is ", i, "]^";
@setrandom i;
#endif; ! FIX_RNG
!
===============================================================================

res = InitGlkWindow(0);
if (res ~= 0) return;

! Now, gg_mainwin and gg_storywin might already be set. If not,
set them.

if (gg_mainwin == 0) {
! Open the story window.
res = InitGlkWindow(GG_MAINWIN_ROCK);
if (res == 0) {
! Left-justify the header style
glk_stylehint_set(wintype_TextBuffer, style_Header,
stylehint_Justification, 0);
! Try to make emphasized type in italics and not boldface
glk_stylehint_set(wintype_TextBuffer, style_Emphasized,
stylehint_Weight, 0);
glk_stylehint_set(wintype_TextBuffer, style_Emphasized,
stylehint_Oblique, 1);
gg_mainwin = glk_window_open(0, 0, 0, wintype_TextBuffer,
GG_MAINWIN_ROCK);
}
if (gg_mainwin == 0) quit; ! If we can't even open one window,
give in
}
else {
! There was already a story window. We should erase it.
glk_window_clear(gg_mainwin);
}

if (gg_statuswin == 0) {
res = InitGlkWindow(GG_STATUSWIN_ROCK);
if (res == 0) {
statuswin_cursize = statuswin_size;
for (sty=0: sty<style_NUMSTYLES: sty++)
glk_stylehint_set(wintype_TextGrid, sty,
stylehint_ReverseColor, 1);
gg_statuswin =
glk_window_open(gg_mainwin, winmethod_Fixed +
winmethod_Above,
statuswin_cursize, wintype_TextGrid,
GG_STATUSWIN_ROCK);
}
}
! It's possible that the status window couldn't be opened, in
which case
! gg_statuswin is now zero. We must allow for that later on.

glk_set_window(gg_mainwin);

InitGlkWindow(1);

!
===============================================================================
! ELIUK BLAU: (BUG) It is an ERROR that all this is located in this
! position because if InitGlkWindow(0) gives back a value different
from
! zero, the boot of the sound channels and random number generator fix
! never get to execute. All this code must be placed before anything
! related to the creation of the Glk windows. [SEE ABOVE]
!
===============================================================================
! if (glk_gestalt(gestalt_Sound, 0)) {
! if (gg_foregroundchan == 0)
! gg_foregroundchan = glk_schannel_create(GG_FOREGROUNDCHAN_ROCK);
! if (gg_backgroundchan == 0)
! gg_backgroundchan = glk_schannel_create(GG_BACKGROUNDCHAN_ROCK);
! }
!
! #ifdef FIX_RNG;
! @random 10000 i;
! i = -i-2000;
! print "[Random number generator seed is ", i, "]^";
! @setrandom i;
! #endif; ! FIX_RNG
!
===============================================================================
];

[ GGRecoverObjects id;
! If GGRecoverObjects() has been called, all these stored IDs are
! invalid, so we start by clearing them all out.
! (In fact, after a restoreundo, some of them may still be good.
! For simplicity, though, we assume the general case.)
gg_mainwin = 0;
gg_statuswin = 0;
gg_quotewin = 0;
gg_scriptfref = 0;
gg_scriptstr = 0;
gg_savestr = 0;
statuswin_cursize = 0;
!
===============================================================================
! ELIUK BLAU: (CORRECCION) CLEANED UP THE REFERENCES TO SOUND
CHANNELS
!
===============================================================================
gg_foregroundchan = 0;
gg_backgroundchan = 0;
!
===============================================================================
#Ifdef DEBUG;
gg_commandstr = 0;
gg_command_reading = false;
#Endif; ! DEBUG
! Also tell the game to clear its object references.
IdentifyGlkObject(0);

id = glk_stream_iterate(0, gg_arguments);
while (id) {
switch (gg_arguments-->0) {
GG_SAVESTR_ROCK: gg_savestr = id;
GG_SCRIPTSTR_ROCK: gg_scriptstr = id;
#Ifdef DEBUG;
GG_COMMANDWSTR_ROCK: gg_commandstr = id;
gg_command_reading = false;
GG_COMMANDRSTR_ROCK: gg_commandstr = id;
gg_command_reading = true;
#Endif; ! DEBUG
default: IdentifyGlkObject(1, 1, id, gg_arguments-->0);
}
id = glk_stream_iterate(id, gg_arguments);
}

id = glk_window_iterate(0, gg_arguments);
while (id) {
switch (gg_arguments-->0) {
GG_MAINWIN_ROCK: gg_mainwin = id;
GG_STATUSWIN_ROCK: gg_statuswin = id;
GG_QUOTEWIN_ROCK: gg_quotewin = id;
default: IdentifyGlkObject(1, 0, id, gg_arguments-->0);
}
id = glk_window_iterate(id, gg_arguments);
}

id = glk_fileref_iterate(0, gg_arguments);
while (id) {
switch (gg_arguments-->0) {
GG_SCRIPTFREF_ROCK: gg_scriptfref = id;
default: IdentifyGlkObject(1, 2, id, gg_arguments-->0);
}
id = glk_fileref_iterate(id, gg_arguments);
}

!
===============================================================================
! ELIUK BLAU: (CORRECTION) WE RECOVER THE REFERENCES TO
! THE SOUNDS AND STOP THEM.
!
===============================================================================
if (glk_gestalt(gestalt_Sound, 0)) {
id = glk_schannel_iterate(0, gg_arguments);
while (id) {
switch (gg_arguments-->0) {
GG_FOREGROUNDCHAN_ROCK: gg_foregroundchan = id;
GG_BACKGROUNDCHAN_ROCK: gg_backgroundchan = id;
}
id = glk_schannel_iterate(id, gg_arguments);
}
! ELIUK BLAU: Stop now all default sound channels
(important!)...
if (gg_foregroundchan ~= 0)
{ glk_schannel_stop(gg_foregroundchan); }
if (gg_backgroundchan ~= 0)
{ glk_schannel_stop(gg_backgroundchan); }
}
!
===============================================================================

! Tell the game to tie up any loose ends.
IdentifyGlkObject(2);
];
--------------------------------------------------------------------------------------

That is the necessary correction that should be applied in the file
Glulx.i6t. Also attached is my corrected version of the same file,
that is ready to work. [Note from Aaron: I did not re-translate
Eliuk's comments in the attached file; see the version here for the
translation.]

Making these changes already fixes the sound channel bug and, in
addition, the bug of potential errors with the creation of channels
and the random number fix if the programmer opens Glk windows by
himself, and all that happens after that line in VM_Initialise() gets
to execute. With the changes, this potential error already is
corrected. Both errors have been corrected.

Again, thank you very much Graham (and others) for your patience
reading this bug report. And congratulations on your great work with
Inform7, that every day becomes better and more complete.

Ah, one more thing, I suppose for David Kinder: in the Glulx
interpreter integrated to the I7 IDE (in Windows), when a game is
executed with a sound that has an infinite loop, if the "Stop" button
is pressed the sound never pauses. This is a problem with the Glulx
interpreter. Please, the interpreter should be corrected so that when
stopping the execution of the game *all the sounds also are stopped
automatically*, because otherwise, to use the IDE becomes very
annoying for those who want to include multimedia. Thanks for
addressing this request. And thanks, David, for your excellent work
with the IDE of Inform7.

Thanks also especially to Aaron Reed for translating this bug report
to English.

Sincerely,

Eliuk Blau
(member of the CAAD, the Hispanic Interactive Fiction community)

David Kinder

unread,
Oct 29, 2008, 4:58:24 AM10/29/08
to
> Ah, one more thing, I suppose for David Kinder: in the Glulx
> interpreter integrated to the I7 IDE (in Windows), when a game is
> executed with a sound that has an infinite loop, if the "Stop" button
> is pressed the sound never pauses. This is a problem with the Glulx
> interpreter. Please, the interpreter should be corrected so that when
> stopping the execution of the game *all the sounds also are stopped
> automatically*, because otherwise, to use the IDE becomes very
> annoying for those who want to include multimedia.

I'll add this to my list for the next version, thanks.
David

0 new messages