Initial commit
This commit is contained in:
406
engines/m4/adv_r/adv_file.cpp
Normal file
406
engines/m4/adv_r/adv_file.cpp
Normal file
@@ -0,0 +1,406 @@
|
||||
/* 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 "common/system.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/util.h"
|
||||
#include "m4/adv_r/adv_file.h"
|
||||
#include "m4/adv_r/adv_chk.h"
|
||||
#include "m4/adv_r/adv_walk.h"
|
||||
#include "m4/adv_r/db_env.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/core/imath.h"
|
||||
#include "m4/fileio/extensions.h"
|
||||
#include "m4/fileio/info.h"
|
||||
#include "m4/graphics/gr_pal.h"
|
||||
#include "m4/gui/gui_buffer.h"
|
||||
#include "m4/gui/gui_vmng.h"
|
||||
#include "m4/platform/tile/tile_read.h"
|
||||
#include "m4/m4.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
static Common::String get_background_filename(const SceneDef *rdef);
|
||||
static Common::String get_attribute_filename(const SceneDef *rdef);
|
||||
static void recreate_animation_draw_screen(GrBuff **loadBuf);
|
||||
static void troll_for_colors(RGB8 *newPal, uint8 minPalEntry, uint8 maxPalEntry);
|
||||
|
||||
void kernel_unload_room(SceneDef *rdef, GrBuff **code_data, GrBuff **loadBuffer) {
|
||||
term_message("Unloading scene %d", _G(game).room_id);
|
||||
|
||||
if (_G(gameDrawBuff)) {
|
||||
gui_buffer_deregister((Buffer *)_G(gameDrawBuff));
|
||||
delete _G(gameDrawBuff);
|
||||
_G(gameDrawBuff) = nullptr;
|
||||
}
|
||||
|
||||
if (*code_data)
|
||||
delete *code_data;
|
||||
*code_data = nullptr;
|
||||
|
||||
if (*loadBuffer)
|
||||
delete *loadBuffer;
|
||||
*loadBuffer = nullptr;
|
||||
|
||||
if (!rdef)
|
||||
return;
|
||||
|
||||
// Must we deallocate existing hot spots?
|
||||
if (rdef->hotspots != nullptr) {
|
||||
hotspot_delete_all(rdef->hotspots);
|
||||
rdef->hotspots = nullptr;
|
||||
}
|
||||
rdef->num_hotspots = 0;
|
||||
|
||||
// Must we deallocate existing parallax?
|
||||
if (rdef->parallax != nullptr) {
|
||||
hotspot_delete_all(rdef->parallax);
|
||||
rdef->parallax = nullptr;
|
||||
}
|
||||
rdef->num_parallax = 0;
|
||||
|
||||
// Must we deallocate existing props?
|
||||
if (rdef->props != nullptr) {
|
||||
hotspot_delete_all(rdef->props);
|
||||
rdef->props = nullptr;
|
||||
}
|
||||
rdef->num_props = 0;
|
||||
|
||||
ClearRails();
|
||||
}
|
||||
|
||||
|
||||
bool kernel_load_room(int minPalEntry, int maxPalEntry, SceneDef *rdef, GrBuff **scr_orig_data, GrBuff **scr_orig) {
|
||||
if (!scr_orig_data || !scr_orig) {
|
||||
error_show(FL, 'BUF!', "load_picture_and_codes");
|
||||
}
|
||||
|
||||
term_message("Reading scene %d", _G(game).new_room);
|
||||
|
||||
if (_G(game).previous_room != KERNEL_RESTORING_GAME) {
|
||||
_G(game).previous_room = _G(game).room_id;
|
||||
}
|
||||
|
||||
// Read DEF file
|
||||
if (db_def_chk_read(_G(game).new_room, rdef) != -1) {
|
||||
error_show(FL, 'DF:(', "trying to find %d.CHK", (uint32)_G(game).new_room);
|
||||
}
|
||||
|
||||
set_walker_scaling(rdef);
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Select background picture
|
||||
|
||||
_G(currBackgroundFN) = get_background_filename(rdef);
|
||||
|
||||
char *tempName = env_find(_G(currBackgroundFN));
|
||||
if (tempName) {
|
||||
// In normal rooms.db mode
|
||||
_G(currBackgroundFN) = f_extension_new(tempName, "TT");
|
||||
} else {
|
||||
// In concat hag mode
|
||||
_G(currBackgroundFN) = f_extension_new(_G(currBackgroundFN), "TT");
|
||||
}
|
||||
|
||||
SysFile *pic_file = new SysFile(_G(currBackgroundFN));
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Select attributes code file
|
||||
|
||||
_G(currCodeFN) = get_attribute_filename(rdef);
|
||||
|
||||
tempName = env_find(_G(currCodeFN));
|
||||
if (tempName) {
|
||||
// In normal rooms.db mode
|
||||
_G(currCodeFN) = f_extension_new(tempName, "COD");
|
||||
} else {
|
||||
// In concat hag mode
|
||||
_G(currCodeFN) = f_extension_new(_G(currCodeFN), "COD");
|
||||
}
|
||||
|
||||
SysFile *code_file = new SysFile(_G(currCodeFN));
|
||||
if (!code_file->exists()) {
|
||||
delete code_file;
|
||||
code_file = nullptr;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Load background picture
|
||||
|
||||
term_message("load background");
|
||||
RGB8 newPal[256];
|
||||
load_background(pic_file, scr_orig, newPal);
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Load attributes code file
|
||||
|
||||
term_message("load codes");
|
||||
*scr_orig_data = load_codes(code_file);
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Prepare buffers for display
|
||||
|
||||
recreate_animation_draw_screen(scr_orig);
|
||||
troll_for_colors(newPal, minPalEntry, maxPalEntry);
|
||||
|
||||
gr_pal_reset_ega_colors(&_G(master_palette)[0]);
|
||||
|
||||
RestoreScreens(MIN_VIDEO_X, MIN_VIDEO_Y, MAX_VIDEO_X, MAX_VIDEO_Y);
|
||||
|
||||
pic_file->close();
|
||||
delete pic_file;
|
||||
|
||||
if (code_file) {
|
||||
code_file->close();
|
||||
delete code_file;
|
||||
}
|
||||
|
||||
if (*scr_orig_data) {
|
||||
Buffer *scr_orig_data_buffer = (**scr_orig_data).get_buffer();
|
||||
RestoreEdgeList(scr_orig_data_buffer);
|
||||
(**scr_orig_data).release();
|
||||
} else
|
||||
RestoreEdgeList(nullptr);
|
||||
|
||||
_G(game).room_id = _G(game).new_room;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool kernel_load_variant(const char *variant) {
|
||||
SceneDef &sceneDef = _G(currentSceneDef);
|
||||
GrBuff *codeBuff = _G(screenCodeBuff);
|
||||
Common::String filename;
|
||||
|
||||
if (!codeBuff)
|
||||
return false;
|
||||
|
||||
if (_G(kernel).hag_mode) {
|
||||
filename = f_extension_new(variant, "COD");
|
||||
} else {
|
||||
char *base = env_find(sceneDef.art_base);
|
||||
char *dotPos = nullptr;
|
||||
if (base)
|
||||
dotPos = strchr(base, '.');
|
||||
|
||||
if (!dotPos)
|
||||
return false;
|
||||
|
||||
filename = f_extension_new(base, "COD");
|
||||
|
||||
if (!f_info_exists(Common::Path(filename)))
|
||||
return false;
|
||||
}
|
||||
|
||||
SysFile code_file(filename);
|
||||
if (!code_file.exists())
|
||||
error("Failed to load variant %s", filename.c_str());
|
||||
|
||||
// TODO: This is just copied from the room loading code,
|
||||
// rather than disassembling the reset of the original method.
|
||||
// Need to determine whether this is correct or not,
|
||||
// then modified to clean screenCodeBuff and the edges.
|
||||
|
||||
GrBuff *scr_orig_data = load_codes(&code_file);
|
||||
|
||||
code_file.close();
|
||||
|
||||
if (scr_orig_data) {
|
||||
_G(screenCodeBuff)->release();
|
||||
free _G(screenCodeBuff);
|
||||
RestoreEdgeList(nullptr);
|
||||
|
||||
Buffer *scr_orig_data_buffer = scr_orig_data->get_buffer();
|
||||
RestoreEdgeList(scr_orig_data_buffer);
|
||||
|
||||
_G(screenCodeBuff) = scr_orig_data;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GrBuff *load_codes(SysFile *code_file) {
|
||||
// No this is not a cheat to allow bugs to live,
|
||||
// if there is no code file, then we don't need a code buffer, either.
|
||||
// it's perfectly acceptable, so there, NYAH!
|
||||
if (!code_file)
|
||||
return nullptr;
|
||||
|
||||
const int16 x_size = code_file->readSint16LE();
|
||||
const int16 y_size = code_file->readSint16LE();
|
||||
|
||||
GrBuff *temp = new GrBuff(x_size, y_size);
|
||||
Buffer *myBuff = temp->get_buffer();
|
||||
byte *bufferHandle = myBuff->data;
|
||||
|
||||
for (int i = 0; i < y_size; i++) {
|
||||
code_file->read(bufferHandle, x_size);
|
||||
bufferHandle += myBuff->stride;
|
||||
}
|
||||
|
||||
// Let the memory float
|
||||
temp->release();
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool load_background(SysFile *pic_file, GrBuff **loadBuffer, RGB8 *palette) {
|
||||
int32 num_x_tiles, num_y_tiles, tile_x, tile_y, file_x, file_y;
|
||||
int32 count = 0;
|
||||
|
||||
tt_read_header(pic_file, &file_x, &file_y,
|
||||
&num_x_tiles, &num_y_tiles, &tile_x, &tile_y, palette);
|
||||
|
||||
*loadBuffer = new GrBuff(file_x, file_y);
|
||||
|
||||
if (!*loadBuffer)
|
||||
error_show(FL, 'OOM!');
|
||||
|
||||
Buffer *theBuff = (**loadBuffer).get_buffer();
|
||||
|
||||
for (int i = 0; i < num_y_tiles; i++) {
|
||||
for (int j = 0; j < num_x_tiles; j++) {
|
||||
Buffer *out = tt_read(pic_file, count, tile_x, tile_y);
|
||||
count++;
|
||||
|
||||
if (out && (out->data)) {
|
||||
const int32 x_end = imath_min(file_x, (1 + j) * tile_x);
|
||||
const int32 y_end = imath_min(file_y, (1 + i) * tile_y);
|
||||
gr_buffer_rect_copy_2(out, theBuff, 0, 0, j * tile_x, i * tile_y,
|
||||
x_end - (j * tile_x), y_end - (i * tile_y));
|
||||
mem_free(out->data);
|
||||
}
|
||||
|
||||
if (out)
|
||||
mem_free(out);
|
||||
}
|
||||
}
|
||||
|
||||
(**loadBuffer).release();
|
||||
return true;
|
||||
}
|
||||
|
||||
static Common::SeekableReadStream *openForLoading(int slot) {
|
||||
const Common::String slotName = g_engine->getSaveStateName(slot);
|
||||
return g_system->getSavefileManager()->openForLoading(slotName);
|
||||
}
|
||||
|
||||
bool kernel_save_game_exists(int32 slot) {
|
||||
Common::SeekableReadStream *save = openForLoading(slot);
|
||||
const bool result = save != nullptr;
|
||||
delete save;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int kernel_save_game(int slot, const char *desc, int32 sizeofDesc, M4sprite *thumbNail, int32 sizeofThumbData) {
|
||||
return g_engine->saveGameState(slot, desc, slot == 0).getCode() == Common::kNoError ? 0 : 1;
|
||||
}
|
||||
|
||||
bool kernel_load_game(int slot) {
|
||||
return g_engine->loadGameStateDoIt(slot).getCode() == Common::kNoError;
|
||||
}
|
||||
|
||||
int32 extract_room_num(const Common::String &name) {
|
||||
if ((name[0] == 'C' || name[0] == 'c') &&
|
||||
(name[1] == 'O' || name[1] == 'o') &&
|
||||
(name[2] == 'M' || name[2] == 'm'))
|
||||
return _G(global_sound_room);
|
||||
|
||||
if (Common::isDigit(name[0]) && Common::isDigit(name[1]) && Common::isDigit(name[2])) {
|
||||
return ((int32)(name[0] - '0')) * 100 + ((int32)(name[1] - '0')) * 10 + ((int32)(name[2] - '0'));
|
||||
}
|
||||
|
||||
return _G(game).room_id;
|
||||
}
|
||||
|
||||
static Common::String get_background_filename(const SceneDef *rdef) {
|
||||
if (_G(art_base_override) != nullptr) {
|
||||
return _G(art_base_override);
|
||||
}
|
||||
|
||||
return rdef->art_base;
|
||||
}
|
||||
|
||||
static Common::String get_attribute_filename(const SceneDef *rdef) {
|
||||
if (_G(art_base_override) == nullptr || !_G(use_alternate_attribute_file)) {
|
||||
return rdef->art_base;
|
||||
}
|
||||
|
||||
return _G(art_base_override);
|
||||
}
|
||||
|
||||
static void recreate_animation_draw_screen(GrBuff **loadBuf) {
|
||||
// Remove previous animation draw screen
|
||||
if (_G(gameDrawBuff)) {
|
||||
gui_buffer_deregister((Buffer *)_G(gameDrawBuff));
|
||||
delete _G(gameDrawBuff);
|
||||
_G(gameDrawBuff) = nullptr;
|
||||
_G(game_buff_ptr) = nullptr;
|
||||
}
|
||||
_G(gameDrawBuff) = new GrBuff((**loadBuf).w, (**loadBuf).h);
|
||||
gui_GrBuff_register(_G(kernel).letter_box_x, _G(kernel).letter_box_y, _G(gameDrawBuff), SF_BACKGRND | SF_GET_ALL | SF_BLOCK_NONE, nullptr);
|
||||
gui_buffer_activate((Buffer *)_G(gameDrawBuff));
|
||||
vmng_screen_to_back((void *)_G(gameDrawBuff));
|
||||
_G(game_buff_ptr) = vmng_screen_find(_G(gameDrawBuff), nullptr);
|
||||
|
||||
Buffer *theBuff = (**loadBuf).get_buffer();
|
||||
Buffer *game_buff = (*_G(gameDrawBuff)).get_buffer();
|
||||
gr_buffer_rect_copy_2(theBuff, game_buff, 0, 0, 0, 0,
|
||||
imath_min((**loadBuf).w, game_buff->w), imath_min((**loadBuf).h, game_buff->h));
|
||||
|
||||
(**loadBuf).release();
|
||||
(*_G(gameDrawBuff)).release();
|
||||
}
|
||||
|
||||
static void troll_for_colors(RGB8 *newPal, uint8 minPalEntry, uint8 maxPalEntry) {
|
||||
bool gotOne = false;
|
||||
for (int16 pal_iter = minPalEntry; pal_iter <= maxPalEntry; pal_iter++) { // accept any colors that came with the background
|
||||
if (gotOne || (newPal[pal_iter].r | newPal[pal_iter].g | newPal[pal_iter].b)) {
|
||||
gotOne = true;
|
||||
// colors are 6 bit...
|
||||
_G(master_palette)[pal_iter].r = newPal[pal_iter].r << 2;
|
||||
_G(master_palette)[pal_iter].g = newPal[pal_iter].g << 2;
|
||||
_G(master_palette)[pal_iter].b = newPal[pal_iter].b << 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (gotOne) {
|
||||
gr_pal_interface(&_G(master_palette)[0]); // enforce interface colors
|
||||
}
|
||||
}
|
||||
|
||||
Common::String expand_name_2_RAW(const Common::String &name, int32 room_num) {
|
||||
Common::String tempName = f_extension_new(name, "RAW");
|
||||
|
||||
if (!_G(kernel).hag_mode) {
|
||||
if (room_num == -1)
|
||||
room_num = extract_room_num(name);
|
||||
|
||||
return Common::String::format("%d\\%s", room_num, tempName.c_str());
|
||||
}
|
||||
|
||||
return tempName;
|
||||
}
|
||||
|
||||
Common::String expand_name_2_HMP(const Common::String &name, int32 room_num) {
|
||||
return f_extension_new(name, "HMP");
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
Reference in New Issue
Block a user