2013-06-18 10:23:29 +02:00

631 lines
14 KiB
C++

/* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on the original source code of Lord Avalot d'Argent version 1.3.
* Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
*/
/*
ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
ENID Edna's manager. */
#define __enid_implementation__
/* Loads/ saves files. */
/*$V-*/
#include "enid.h"
/*#include "Dos.h"*/
#include "scrolls.h"
#include "lucerna.h"
#include "trip5.h"
#include "timeout.h"
#include "Celer.h"
#include "sequence.h"
#include "fileunit.h"
#include "basher.h"
namespace Avalanche {
const string crlf = string('\15') + '\12';
const char tab = '\11';
const char eof_ = '\32';
const array<1, 177, char> ednafirst =
string("This is an EDNA-based file, saved by a Thorsoft game. Good luck!") + /*64*/
crlf + eof_ + crlf + crlf + /*7*/
tab + "Glory to God in the highest," + crlf + /*31*/
tab + "and on earth peace, goodwill toward men." + /*42*/
crlf + tab + tab + tab + tab + /*6*/
"Luke 2:14." + /*10*/
crlf + crlf + crlf + /* 6 */
"1234567890" +crlf; /*11*/
const string ednaid = string("TT") + '\261' + '\60' + '\1' + '\165' + '\261' + '\231' + '\261';
const integer ttage = 18;
const array<1, 16, char> ttwashere = "Thomas was here ";
boolean bug;
string expanddate(byte d, byte m, word y);
const array<1, 12, varying_string<7> > months = {
{
"Jan#", "Febr#", "March", "April", "May", "June", "July", "August",
"Septem*", "Octo*", "Novem*", "Decem*"
}
};
static varying_string<10> month;
static void addon(string x) {
month[0] -= 1;
month = month + x;
}
string expanddate(byte d, byte m, word y) {
varying_string<4> day;
string expanddate_result;
month = months[m];
switch (month[length(month)]) {
case '#':
addon("uary");
break;
case '*':
addon("ber");
break;
}
day = strf(d);
if (set::of(range(1, 9), range(21, 31), eos).has(d))
switch (d % 10) {
case 1:
day = day + "st";
break;
case 2:
day = day + "nd";
break;
case 3:
day = day + "rd";
break;
default:
day = day + "th";
}
expanddate_result = day + ' ' + month + ' ' + strf(y);
return expanddate_result;
}
void edna_save(string name);
static void show_bug(char icon, string strn) {
display(string("\7\6\23") + icon + "\26\r" + strn + '\15');
}
static boolean test_bug(byte what) {
boolean test_bug_result;
if (what == 0) {
test_bug_result = false;
return test_bug_result;
}
switch (what) {
case 2:
show_bug('7', "Error in filename!");
break;
case 101:
show_bug('6', "Disk full!");
break;
case 150:
show_bug('4', "Disk is write-protected!");
break;
default:
show_bug('B', "Saving error!");
}
test_bug_result = true;
return test_bug_result;
}
void edna_save(string name) {
untyped_file f;
ednahead eh;
word groi;
string groi2, path;
word tempd, tempm;
if (name == "") {
/* We were given no name. Do we have a default? */
if (enid_filename == "") {
/* No */
filename_edit(); /* Request one. */
return;
} else /* Yes */
name = enid_filename;
}
wait(); /* Put up hourglass pointer */
fillchar(eh, sizeof(eh), '\261'); /* Fill up the edhead */
dna.saves += 1; /* It's been saved one more time... */
{
/* Info about this program */
eh.id = ednaid; /* Edna's signature */
eh.revision = thisgamecode; /* 2- second revision of .ASG format */
eh.game = "Lord Avalot d'Argent"; /* Title of game */
eh.shortname = "Avalot";
eh.number = 2; /* Second Avvy game */
eh.ver = thisvercode; /* Version 1.00 */
eh.verstr = vernum; /* ditto */
eh.filename = "AVALOT.EXE"; /* program's filename */
eh.osbyte = 1; /* Saved under DOS */
eh.os = "DOS";
/* Info on this particular game */
fsplit(name, path, eh.fn, groi2); /* fn = filename of this game */
getdate(eh.y, tempm, tempd, groi); /* Day, month & year when the game was saved */
eh.d = tempd;
eh.m = tempm;
eh.desc = roomname; /* Description of game (same as in Avaricius!) */
eh.len = sizeof(dna); /* Length of DNA. */
/* Quick reference & miscellaneous */
eh.saves = dna.saves; /* no. of times this game has been saved */
eh.cash = dna.pence; /* contents of your wallet in numerical form */
eh.money = lsd(); /* ditto in string form (eg 5/-, or 1 denarius)*/
eh.points = dna.score; /* your score */
name = path + eh.fn + ".ASG";
}
assign(f, name);
/*$I-*/
rewrite(f, 1);
if (test_bug(ioresult)) return;
blockwrite(f, ednafirst, 177);
if (test_bug(ioresult)) return;
blockwrite(f, eh, sizeof(eh));
if (test_bug(ioresult)) return;
blockwrite(f, dna, sizeof(dna));
if (test_bug(ioresult)) return;
for (groi = 1; groi <= numtr; groi ++) {
triptype &with = tr[groi];
if (with.quick) {
blockwrite(f, groi, 1);
if (test_bug(ioresult)) return;
savedata(f);
if (test_bug(ioresult)) return;
}
}
groi = 177;
blockwrite(f, groi, 1);
blockwrite(f, times, sizeof(times)); /* Timeout.times: Timers. */
if (test_bug(ioresult)) return;
blockwrite(f, seq, sizeof(seq)); /* Sequencer information. */
if (test_bug(ioresult)) return;
for (groi = 1; groi <= ttage; groi ++)
blockwrite(f, ttwashere[1 - 1], 16);
if (test_bug(ioresult)) return;
close(f);
if (test_bug(ioresult)) return;
/*$I+*/
display(string('\6') + "Saved: " + '\22' + name + '.');
enid_filename = name;
}
void loaderror(string x, char icon) {
if (holdthedawn) {
holdthedawn = false;
dawn();
}
display(string('\7') + '\6' + '\23' + icon + '\26' + "Loading error: " + "\r\r\22" + x);
bug = true;
}
typedef array<1, 4, char> fourtype;
const fourtype avaricius_file = "Avvy";
void edna_load(string name)
{
untyped_file f;
ednahead eh;
byte fv;
byte io;
string path, fn, groi;
fourtype id4;
word len2load;
if (name == "") {
/* No filename specified, so let's call the filer. */
name = do_filer();
if (name == "") return; /* STILL no filename, so they must have cancelled. */
}
bug = false;
wait(); /* Put up hourglass pointer */
fsplit(name, path, fn, groi);
name = path + fn + ".ASG";
/* Load the file into memory */
/*$I-*/
assign(f, name);
reset(f, 1);
io = ioresult;
if (io != 0)
switch (io) {
case 2:
loaderror("File not found!", '8');
break;
case 3:
loaderror("Directory not found!", '3');
break;
default:
loaderror(string("Error no.") + strf(io), '1');
}
if (bug) return;
seek(f, 11);
blockread(f, id4, 4);
if (id4 == avaricius_file) {
loaderror("That's an Avaricius file!", '1');
close(f);
return;
}
seek(f, 177); /* bypass ednafirst */
blockread(f, eh, sizeof(eh)); /* load ednahead */
/* Check ednahead for errors */
{
if ((eh.id != ednaid) || (eh.revision != 2)) loaderror("Not an EDNA file!", '7');
else if (eh.number != 2) loaderror(string("That file was saved by ") + eh.shortname + '!', '1');
}
if (bug) {
close(f);
return;
}
len2load = eh.len;
if (eh.len != (cardinal)sizeof(dna)) {
if (holdthedawn) {
holdthedawn = false;
dawn();
}
display("\233\26Warning: \3\rEDNA size doesn't match.\f");
if (eh.len > (cardinal)sizeof(dna))
len2load = sizeof(dna); /* BIGGER than ours */
else fillchar(dna, sizeof(dna), '\0'); /* Otherwise, smaller. */
}
blockread(f, dna, len2load);
for (fv = 1; fv <= numtr; fv ++) {
triptype &with = tr[fv];
if (with.quick) done();
} /* Deallocate sprite */
do {
blockread(f, fv, 1);
if (fv != 177) tr[fv].loaddata(f);
} while (!(fv == 177));
blockread(f, times, sizeof(times)); /* Timeout.times: Timers. */
blockread(f, seq, sizeof(seq)); /* Sequencer information. */
close(f);
seescroll = true; /* This prevents display of the new sprites before the
new picture is loaded. */
if (holdthedawn) {
holdthedawn = false;
dawn();
}
display(string('\6') + "Loaded: " + '\22' + name + '\3' + "\r\r" + eh.desc + "\r\r" + "saved on " +
expanddate(eh.d, eh.m, eh.y) + '.');
forget_chunks();
minor_redraw();
whereis[pavalot] = dna.room;
/* showscore;*/
alive = true;
objectlist();
/*$I+*/
enid_filename = name;
}
void dir(string where);
static string path, groi;
static void showheader() {
display(string("Dir: ") + path + "\r\r\4");
}
void dir(string where)
/* OK, it worked in Avaricius, let's do it in Avalot! */
{
searchrec s;
byte count;
if ((where != "") && (!(set::of('\\', ':', eos).has(where[length(where)]))))
where = where + '\\';
fsplit(where, path, groi, groi);
path = path + "*.asg";
count = 0;
findfirst(path, anyfile, s);
showheader();
while (doserror == 0) {
count += 1;
if (count == 11) {
display("\r\nPress Enter...");
showheader();
count = 1;
}
display(s.name + "\r\4");
findnext(s);
}
if (count == 0)
display("No files found!");
else display("\nThat's all!");
}
void avvy_background() /* Not really a filing procedure,
but it's only called just before edna_load, so I thought I'd put it
in Enid instead of, say, Lucerna. */
{
/* port[$3c4]:=2; port[$3ce]:=4; port[$3C5]:=1; port[$3CF]:=1; { Blue. }*/
/*
asm
mov dx,$3c4; mov al,2; out dx,al; { Set up the VGA to use the "blue" }
mov dx,$3ce; mov al,4; out dx,al; { register. }
mov dx,$3c5; mov al,1; out dx,al;
mov dx,$3cf; out dx,al;
mov bx,$A000; call far ptr @drawup;
mov bx,$A400; call far ptr @drawup;
jmp @the_end;
@drawup:
mov es,bx; { The segment to copy it to... }
mov di,$370; { The offset (10 pixels down, plus 1 offset.) }
mov cx,10;
mov ax,$AA4A; call far ptr @sameline; { Print "AVVY" }
mov ax,$AEAA; call far ptr @sameline;
mov ax,$A4EA; call far ptr @sameline;
mov ax,$44A4; call far ptr @sameline;
mov cx,9;
mov ax,$AAA4; call far ptr @sameline; { Print "YAVV" }
mov ax,$AAEA; call far ptr @sameline;
mov ax,$AA4E; call far ptr @sameline;
mov ax,$444A; call far ptr @sameline;
mov ax,$4AAA; call far ptr @sameline; { Print "VYAV" }
mov ax,$AAAE; call far ptr @sameline;
mov ax,$EAA4; call far ptr @sameline;
mov ax,$A444; call far ptr @sameline;
mov ax,$A4AA; call far ptr @sameline; { Print "VVYA" }
mov ax,$EAAA; call far ptr @sameline;
mov ax,$4EAA; call far ptr @sameline;
mov ax,$4A44; call far ptr @sameline;
ret;
{ Replicate the same line many times. }
@sameline:
{ Requires:
what to copy in AX,
how many lines in CX, and
original offset in DI. }
push cx;
push di;
@samelineloop:
push cx;
mov cx,40; { No. of times to repeat it on one line. }
repz stosw; { Fast word-copying }
pop cx;
add di,1200; { The next one will be 16 lines down. }
loop @samelineloop;
pop di;
add di,80;
pop cx;
ret;
@the_end:
end;
*/
blitfix();
}
void to_sundry(sundry &sund) {
{
sund.qenid_filename = enid_filename;
sund.qsoundfx = soundfx;
sund.qthinks = thinks;
sund.qthinkthing = thinkthing;
}
}
void from_sundry(sundry sund) {
{
enid_filename = sund.qenid_filename;
soundfx = sund.qsoundfx;
thinks = sund.qthinks;
thinkthing = sund.qthinkthing;
}
}
void restore_dna() {
word here, fv;
sundry sund;
move(mem[storage_seg * storage_ofs + 3], dna, sizeof(dna));
move(mem[storage_seg * storage_ofs + 3 + sizeof(dna)], times, sizeof(times));
move(mem[storage_seg * storage_ofs + 3 + sizeof(dna) + sizeof(times)],
seq, sizeof(seq));
move(mem[storage_seg * storage_ofs + 3 + sizeof(dna) + sizeof(times) + sizeof(seq)],
sund, sizeof(sund));
from_sundry(sund);
here = storage_ofs + 3 + sizeof(dna) + sizeof(times) + sizeof(seq) + sizeof(sund);
do {
fv = mem[storage_seg * here];
here += 1;
if (fv != 177) tr[fv].load_data_from_mem(here);
} while (!(fv == 177));
}
void edna_reload() {
restore_dna();
seescroll = true; /* This prevents display of the new sprites before the
new picture is loaded. */
major_redraw();
whereis[pavalot] = dna.room;
alive = true;
objectlist();
if (holdthedawn) {
holdthedawn = false;
dawn();
}
}
void back_to_bootstrap(byte what) {
byte fv;
word here;
sundry sund;
mem[storage_seg * storage_ofs] = what; /* Save the operation code. */
to_sundry(sund); /* Save the sundry information. */
/* Save the DNA, times and sequencer info: */
move(dna, mem[storage_seg * storage_ofs + 3], sizeof(dna));
move(times, mem[storage_seg * storage_ofs + 3 + sizeof(dna)], sizeof(times));
move(seq, mem[storage_seg * storage_ofs + 3 + sizeof(dna) + sizeof(times)],
sizeof(seq));
move(sund,
mem[storage_seg * storage_ofs + 3 + sizeof(dna) + sizeof(times) + sizeof(seq)],
sizeof(sund));
here = storage_ofs + 3 + sizeof(dna) + sizeof(times) + sizeof(seq) + sizeof(sund);
for (fv = 1; fv <= numtr; fv ++) {
triptype &with = tr[fv];
if (with.quick) {
mem[storage_seg * here] = fv;
here += 1;
save_data_to_mem(here);
}
}
mem[storage_seg * here] = 177;
exit(77); /* Code to return to the Bootstrap. */
}
boolean there_was_a_problem() {
boolean there_was_a_problem_result;
there_was_a_problem_result = bug;
return there_was_a_problem_result;
}
} // End of namespace Avalanche.