Initial commit
This commit is contained in:
315
engines/glk/adrift/scresour.cpp
Normal file
315
engines/glk/adrift/scresour.cpp
Normal file
@@ -0,0 +1,315 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/adrift/scare.h"
|
||||
#include "glk/adrift/scprotos.h"
|
||||
#include "glk/adrift/scgamest.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Adrift {
|
||||
|
||||
/* Assorted definitions and constants. */
|
||||
static const sc_char NUL = '\0';
|
||||
|
||||
|
||||
/*
|
||||
* res_has_sound()
|
||||
* res_has_graphics()
|
||||
*
|
||||
* Return TRUE if the game uses sound or graphics.
|
||||
*/
|
||||
sc_bool res_has_sound(sc_gameref_t game) {
|
||||
const sc_prop_setref_t bundle = gs_get_bundle(game);
|
||||
sc_vartype_t vt_key[2];
|
||||
sc_bool has_sound;
|
||||
assert(gs_is_game_valid(game));
|
||||
|
||||
vt_key[0].string = "Globals";
|
||||
vt_key[1].string = "Sound";
|
||||
has_sound = prop_get_boolean(bundle, "B<-ss", vt_key);
|
||||
return has_sound;
|
||||
}
|
||||
|
||||
sc_bool res_has_graphics(sc_gameref_t game) {
|
||||
const sc_prop_setref_t bundle = gs_get_bundle(game);
|
||||
sc_vartype_t vt_key[2];
|
||||
sc_bool has_graphics;
|
||||
assert(gs_is_game_valid(game));
|
||||
|
||||
vt_key[0].string = "Globals";
|
||||
vt_key[1].string = "Graphics";
|
||||
has_graphics = prop_get_boolean(bundle, "B<-ss", vt_key);
|
||||
return has_graphics;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* res_set_resource()
|
||||
* res_clear_resource()
|
||||
* res_compare_resource()
|
||||
*
|
||||
* Convenience functions to set, clear, and compare resource fields.
|
||||
*/
|
||||
static void res_set_resource(sc_resourceref_t resource, const sc_char *name,
|
||||
sc_int offset, sc_int length) {
|
||||
resource->name = name;
|
||||
resource->offset = offset;
|
||||
resource->length = length;
|
||||
}
|
||||
|
||||
void res_clear_resource(sc_resourceref_t resource) {
|
||||
res_set_resource(resource, "", 0, 0);
|
||||
}
|
||||
|
||||
sc_bool res_compare_resource(sc_resourceref_t from, sc_resourceref_t with) {
|
||||
return strcmp(from->name, with->name) == 0
|
||||
&& from->offset == with->offset && from->length == with->length;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* res_handle_resource()
|
||||
*
|
||||
* General helper for handling graphics and sound resources. Supplied with a
|
||||
* partial key to the node containing resources, it identifies what resource
|
||||
* is appropriate, and sets this as the requested resource in the game, for
|
||||
* later use on sync'ing, using the handler appropriate for the game version.
|
||||
*
|
||||
* The partial format is something like "sis" (the bit to follow I<- or S<-
|
||||
* in prop_get), and the partial key is guaranteed to contain at least
|
||||
* strlen(partial_format) elements.
|
||||
*/
|
||||
void res_handle_resource(sc_gameref_t game, const sc_char *partial_format,
|
||||
const sc_vartype_t vt_partial[]) {
|
||||
const sc_prop_setref_t bundle = gs_get_bundle(game);
|
||||
sc_vartype_t vt_key[2], *vt_full;
|
||||
sc_int partial_length, resource_start_offset;
|
||||
sc_bool embedded;
|
||||
sc_char *format;
|
||||
assert(gs_is_game_valid(game));
|
||||
assert(partial_format && vt_partial);
|
||||
|
||||
/*
|
||||
* Check for resources. If this game doesn't use any, exit now to avoid the
|
||||
* overhead of pointless lookups and allocations.
|
||||
*/
|
||||
if (!(res_has_sound(game) || res_has_graphics(game)))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Get the global offset for all resources. For version 3.9 games this
|
||||
* should be zero. For version 4.0 games, it's the start of resource data
|
||||
* in the TAF file where resources are embedded.
|
||||
*/
|
||||
vt_key[0].string = "ResourceOffset";
|
||||
resource_start_offset = prop_get_integer(bundle, "I<-s", vt_key);
|
||||
|
||||
/*
|
||||
* Get the flag that indicated embedded resources. For version 3.9 games
|
||||
* this should be false. If not set, offset and length are forced to zero
|
||||
* for interface functions.
|
||||
*/
|
||||
vt_key[0].string = "Globals";
|
||||
vt_key[1].string = "Embedded";
|
||||
embedded = prop_get_boolean(bundle, "B<-ss", vt_key);
|
||||
|
||||
/*
|
||||
* Allocate a format for use with properties calls, five characters longer
|
||||
* than the partial passed in. Build a key one element larger than the
|
||||
* partial supplied, and copy over all supplied elements.
|
||||
*/
|
||||
partial_length = strlen(partial_format);
|
||||
format = (sc_char *)sc_malloc(partial_length + 5);
|
||||
|
||||
vt_full = (sc_vartype_t *)sc_malloc((partial_length + 1) * sizeof(vt_partial[0]));
|
||||
memcpy(vt_full, vt_partial, partial_length * sizeof(vt_partial[0]));
|
||||
|
||||
/* Search for sound resources, and offer if found. */
|
||||
if (res_has_sound(game)) {
|
||||
const sc_char *soundfile;
|
||||
sc_int soundoffset, soundlen;
|
||||
|
||||
/* Get soundfile property from the node supplied. */
|
||||
vt_full[partial_length].string = "SoundFile";
|
||||
Common::strcpy_s(format, partial_length + 5, "S<-");
|
||||
Common::strcat_s(format, partial_length + 5, partial_format);
|
||||
Common::strcat_s(format, partial_length + 5, "s");
|
||||
soundfile = prop_get_string(bundle, format, vt_full);
|
||||
|
||||
/* If a sound is defined, handle it. */
|
||||
if (!sc_strempty(soundfile)) {
|
||||
if (embedded) {
|
||||
/* Retrieve offset and length. */
|
||||
vt_full[partial_length].string = "SoundOffset";
|
||||
Common::strcpy_s(format, partial_length + 5, "I<-");
|
||||
Common::strcat_s(format, partial_length + 5, partial_format);
|
||||
Common::strcat_s(format, partial_length + 5, "s");
|
||||
soundoffset = prop_get_integer(bundle, format, vt_full)
|
||||
+ resource_start_offset;
|
||||
|
||||
vt_full[partial_length].string = "SoundLen";
|
||||
Common::strcpy_s(format, partial_length + 5, "I<-");
|
||||
Common::strcat_s(format, partial_length + 5, partial_format);
|
||||
Common::strcat_s(format, partial_length + 5, "s");
|
||||
soundlen = prop_get_integer(bundle, format, vt_full);
|
||||
} else {
|
||||
/* Coerce offset and length to zero. */
|
||||
soundoffset = 0;
|
||||
soundlen = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the sound is the special "##", latch stop, otherwise note
|
||||
* details to play on sync.
|
||||
*/
|
||||
if (!strcmp(soundfile, "##")) {
|
||||
game->stop_sound = TRUE;
|
||||
res_clear_resource(&game->requested_sound);
|
||||
} else {
|
||||
res_set_resource(&game->requested_sound,
|
||||
soundfile, soundoffset, soundlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now do the same thing for graphics resources. */
|
||||
if (res_has_graphics(game)) {
|
||||
const sc_char *graphicfile;
|
||||
sc_int graphicoffset, graphiclen;
|
||||
|
||||
/* Get graphicfile property from the node supplied. */
|
||||
vt_full[partial_length].string = "GraphicFile";
|
||||
Common::strcpy_s(format, partial_length + 5, "S<-");
|
||||
Common::strcat_s(format, partial_length + 5, partial_format);
|
||||
Common::strcat_s(format, partial_length + 5, "s");
|
||||
graphicfile = prop_get_string(bundle, format, vt_full);
|
||||
|
||||
/* If a graphic is defined, handle it. */
|
||||
if (!sc_strempty(graphicfile)) {
|
||||
if (embedded) {
|
||||
/* Retrieve offset and length. */
|
||||
vt_full[partial_length].string = "GraphicOffset";
|
||||
Common::strcpy_s(format, partial_length + 5, "I<-");
|
||||
Common::strcat_s(format, partial_length + 5, partial_format);
|
||||
Common::strcat_s(format, partial_length + 5, "s");
|
||||
graphicoffset = prop_get_integer(bundle, format, vt_full)
|
||||
+ resource_start_offset;
|
||||
|
||||
vt_full[partial_length].string = "GraphicLen";
|
||||
Common::strcpy_s(format, partial_length + 5, "I<-");
|
||||
Common::strcat_s(format, partial_length + 5, partial_format);
|
||||
Common::strcat_s(format, partial_length + 5, "s");
|
||||
graphiclen = prop_get_integer(bundle, format, vt_full);
|
||||
} else {
|
||||
/* Coerce offset and length to zero. */
|
||||
graphicoffset = 0;
|
||||
graphiclen = 0;
|
||||
}
|
||||
|
||||
/* Graphics resource retrieved, note to show on sync. */
|
||||
res_set_resource(&game->requested_graphic,
|
||||
graphicfile, graphicoffset, graphiclen);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free allocated memory. */
|
||||
sc_free(format);
|
||||
sc_free(vt_full);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* res_sync_resources()
|
||||
*
|
||||
* Bring resources into line with the game; called on undo, restart,
|
||||
* restore, and so on.
|
||||
*/
|
||||
void res_sync_resources(sc_gameref_t game) {
|
||||
assert(gs_is_game_valid(game));
|
||||
|
||||
/* Deal with any latched sound stop first. */
|
||||
if (game->stop_sound) {
|
||||
if (game->sound_active) {
|
||||
if_update_sound("", 0, 0, FALSE);
|
||||
game->sound_active = FALSE;
|
||||
|
||||
res_clear_resource(&game->playing_sound);
|
||||
}
|
||||
game->stop_sound = FALSE;
|
||||
}
|
||||
|
||||
/* Look for a change of sound, and pass to interface on change. */
|
||||
if (!res_compare_resource(&game->playing_sound,
|
||||
&game->requested_sound)) {
|
||||
const sc_char *name;
|
||||
sc_char *clean_name;
|
||||
sc_bool is_looping;
|
||||
|
||||
/* If the sound name ends '##', this is a looping sound. */
|
||||
name = game->requested_sound.name;
|
||||
is_looping = !strcmp(name + strlen(name) - 2, "##");
|
||||
|
||||
size_t ln = strlen(name) + 1;
|
||||
clean_name = (sc_char *)sc_malloc(ln);
|
||||
Common::strcpy_s(clean_name, ln, name);
|
||||
if (is_looping)
|
||||
clean_name[strlen(clean_name) - 2] = NUL;
|
||||
|
||||
if_update_sound(clean_name,
|
||||
game->requested_sound.offset,
|
||||
game->requested_sound.length, is_looping);
|
||||
game->playing_sound = game->requested_sound;
|
||||
game->sound_active = TRUE;
|
||||
|
||||
sc_free(clean_name);
|
||||
}
|
||||
|
||||
/* Look for a change of graphic, and pass to interface on change. */
|
||||
if (!res_compare_resource(&game->displayed_graphic,
|
||||
&game->requested_graphic)) {
|
||||
if_update_graphic(game->requested_graphic.name,
|
||||
game->requested_graphic.offset,
|
||||
game->requested_graphic.length);
|
||||
game->displayed_graphic = game->requested_graphic;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* res_cancel_resources()
|
||||
*
|
||||
* Turn off sound and graphics, and reset the game's tracking of resources in
|
||||
* use to match. Called on game restart or restore.
|
||||
*/
|
||||
void res_cancel_resources(sc_gameref_t game) {
|
||||
assert(gs_is_game_valid(game));
|
||||
|
||||
/* Request that everything stops and clears. */
|
||||
game->stop_sound = FALSE;
|
||||
res_clear_resource(&game->requested_sound);
|
||||
res_clear_resource(&game->requested_graphic);
|
||||
|
||||
/* Synchronize to have the above take effect. */
|
||||
res_sync_resources(game);
|
||||
}
|
||||
|
||||
} // End of namespace Adrift
|
||||
} // End of namespace Glk
|
||||
Reference in New Issue
Block a user