Constant Story "StartSaveTest"; Constant Headline "^Not a game.^"; Release 1; ! Sample code for a game which launches with a pre-built built-in save file. ! ! Building this requires several stages. (The sample script below uses ! my blorbtool.py script for constructing Blorb files, but any valid ! Blorb generator will work.) ! ! * Compile the Inform 6 source code. ! ! inform6 -G +$I6LIBRARY startsavetest.inf ! ! (The resulting startsavetest.ulx file will run, but there's no built-in ! save file, so it will do all the necessary setup at launch time. This is ! the old-fashioned way of starting up.) ! ! * Construct a Blorb file containing the .ulx file and an *empty* binary ! data file. ! ! blorbtool.py -n startsavetest-empty.gblorb import Exec 0 GLUL startsavetest.ulx ! touch empty.dat ! blorbtool.py -f startsavetest-empty.gblorb import Data 9998 BINA empty.dat ! ! The empty data chunk (with number 9998) is a signal to the game to set ! itself up and then write out a save file for future use. ! ! * Run the game. ! ! glulxe startsavetest-empty.gblorb ! ! The game should report "The autorestore file has been created successfully" ! before the banner. Quit the game, and you will see a "autorestore.glkdata" ! file now exists. ! ! * Construct a new Blorb file containing the .ulx file and this new file, ! as a FORM data chunk. ! ! blorbtool.py -n startsavetest.gblorb import Exec 0 GLUL startsavetest.ulx ! blorbtool.py -f startsavetest.gblorb import Data 9998 IFZS autorestore.glkdata ! ! * Now, when you run the game, it should report "The autorestore file has ! been restored successfully." It starts up in a fully-set-up position, but ! the setup code does not have to be run; the game restores itself to this ! position, using the built-in autorestore file. Include "Parser"; Include "VerbLib"; Global testglob; [ Initialise; location = Kitchen; SetUpOrLoad(); new_line; ]; [ SetUpOrLoad val name len fref; val = glk($0004, 22, 0); ! gestalt_ResourceStream if (~~val) { print "(This interpreter does not support resource streams.)^"; SlowSetUpWork(); return; } ! Look in chunk 9998. Why 9998? Because in an unrelated sample game, ! I used chunk 9999 for I6 debug data. None of this has to be standardized ! but it's nice to be consistent. gg_savestr = glk($0049, 9998, GG_SAVESTR_ROCK); ! stream_open_resource if (~~gg_savestr) { print "(No autorestore resource chunk.)^"; SlowSetUpWork(); return; } val = glk($0090, gg_savestr); ! get_char_stream if (val < 0) { print "(The autorestore chunk is empty, which is the signal to create a new autorestore file on disk.)^"; glk($0044, gg_savestr, 0); ! stream_close (close the empty chunk) gg_savestr = 0; SlowSetUpWork(); ! Set up the filename in a handy buffer name = "autorestore.dat"; len = name.print_to_array(buffer, INPUT_BUFFER_LEN-4); buffer->3 = $E0; buffer->(4+len) = 0; fref = glk($0061, 0, buffer+3, 0); ! fileref_create_by_name ! (This is a type-data, binary file.) if (~~fref) { print "(Oops, couldn't create a fileref. Skip this.)^"; return; } gg_savestr = glk($0042, fref, 1, GG_SAVESTR_ROCK); ! stream_open_file if (~~gg_savestr) { print "(Oops, couldn't create a new file. Skip this.)^"; glk($0063, fref); ! fileref_destroy return; } @save gg_savestr val; if (val == -1) { ! We actually just *restored* the auto-restore file. ! We now have to recover all the Glk objects; the values ! in our global variables are all wrong. GGRecoverObjects(); glk($0044, gg_savestr, 0); ! stream_close gg_savestr = 0; print "(The autorestore file has been restored successfully.)^"; return; } glk($0044, gg_savestr, 0); ! stream_close gg_savestr = 0; if (val == 0) { print "(The autorestore file has been created successfully.)^"; return; } print "(We tried to create the autorestore file, but it didn't work.)^"; return; } else { print "(The autorestore chunk exists. We'll restore it now.)^"; glk($0045, gg_savestr, 0, 0); ! stream_set_position (rewind to start) @restore gg_savestr val; ! If we got to this point, the restore must have failed. glk($0044, gg_savestr, 0); ! stream_close gg_savestr = 0; print "(We tried to load the autorestore file, but it didn't work.)^"; SlowSetUpWork(); return; } ]; [ SlowSetUpWork; print "(We now perform the slow, tedious set-up stage.)^"; testglob++; move table to kitchen; move apple to table; ]; Object Kitchen "Kitchen" with description [; print "This kitchen is boring. A sign on the wall reads "; if (testglob == 0) print "~SlowSetUpWork has never been run! That's bad.~"; else if (testglob == 1) print "~SlowSetUpWork has been run correctly.~"; else print "~SlowSetUpWork has run ", testglob, " times! That's bad.~"; print "^"; rtrue; ], has light; Object table "table" with name 'table', has supporter static; Object apple "apple" with name 'apple', article "an"; Include "Grammar";