aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/avalanche/1stoff.cpp57
-rw-r--r--engines/avalanche/access.cpp170
-rw-r--r--engines/avalanche/access.h9
-rw-r--r--engines/avalanche/acci.cpp1671
-rw-r--r--engines/avalanche/acci.h223
-rw-r--r--engines/avalanche/also.cpp1028
-rw-r--r--engines/avalanche/andexor.cpp122
-rw-r--r--engines/avalanche/andexor2.cpp133
-rw-r--r--engines/avalanche/andextst.cpp64
-rw-r--r--engines/avalanche/arch.cpp122
-rw-r--r--engines/avalanche/arch.h10
-rw-r--r--engines/avalanche/avalot9.cpp114
-rw-r--r--engines/avalanche/avbkgrnd.cpp88
-rw-r--r--engines/avalanche/avmenu.cpp312
-rw-r--r--engines/avalanche/avvyans.cpp84
-rw-r--r--engines/avalanche/avvyans2.cpp185
-rw-r--r--engines/avalanche/avvymonk.cpp72
-rw-r--r--engines/avalanche/bakchunk.cpp28
-rw-r--r--engines/avalanche/basher.cpp385
-rw-r--r--engines/avalanche/basher.h40
-rw-r--r--engines/avalanche/bootstrp.cpp349
-rw-r--r--engines/avalanche/cadburys.cpp109
-rw-r--r--engines/avalanche/cadburys.h41
-rw-r--r--engines/avalanche/celer.cpp472
-rw-r--r--engines/avalanche/celer.h53
-rw-r--r--engines/avalanche/ch_egats.cpp155
-rw-r--r--engines/avalanche/charmap.cpp30
-rw-r--r--engines/avalanche/chunker.cpp86
-rw-r--r--engines/avalanche/chunkxf1.cpp259
-rw-r--r--engines/avalanche/chunkxf2.cpp192
-rw-r--r--engines/avalanche/chunkxf3.cpp250
-rw-r--r--engines/avalanche/chunkxf4.cpp285
-rw-r--r--engines/avalanche/chunkxf5.cpp244
-rw-r--r--engines/avalanche/chunkxf6.cpp251
-rw-r--r--engines/avalanche/chunkxf7.cpp236
-rw-r--r--engines/avalanche/chunkxf8.cpp243
-rw-r--r--engines/avalanche/chunkxf9.cpp237
-rw-r--r--engines/avalanche/chunkxfa.cpp240
-rw-r--r--engines/avalanche/chunkxfb.cpp238
-rw-r--r--engines/avalanche/chunkxfc.cpp236
-rw-r--r--engines/avalanche/chunkxfd.cpp236
-rw-r--r--engines/avalanche/chunkxfe.cpp236
-rw-r--r--engines/avalanche/chunkxff.cpp236
-rw-r--r--engines/avalanche/chunkxfg.cpp236
-rw-r--r--engines/avalanche/chunkxfh.cpp237
-rw-r--r--engines/avalanche/chunkxfi.cpp246
-rw-r--r--engines/avalanche/chunkxfj.cpp237
-rw-r--r--engines/avalanche/chunkxfk.cpp237
-rw-r--r--engines/avalanche/chunkxfl.cpp127
-rw-r--r--engines/avalanche/clock.cpp60
-rw-r--r--engines/avalanche/closing.cpp119
-rw-r--r--engines/avalanche/closing.h15
-rw-r--r--engines/avalanche/convert.cpp79
-rw-r--r--engines/avalanche/convmous.cpp80
-rw-r--r--engines/avalanche/credits.cpp88
-rw-r--r--engines/avalanche/displtxt.cpp34
-rw-r--r--engines/avalanche/dropdown.cpp802
-rw-r--r--engines/avalanche/dropdown.h94
-rw-r--r--engines/avalanche/dwidth.cpp20
-rw-r--r--engines/avalanche/edhead.cpp86
-rw-r--r--engines/avalanche/edna.cpp337
-rw-r--r--engines/avalanche/enhanced.cpp86
-rw-r--r--engines/avalanche/enhanced.h22
-rw-r--r--engines/avalanche/enid.cpp581
-rw-r--r--engines/avalanche/enid.h22
-rw-r--r--engines/avalanche/filer.cpp791
-rw-r--r--engines/avalanche/fileunit.cpp1118
-rw-r--r--engines/avalanche/fileunit.h7
-rw-r--r--engines/avalanche/filing.cpp144
-rw-r--r--engines/avalanche/folktemp.cpp79
-rw-r--r--engines/avalanche/fontslid.cpp25
-rw-r--r--engines/avalanche/frere.cpp102
-rw-r--r--engines/avalanche/g-room.cpp413
-rw-r--r--engines/avalanche/golden.cpp437
-rw-r--r--engines/avalanche/gyro.cpp532
-rw-r--r--engines/avalanche/gyro.h702
-rw-r--r--engines/avalanche/help.cpp225
-rw-r--r--engines/avalanche/help2.cpp244
-rw-r--r--engines/avalanche/helpbak.cpp161
-rw-r--r--engines/avalanche/helpbak.h11
-rw-r--r--engines/avalanche/helper.cpp282
-rw-r--r--engines/avalanche/helper.h11
-rw-r--r--engines/avalanche/hibits.cpp27
-rw-r--r--engines/avalanche/highs.cpp116
-rw-r--r--engines/avalanche/highs.h9
-rw-r--r--engines/avalanche/hiz.cpp287
-rw-r--r--engines/avalanche/incline.cpp172
-rw-r--r--engines/avalanche/incline.h10
-rw-r--r--engines/avalanche/initxf.cpp32
-rw-r--r--engines/avalanche/inputtes.cpp47
-rw-r--r--engines/avalanche/intro.cpp596
-rw-r--r--engines/avalanche/ints.cpp29
-rw-r--r--engines/avalanche/joysetup.cpp97
-rw-r--r--engines/avalanche/joystick.cpp183
-rw-r--r--engines/avalanche/joystick.h22
-rw-r--r--engines/avalanche/loading.cpp23
-rw-r--r--engines/avalanche/logger.cpp210
-rw-r--r--engines/avalanche/logger.h33
-rw-r--r--engines/avalanche/lucerna.cpp1489
-rw-r--r--engines/avalanche/lucerna.h76
-rw-r--r--engines/avalanche/magic2.cpp37
-rw-r--r--engines/avalanche/magidraw.cpp34
-rw-r--r--engines/avalanche/magishuf.cpp60
-rw-r--r--engines/avalanche/make!.cpp62
-rw-r--r--engines/avalanche/makeregi.cpp142
-rw-r--r--engines/avalanche/makesez.cpp47
-rw-r--r--engines/avalanche/makevmou.cpp270
-rw-r--r--engines/avalanche/menuxf.cpp48
-rw-r--r--engines/avalanche/minstran.cpp37
-rw-r--r--engines/avalanche/newsprit.cpp124
-rw-r--r--engines/avalanche/nim.cpp381
-rw-r--r--engines/avalanche/nimdraw.cpp94
-rw-r--r--engines/avalanche/nimunit.cpp443
-rw-r--r--engines/avalanche/nimunit.h18
-rw-r--r--engines/avalanche/oldfiler.cpp260
-rw-r--r--engines/avalanche/oldhighs.cpp249
-rw-r--r--engines/avalanche/oldincln.cpp249
-rw-r--r--engines/avalanche/oldincln.h10
-rw-r--r--engines/avalanche/oldtrip.cpp448
-rw-r--r--engines/avalanche/oldtrip.h95
-rw-r--r--engines/avalanche/omtest.cpp177
-rw-r--r--engines/avalanche/oopmenu.cpp295
-rw-r--r--engines/avalanche/oopmenu.h82
-rw-r--r--engines/avalanche/overlap.cpp53
-rw-r--r--engines/avalanche/overscro.cpp53
-rw-r--r--engines/avalanche/particle.cpp233
-rw-r--r--engines/avalanche/pictemp.cpp65
-rw-r--r--engines/avalanche/pictemp2.cpp64
-rw-r--r--engines/avalanche/pingo.cpp229
-rw-r--r--engines/avalanche/pingo.h19
-rw-r--r--engines/avalanche/plottest.cpp42
-rw-r--r--engines/avalanche/preview1.cpp122
-rw-r--r--engines/avalanche/qintro.cpp277
-rw-r--r--engines/avalanche/qstars.cpp237
-rw-r--r--engines/avalanche/rawupd.cpp71
-rw-r--r--engines/avalanche/readsez.cpp80
-rw-r--r--engines/avalanche/reginam.cpp91
-rw-r--r--engines/avalanche/sackb1.cpp52
-rw-r--r--engines/avalanche/sackb1.h14
-rw-r--r--engines/avalanche/sackb3.cpp23
-rw-r--r--engines/avalanche/sackblas.cpp0
-rw-r--r--engines/avalanche/saving.cpp48
-rw-r--r--engines/avalanche/scr_1.cpp89
-rw-r--r--engines/avalanche/scr_2.cpp113
-rw-r--r--engines/avalanche/scr_3.cpp93
-rw-r--r--engines/avalanche/scr_4.cpp89
-rw-r--r--engines/avalanche/scr_5.cpp93
-rw-r--r--engines/avalanche/scr_9.cpp21
-rw-r--r--engines/avalanche/scrolls.cpp781
-rw-r--r--engines/avalanche/scrolls.h33
-rw-r--r--engines/avalanche/sequence.cpp92
-rw-r--r--engines/avalanche/sequence.h32
-rw-r--r--engines/avalanche/setup.cpp1268
-rw-r--r--engines/avalanche/seu.cpp977
-rw-r--r--engines/avalanche/seu_avvy.cpp90
-rw-r--r--engines/avalanche/sez.cpp0
-rw-r--r--engines/avalanche/sezedit.cpp406
-rw-r--r--engines/avalanche/sezunit.cpp76
-rw-r--r--engines/avalanche/sezunit.h42
-rw-r--r--engines/avalanche/sezxfr.cpp95
-rw-r--r--engines/avalanche/shell1.cpp36
-rw-r--r--engines/avalanche/shell2.cpp26
-rw-r--r--engines/avalanche/slope.cpp349
-rw-r--r--engines/avalanche/spread.cpp306
-rw-r--r--engines/avalanche/spread2.cpp855
-rw-r--r--engines/avalanche/squish.cpp455
-rw-r--r--engines/avalanche/ss_blank.cpp38
-rw-r--r--engines/avalanche/ss_clock.cpp84
-rw-r--r--engines/avalanche/stars.cpp562
-rw-r--r--engines/avalanche/status.cpp34
-rw-r--r--engines/avalanche/sticks.cpp90
-rw-r--r--engines/avalanche/sticks.h13
-rw-r--r--engines/avalanche/sunrise.cpp57
-rw-r--r--engines/avalanche/tempo.cpp77
-rw-r--r--engines/avalanche/test.cpp19
-rw-r--r--engines/avalanche/test2.cpp17
-rw-r--r--engines/avalanche/testblit.cpp49
-rw-r--r--engines/avalanche/testcard.cpp56
-rw-r--r--engines/avalanche/testenh.cpp18
-rw-r--r--engines/avalanche/timeout.cpp594
-rw-r--r--engines/avalanche/timeout.h229
-rw-r--r--engines/avalanche/travel.cpp64
-rw-r--r--engines/avalanche/trip.cpp139
-rw-r--r--engines/avalanche/trip.h17
-rw-r--r--engines/avalanche/trip3.cpp231
-rw-r--r--engines/avalanche/trip3.h20
-rw-r--r--engines/avalanche/trip42.cpp450
-rw-r--r--engines/avalanche/trip42.h90
-rw-r--r--engines/avalanche/trip5.cpp1888
-rw-r--r--engines/avalanche/trip5.h175
-rw-r--r--engines/avalanche/trip5tst.cpp135
-rw-r--r--engines/avalanche/trip5xf.cpp172
-rw-r--r--engines/avalanche/tripoop.cpp290
-rw-r--r--engines/avalanche/ttmenuxf.cpp112
-rw-r--r--engines/avalanche/unsquish.cpp524
-rw-r--r--engines/avalanche/viewdocs.cpp522
-rw-r--r--engines/avalanche/visa.cpp264
-rw-r--r--engines/avalanche/visa.h9
-rw-r--r--engines/avalanche/visatest.cpp84
-rw-r--r--engines/avalanche/waver.cpp0
-rw-r--r--engines/avalanche/xf_gover.cpp95
-rw-r--r--engines/avalanche/xf_help.cpp86
-rw-r--r--engines/avalanche/xf_visa.cpp178
-rw-r--r--engines/avalanche/xfbutton.cpp62
-rw-r--r--engines/avalanche/xfghost.cpp246
-rw-r--r--engines/avalanche/zapdraw.cpp38
206 files changed, 42098 insertions, 0 deletions
diff --git a/engines/avalanche/1stoff.cpp b/engines/avalanche/1stoff.cpp
new file mode 100644
index 0000000000..99198b4638
--- /dev/null
+++ b/engines/avalanche/1stoff.cpp
@@ -0,0 +1,57 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+/*#include "Dos.h"*/
+
+
+matrix<1,7,1,3,byte> cols;
+byte fv;
+
+void adjust()
+{
+ registers r;
+;
+ {;
+ ax=0x1012;
+ bx=1;
+ cx=2;
+ es=seg(cols);
+ dx=ofs(cols);
+
+ }
+
+ intr(0x10,r);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ textattr=0;
+ clrscr;
+
+ fillchar(cols,sizeof(cols),'\0');
+ adjust();
+
+ gotoxy(29,10); textattr=1; output << "Thorsoft of Letchworth";
+ gotoxy(36,12); textattr=2; output << "presents";
+
+ for( fv=1; fv <= 77; fv ++)
+ {;
+ delay(77);
+ if (fv<64) fillchar(cols[1],3,chr(fv));
+ if (fv>14) fillchar(cols[2],3,chr(fv-14));
+ adjust();
+ }
+
+ delay(100);
+
+ for( fv=63; fv >= 1; fv --)
+ {;
+ fillchar(cols,sizeof(cols),chr(fv));
+ delay(37);
+ adjust();
+ }
+
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/access.cpp b/engines/avalanche/access.cpp
new file mode 100644
index 0000000000..37c9649193
--- /dev/null
+++ b/engines/avalanche/access.cpp
@@ -0,0 +1,170 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ ACCESS The temporary Sez handler. */
+
+#define __access_implementation__
+
+
+#include "access.h"
+
+
+/*#include "Gyro.h"*/
+/*#include "Scrolls.h"*/
+/*#include "Acci.h"*/
+/*#include "Trip5.h"*/
+/*#include "Lucerna.h"*/
+
+
+boolean int_say_went_ok;
+
+void int_say(string filename, boolean bubble)
+ /* Internal use ONLY! */
+{
+ untyped_file f;
+;
+ /*$I-*/
+ assign(f,filename);
+ reset(f,1);
+ if (ioresult!=0)
+ {;
+ int_say_went_ok=false;
+ return;
+ }
+ bufsize=filesize(f);
+ blockread(f,buffer,bufsize);
+ if (bubble)
+ {;
+ bufsize += 1;
+ buffer[bufsize]='\2';
+ }
+ close(f);
+ /*$I+*/
+
+ calldrivers;
+
+ int_say_went_ok=true;
+}
+
+void dixi(char p, byte n)
+{; exit(153);
+ int_say(string('s')+p+strf(n)+".raw",false);
+}
+
+void talkto(byte whom)
+{
+ byte fv;
+ boolean no_matches;
+; exit(153);
+ if (person==pardon)
+ {;
+ person=chr(subjnumber);
+ subjnumber=0;
+ }
+
+ switch (chr(whom)) {
+ case pspludwick:
+
+ if ((dna.lustie_is_asleep) & (~ dna.obj[potion]))
+ {;
+ dixi('q',68);
+ dna.obj[potion]=true;
+ objectlist; points(3); return;
+ } else
+ {;
+ if (dna.talked_to_crapulus)
+ switch (dna.given2spludwick) { /* Spludwick - what does he need? */
+ /* 0 - let it through to use normal routine. */
+ case RANGE_2(1,2): {;
+ display(string("Can you get me ")+
+ get_better(spludwick_order[dna.given2spludwick])+", please?"+
+ "\232\2");
+ return;
+ }
+ break;
+ case 3: {;
+ dixi('q',30); /* need any help with the game? */
+ return;
+ }
+ break;
+ }
+ else dixi('q',42); /* Haven't talked to Crapulus. Go and talk to him. */
+ }
+ break;
+
+ case pibythneth: if (dna.givenbadgetoiby)
+ {;
+ dixi('q',33); /* Thanks a lot! */
+ return; /* And leave the proc. */
+ }
+ break; /* Or... just continue, 'cos he hasn't got it. */
+ case pdogfood: if (dna.wonnim)
+ {; /* We've won the game. */
+ dixi('q',6); /* "I'm Not Playing!" */
+ return; /* Zap back. */
+ }
+ break;
+ case payles: if (~ dna.ayles_is_awake)
+ {;
+ dixi('q',43); /* He's fast asleep! */
+ return;
+ }
+ break;
+ case pgeida: if (dna.geida_given_potion)
+ dna.geida_follows=true; else
+ {;
+ dixi('u',17);
+ return;
+ }
+ break;
+ }
+
+ if (whom>149) whom -= 149;
+
+ no_matches=true;
+ for( fv=1; fv <= numtr; fv ++)
+ if (tr[fv].a.accinum==whom)
+ {;
+ display(string('\23')+chr(fv+48)+'\4');
+ no_matches=false;
+ flush();
+ }
+
+ if (no_matches) display("\23\23\4");
+
+ if (subjnumber==0) /* For the moment... later we'll parse "say". */
+ int_say(string("ss")+strf(whom)+".raw",true);
+ else
+ {;
+ int_say(string("ss")+strf(whom)+'-'+strf(subjnumber)+".raw",true);
+ if (! int_say_went_ok) /* File not found! */
+ dixi('n',whom);
+ }
+
+ switch (chr(whom+149)) {
+ case pcrapulus:
+ {; /* Crapulus: get the badge - first time only */
+ dna.obj[badge]=true;
+ objectlist;
+ dixi('q',1); /* Circular from Cardiff. */
+ dna.talked_to_crapulus=true;
+
+ whereis[pcrapulus]=177; /* Crapulus walks off. */
+
+ tr[2].vanishifstill=true;
+ tr[2].walkto(4); /* Walks away. */
+
+ points(2);
+ }
+ break;
+
+ case payles: dixi('q',44); break; /* Can you get me a pen? */
+
+ }
+}
+
+
diff --git a/engines/avalanche/access.h b/engines/avalanche/access.h
new file mode 100644
index 0000000000..825deeb59d
--- /dev/null
+++ b/engines/avalanche/access.h
@@ -0,0 +1,9 @@
+#ifndef __access_h__
+#define __access_h__
+
+
+void dixi(char p, byte n);
+
+void talkto(byte whom);
+
+#endif
diff --git a/engines/avalanche/acci.cpp b/engines/avalanche/acci.cpp
new file mode 100644
index 0000000000..86fac18585
--- /dev/null
+++ b/engines/avalanche/acci.cpp
@@ -0,0 +1,1671 @@
+#include "ptoc.h"
+
+/* $D-*/
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ ACCIDENCE II The parser. */
+#define __acci_implementation__
+
+
+/*$V-*/
+
+#include "acci.h"
+
+/*#include "Gyro.h"*/
+/*#include "Lucerna.h"*/
+/*#include "Scrolls.h"*/
+/*#include "Pingo.h"*/
+/*#include "Trip5.h"*/
+/*#include "Visa.h"*/
+/*#include "Enid.h"*/
+/*#include "NimUnit.h"*/
+/*#include "Timeout.h"*/
+/*#include "Celer.h"*/
+/*#include "Highs.h"*/
+/*#include "Helper.h"*/
+/*#include "Sequence.h"*/
+
+
+byte fv;
+
+string wordnum(string x);
+static char whatsit;
+static word fv;
+static boolean gotcha;
+
+static void checkword(string& x) /* Checks word "fv". */
+{
+ {
+ vocab& with = words[fv];
+
+ if ((with.w==x) || ((copy(with.w,1,length(x))==x) && ! gotcha))
+ whatsit=chr(with.n);
+ if (with.w==x) gotcha=true;
+ }
+}
+
+string wordnum(string x)
+
+{
+ string wordnum_result;
+ if (x=="") { wordnum_result=""; return wordnum_result; }
+ whatsit=pardon; gotcha=false;
+ for( fv=nowords; fv >= 1; fv --) checkword(x);
+ wordnum_result=whatsit;
+ return wordnum_result;
+}
+
+void replace(string old1,string new1)
+{
+ byte q;
+
+ q=pos(old1,thats);
+ while (q!=0)
+ {
+ thats=copy(thats,1,q-1)+new1+copy(thats,q+length(old1),255);
+ q=pos(old1,thats);
+ }
+}
+
+/*procedure ninetydump;
+var f:file; y:integer; bit:byte; a:byte absolute $A000:800;
+begin
+ off;
+ assign(f,'avvydump.avd');
+ rewrite(f,1);
+ blockwrite(f,dna,177); { just anything }
+ for bit:=0 to 3 do
+ begin
+ port[$3c4]:=2; port[$3ce]:=4; port[$3C5]:=1 shl bit; port[$3CF]:=bit;
+ blockwrite(f,a,12080);
+ end;
+ close(f); on;
+ display('Dumped.');
+end;*/
+
+string rank()
+{
+ byte fv;
+
+ string rank_result;
+ for( fv=1; fv <= 8; fv ++)
+ if ((dna.score>=ranks[fv].score)
+ && (dna.score<ranks[fv+1].score))
+ {
+ rank_result=ranks[fv].title;
+ return rank_result;
+ }
+ return rank_result;
+}
+
+string totaltime()
+{
+ const real ticks_in_1_sec = (real)(65535)/3600;
+ word h,m,s; varying_string<70> a;
+
+ /* There are 65535 clock ticks in a second,
+ 1092.25 in a minute, and
+ 65535 in an hour. */
+ string totaltime_result;
+ h=trunc(dna.total_time/ticks_in_1_sec); /* No. of seconds. */
+ m=h % 3600; h=h / 3600;
+ s=m % 60; m=m / 60;
+
+ a="You've been playing for ";
+
+ if (h>0) a=a+strf(h)+" hours, ";
+ if ((m>0) || (h!=0)) a=a+strf(m)+" minutes and ";
+ a=a+strf(s)+" seconds.";
+
+ totaltime_result=a;
+ return totaltime_result;
+}
+
+void cheatparse(string codes);
+static word num;
+static integer e;
+
+static void number(string& codes)
+{
+ val(codes,num,e);
+}
+
+void cheatparse(string codes)
+{
+ char cmd;integer se,sx,sy;
+
+ if (~ cheat)
+ { /* put them off the scent! */
+ display("Have you gone dotty\??!");
+ return;
+ }
+ cmd=upcase(codes[2]); Delete(codes,1,2); /* strip header */
+ display("\6Ninety: \22\4");
+ switch (cmd) {
+ case 'R': {
+ number(codes); if (e!=0) return;
+ display(string("room swap to ")+codes+'.');
+ fliproom(num,1);
+ }
+ break;
+ case 'Z': { zonk; display("Zonk OK!"); } break;
+ case 'W': { wobble; display("Ow my head!"); } break;
+ case 'A': {
+ tr[1].done;
+ tr[1].init(1,true);
+ dna.user_moves_avvy=true;
+ alive=true;
+ display("Reincat.");
+ }
+ break;
+ case 'B': {
+ sx=tr[1].x;
+ sy=tr[1].y;
+ se=tr[1].face;
+ delavvy;
+ number(codes);
+ {
+ void& with = tr[1];
+
+ done;
+ init(num,true);
+ display(string("Become ")+codes+':'+"\r\r"+a.name+'\15'+a.comment);
+ appear(sx,sy,se);
+ }
+ }
+ break;
+/* 'D': ninetydump;*/
+ case 'G': play_nim; break;
+ case '±': display("\232\25"); break;
+ default: display("unknown code!");
+ }
+}
+
+void punctustrip(string& x) /* Strips punctuation from x. */
+{
+ const varying_string<32> punct = "~`!@#$%^&*()_+-={}[]:\"|;'\\,./<>?";
+ byte fv,p;
+
+ for( fv=1; fv <= 32; fv ++)
+ do {
+ p=pos(punct[fv-1],x);
+ if (p==0) flush(); /* <<< The first time I've ever used it! */
+ Delete(x,p,1);
+ } while (!false);
+}
+
+boolean do_pronouns();
+static boolean ambiguous;
+
+static void displaywhat(char ch, boolean animate) /* << it's an adjective! */
+{
+ byte ff; string z;
+
+ if (ch==pardon)
+ {
+ ambiguous=true;
+ if (animate) display("Whom?"); else display("What?");
+ } else
+ {
+ if (animate) display(string("{ ")+getname(ch)+" }");
+ else
+ {
+ z=get_better(ch);
+ if (z!="") display(string("{ ")+z+" }");
+ }
+ }
+}
+
+boolean do_pronouns()
+{
+ byte fv;
+
+ boolean do_pronouns_result;
+ ambiguous=false;
+ for( fv=1; fv <= length(thats); fv ++)
+ switch (thats[fv]) {
+ case '\310': {
+ displaywhat(him,true);
+ thats[fv]=him;
+ }
+ break;
+ case '\311': {
+ displaywhat(her,true);
+ thats[fv]=her;
+ }
+ break;
+ case '\312': {
+ displaywhat(it,false);
+ thats[fv]=it;
+ }
+ break;
+ }
+ do_pronouns_result=ambiguous;
+ return do_pronouns_result;
+}
+
+void store_interrogation(byte interrogation);
+
+
+static void lowercase()
+{
+ byte fv;
+
+ for( fv=1; fv <= length(current); fv ++)
+ if (set::of(range('A','Z'), eos).has(current[fv]))
+ current[fv] += 32;
+}
+
+
+
+static void propernouns()
+{
+ byte fv;
+
+ lowercase();
+ for( fv=2; fv <= length(current)-1; fv ++)
+ if (current[fv]==' ')
+ current[fv+1]=upcase(current[fv+1]);
+ current[1]=upcase(current[1]);
+}
+
+
+
+static void sayit() /* This makes Avalot say the response. */
+{
+ string x;
+
+ x=current; x[1]=upcase(x[1]);
+ display(string("\231")+x+'.'+'\2'+'\23'+'2');
+}
+
+void store_interrogation(byte interrogation)
+{
+ byte fv;
+
+
+ if (current=="") return;
+
+ /* Strip current: */
+ while ((current[1]==' ') && (current!="")) Delete(current,1,1);
+ while ((current[length(current)]==' ') && (current!="")) current[0] -= 1;
+
+ lose_timer(reason_cardiffsurvey); /* if you want to use any other timer,
+ put this into the case statement. */
+ switch (interrogation) {
+ case 1: {
+ lowercase(); sayit();
+ like2drink=current;
+ dna.cardiff_things=2;
+ }
+ break;
+ case 2: {
+ propernouns(); sayit();
+ favourite_song=current;
+ dna.cardiff_things=3;
+ }
+ break;
+ case 3: {
+ propernouns(); sayit();
+ worst_place_on_earth=current;
+ dna.cardiff_things=4;
+ }
+ break;
+ case 4: {
+ lowercase(); sayit();
+ fillchar(spare_evening,sizeof(spare_evening),'\261');
+ spare_evening=current;
+ dixi('z',5); /* His closing statement... */
+ tr[2].walkto(4); /* The end of the drawbridge */
+ tr[2].vanishifstill=true; /* Then go away! */
+ magics[2].op=nix;
+ dna.cardiff_things=5;
+ }
+ break;
+
+ case 99: store_high(current); break;
+ }
+ if (interrogation<4) cardiff_survey;
+}
+
+void clearwords()
+{
+ fillchar(realwords,sizeof(realwords),'\0');
+}
+
+void parse()
+{
+ byte n,fv,ff; string c,cc,thisword; varying_string<1> answer; boolean notfound;
+
+ /* first parsing - word identification */
+
+ thats=""; c=current+'\40'; n=1; polite=false;
+ verb=pardon; thing=pardon; thing2=pardon; person=pardon;
+ clearwords();
+ if (current[1]=='.')
+ { /* a cheat mode attempt */
+ cheatparse(current); thats=nowt; return;
+ } /* not our department! Otherwise... */
+
+ /* Are we being interrogated right now? */
+
+ if (interrogation>0)
+ {
+ store_interrogation(interrogation);
+ weirdword=true;
+ return;
+ }
+
+ cc=c; for( fv=1; fv <= length(c); fv ++) c[fv]=upcase(c[fv]);
+ while (c!="")
+ {
+ while ((c[1]=='\40') && (c!=""))
+ { Delete(c,1,1); Delete(cc,1,1); }
+ thisword=copy(c,1,pos("\40",c)-1);
+ realwords[n]=copy(cc,1,pos("\40",cc)-1);
+ punctustrip(c);
+
+ notfound=true;
+
+ if (thisword!="")
+ {
+ for( ff=1; ff <= 30; ff ++)
+ { /* Check Also, FIRST! */
+ if (pos(string(',')+thisword,also[ff][0])>0)
+ {
+ thats=thats+chr(99+ff);
+ notfound=false;
+ }
+ }
+ }
+
+ if (notfound)
+ {
+ answer=wordnum(thisword);
+ if (answer==pardon)
+ {
+ notfound=true;
+ thats=thats+pardon;
+ } else
+ thats=thats+wordnum(thisword);
+ n += 1;
+ }
+ Delete(c,1,pos("\40",c)); Delete(cc,1,pos("\40",cc));
+ }
+
+ if (pos("\376",thats)>0) unknown=realwords[pos("\376",thats)]; else unknown=""; replace("\377",""); /* zap noise words */
+ replace(string('\15')+'\342',"\1"); /* "look at" = "examine" */
+ replace(string('\15')+'\344',"\1"); /* "look in" = "examine" */
+ replace(string('\4')+'\343',"\21"); /* "get up" = "stand" */
+ replace(string('\4')+'\347',"\21"); /* "get down" = "stand"... well, why not? */
+ replace(string('\22')+'\344',"\2"); /* "go in" = "open [door]" */
+ replace(string('\34')+'\345',"\375"); /* "P' off" is a swear word */
+ replace(string('\4')+'\6',"\6"); /* "Take inventory" (remember Colossal Adventure?) */
+ replace(string('\50')+'\350',"\25"); /* "put on" = "don" */
+ replace(string('\4')+'\345',"\24"); /* "take off" = "doff" */
+
+ /* Words that could mean more than one person */
+ {
+ if (room==r__nottspub) replace("\314","\244"); /* Barman = Port */
+ else replace("\314","\232"); /* Barman = Malagauche */
+ switch (room) {
+ case r__aylesoffice: replace("\313","\243"); break; /* Monk = Ayles */
+ case r__musicroom: replace("\313","\246"); break; /* Monk = Jacques */
+ default: replace("\313","\242"); /* Monk = Ibythneth */
+ }
+ }
+
+ if (do_pronouns())
+ {
+ weirdword=true;
+ thats=nowt;
+ return;
+ }
+
+ /* second parsing - accidence */
+
+ subject=""; subjnumber=0; /* Find subject of conversation. */
+ for( fv=1; fv <= 11; fv ++)
+ if (set::of('`','\'', eos).has(realwords[fv][1]))
+ {
+ subjnumber=ord(thats[fv]);
+ thats[fv]=moved;
+ flush(); /* Only the second time I've used that! */
+ }
+ if (subjnumber==0) /* Still not found. */
+ for( fv=1; fv <= 10; fv ++)
+ if (thats[fv]=='\374') /* the word is "about", or something similar */
+ {
+ subjnumber=ord(thats[fv+1]);
+ thats[fv+1]='\0';
+ flush(); /* ...Third! */
+ }
+ if (subjnumber==0) /* STILL not found! Must be the word after "say". */
+ for( fv=1; fv <= 10; fv ++)
+ if ((thats[fv]=='\7') && ! (set::of('\0',range('\341','\345'), eos).has(thats[fv+1])))
+ { /* SAY not followed by a preposition */
+ subjnumber=ord(thats[fv+1]);
+ thats[fv+1]='\0';
+ flush(); /* ...Fourth! */
+ }
+
+ for( fv=length(thats); fv >= 1; fv --) /* Reverse order- so first'll be used */
+ switch (thats[fv]) {
+ case '\1' ... '\61':case '\375':case '\371': verb=thats[fv]; break;
+ case '\62' ... '\225': { thing2=thing; thing=thats[fv]; } break;
+ case '\226' ... '\307': person=thats[fv]; break;
+ case '\373': polite=true; break;
+ }
+
+ if ((unknown!="") && !
+ (set::of(vb_exam,vb_talk,vb_save,vb_load,vb_dir, eos).has(verb)))
+ {
+ display(string("Sorry, but I have no idea what `")+unknown+
+ "\" means. Can you rephrase it?");
+ weirdword=true;
+ } else weirdword=false;
+ if (thats=="") thats=nowt;
+
+ if (thing!=pardon) it=thing;
+ if (person!=pardon)
+ {
+ if (person<'\257') him=person; else her=person;
+ }
+}
+
+void examobj() /* Examine a standard object-thing */
+{
+ if (thing!=thinks) thinkabout(thing,a_thing);
+ switch (thing) {
+ case wine : switch (winestate) {
+ /* 4 is perfect wine. 0 is not holding the wine. */
+ case 1: dixi('t',1); break; /* Normal examine wine scroll */
+ case 2: dixi('d',6); break; /* Bad wine */
+ case 3: dixi('d',7); break; /* Vinegar */
+ }
+ break;
+ case onion: if (rotten_onion)
+ dixi('q',21); /* Yucky onion. */
+ else
+ dixi('t',18);
+ break; /* Normal onion scroll */
+ default:
+ dixi('t',ord(thing)); /* <<< Ordinarily */
+ }
+}
+
+boolean personshere() /* Person equivalent of "holding" */
+{
+ boolean personshere_result;
+ if ((person==pardon) || (person=='\0')
+ || (whereis[person]==dna.room)) personshere_result=true;
+ else {
+ if (person<'\257') display("H\4"); else display("Sh\4");
+ display("e isn't around at the moment.");
+ personshere_result=false;
+ }
+ return personshere_result;
+}
+
+void exampers()
+{
+ if (personshere())
+ {
+ if (thing!=thinks) thinkabout(person,a_person);
+ person -= 149;
+ switch (person) { /* Special cases */
+ case '\13': if (wonnim)
+ {
+ dixi('Q',8); /* "I'm Not Playing!" */
+ return;
+ }
+ break;
+ case '\11': if (lustie_is_asleep)
+ { dixi('Q',65); /* He's asleep. (65! Wow!) */ return; }
+ break;
+ }
+ /* Otherwise... */ dixi('p',ord(person));
+ } /* And afterwards... */
+ switch (person) {
+ case '\16': if (~ dna.ayles_is_awake) dixi('Q',13); break; /* u.f.s.? */
+ }
+}
+
+boolean holding()
+{
+ boolean holding_result;
+ if (set::of(range('\63','\143'), eos).has(thing)) { holding_result=true; return holding_result; } /* Also */
+ holding_result=false;
+ if (thing>'\144') display("Be reasonable!"); else
+ if (~ dna.obj[thing]) /* verbs that need "thing" to be in the inventory */
+ display("You're not holding it, Avvy."); else
+ holding_result=true;
+ return holding_result;
+}
+
+void examine();
+
+static void special(boolean before)
+{
+ switch (dna.room) {
+ case r__yours: switch (thing) {
+ case '\66': if (before) show_one(5); else show_one(6); break;
+ }
+ break;
+ }
+}
+
+void examine()
+{
+ /* Examine. EITHER it's an object OR it's an Also OR it's a person OR
+ it's something else. */
+ if ((person==pardon) && (thing!=pardon))
+ {
+ if (holding())
+ switch (thing) { /* remember it's been Slipped- ie subtract 49 */
+ case '\1' ... '\61' : examobj(); break; /* Standard object */
+ case '\62' ... '\144' : {
+ special(true);
+ display(also[ord(thing)-50][1]); /* Also thing */
+ special(false);
+ }
+ break;
+ }
+ } else
+ if (person!=pardon) exampers();
+ else display("It's just as it looks on the picture."); /* don't know- guess */
+}
+
+void inv() /* the time-honoured command... */
+{
+ char fv; byte q;
+
+ q=0; display(string("You're carrying ")+'\4');
+ {
+ for( fv='\1'; fv <= numobjs; fv ++)
+ if (obj[fv])
+ {
+ q += 1; if (q==carrying) display(string("and ")+'\4');
+ display(get_better(fv)+'\4');
+ if (fv==wearing) display(string(", which you're wearing")+'\4');
+ if (q<carrying) display(string(", ")+'\4');
+ }
+ if (wearing==nowt) display("...\r\r...and you're stark naked!"); else
+ display('.');
+ }
+}
+
+void swallow() /* Eat something. */
+{
+ switch (thing) {
+ case wine: switch (dna.winestate) {
+ /* 4 is perfect */
+ case 1: {
+ if (dna.teetotal) { dixi('D',6); return; }
+ dixi('U',1); wobble; dixi('U',2);
+ dna.obj[wine]=false; objectlist;
+ have_a_drink();
+ }
+ break;
+ case 2:case 3: dixi('d',8); break; /* You can't drink it! */
+ }
+ break;
+ case potion: { background(4); dixi('U',3); gameover; background(0); } break;
+ case ink: dixi('U',4); break;
+ case chastity: dixi('U',5); break;
+ case mushroom: {
+ dixi('U',6);
+ gameover;
+ }
+ break;
+ case onion: if (dna.rotten_onion) dixi('U',11);
+ else {
+ dixi('U',8);
+ dna.obj[onion]=false;
+ objectlist;
+ }
+ break;
+ default:
+ if (set::of(r__argentpub,r__nottspub, eos).has(dna.room))
+ display("Try BUYing things before you drink them!");
+ else
+ display("The taste of it makes you retch!");
+ /* Constant- leave this one */
+ }
+}
+
+void others()
+ /* This lists the other people in the room. */
+{
+ char fv;
+ byte num_people,this_person,here;
+
+
+ num_people=0;
+ this_person=0;
+ here=dna.room;
+
+ for( fv='\227'; fv <= '\262'; fv ++) /* Start at 151 so we don't list Avvy himself! */
+ if (whereis[fv]==here)
+ num_people += 1;
+
+ /* If nobody's here, we can cut out straight away. */
+
+ if (num_people==0) return; /* Leave the procedure. */
+
+ for( fv='\227'; fv <= '\262'; fv ++)
+ if (whereis[fv]==here)
+ {
+ this_person += 1;
+ if (this_person==1) /* First on the list. */
+ display(getname(fv)+'\4'); else
+ if (this_person<num_people) /* The middle... */
+ display(string(", ")+getname(fv)+'\4'); else
+ display(string(" and ")+getname(fv)+'\4'); /* The end. */
+ }
+
+ if (num_people==1) display(" is\4"); else display(" are\4");
+
+ display(" here."); /* End and display it. */
+}
+
+void lookaround()
+/* This is called when you say "look." */
+{
+ display(also[0][1]);
+ switch (dna.room) {
+ case r__spludwicks: if (dna.avaricius_talk>0) dixi('q',23); else others(); break;
+ case r__robins: {
+ if (dna.tied_up) dixi('q',38);
+ if (dna.mushroom_growing) dixi('q',55);
+ }
+ break;
+ case r__insidecardiffcastle: if (~ dna.taken_pen) dixi('q',49); break;
+ case r__lustiesroom: if (dna.lustie_is_asleep) dixi('q',65); break;
+ case r__catacombs: switch (dna.cat_y*256+dna.cat_x) {
+ case 258 : dixi('q',80); break; /* Inside art gallery */
+ case 514 : dixi('q',81); break; /* Outside ditto */
+ case 260 : dixi('q',82); break; /* Outside Geida's room. */
+ }
+ break;
+ default: others();
+ }
+}
+
+void opendoor() /* so whaddya THINK this does?! */
+{
+ byte fv;
+
+ switch (dna.room) { /* Special cases. */
+ case r__yours: if (infield(2))
+ { /* Opening the box. */
+ thing='\66'; /* The box. */ person=pardon;
+ examine();
+ return;
+ }
+ break;
+ case r__spludwicks: if (thing=='\75') {
+ dixi('q',85);
+ return;
+ }
+ break;
+ }
+
+
+ if ((~ dna.user_moves_avvy) & (dna.room!=r__lusties))
+ return; /* No doors can open if you can't move Avvy. */
+ for( fv=9; fv <= 15; fv ++)
+ if (infield(fv))
+ {
+ { void& with = portals[fv];
+ switch (op) {
+ case exclaim: { tr[1].bounce; dixi('x',data); } break;
+ case transport: fliproom(hi(data),lo(data)); break;
+ case unfinished: {
+ tr[1].bounce;
+ display("\7Sorry.\3\rThis place is not available yet!");
+ }
+ break;
+ case special: call_special(data); break;
+ case mopendoor: open_the_door(hi(data),lo(data),fv); break;
+ }}
+ return;
+ }
+ if (dna.room==r__map)
+ display(string("Avvy, you can complete the whole game without ever going ")+
+ "to anywhere other than Argent, Birmingham, Cardiff, "+
+ "Nottingham and Norwich.");
+ else display("Door? What door?");
+}
+
+void putproc();
+
+
+static void silly()
+{
+ display("Don't be silly!");
+}
+
+void putproc() /* Called when you call vb_put. */
+{
+ char temp;
+
+
+ if (! holding()) return;
+ thing2 -= 49; /* Slip the second object */
+ temp=thing; thing=thing2; if (! holding()) return;
+ thing=temp;
+
+ /* Thing is the thing which you're putting in. Thing2 is where you're
+ putting it. */
+ /* Convenience thing. */
+ switch (thing2) {
+ case wine: if (thing==onion)
+ {
+ if (dna.rotten_onion)
+ display(string("That's a bit like shutting the stable door after the ")+
+ "horse has bolted!");
+ else { /* Put onion into wine? */
+ if (dna.winestate!=3)
+ display("\6Oignon au vin\22 is a bit too strong for your tastes!");
+ else { /* Put onion into vinegar! Yes! */
+ onion_in_vinegar=true;
+ points(7);
+ dixi('u',9);
+ }
+ }
+ } else silly();
+ break;
+
+ case '\66': if (room==1) /* Put something into the box. */
+ {
+ if (box_contents!=nowt)
+ display(string("There's something in the box already, Avvy. Try taking")+
+ " that out first.");
+ else
+ switch (thing) {
+ case money: display("You'd better keep some ready cash on you!"); break;
+ case bell: display("That's a silly place to keep a bell."); break;
+ case bodkin: display("But you might need it!"); break;
+ case onion: display("Just give it to Spludwick, Avvy!"); break;
+ default:
+ { /* Put the object into the box... */
+ if (wearing==thing)
+ display(string("You'd better take ")+get_better(thing)+" off first!");
+ else
+ {
+ show_one(5); /* Open box. */
+ box_contents=thing;
+ dna.obj[thing]=false;
+ objectlist;
+ display("OK, it's in the box.");
+ show_one(6); /* Shut box. */
+ }
+ }
+ }
+ } else silly();
+ break;
+
+ default: silly();
+ }
+}
+
+boolean give2spludwick();
+
+ /* The result of this fn is whether or not he says "Hey, thanks!" */
+static void not_in_order()
+{
+ display(string("Sorry, I need the ingredients in the right order for this potion.")+
+ " What I need next is "+
+ get_better(spludwick_order[dna.given2spludwick])+".\232\2");
+}
+
+
+
+static void go_to_cauldron()
+{
+ tr[2].call_eachstep=false; /* Stops Geida_Procs. */
+ set_up_timer(1,procspludwick_goes_to_cauldron,reason_spludwalk);
+ tr[2].walkto(2);
+}
+
+boolean give2spludwick()
+
+{
+ boolean give2spludwick_result;
+ {
+
+ give2spludwick_result=false;
+
+ if (spludwick_order[given2spludwick]!=thing)
+ {
+ not_in_order();
+ return give2spludwick_result;
+ }
+
+ switch (thing) {
+ case onion:
+ {
+ obj[onion]=false;
+ if (rotten_onion)
+ dixi('q',22);
+ else {
+ given2spludwick += 1;
+ dixi('q',20);
+ go_to_cauldron();
+ points(3);
+ }
+ objectlist;
+ }
+ break;
+ case ink: {
+ obj[ink]=false;
+ objectlist;
+ given2spludwick += 1;
+ dixi('q',24);
+ go_to_cauldron();
+ points(3);
+ }
+ break;
+ case mushroom: {
+ obj[mushroom]=false;
+ dixi('q',25);
+ points(5);
+ given2spludwick += 1;
+ go_to_cauldron();
+ obj[potion]=true;
+ objectlist;
+ }
+ break;
+ default: give2spludwick_result=true;
+ }
+ }
+ return give2spludwick_result;
+}
+
+void have_a_drink()
+{
+ {
+ alcohol += 1;
+ if (alcohol==5)
+ {
+ obj[key]=true; /* Get the key. */
+ teetotal=true;
+ avvy_is_awake=false;
+ avvy_in_bed=true;
+ objectlist;
+ dusk;
+ hang_around_for_a_while;
+ fliproom(1,1);
+ background(14);
+ new_game_for_trippancy; /* Not really */
+ }
+ }
+}
+
+void cardiff_climbing()
+{
+ if (dna.standing_on_dais)
+ { /* Clamber up. */
+ display("You climb down, back onto the floor.");
+ dna.standing_on_dais=false;
+ apped(1,3);
+ } else
+ { /* Clamber down. */
+ if (infield(1))
+ {
+ display("You clamber up onto the dais.");
+ dna.standing_on_dais=true;
+ apped(1,2);
+ } else
+ display("Get a bit closer, Avvy.");
+ }
+}
+
+void stand_up();
+
+ /* Called when you ask Avvy to stand. */
+static void already()
+{
+ display("You're already standing!");
+}
+
+void stand_up()
+{
+ switch (dna.room) {
+ case r__yours: /* Avvy isn't asleep. */
+ if (avvy_in_bed) /* But he's in bed. */
+ {
+ if (teetotal)
+ {
+ dixi('d',12);
+ background(0);
+ dixi('d',14);
+ }
+ tr[1].visible=true;
+ user_moves_avvy=true;
+ apped(1,2);
+ dna.rw=left;
+ show_one(4); /* Picture of empty pillow. */
+ points(1);
+ avvy_in_bed=false;
+ lose_timer(reason_arkata_shouts);
+ } else already();
+ break;
+
+ case r__insidecardiffcastle: cardiff_climbing(); break;
+
+ case r__nottspub: if (sitting_in_pub) {
+ show_one(4); /* Not sitting down. */
+ tr[1].visible=true; /* But standing up. */
+ apped(1,4); /* And walking away. */
+ sitting_in_pub=false; /* Really not sitting down. */
+ user_moves_avvy=true; /* And ambulant. */
+ } else already();
+ break;
+ default: already();
+ }
+}
+
+void getproc(char thing)
+{
+ switch (room) {
+ case r__yours:
+ if (infield(2))
+ {
+ if (box_contents==thing)
+ {
+ show_one(5);
+ display("OK, I've got it.");
+ obj[thing]=true; objectlist;
+ box_contents=nowt;
+ show_one(6);
+ } else
+ display(string("I can't see ")+get_better(thing)+" in the box.");
+ } else dixi('q',57);
+ break;
+ case r__insidecardiffcastle:
+ switch (thing) {
+ case pen:
+ {
+ if (infield(2))
+ { /* Standing on the dais. */
+
+ if (dna.taken_pen)
+ display("It's not there, Avvy.");
+ else
+ { /* OK: we're taking the pen, and it's there. */
+ show_one(4); /* No pen there now. */
+ call_special(3); /* Zap! */
+ dna.taken_pen=true;
+ dna.obj[pen]=true;
+ objectlist;
+ display("Taken.");
+ }
+ } else if (dna.standing_on_dais) dixi('q',53); else dixi('q',51);
+ }
+ break;
+ case bolt: dixi('q',52); break;
+ default: dixi('q',57);
+ }
+ break;
+ case r__robins: if ((thing==mushroom) & (infield(1)) & (dna.mushroom_growing))
+ {
+ show_one(3);
+ display("Got it!");
+ dna.mushroom_growing=false;
+ dna.taken_mushroom=true;
+ dna.obj[mushroom]=true;
+ objectlist;
+ points(3);
+ } else dixi('q',57);
+ break;
+ default: dixi('q',57);
+ }
+}
+
+void give_geida_the_lute()
+{
+ {
+ if (room!=r__lustiesroom)
+ {
+ display("Not yet. Try later!\232\2");
+ return;
+ }
+ dna.obj[lute]=false;
+ objectlist;
+ dixi('q',64); /* She plays it. */
+
+ /* And the rest has been moved to Timeout... under give_lute_to_Geida. */
+
+ set_up_timer(1,procgive_lute_to_geida,reason_geida_sings);
+ back_to_bootstrap(4);
+ }
+}
+
+void play_harp()
+{
+ if (infield(7))
+ musical_scroll;
+ else display("Get a bit closer to it, Avvy!");
+}
+
+void winsequence()
+{
+ dixi('q',78);
+ first_show(7); then_show(8); then_show(9);
+ start_to_close;
+ set_up_timer(30,procwinning,reason_winning);
+}
+
+void person_speaks()
+{
+ boolean found; byte fv; char cfv;
+
+
+ if ((person==pardon) || (person=='\0'))
+ {
+ if ((him==pardon) || (whereis[him]!=dna.room)) person=her;
+ else person=him;
+ }
+
+ if (whereis[person]!=dna.room)
+ {
+ display("\231\4"); /* Avvy himself! */
+ return;
+ }
+
+ found=false; /* The person we're looking for's code is in Person. */
+
+ for( fv=1; fv <= numtr; fv ++)
+ if (tr[fv].quick & (chr(tr[fv].a.accinum+149)==person))
+ {
+ display(string('\23')+chr(fv+48)+'\4');
+ found=true;
+ }
+
+ if (! found)
+ for( fv=10; fv <= 25; fv ++)
+ { void& with = quasipeds[fv];
+ if ((who==person) && (room==dna.room))
+ {
+ display(string('\23')+chr(fv+55)+'\4');
+ }}
+}
+
+void do_that();
+
+static void heythanks()
+{
+ person_speaks();
+ display("Hey, thanks!\2(But now, you've lost it!)");
+ dna.obj[thing]=false;
+}
+
+void do_that()
+{
+ const array<'\63','\72',varying_string<6> > booze = {{"Bitter","GIED","Whisky","Cider","","","","Mead"}};
+ byte fv,ff; integer sx,sy; boolean ok;
+
+
+ if (thats==nowt) { thats=""; return; }
+ if (weirdword) return;
+ if (thing<'\310') thing -= 49; /* "Slip" */
+
+ if ((~ alive) &
+ ! (set::of(vb_load,vb_save,vb_quit,vb_info,vb_help,vb_larrypass,
+ vb_phaon,vb_boss,vb_cheat,vb_restart,vb_dir,vb_score,
+ vb_highscores,vb_smartalec, eos).has(verb)))
+ {
+ display(string("You're dead, so don't talk. What are you, a ghost ")+
+ "or something? Try restarting, or restoring a saved game!"); return;
+ }
+
+ if ((~ dna.avvy_is_awake) &
+ ! (set::of(vb_load,vb_save,vb_quit,vb_info,vb_help,vb_larrypass,
+ vb_phaon,vb_boss,vb_cheat,vb_restart,vb_dir,vb_die,vb_score,
+ vb_highscores,vb_smartalec,vb_expletive,vb_wake, eos).has(verb)))
+ {
+ display("Talking in your sleep? Try waking up!"); return;
+ }
+
+
+ switch (verb) {
+ case vb_exam: examine(); break;
+ case vb_open: opendoor(); break;
+ case vb_pause: display(string("Game paused.")+'\3'+'\15'+'\15'+"Press Enter, Esc, or click "+
+ "the mouse on the `O.K.\" box to continue.");
+ break;
+ case vb_get: {
+ if (thing!=pardon)
+ { /* Legitimate try to pick something up. */
+ if (dna.carrying>=maxobjs) display("You can't carry any more!");
+ else getproc(thing);
+
+ } else
+ { /* Not... ditto. */
+ if (person!=pardon)
+ display("You can't sweep folk off their feet!"); else
+ display("I assure you, you don't need it.");
+ }
+ }
+ break;
+ case vb_drop: display(string("Two years ago you dropped a florin in the street. Three days ")+
+ "later it was gone! So now you never leave ANYTHING lying around. OK?");
+ break;
+/* begin dna.obj[thing]:=false; objectlist; end;*/
+ case vb_inv: inv(); break;
+ case vb_talk: if (person==pardon)
+ {
+ if (subjnumber==99) /* They typed "say password". */
+ display("Yes, but what \6is\22 the password?");
+ else if (set::of(range(1,49),253,249, eos).has(subjnumber))
+ {
+ Delete(thats,1,1);
+ move(realwords[2],realwords[1],sizeof(realwords)-sizeof(realwords[1]));
+ verb=chr(subjnumber);
+ do_that(); return;
+ } else
+ {
+ person=chr(subjnumber); subjnumber=0;
+ if (set::of(pardon,'\0', eos).has(person)) display("Talk to whom?");
+ else if (personshere()) talkto(ord(person));
+ }
+ } else if (person==pardon) display("Talk to whom?");
+ else if (personshere()) talkto(ord(person));
+ break;
+
+ case vb_give: if (holding())
+ {
+ if (person==pardon) display("Give to whom?"); else
+ if (personshere())
+ {
+ switch (thing) {
+ case money : display("You can't bring yourself to give away your moneybag."); break;
+ case bodkin:case bell:case clothes:case habit :
+ display("Don't give it away, it might be useful!");
+ break;
+ default: switch (person) {
+ case pcrapulus: switch (thing) {
+ case wine: {
+ display("Crapulus grabs the wine and gulps it down.");
+ dna.obj[wine]=false;
+ }
+ break;
+ default: heythanks();
+ }
+ break;
+ case pcwytalot: if (set::of(crossbow,bolt, eos).has(thing))
+ display(string("You might be able to influence ")+
+ "Cwytalot more if you used it!");
+ else heythanks();
+ break;
+ case pspludwick: if (give2spludwick()) heythanks(); break;
+ case pibythneth: if (thing==badge)
+ {
+ dixi('q',32); /* Thanks! Wow! */
+ points(3);
+ dna.obj[badge]=false;
+ dna.obj[habit]=true;
+ dna.givenbadgetoiby=true;
+ show_one(8); show_one(9);
+ } else heythanks();
+ break;
+ case payles: if (dna.ayles_is_awake)
+ {
+ if (thing==pen)
+ {
+ dna.obj[pen]=false;
+ dixi('q',54);
+ dna.obj[ink]=true;
+ dna.given_pen_to_ayles=true;
+ objectlist;
+ points(2);
+ } else heythanks();
+ } else
+ display("But he's asleep!");
+ break;
+ case pgeida: switch (thing) {
+ case potion : {
+ dna.obj[potion]=false;
+ dixi('u',16); /* She drinks it. */
+ points(2);
+ dna.geida_given_potion=true;
+ objectlist;
+ }
+ break;
+ case lute: give_geida_the_lute(); break;
+ default: heythanks();
+ }
+ break;
+ case parkata: switch (thing) {
+ case potion: if (dna.geida_given_potion)
+ winsequence();
+ else dixi('q',77);
+ break; /* That Geida woman! */
+ default: heythanks();
+ }
+ break;
+ default: heythanks();
+ }
+ }
+ }
+ objectlist; /* Just in case... */
+ }
+ break;
+
+ case vb_eat:case vb_drink: if (holding()) swallow(); break;
+ case vb_load: edna_load(realwords[2]); break;
+ case vb_save: if (alive) edna_save(realwords[2]);
+ else display("It's a bit late now to save your game!");
+ break;
+ case vb_pay: display("No money need change hands."); break;
+ case vb_look: lookaround(); break;
+ case vb_break: display("Vandalism is prohibited within this game!"); break;
+ case vb_quit: { /* quit */
+ if (demo)
+ {
+ dixi('q',31);
+ close(demofile);
+ exit(0); /* Change this later!!! */
+ }
+ if (! polite) display("How about a `please\", Avvy?"); else
+ if (ask("\23C\26Do you really want to quit?")) lmo=true;
+ }
+ break;
+ case vb_go: display("Just use the arrow keys to walk there."); break;
+ case vb_info: {
+ aboutscroll=true;
+/* display('Thorsoft of Letchworth presents:'+^c+^m+^m+
+ 'The medi‘val descendant of'+^m+
+ 'Denarius Avaricius Sextus'+^m+'in:'+
+ ^m+^m+'LORD AVALOT D''ARGENT'+
+ ^m+'version '+vernum+^m+^m+'Copyright ï '
+ +copyright+', Mark, Mike and Thomas Thurman.');*/
+ display(string("\r\r\r\r\r\r\r")+"LORD AVALOT D'ARGENT"+"\3\r"+
+ "The medi‘val descendant of"+'\15'+
+ "Denarius Avaricius Sextus"+
+ '\15'+'\15'+"version "+vernum+'\15'+'\15'+"Copyright ï "
+ +copyright+", Mark, Mike and Thomas Thurman."+'\23'+'Y'+'\26');
+ aboutscroll=false;
+ }
+ break;
+ case vb_undress: if (dna.wearing==nowt) display("You're already stark naked!");
+ else
+ if (dna.avvys_in_the_cupboard)
+ {
+ display(string("You take off ")+get_better(dna.wearing)+'.');
+ dna.wearing=nowt; objectlist;
+ } else
+ display("Hadn't you better find somewhere more private, Avvy?");
+ break;
+ case vb_wear: if (holding())
+ { /* wear something */
+ switch (thing) {
+ case chastity: display("Hey, what kind of a weirdo are you\??!"); break;
+ case clothes:case habit: { /* Change this! */
+ if (dna.wearing!=nowt)
+ {
+ if (dna.wearing==thing)
+ display("You're already wearing that.");
+ else
+ display(string("You'll be rather warm wearing two ")+
+ "sets of clothes!");
+ return;
+ } else
+ dna.wearing=thing; objectlist;
+ if (thing==habit) fv=3; else fv=0;
+ { void& with = tr[1];
+ if (whichsprite!=fv)
+ {
+ sx=tr[1].x; sy=tr[1].y;
+ done;
+ init(fv,true);
+ appear(sx,sy,left);
+ tr[1].visible=false;
+ }}
+ }
+ break;
+ default: display(what);
+ }
+ }
+ break;
+ case vb_play: if (thing==pardon)
+ switch (dna.room) { /* They just typed "play"... */
+ case r__argentpub: play_nim; break; /* ...in the pub, => play Nim. */
+ case r__musicroom: play_harp(); break;
+ }
+ else if (holding())
+ {
+ switch (thing) {
+ case lute : {
+ dixi('U',7);
+ if (whereis[pcwytalot]==dna.room) dixi('U',10);
+ if (whereis[pdulustie]==dna.room) dixi('U',15);
+ }
+ break;
+ case '\64' : if (dna.room==r__musicroom) play_harp();
+ else display(what);
+ break;
+ case '\67' : if (dna.room==r__argentpub) play_nim;
+ else display(what);
+ break;
+ default: display(what);
+ }
+ }
+ break;
+ case vb_ring: if (holding())
+ {
+ if (thing==bell)
+ {
+ display("Ding, dong, ding, dong, ding, dong, ding, dong...");
+ if ((dna.ringing_bells) & (flagset('B')))
+ display("(Are you trying to join in, Avvy\?\?!)");
+ } else display(what);
+ }
+ break;
+ case vb_help: boot_help; break;
+ case vb_larrypass: display("Wrong game!"); break;
+ case vb_phaon: display("Hello, Phaon!"); break;
+ case vb_boss: bosskey; break;
+ case vb_pee: if (flagset('P'))
+ {
+ display("Hmm, I don't think anyone will notice...");
+ set_up_timer(4,procurinate,reason_gototoilet);
+ } else display("It would be \6VERY\22 unwise to do that here, Avvy!");
+ break;
+ case vb_cheat: {
+ display(string('\6')+"Cheat mode now enabled.");
+ cheat=true;
+ }
+ break;
+ case vb_magic: if (dna.avaricius_talk>0)
+ dixi('q',19);
+ else {
+ if ((dna.room==12) & (infield(2)))
+ { /* Avaricius appears! */
+ dixi('q',17);
+ if (whereis['\227']==12)
+ dixi('q',18);
+ else
+ {
+ tr[2].init(1,false); /* Avaricius */
+ apped(2,4);
+ tr[2].walkto(5);
+ tr[2].call_eachstep=true;
+ tr[2].eachstep=procback_and_forth;
+ dna.avaricius_talk=14;
+ set_up_timer(177,procavaricius_talks,reason_avariciustalks);
+ }
+ } else display("Nothing appears to happen...");
+ }
+ break;
+ case vb_smartalec: display("Listen, smart alec, that was just rhetoric."); break;
+ case vb_expletive: {
+ switch (swore) {
+ case 0: display(string("Avvy! Do you mind? There might be kids playing!\r\r")+
+ "(I shouldn't say it again, if I were you!)");
+ break;
+ case 1: display(string("You hear a distant rumble of thunder. Must you always ")+
+ "do things I tell you not to?\r\rDon't do it again!");
+ break;
+ default:
+ {
+ zonk;
+ display(string("A crack of lightning shoots from the sky, ")+
+ "and fries you.\r\r(`Such is the anger of the gods, Avvy!\")");
+ gameover;
+ }
+ }
+ swore += 1;
+ }
+ break;
+ case vb_listen: if ((dna.ringing_bells) & (flagset('B')))
+ display(string("All other noise is drowned out by the ringing of ")+
+ "the bells.");
+ else
+ if (listen=="")
+ display("You can't hear anything much at the moment, Avvy.");
+ else display(listen);
+ break;
+ case vb_buy: {
+ /* What are they trying to buy? */
+ switch (dna.room) {
+ case r__argentpub: if (infield(6))
+ { /* We're in a pub, and near the bar. */
+ switch (thing) {
+ case '\63':case '\65':case '\66':case '\72': { /* Beer, whisky, cider or mead */
+ if (dna.malagauche==177) /* Already getting us one. */
+ { dixi('D',15); return; }
+ if (dna.teetotal) { dixi('D',6); return; }
+ if (dna.alcohol==0) points(3);
+ show_one(12);
+ display(booze[thing]+", please.\231\2");
+ dna.drinking=thing;
+
+ show_one(10);
+ dna.malagauche=177;
+ set_up_timer(27,procbuydrinks,reason_drinks);
+ }
+ break;
+ case '\64': examine(); break; /* We have a right one here- buy Pepsi??! */
+ case wine: if (dna.obj[wine]) /* We've already got the wine! */
+ dixi('D',2); /* 1 bottle's shufishent! */
+ else {
+ if (dna.malagauche==177) /* Already getting us one. */
+ { dixi('D',15); return; }
+ if (dna.carrying>=maxobjs)
+ { display("Your hands are full."); return; }
+ show_one(12); display("Wine, please.\231\2");
+ if (dna.alcohol==0) points(3);
+ show_one(10);
+ dna.malagauche=177;
+
+ set_up_timer(27,procbuywine,reason_drinks);
+ }
+ break;
+ }
+ } else dixi('D',5);
+ break; /* Go to the bar! */
+
+ case r__outsideducks: if (infield(6))
+ {
+ if (thing==onion)
+ {
+ if (dna.obj[onion])
+ dixi('D',10); /* not planning to juggle with the things! */
+ else
+ if (dna.carrying>=maxobjs)
+ display("Before you ask, you remember that your hands are full.");
+ else
+ {
+ if (dna.bought_onion)
+ dixi('D',11); else
+ { dixi('D',9); points(3); }
+ pennycheck(3); /* It costs thruppence. */
+ dna.obj[onion]=true;
+ objectlist;
+ dna.bought_onion=true;
+ dna.rotten_onion=false; /* It's OK when it leaves the stall! */
+ dna.onion_in_vinegar=false;
+ }
+ } else dixi('D',0);
+ } else dixi('D',0);
+ break;
+
+ case r__nottspub: dixi('n',15); break; /* Can't sell to southerners. */
+ default: dixi('D',0); /* Can't buy that. */
+ }
+ }
+ break;
+ case vb_attack: {
+ if ((dna.room==r__brummieroad) &&
+ ((person=='\235') || (thing==crossbow) || (thing==bolt))
+ && (whereis['\235']==dna.room))
+ {
+ switch (ord(dna.obj[bolt])+ord(dna.obj[crossbow])*2) {
+ /* 0 = neither, 1 = only bolt, 2 = only crossbow,
+ 3 = both. */
+ case 0: {
+ dixi('Q',10);
+ display("(At the very least, don't use your bare hands!)");
+ }
+ break;
+ case 1: display(string("Attack him with only a crossbow bolt? Are you ")+
+ "planning on playing darts?!");
+ break;
+ case 2: display(string("Come on, Avvy! You're not going to get very far ")+
+ "with only a crossbow!");
+ break;
+ case 3: {
+ dixi('Q',11);
+ dna.cwytalot_gone=true;
+ dna.obj[bolt]=false; dna.obj[crossbow]=false;
+ objectlist;
+ magics[12].op=nix;
+ points(7);
+ tr[2].walkto(2);
+ tr[2].vanishifstill=true;
+ tr[2].call_eachstep=false;
+ whereis['\235']=177;
+ }
+ break;
+ default: dixi('Q',10); /* Please try not to be so violent! */
+ }
+ } else dixi('Q',10);
+ }
+ break;
+ case vb_password: if (dna.room!=r__bridge)
+ dixi('Q',12); else
+ {
+ ok=true;
+ for( ff=1; ff <= length(thats); ff ++)
+ for( fv=1; fv <= length(words[dna.pass_num+first_password].w); fv ++)
+ if (words[dna.pass_num+first_password].w[fv] !=
+ upcase(realwords[ff][fv]))
+ ok=false;
+ if (ok)
+ {
+ if (dna.drawbridge_open!=0)
+ display("Contrary to your expectations, the drawbridge fails to close again.");
+ else
+ {
+ points(4);
+ display("The drawbridge opens!");
+ set_up_timer(7,procopen_drawbridge,reason_drawbridgefalls);
+ dna.drawbridge_open=1;
+ }
+ } else dixi('Q',12);
+ }
+ break;
+ case vb_dir: dir(realwords[2]); break;
+ case vb_die: gameover; break;
+ case vb_score: display(string("Your score is ")+strf(dna.score)+",\3\rout of a "+
+ "possible 128.\r\rThis gives you a rank of "+rank()+
+ ".\r\r"+totaltime());
+ break;
+ case vb_put: putproc(); break;
+ case vb_stand: stand_up(); break;
+
+ case vb_kiss: if (person==pardon)
+ display("Kiss whom?");
+ else if (personshere())
+ switch (person) {
+ case '\226' ... '\256': display("Hey, what kind of a weirdo are you??"); break;
+ case parkata: dixi('U',12); break;
+ case pgeida: dixi('U',13); break;
+ case pwisewoman: dixi('U',14); break;
+ default: dixi('U',5); /* You WHAT? */
+ }
+ break;
+
+ case vb_climb: if (dna.room==r__insidecardiffcastle) cardiff_climbing();
+ else /* In the wrong room! */
+ display("Not with your head for heights, Avvy!");
+ break;
+
+ case vb_jump: {
+ set_up_timer(1,procjump,reason_jumping);
+ dna.user_moves_avvy=false;
+ }
+ break;
+
+ case vb_highscores: show_highs; break;
+
+ case vb_wake: if (personshere())
+ switch (person) {
+ case pardon:case pavalot:case '\0': if (~ avvy_is_awake)
+ {
+ avvy_is_awake=true;
+ points(1);
+ avvy_in_bed=true;
+ show_one(3); /* Picture of Avvy, awake in bed. */
+ if (teetotal) dixi('d',13);
+ } else display("You're already awake, Avvy!");
+ break;
+ case payles: if (~ ayles_is_awake) display("You can't seem to wake him by yourself."); break;
+ case pjacques: display(string("Brother Jacques, Brother Jacques, are you asleep?\231\2")+
+ "Hmmm... that doesn't seem to do any good...");
+ break;
+ default: display("It's difficult to awaken people who aren't asleep...!");
+ }
+ break;
+
+ case vb_sit: if (dna.room==r__nottspub)
+ {
+ if (dna.sitting_in_pub)
+ display("You're already sitting!");
+ else
+ {
+ tr[1].walkto(4); /* Move Avvy to the place, and sit him down. */
+ set_up_timer(1,procavvy_sit_down,reason_sitting_down);
+ }
+ } else
+ { /* Default doodah. */
+ dusk;
+ hang_around_for_a_while;
+ dawn;
+ display("A few hours later...\20nothing much has happened...");
+ }
+ break;
+
+ case vb_restart: if (ask("Restart game and lose changes?")) {
+ dusk;
+ newgame;
+ dawn;
+ }
+ break;
+
+ case pardon: display("Hey, a verb would be helpful!"); break;
+
+ case vb_hello: { person_speaks(); display("Hello.\2"); } break;
+ case vb_thanks: { person_speaks(); display("That's OK.\2"); } break;
+ default: display(string('\7')+"Parser bug!");
+ }
+}
+
+void verbopt(char n, string& answer, char& anskey)
+{
+ switch (n) {
+ case vb_exam: { answer="Examine"; anskey='x'; } break; /* the ubiqutous one */
+ /* vb_give isn't dealt with by this procedure, but by ddm__with */
+ case vb_drink: { answer="Drink"; anskey='D'; } break;
+ case vb_wear: { answer="Wear"; anskey='W'; } break;
+ case vb_ring: { answer="Ring"; anskey='R'; } break; /* only the bell! */
+ case vb_play: { answer="Play"; anskey='P'; } break;
+ case vb_eat: { answer="Eat"; anskey='E'; } break;
+ default: { answer="? Unknown!"; anskey='?'; } /* Bug! */
+ }
+}
+
+class unit_acci_initialize {
+ public: unit_acci_initialize();
+};
+static unit_acci_initialize acci_constructor;
+
+unit_acci_initialize::unit_acci_initialize() {
+ weirdword=false;
+}
diff --git a/engines/avalanche/acci.h b/engines/avalanche/acci.h
new file mode 100644
index 0000000000..f9d1265b32
--- /dev/null
+++ b/engines/avalanche/acci.h
@@ -0,0 +1,223 @@
+#ifndef __acci_h__
+#define __acci_h__
+
+
+/* verb codes */
+const char vb_exam = '\1'; const char vb_open = '\2'; const char vb_pause = '\3'; const char vb_get = '\4'; const char vb_drop = '\5';
+const char vb_inv = '\6'; const char vb_talk = '\7'; const char vb_give = '\10'; const char vb_drink = '\11'; const char vb_load = '\12';
+const char vb_save = '\13'; const char vb_pay = '\14'; const char vb_look = '\15'; const char vb_break = '\16'; const char vb_quit = '\17';
+const char vb_sit = '\20'; const char vb_stand = '\21'; const char vb_go = '\22'; const char vb_info = '\23'; const char vb_undress = '\24';
+const char vb_wear = '\25'; const char vb_play = '\26'; const char vb_ring = '\27'; const char vb_help = '\30';
+const char vb_larrypass = '\31'; const char vb_phaon = '\32'; const char vb_boss = '\33'; const char vb_pee = '\34';
+const char vb_cheat = '\35'; const char vb_magic = '\36'; const char vb_restart = '\37'; const char vb_eat = '\40';
+const char vb_listen = '\41'; const char vb_buy = '\42'; const char vb_attack = '\43'; const char vb_password = '\44';
+const char vb_dir = '\45'; const char vb_die = '\46'; const char vb_score = '\47'; const char vb_put = '\50';
+const char vb_kiss = '\51'; const char vb_climb = '\52'; const char vb_jump = '\53'; const char vb_highscores = '\54';
+const char vb_wake = '\55'; const char vb_hello = '\56'; const char vb_thanks = '\57';
+
+const char vb_smartalec = '\371'; const char vb_expletive = '\375';
+
+const char pardon = '\376'; /* =didn't understand / wasn't given. */
+
+struct vocab {
+ byte n; varying_string<11> w;
+};
+
+struct ranktype {
+ word score; varying_string<12> title;
+};
+
+
+const integer nowords = 277; /* how many words does the parser know? */
+const char nowt = '\372';
+const char moved = '\0'; /* This word was moved. (Usually because it was the subject of
+ conversation.) */
+
+const integer first_password = 89; /* Words[first_password] should equal "TIROS". */
+
+const array<1,nowords,vocab> words =
+
+/* Verbs, 1-49 */
+{{{1, "EXAMINE"}, {1, "READ"}, {1, "XAM"}, /* short */
+ {2, "OPEN"}, {2, "LEAVE"}, {2, "UNLOCK"},
+ {3, "PAUSE"}, {47, "TA"}, /* Early to avoid Take and Talk. */
+ {4, "TAKE"}, {4, "GET"}, {4, "PICK"},
+ {5, "DROP"}, {6, "INVENTORY"}, {7, "TALK"},
+ {7, "SAY"}, {7, "ASK"},
+ {8, "GIVE"}, {9, "DRINK"}, {9, "IMBIBE"},
+ {9, "DRAIN"}, {10, "LOAD"}, {10, "RESTORE"},
+ {11, "SAVE"}, {12, "BRIBE"}, {12, "PAY"},
+ {13, "LOOK"}, {14, "BREAK"}, {15, "QUIT"},
+ {15, "EXIT"}, {16, "SIT"}, {16, "SLEEP"},
+ {17, "STAND"},
+
+ {18, "GO"}, {19, "INFO"}, {20, "UNDRESS"},
+ {20, "DOFF"},
+ {21, "DRESS"}, {21, "WEAR"}, {21, "DON"},
+ {22, "PLAY"},
+ {22, "STRUM"}, {23, "RING"}, {24, "HELP"},
+ {25, "KENDAL"}, {26, "CAPYBARA"}, {27, "BOSS"},
+ {255,"NINET"}, /* block for NINETY */
+ {28, "URINATE"}, {28, "MINGITE"}, {29, "NINETY"},
+ {30,"ABRACADABRA"},{30, "PLUGH"}, {30, "XYZZY"},
+ {30, "HOCUS"}, {30, "POCUS"}, {30, "IZZY"},
+ {30, "WIZZY"}, {30, "PLOVER"},
+ {30,"MELENKURION"},{30, "ZORTON"}, {30, "BLERBI"},
+ {30, "THURB"}, {30, "SNOEZE"}, {30, "SAMOHT"},
+ {30, "NOSIDE"}, {30, "PHUGGG"}, {30, "KNERL"},
+ {30, "MAGIC"}, {30, "KLAETU"}, {30, "VODEL"},
+ {30, "BONESCROLLS"},{30, "RADOF"},
+
+ {31, "RESTART"},
+ {32, "SWALLOW"}, {32, "EAT"}, {33, "LISTEN"},
+ {33, "HEAR"}, {34, "BUY"}, {34, "PURCHASE"},
+ {34, "ORDER"}, {34, "DEMAND"},
+ {35, "ATTACK"}, {35, "HIT"}, {35, "KILL"},
+ {35, "PUNCH"}, {35, "KICK"}, {35, "SHOOT"},
+ {35, "FIRE"},
+
+ /* Passwords, 36: */
+
+ {36, "TIROS"}, {36, "WORDY"}, {36, "STACK"},
+ {36, "SHADOW"}, {36, "OWL"}, {36, "ACORN"},
+ {36, "DOMESDAY"}, {36, "FLOPPY"}, {36, "DIODE"},
+ {36, "FIELD"}, {36, "COWSLIP"}, {36, "OSBYTE"},
+ {36, "OSCLI"}, {36, "TIMBER"}, {36, "ADVAL"},
+ {36, "NEUTRON"}, {36, "POSITRON"}, {36, "ELECTRON"},
+ {36, "CIRCUIT"}, {36, "AURUM"}, {36, "PETRIFY"},
+ {36, "EBBY"}, {36, "CATAPULT"}, {36, "GAMERS"},
+ {36, "FUDGE"}, {36, "CANDLE"}, {36, "BEEB"},
+ {36, "MICRO"}, {36, "SESAME"}, {36, "LORDSHIP"},
+
+ {37, "DIR"}, {37, "LS"}, {38, "DIE"},
+ {39, "SCORE"},
+ {40, "PUT"}, {40, "INSERT"}, {41, "KISS"},
+ {41, "SNOG"}, {41, "CUDDLE"}, {42, "CLIMB"},
+ {42, "CLAMBER"}, {43, "JUMP"}, {44, "HIGHSCORES"},
+ {44, "HISCORES"}, {45, "WAKEN"}, {45, "AWAKEN"},
+ {46, "HELLO"}, {46, "HI"}, {46, "YO"},
+ {47, "THANKS"}, /* = 47, "ta", which was defined earlier. */
+
+
+/* Nouns - Objects: 50-100. */
+
+ {50, "WINE"}, {50, "BOOZE"}, {50,"NASTY"},
+ {50, "VINEGAR"}, {51, "MONEYBAG"},
+ {51, "BAG"}, {51, "CASH"}, {51,"DOSH"},
+ {51, "WALLET"},
+ {52, "BODKIN"}, {52, "DAGGER"}, {53,"POTION"},
+ {54, "CHASTITY"}, {54, "BELT"}, {55,"BOLT"},
+ {55, "ARROW"}, {55, "DART"},
+ {56, "CROSSBOW"}, {56, "BOW"}, {57,"LUTE"},
+ {58, "PILGRIM"}, {58, "BADGE"}, {59,"MUSHROOMS"},
+ {59, "TOADSTOOLS"},{60, "KEY"}, {61,"BELL"},
+ {62, "PRESCRIPT"}, {62, "SCROLL"}, {62,"MESSAGE"},
+ {63, "PEN"}, {63, "QUILL"}, {64,"INK"},
+ {64, "INKPOT"}, {65, "CLOTHES"}, {66,"HABIT"},
+ {66, "DISGUISE"}, {67, "ONION"},
+
+ {99,"PASSWORD"},
+
+/* Objects from Also are placed between 101 and 131. */
+
+/* Nouns - People - Male, 150-174 */
+ {150, "AVVY"}, {150,"AVALOT"}, {150,"YOURSELF"},
+ {150, "ME"}, {150,"MYSELF"}, {151,"SPLUDWICK"},
+ {151, "THOMAS"}, {151,"ALCHEMIST"}, {151,"CHEMIST"},
+ {152, "CRAPULUS"}, {152,"SERF"}, {152,"SLAVE"},
+ {158, "DU"}, /* <<< Put in early for Baron DU Lustie to save confusion with Duck & Duke.*/
+ {152, "CRAPPY"}, {153,"DUCK"}, {153,"DOCTOR"},
+ {154, "MALAGAUCHE"},
+ {155, "FRIAR"}, {155,"TUCK"}, {156,"ROBIN"},
+ {156, "HOOD"}, {157,"CWYTALOT"}, {157,"GUARD"},
+ {157, "BRIDGEKEEP"},{158,"BARON"}, {158,"LUSTIE"},
+ {159, "DUKE"}, {159,"GRACE"}, {160,"DOGFOOD"},
+ {160, "MINSTREL"}, {161,"TRADER"}, {161,"SHOPKEEPER"},
+ {161,"STALLHOLDER"},
+ {162, "PILGRIM"}, {162,"IBYTHNETH"}, {163,"ABBOT"},
+ {163, "AYLES"}, {164,"PORT"}, {165,"SPURGE"},
+ {166, "JACQUES"}, {166,"SLEEPER"}, {166,"RINGER"},
+
+/* Nouns- People - Female: 175-199 */
+ {175, "WIFE"}, {175,"ARKATA"}, {176,"GEDALODAVA"},
+ {176, "GEIDA"}, {176,"PRINCESS"}, {178,"WISE"},
+ {178, "WITCH"},
+
+/* Pronouns, 200-224 */
+ {200, "HIM"}, {200,"MAN"}, {200,"GUY"},
+ {200, "DUDE"}, {200,"CHAP"}, {200,"FELLOW"},
+ {201, "HER"}, {201,"GIRL"}, {201,"WOMAN"},
+ {202, "IT"}, {202,"THING"},
+
+ {203,"MONK"}, {204,"BARMAN"}, {204,"BARTENDER"},
+
+/* Prepositions, 225-249 */
+ {225, "TO"}, {226,"AT"}, {227,"UP"},
+ {228, "INTO"}, {228,"INSIDE"}, {229,"OFF"},
+ {230, "UP"}, {231,"DOWN"}, {232,"ON"},
+
+
+/* Please, 251 */
+ {251, "PLEASE"},
+
+/* About, 252 */
+ {252, "ABOUT"}, {252, "CONCERNING"},
+
+/* Swear words, 253 */
+ /* I M P O R T A N T M E S S A G E
+
+ DO *NOT* READ THE LINES BELOW IF YOU ARE OF A SENSITIVE
+ DISPOSITION. THOMAS IS *NOT* RESPONSIBLE FOR THEM.
+ GOODNESS KNOWS WHO WROTE THEM.
+ READ THEM AT YOUR OWN RISK. BETTER STILL, DON'T READ THEM.
+ WHY ARE YOU SNOOPING AROUND IN MY PROGRAM, ANYWAY? */
+
+ {253, "SHIT"}, {28 ,"PISS"}, {28 ,"PEE"},
+ {253, "FART"}, {253,"FUCK"}, {253,"BALLS"},
+ {253, "BLAST"}, {253,"BUGGER"}, {253,"KNICKERS"},
+ {253, "BLOODY"}, {253,"HELL"}, {253,"DAMN"},
+ {253, "SMEG"},
+ /* and other even ruder words. You didn't read them, did you? Good. */
+
+/* Answer-back smart-alec words, 249 */
+ {249, "YES"}, {249,"NO"}, {249,"BECAUSE"},
+
+/* Noise words, 255 */
+ {255, "THE"}, {255,'A'}, {255,"NOW"},
+ {255, "SOME"}, {255,"AND"}, {255,"THAT"},
+ {255, "POCUS"}, {255,"HIS"},
+ {255, "THIS"}, {255,"SENTINEL"}}}; /* for "Ken SENT Me" */
+
+const char what[] = "That's not possible!";
+
+const array<1,9,ranktype> ranks =
+{{{0, "Beginner"}, {10, "Novice"},
+{20, "Improving"}, {35, "Not bad"},
+{50, "Passable"}, {65, "Good"},
+{80, "Experienced"}, {108, "The BEST!"},
+{maxint, "copyright'93"}}};
+
+
+#ifdef __acci_implementation__
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN varying_string<11> thats;
+EXTERN varying_string<20> unknown;
+EXTERN array<1,11,varying_string<20> > realwords;
+EXTERN char verb,person,thing,thing2;
+EXTERN boolean polite;
+#undef EXTERN
+#define EXTERN extern
+
+
+void clearwords();
+void parse();
+void lookaround();
+void opendoor();
+void do_that();
+void verbopt(char n, string& answer, char& anskey);
+void have_a_drink();
+
+#endif
diff --git a/engines/avalanche/also.cpp b/engines/avalanche/also.cpp
new file mode 100644
index 0000000000..17853e6189
--- /dev/null
+++ b/engines/avalanche/also.cpp
@@ -0,0 +1,1028 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Rodent.h"*/
+/*#include "Crt.h"*/
+
+/*$R+,V-*/
+
+typedef matrix<0,255,0,15,byte> fonttype;
+
+class fieldtype {
+public:
+ integer x1,y1,x2,y2;
+};
+
+class linetype : public fieldtype {
+public:
+ byte col;
+};
+
+struct pedtype {
+ integer x,y; byte dir;
+};
+
+struct magictype {
+ byte op; /* one of the operations */
+ word data; /* data for them */
+};
+
+const integer numlines = 50; const integer up = 0; const integer right = 1; const integer down = 2; const integer left = 3; const integer ur = 4; const integer dr = 5; const integer dl = 6; const integer ul = 7;
+const integer still = 8;
+
+const integer nay = maxint;
+
+/* Magic commands are */
+
+/*N*/ const integer nix = 0; /* ignore it if this line is touched */
+/*B*/ const integer bounce = 1; /* bounce off this line */
+/*E*/ const integer exclaim = 2; /* put up a chain of scrolls */
+/*T*/ const integer transport = 3; /* enter new room */
+/*U*/ const integer unfinished = 4; /* unfinished connection */
+/*S*/ const integer special = 5; /* special call */
+/*O*/ const integer opendoor = 6; /* slowly opening door. */
+
+integer gd,gm;
+array<1,numlines,linetype> lines;
+array<1,numlines,fieldtype> fields;
+boolean do1;
+byte current;
+string n;
+matrix<0,29,1,2,string> names;
+file<fonttype> f;
+fonttype skinny;
+byte tx,ty;
+matrix<0,79,0,22,char> chars;
+byte cursorflash;
+array<1,15,pedtype> peds;
+array<1,15,magictype> magics;
+array<9,15,magictype> portals;
+varying_string<26> flags;
+string listen;
+
+const graphcursmasktype crosshairs =
+{
+ ((63551,63807,63807,63807,61727,257,897,32765,897,257,61727,63807,63807,63807,63551,65535),
+ (4368,21140,8840,53910,640,640,31868,33026,31868,640,640,53910,8840,21140,4368,0)),
+ 7,
+ 7};
+
+const graphcursmasktype hook =
+{
+ ((32831,32831,49279,49279,57599,61695,61471,61447,63491,57089,36801,32771,49159,57375,63743,65535),
+ (0,16256,7936,7936,3584,1536,1792,2016,248,28,8220,12344,8160,1792,0,0)),
+ 2,
+ 9};
+
+const graphcursmasktype tthand =
+{
+ ((62463,57855,57855,57855,57471,49167,32769,0,0,0,0,32768,49152,57344,61441,61443),
+ (3072,4608,4608,4608,4992,12912,21070,36937,36873,36865,32769,16385,8193,4097,2050,4092)),
+ 4,
+ 0};
+
+string strf(longint x)
+{
+ string q;
+string strf_result;
+;
+ str(x,q); strf_result=q;
+return strf_result;
+}
+
+void glimpse(byte ret) /* glimpse of screen 3 */
+{
+ char sink;
+;
+ hidemousecursor; setvisualpage(3); setcrtpagenumber(3); showmousecursor;
+ do {; } while (!(~ anymousekeypressed));
+ do {; } while (!anymousekeypressed);
+ hidemousecursor; setvisualpage(ret); setcrtpagenumber(ret); showmousecursor;
+ while (keypressed()) sink=readkey();
+}
+
+void newline(byte t, integer p,integer q,integer r,integer s, byte c)
+{;
+ {
+ linetype& with = lines[t];
+ ;
+ x1=p; y1=q; x2=r; y2=s; with.col=c;
+ }
+}
+
+void newfield(byte t, integer p,integer q,integer r,integer s)
+{; {
+ fieldtype& with = fields[t]; ; with.x1=p; with.y1=q; with.x2=r; with.y2=s; } }
+
+void drawped(byte p)
+{;
+ { pedtype& with = peds[p];
+ if (with.dir<177)
+ {;
+ setcolor(p); circle(with.x,with.y,5); moveto(with.x,with.y);
+ switch (with.dir) {
+ case up: linerel(0,-5); break; case down: linerel(0,5); break;
+ case left: linerel(-7,0); break; case right: linerel(7,0); break;
+ case ul: linerel(-7,-5); break; case dl: linerel(-7, 5); break;
+ case ur: linerel( 7,-5); break; case dr: linerel( 7, 5); break;
+ }
+ }}
+}
+
+void drawup()
+{
+ byte fv;
+;
+ cleardevice();
+ for( fv=1; fv <= numlines; fv ++)
+ { linetype& with = lines[fv];
+ if (x1!=nay)
+ {;
+ setcolor(with.col);
+ line(x1,y1,x2,y2);
+ }}
+ for( fv=1; fv <= numlines; fv ++)
+ { fieldtype& with = fields[fv];
+ if (with.x1!=nay)
+ {;
+ setcolor(fv);
+ rectangle(with.x1,with.y1,with.x2,with.y2);
+ }}
+ for( fv=1; fv <= 15; fv ++) drawped(fv);
+}
+
+void addped()
+{
+ byte n,fv;
+;
+ n=0; do { n += 1; } while (!((n==16) || (peds[n].dir==177)));
+ setcrtpagenumber(0); setactivepage(0); setvisualpage(0);
+ drawup(); setgraphicscursor(tthand); showmousecursor;
+ do {
+ if (rightmousekeypressed) return;
+ if (keypressed()) glimpse(0);
+ } while (!leftmousekeypressed);
+ hidemousecursor;
+ {
+ pedtype& with = peds[n];
+ ;
+ with.x=mousex; with.y=mousey;
+ }
+ cleardevice(); setfillstyle(6,9); for( fv=1; fv <= 3; fv ++) bar(200*fv,0,200*fv,200);
+ for( fv=1; fv <= 2; fv ++) bar(0,60*fv,640,60*fv);
+ showmousecursor;
+ do { if (rightmousekeypressed) return; } while (!leftmousekeypressed);
+ hidemousecursor;
+ { pedtype& with = peds[n];
+ switch (((mousex / 200)*10)+(mousey / 60)) {
+ case 0: with.dir=ul; break; case 10: with.dir=up; break; case 20: with.dir=ur; break;
+ case 1: with.dir=left; break; case 11: with.dir=still; break; case 21: with.dir=right; break;
+ case 2: with.dir=dl; break; case 12: with.dir=down; break; case 22: with.dir=dr; break;
+ }}
+}
+
+void addline(byte ccc)
+{
+ byte fv;
+;
+ do {
+ for( fv=1; fv <= numlines; fv ++)
+ { linetype& with = lines[fv];
+ if (x1==nay)
+ {;
+ x1=fv*17; x2=x1; y1=200; y2=190; with.col=ccc;
+ return; /* bad style! */
+ }}
+ } while (!false);
+}
+
+byte colour()
+{
+ byte fv;
+byte colour_result;
+;
+ setactivepage(0); setvisualpage(0); setcrtpagenumber(0);
+ outtextxy(0,0,"Select a colour, please...");
+ for( fv=1; fv <= 15; fv ++)
+ {;
+ setfillstyle(1,fv);
+ bar(fv*40,27,39+fv*40,200);
+ }
+ showmousecursor;
+ do {
+ if (rightmousekeypressed) {; hidemousecursor; return colour_result; }
+ if (keypressed()) glimpse(2);
+ } while (!leftmousekeypressed);
+ hidemousecursor;
+ colour_result=getpixel(mousex,mousey); cleardevice();
+return colour_result;
+}
+
+void addfield()
+{
+ byte fv; boolean ok;
+;
+ do {
+ fv=colour();
+ ok=fields[fv].x1==nay;
+ if (! ok) output << '\7';
+ } while (!ok);
+ {
+ fieldtype& with = fields[fv];
+ ;
+ with.x1=300+fv*17; with.x2=with.x1+1; with.y1=200; with.y2=177;
+ }
+}
+
+byte checkline()
+{
+ byte fv,ans;
+byte checkline_result;
+;
+ setgraphicscursor(crosshairs);
+ setcrtpagenumber(0); setactivepage(0); setvisualpage(0); drawup();
+ do {
+ showmousecursor;
+ do {
+ if (rightmousekeypressed) {; checkline_result=255; return checkline_result; }
+ if (keypressed()) glimpse(0);
+ } while (!leftmousekeypressed);
+ hidemousecursor;
+ setactivepage(1); ans=177;
+ for( fv=1; fv <= numlines; fv ++) /* */
+ {;
+ { linetype& with = lines[fv];
+ if (x1!=nay)
+ {;
+ setcolor( 9); line(x1,y1,x2,y2);
+ if (getpixel(mousex,mousey)==9) ans=fv;
+ setcolor( 0); line(x1,y1,x2,y2);
+ }}
+ { fieldtype& with = fields[fv];
+ if (with.x1!=nay)
+ {;
+ setcolor( 9); rectangle(with.x1,with.y1,with.x2,with.y2);
+ if (getpixel(mousex,mousey)==9) ans=fv+100;
+ setcolor( 0); rectangle(with.x1,with.y1,with.x2,with.y2);
+ }}
+ }
+ setactivepage(0);
+ } while (!(ans!=177));
+ checkline_result=ans;
+return checkline_result;
+}
+
+void chooseside();
+static boolean itsaline;
+
+static void plotline()
+{;
+ if (itsaline)
+ { linetype& with = lines[gd];
+ if (do1) line(mousex,mousey,x2,y2); else
+ line(x1,y1,mousex,mousey);}
+ else
+ { fieldtype& with = fields[gd];
+ if (do1) rectangle(mousex,mousey,with.x2,with.y2); else
+ rectangle(with.x1,with.y1,mousex,mousey);}
+}
+
+void chooseside()
+{
+ byte clicol,savelcol;fieldtype current; integer temp;
+;
+ do {
+ gd=checkline(); itsaline=gd<100;
+ if (gd==255) {; hidemousecursor; return; }
+ if (! itsaline) gd -= 100;
+ setactivepage(2); setvisualpage(2); cleardevice();
+ setgraphicscursor(tthand); setcrtpagenumber(2);
+ if (itsaline)
+ {;
+ current=lines[gd];
+ savelcol=lines[gd].col;
+ } else current=fields[gd];
+ {;
+ setcolor(9);
+ if (itsaline) line(current.x1,current.y1,current.x2,current.y2); else rectangle(current.x1,current.y1,current.x2,current.y2);
+ setcolor(9);
+ setfillstyle(1,red); bar(current.x1-3,current.y1-3,current.x1+3,current.y1+3);
+ setfillstyle(1,green); bar(current.x2-3,current.y2-3,current.x2+3,current.y2+3);
+ do {; } while (!(~ anymousekeypressed));
+ clicol=177; showmousecursor;
+ do {
+ if (anymousekeypressed)
+ {;
+ hidemousecursor;
+ clicol=getpixel(mousex,mousey);
+ showmousecursor;
+ }
+ if (rightmousekeypressed)
+ {; hidemousecursor; return; }
+ if (keypressed()) glimpse(2);
+ } while (!(set::of(red,green, eos).has(clicol)));
+ do1=clicol==red; hidemousecursor;
+ setgraphicscursor(hook); setcrtpagenumber(0);
+ setactivepage(0); setvisualpage(0); setcolor(0);
+ if (itsaline)
+ {
+ linetype& with1 = lines[gd]; ; line(current.x1,current.y1,current.x2,current.y2); setcolor(with1.col); } else
+ {
+ fieldtype& with1 = fields[gd]; ; rectangle(with1.x1,with1.y1,with1.x2,with1.y2); setcolor(gd); }
+ setwritemode(xorput);
+ while (~ anymousekeypressed)
+ {;
+ plotline();
+ showmousecursor; delay(1); hidemousecursor;
+ plotline();
+ if (rightmousekeypressed) {; hidemousecursor; return; }
+ if (keypressed()) glimpse(0);
+ }
+ /* update "current" rec */
+ if (do1) {; current.x1=mousex; current.y1=mousey; }
+ else {; current.x2=mousex; current.y2=mousey; }
+ if (! itsaline)
+ {;
+ if (current.x1>current.x2) {; temp=current.x2; current.x2=current.x1; current.x1=temp; }
+ if (current.y1>current.y2) {; temp=current.y2; current.y2=current.y1; current.y1=temp; }
+ }
+ /* copy "current" to line/field */
+ if (itsaline)
+ {
+ linetype& with1 = lines[gd];
+ ;
+ current.x1=current.x1; current.x2=current.x2; current.y1=current.y1; current.y2=current.y2;
+ with1.col=savelcol;
+ } else fields[gd]=current;
+ }
+ setwritemode(0);
+ } while (!false);
+}
+
+void delped()
+{;
+ setcrtpagenumber(0); setactivepage(0); setvisualpage(0);
+ drawup(); setgraphicscursor(tthand); showmousecursor;
+ do {; } while (!leftmousekeypressed); peds[colour()].dir=177;
+}
+
+byte menu();
+
+static void say(byte y, string x)
+{;
+ setfillstyle(1,y);
+ bar(0,y*17,100,y*17+15); outtextxy(123,y*17,x);
+}
+
+byte menu()
+{
+ byte clicol;
+byte menu_result;
+;
+ setcolor(15); settextstyle(0,0,2); clicol=0; setgraphicscursor(tthand);
+ setvisualpage(2); setactivepage(2); setcrtpagenumber(2); cleardevice();
+ say(3,"Move lines around");
+ say(4,"Add a new line");
+ say(5,"Delete a line");
+ say(6,"Add a ped");
+ say(7,"Delete a ped");
+ say(8,"Add a field");
+ say(10,"Return to Also.");
+ showmousecursor;
+ do {
+ if (leftmousekeypressed)
+ {;
+ hidemousecursor;
+ clicol=getpixel(mousex,mousey);
+ showmousecursor;
+ }
+ if (rightmousekeypressed) {; hidemousecursor; return menu_result; }
+ if (keypressed()) glimpse(2);
+ } while (!(clicol>0));
+ do {; } while (!(~ anymousekeypressed));
+ hidemousecursor;
+ menu_result=clicol;
+return menu_result;
+}
+
+void removeline()
+{;
+ gd=checkline(); if (gd==255) {; hidemousecursor; return; }
+ if (gd>100)
+ fields[gd-100].x1=nay;
+ else lines[gd].x1=nay; /* cancels it out */
+ cleardevice(); drawup();
+}
+
+void lino()
+{;
+ resetmouse;
+ do {
+ switch (menu()) {
+ case 3: chooseside(); break;
+ case 4: addline(colour()); break;
+ case 5: removeline(); break;
+ case 6: addped(); break;
+ case 7: delped(); break;
+ case 8: addfield(); break;
+ case 10: return; break;
+ }
+ } while (!false);
+}
+
+void loadscreen() /* load2 */
+{
+ byte a /*absolute $A000:246560*/;
+ byte bit;
+ untyped_file f;
+;
+ setactivepage(3); setvisualpage(3);
+ assign(f,string("c:\\avalot\\place")+n+".avd"); reset(f,1); seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a,12080);
+ }
+ close(f);
+ setvisualpage(0);
+ outtextxy(0,190,"Look carefully, and then press any key...");
+ setactivepage(0);
+}
+
+void ctrlsout(string& x) /* Replace real ctrls with caret codes */
+{
+ byte fv; string xx;
+;
+ xx="";
+ for( fv=1; fv <= length(x); fv ++)
+ if (x[fv]>'\37') xx=xx+x[fv]; else xx=xx+'^'+chr(ord(x[fv])+64);
+ x=xx;
+}
+
+void ctrlsin(string& x) /* Opposite of ctrlsout */
+{
+ byte fv; string xx; boolean ctrlwas;
+;
+ xx=""; ctrlwas=false;
+ for( fv=1; fv <= length(x); fv ++)
+ if (ctrlwas) /* last char was a caret */
+ {;
+ xx=xx+chr(ord(upcase(x[fv]))-64);
+ ctrlwas=false;
+ }
+ else
+ {; /* last char wasn't a caret... */
+ if (x[fv]=='^') ctrlwas=true; else /* ...but this one is */
+ xx=xx+x[fv]; /* ...but this one isn't */
+ }
+ x=xx;
+}
+
+void flipover() /* temp view other screen */
+{
+ char r;
+;
+ setvisualpage(3); r=readkey(); setvisualpage(0);
+}
+
+void plotchar(byte x,byte y, char n)
+{
+ byte fv;
+;
+ if (chars[x][y]==n) return;
+ for( fv=0; fv <= 15; fv ++)
+ mem[0xa000*y*1200+(fv+3)*80+x]=skinny[ord(n)][fv];
+ chars[x][y]=n;
+}
+
+void cursor()
+{
+ byte fv;
+;
+ cursorflash += 1;
+ switch (cursorflash) {
+ case 1:case 127: for( fv=12; fv <= 14; fv ++)
+ mem[0xa000*ty*1200+(3+fv)*80+tx]=~(mem[0xa000*ty*1200+(3+fv)*80+tx]);
+ break;
+ case 255: cursorflash=0; break;
+ }
+}
+
+void losecursor()
+{;
+ if (cursorflash<127) {; cursorflash=126; cursor(); }
+ cursorflash=0;
+}
+
+void gwrite(string x)
+{
+ byte fv;
+;
+ for( fv=1; fv <= length(x); fv ++)
+ {;
+ plotchar(tx,ty,x[fv]);
+ tx += 1;
+ if (tx==80) {; ty += 1; tx=0; }
+ }
+}
+
+string typein(string x)
+{
+ const char marker = '\2';
+ byte p; char r;
+string typein_result;
+;
+ setvisualpage(0); setactivepage(0); cleardevice();
+ settextstyle(0,0,1); setcolor(15);
+ outtextxy( 0, 0,"Press TAB to see the room...");
+ outtextxy( 0, 20,"You may use any of these Control Codes:");
+ outtextxy(30, 30,"Anywhere: ^M = new line, ^P = new scroll, |1 fix to speaker 1.");
+ outtextxy(90, 40,"^B = new bubble");
+ outtextxy(30, 50,"At end of line: ^C = centre line, ^L = left justify.");
+ outtextxy(30, 60,"At end of scroll: ^D = Don't add automatic ^P here.");
+ outtextxy( 0, 80,"(Use by typing in (eg for ^P) ^ then P, not Ctrl-P.)");
+ p=0; ctrlsout(x); fillchar(chars,sizeof(chars),'\40');
+ do {
+ tx=0; ty=6; gwrite(x+'\4'+'\40');
+ tx=(p % 80); ty=(p / 80)+6;
+ while (! keypressed()) {; delay(1); cursor(); } losecursor();
+ r=readkey();
+ switch (r) {
+ case '\10': if (p>0) {; x=copy(x,1,p-1)+copy(x,p+1,255); p -= 1; } break; /* backspace */
+ case '\11': flipover(); break;
+ case '\40' ... '\377': {; x=copy(x,1,p)+r+copy(x,p+1,255); p += 1; } break;
+ case '\0': switch (readkey()) { /* extd. keystroke */
+ case 'G': p=0; break; /* Home */
+ case 'K': if (p>0) p -= 1; break; /* left */
+ case 'M': if (p<length(x)) p += 1; break; /* right */
+ case 'H': if (p>80) p -= 80; break; /* up */
+ case 'P': if (p<length(x)-80) p += 80; break; /* down */
+ case 'O': p=length(x); break; /* End */
+ case 'S': x=copy(x,1,p)+copy(x,p+2,255); break; /* Del */
+ }
+ break;
+ }
+ } while (!(r=='\15'));
+ ctrlsin(x); typein_result=x;
+return typein_result;
+}
+
+byte typeno(string title)
+{
+ varying_string<2> x; char r; integer e; word p;
+byte typeno_result;
+;
+ cleardevice(); x="000";
+ settextstyle(0,0,3); setcolor(9); outtextxy(0,0,title);
+ setfillstyle(1,0); setcolor(10); fillchar(chars,sizeof(chars),'\40');
+ do {
+ bar(100,100,150,125);
+ outtextxy(100,100,x);
+ do { r=readkey(); } while (!(set::of(range('0','9'),'\33','\15', eos).has(r)));
+ if (r=='\33') {; typeno_result=255; return typeno_result; }
+ if (r!='\15') x=string(x[2])+r;
+ } while (!(r=='\15'));
+ val(x,p,e); typeno_result=p;
+return typeno_result;
+}
+
+void showallnames()
+{
+ byte fv; varying_string<2> s; char r;
+;
+ settextstyle(0,0,2); cleardevice(); setcolor(13); outtextxy(0,0,"Descriptions start...");
+ settextstyle(0,0,1); setcolor(7);
+ for( fv=1; fv <= 29; fv ++)
+ {;
+ str(fv,2,s);
+ outtextxy((fv / 15)*320,((fv % 15)*10)+30,s+'='+copy(names[fv][1],0,33));
+ }
+ setcolor(15); outtextxy(500,190,"Press any key...");
+ r=readkey();
+}
+
+void showallassoc();
+
+
+static void saascreen()
+{;
+ settextstyle(0,0,2); cleardevice(); setcolor(10); outtextxy(0,0,"Everything...");
+ settextstyle(0,0,1); setcolor(2);
+ outtextxy(17,20,"(Format: <number> : <start of names> : <start of desc.>)");
+}
+
+void showallassoc()
+{
+ byte fv; varying_string<2> s; char r;
+
+;
+ saascreen();
+ for( fv=1; fv <= 30; fv ++)
+ {;
+ str(fv-1,2,s);
+ outtextxy(0,(((fv-1) % 10)*10)+30,
+ s+':'+copy(names[fv-1][1],1,7)+':'+copy(names[fv-1][2],1,70));
+ if ((fv % 10)==0) {; r=readkey(); saascreen(); }
+ }
+ setcolor(15); outtextxy(500,190,"Press any key...");
+ r=readkey();
+}
+
+void clear()
+{
+ byte fv;
+;
+ fillchar(names ,sizeof(names ), '\0');
+ for( fv=1; fv <= numlines; fv ++) {; lines[fv].x1=nay; fields[fv].x1=nay; }
+ fillchar(peds ,sizeof(peds ),'\261');
+}
+
+void scramble();
+
+static void scram1(string& x)
+{
+ byte fz;
+;
+ for( fz=1; fz <= length(x); fz ++)
+ x[fz]=chr(ord(x[fz]) ^ 177);
+}
+
+void scramble() /* Works both ways. */
+{
+ byte fv,ff;
+;
+ for( fv=0; fv <= 29; fv ++)
+ for( ff=1; ff <= 2; ff ++)
+ scram1(names[fv][ff]);
+ scram1(listen);
+ scram1(flags);
+}
+
+void save()
+{
+ string x; untyped_file f; byte minnames,minlines,minpeds,minfields,fv,ff;
+;
+ minnames =0; for( fv=0; fv <= 29; fv ++) if (names[fv][1]!="") minnames =fv;
+ minlines =0; for( fv=1; fv <= numlines; fv ++)
+ if (lines[fv].x1!=nay) minlines =fv;
+ minpeds =0; for( fv=1; fv <= 15; fv ++) if (peds[fv].dir<177) minpeds =fv;
+ minfields=0; for( fv=1; fv <= 30; fv ++) if (fields[fv].x1!=nay) minfields=fv;
+ assign(f,string("c:\\avalot\\also")+n+".avd");
+ rewrite(f,1);
+ x=string("This is an Also .AVD file, which belongs to AVALOT.EXE. Its contents")+
+ '\15'+'\12'+"are subject to copyright, so there. Have fun!"+'\32'+" *Minstrel* ";
+ blockwrite(f,x[1],128);
+ scramble();
+ blockwrite(f,minnames,1);
+ for( fv=0; fv <= minnames; fv ++)
+ for( ff=1; ff <= 2; ff ++)
+ blockwrite(f,names[fv][ff],length(names[fv][ff])+1);
+ blockwrite(f,minlines,1);
+ blockwrite(f,lines,sizeof(lines[1])*minlines);
+ blockwrite(f,minpeds,1);
+ blockwrite(f,peds,sizeof(peds[1])*minpeds);
+ blockwrite(f,minfields,1);
+ blockwrite(f,fields,sizeof(fields[1])*minfields);
+ blockwrite(f,magics,sizeof(magics));
+ blockwrite(f,portals,sizeof(portals));
+ blockwrite(f,flags,sizeof(flags));
+ blockwrite(f,listen[0],1);
+ blockwrite(f,listen[1],length(listen));
+ close(f);
+ scramble();
+}
+
+void load();
+static untyped_file f;
+
+
+static string nextstring()
+{
+ byte l; string x;
+string nextstring_result;
+;
+ x=""; blockread(f,l,1); blockread(f,x[1],l); x[0]=chr(l); nextstring_result=x;
+return nextstring_result;
+}
+
+void load()
+{
+ byte minnames,minlines,minpeds,minfields; byte ff,fv;
+
+;
+ clear();
+ assign(f,string("c:\\avalot\\also")+n+".avd");
+/*$I-*/ reset(f,1); /*$I+*/ if (ioresult!=0) return; /* no Also file */
+ seek(f,128); blockread(f,minnames,1);
+ for( fv=0; fv <= minnames; fv ++)
+ for( ff=1; ff <= 2; ff ++)
+ names[fv][ff]=nextstring();
+ blockread(f,minlines,1);
+ blockread(f,lines,sizeof(lines[1])*minlines);
+ blockread(f,minpeds,1);
+ blockread(f,peds,sizeof(peds[1])*minpeds);
+ blockread(f,minfields,1);
+ blockread(f,fields,sizeof(fields[1])*minfields);
+ blockread(f,magics,sizeof(magics));
+ blockread(f,portals,sizeof(portals));
+ blockread(f,flags,sizeof(flags));
+ blockread(f,listen[0],1);
+ blockread(f,listen[1],length(listen));
+ close(f);
+ scramble();
+}
+
+void editmagics();
+const array<1,15,char> codes = "123456789ABCDEF";
+
+static integer y;
+
+
+static void display()
+{
+ byte fv;
+;
+ cleardevice();
+ settextstyle(0,0,2); setcolor(15); outtextxy(0,0,"Magics.");
+ settextstyle(0,0,1);
+ for( fv=1; fv <= 15; fv ++)
+ {;
+ y=23+fv*10;
+ setcolor(fv); outtextxy(100,y,string('$')+codes[fv-1]);
+ {
+ magictype& with = magics[fv];
+ ;
+ switch (with.op) {
+ case nix: {; setcolor(8); outtextxy(140,y,"Nix"); } break;
+ case bounce: {; setcolor(10); outtextxy(143,y,"Bounce!"); } break;
+ case exclaim: {;
+ setcolor(14); outtextxy(143,y,string("Exclaim: ")+strf(with.data));
+ }
+ break;
+ case transport: {;
+ setcolor(12);
+ outtextxy(143,y,string("Transport to ")+strf(hi(with.data))+
+ ", ped "+strf(lo(with.data)));
+ }
+ break;
+ case unfinished: {;
+ setcolor(15); outtextxy(143,y,"*** UNFINISHED! ***");
+ }
+ break;
+ case special: {;
+ setcolor(6); outtextxy(143,y,string("Special call no. ")+strf(with.data));
+ }
+ break;
+ case opendoor: {;
+ setcolor(11);
+ outtextxy(143,y,string("Opening door to ")+strf(hi(with.data))+
+ ", ped "+strf(lo(with.data)));
+ }
+ break;
+ }
+ }
+ }
+ outtextxy(177,190,"Which do you want to change\? (Esc=Exit) $");
+}
+
+
+
+static word ask(string x)
+{
+ string q; word thomaswashere; integer e;
+word ask_result;
+;
+ cleardevice();
+ setcolor(10); settextstyle(0,0,3); outtextxy(0,100,x);
+ do {
+ input >> q >> NL; val(q,thomaswashere,e);
+ } while (!(e==0)); ask_result=thomaswashere;
+return ask_result;
+}
+
+void editmagics()
+{
+ char r,rr; byte p;
+
+;
+ do {
+ display();
+ do {
+ r=upcase(readkey());
+ if (r=='\33') return;
+ p=pos(r,codes); /* which are we editing? */
+ } while (!(p>0)); /* it must BE there... */
+ setcolor(p); cleardevice();
+ outtextxy(177,17,string("Editing magic $")+r+'.');
+ outtextxy(0,30,"New operation ( (N)ix, (B)ounce, (E)xclaim, (T)ransport, (U)nfinished),");
+ outtextxy(30,40,"(S)pecial, (O)pening Door?");
+ do { rr=upcase(readkey()); } while (!(set::of('N','B','E','T','U','S','O','\33', eos).has(rr)));
+ { magictype& with = magics[p];
+ switch (rr) {
+ case '\33': return; break; /* cancelling code */
+ case 'N': with.op=nix; break;
+ case 'B': with.op=bounce; break;
+ case 'E': {; with.op=exclaim; with.data=ask("Which scroll?"); } break;
+ case 'T': {; with.op=transport; with.data=ask("Ped no.?")+ask("Whither?")*256; } break;
+ case 'U': with.op=unfinished; break;
+ case 'S': {; with.op=special; with.data=ask("Which call?"); } break;
+ case 'O': {; with.op=opendoor; with.data=ask("Ped no.?")+ask("Whither?")*256; } break;
+ }}
+ } while (!false);
+}
+
+void editportals();
+const array<9,15,char> codes1 = "9ABCDEF";
+
+static integer y2;
+
+
+static void display1()
+{
+ byte fv;
+;
+ cleardevice();
+ settextstyle(0,0,2); setcolor(15); outtextxy(0,0,"Portals.");
+ settextstyle(0,0,1);
+ for( fv=9; fv <= 15; fv ++)
+ {;
+ y2=fv*10-53;
+ setcolor(fv); outtextxy(100,y2,string('$')+codes1[fv-1]);
+ {
+ magictype& with = portals[fv];
+ ;
+ switch (with.op) {
+ case nix: {; setcolor(8); outtextxy(140,y2,"Nix"); } break;
+ case exclaim: {;
+ setcolor(14); outtextxy(143,y2,string("Exclaim: ")+strf(with.data));
+ }
+ break;
+ case transport: {;
+ setcolor(12);
+ outtextxy(143,y2,string("Transport to ")+strf(hi(with.data))+
+ ", ped "+strf(lo(with.data)));
+ }
+ break;
+ case unfinished: {;
+ setcolor(15); outtextxy(143,y2,"*** UNFINISHED! ***");
+ }
+ break;
+ case special: {;
+ setcolor(6); outtextxy(143,y2,string("Special call no. ")+strf(with.data));
+ }
+ break;
+ case opendoor: {;
+ setcolor(11);
+ outtextxy(143,y2,string("Opening door to ")+strf(hi(with.data))+
+ ", ped "+strf(lo(with.data)));
+ }
+ break;
+ }
+ }
+ }
+ outtextxy(177,190,"Which do you want to change\? (Esc=Exit) $");
+}
+
+
+
+static word ask1(string x)
+{
+ string q; word thomaswashere; integer e;
+word ask1_result;
+;
+ cleardevice();
+ setcolor(10); settextstyle(0,0,3); outtextxy(0,100,x);
+ do {
+ input >> q >> NL; val(q,thomaswashere,e);
+ } while (!(e==0)); ask1_result=thomaswashere;
+return ask1_result;
+}
+
+void editportals() /* much t'same as editmagics */
+{
+ char r,rr; byte p;
+
+;
+ do {
+ display1();
+ do {
+ r=upcase(readkey());
+ if (r=='\33') return;
+ p=pos(r,codes1); /* which are we editing? */
+ } while (!(p>0)); /* it must BE there... */
+ p += 8; setcolor(p); cleardevice();
+ outtextxy(177,17,string("Editing portal $")+r+'.');
+ outtextxy(0,30,"New operation ( (N)ix, (E)xclaim, (T)ransport, (U)nfinished),");
+ outtextxy(30,40,"(S)pecial, (O)pening Door?");
+ do { rr=upcase(readkey()); } while (!(set::of('N','E','T','U','S','O','\33', eos).has(rr)));
+ { magictype& with = portals[p];
+ switch (rr) {
+ case '\33': return; break; /* cancelling code */
+ case 'N': with.op=nix; break;
+ case 'E': {; with.op=exclaim; with.data=ask1("Which scroll?"); } break;
+ case 'T': {; with.op=transport; with.data=ask1("Ped no.?")+ask1("Whither?")*256; } break;
+ case 'U': with.op=unfinished; break;
+ case 'S': {; with.op=special; with.data=ask1("Which call?"); } break;
+ case 'O': {; with.op=opendoor; with.data=ask1("Ped no.?")+ask1("Whither?")*256; } break;
+ }}
+ } while (!false);
+}
+
+void editflags()
+{
+ char r;
+;
+ cleardevice();
+ settextstyle(0,0,2); setcolor(15); outtextxy(0,0,"Flags.");
+ settextstyle(0,0,1); setcolor(10);
+ outtextxy(100,30,"Press the letter of the flag you want to toggle.");
+ outtextxy(100,40,"Tab = flip screens, Esc/Enter = return to menu.");
+ setcolor(14); setfillstyle(1,0);
+ for( r='A'; r <= 'Z'; r ++)
+ if (pos(r,flags)>0) outtextxy(ord(r)*20-1223,77,r);
+ do {
+ do { r=upcase(readkey()); } while (!(set::of(range('A','Z'),'\33','\15','\11', eos).has(r)));
+ switch (r) {
+ case RANGE_26('A','Z'): {;
+ if (pos(r,flags)>0)
+ {; /* flag is on- switch it off */
+ Delete(flags,pos(r,flags),1);
+ bar(ord(r)*20-1223,77,ord(r)*20-1213,87);
+ sound(1777); delay(7); nosound;
+ } else
+ {; /* flag is off- switch it on */
+ flags=flags+r;
+ outtextxy(ord(r)*20-1223,77,r);
+ sound(177); delay(7); nosound;
+ }
+ }
+ break;
+ case '\33':case '\15': return; break;
+ case '\11': flipover(); break;
+ }
+ } while (!false);
+}
+
+void alsomenu()
+{
+ char r; byte t;
+;
+ do {
+ setactivepage(0); setvisualpage(0);
+ cleardevice(); setcolor(15); settextstyle(0,0,2);
+ outtextxy(0,0,"Also... Main Menu");
+ settextstyle(0,0,1); setcolor(10);
+ outtextxy(100, 40,"1) Edit the names of an object");
+ outtextxy(100, 50,"2) View all names");
+ outtextxy(100, 60,"3) Edit the description of this object");
+ outtextxy(100, 70,"4) View all associations.");
+ outtextxy(100, 80,"5) Enter Lino mode.");
+ outtextxy(100, 90,"6) Edit magics.");
+ outtextxy(100,100,"7) Edit portals.");
+ outtextxy(100,110,"8) Edit flags.");
+ outtextxy(100,120,"9) Edit listen field.");
+ outtextxy(100,160,"S) Save");
+ outtextxy(100,170,"L) Load");
+ outtextxy( 80,180,"Tab) View other screen");
+ if (current==0) outtextxy(0,140,"< Main description of room >"); else
+ outtextxy(0,140,string('<')+names[current][1]+'>');
+ do {
+ r=upcase(readkey()); if (r=='\11') flipover();
+ } while (!(set::of(range('1','9'),'S','L','\0', eos).has(r)));
+ switch (r) {
+ case '1': {;
+ do {
+ t=typeno("Which object\? (0-30)");
+ } while (!((t<30) || (t==255)));
+ if ((t!=255) && (t!=0)) names[t][1]=typein(names[t][1]);
+ current=t;
+ }
+ break;
+ case '2': showallnames(); break;
+ case '3': names[current][2]=typein(names[current][2]); break;
+ case '4': showallassoc(); break;
+ case '5': lino(); break;
+ case '6': editmagics(); break;
+ case '7': editportals(); break;
+ case '8': editflags(); break;
+ case '9': listen=typein(listen); break;
+ case 'S': save(); break;
+ case 'L': load(); break;
+ case '\0': if (readkey()=='\55') return; break;
+ }
+ } while (!false);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ output << "*** ALSO ***" << NL;
+ output << NL;
+ output << "No. of screen to edit?"; input >> n >> NL; load();
+ assign(f,"v:avalot.fnt"); reset(f); f >> skinny; close(f);
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi"); current=0;
+ loadscreen();
+ alsomenu();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/andexor.cpp b/engines/avalanche/andexor.cpp
new file mode 100644
index 0000000000..03cedfdfcc
--- /dev/null
+++ b/engines/avalanche/andexor.cpp
@@ -0,0 +1,122 @@
+#include "ptoc.h"
+
+ /* Trippancy IV - original file */
+#include "graph.h"
+
+const integer taboo = cyan;
+
+struct adxtype {
+ varying_string<12> name; /* name of character */
+ byte num; /* number of pictures */
+ byte xl,yl; /* x & y lengths of pictures */
+ byte seq; /* how many in one stride */
+ word size; /* the size of all the pictures */
+};
+
+
+integer gd,gm;
+adxtype adx;
+matrix<1,24,0,1,pointer> adxpic; /* the pictures themselves */
+untyped_file f; string x; byte n;
+
+void load(string nam)
+{
+ byte z;
+ array<1,4,pointer> a;
+ untyped_file f; word s;
+ varying_string<40> xxx;
+ string check;
+
+;
+ assign(f,nam);
+ reset(f,1);
+ blockread(f,xxx,41);
+ blockread(f,check,13);
+ blockread(f,check,31);
+ s=imagesize(0,0,getmaxx(),75);
+ for( z=1; z <= 2; z ++)
+ {;
+ getmem(a[z],s);
+ blockread(f,a[z],s);
+ putimage(0,15+(z-1)*75,a[z],0);
+ freemem(a[z],s);
+ }
+ close(f);
+}
+
+void silhouette()
+{
+ byte x,y,c;
+;
+ setvisualpage(1); setactivepage(1); setfillstyle(1,15);
+ for( gm=0; gm <= 3; gm ++)
+ for( gd=1; gd <= 6; gd ++)
+ {; /* 26,15 */
+/* bar((gm div 2)*320+gd*40,20+(gm mod 2)*40,(gm div 2)*320+gd*40+35,(gm mod 2)*40+60); */
+ for( y=1; y <= adx.yl; y ++)
+ for( x=1; x <= adx.xl; x ++)
+ {;
+ setactivepage(0);
+ c=getpixel((gm / 2)*320+gd*40+x,20+(gm % 2)*40+y);
+ setactivepage(1);
+/* if c<>taboo then putpixel((gm div 2)*320+gd*40+x,20+(gm mod 2)*40+y,0); */
+ if (c==taboo) putpixel((gm / 2)*320+gd*40+x,20+(gm % 2)*40+y,15);
+ }
+ getmem(adxpic[gm*6+gd][0],adx.size);
+ getimage((gm / 2)*320+gd*40+1,20+(gm % 2)*40+1,
+ (gm / 2)*320+gd*40+adx.xl,20+(gm % 2)*40+adx.yl,
+ adxpic[gm*6+gd][0]);
+ }
+}
+
+void standard()
+{
+ byte x,y,c;
+;
+ setvisualpage(2); setactivepage(2);
+ for( gm=0; gm <= 3; gm ++)
+ for( gd=1; gd <= 6; gd ++)
+ {; /* 26,15 */
+ for( y=1; y <= adx.yl; y ++)
+ for( x=1; x <= adx.xl; x ++)
+ {;
+ setactivepage(0);
+ c=getpixel((gm / 2)*320+gd*40+x,20+(gm % 2)*40+y);
+ setactivepage(2);
+ if (c!=taboo) putpixel((gm / 2)*320+gd*40+x,20+(gm % 2)*40+y,c);
+ }
+ getmem(adxpic[gm*6+gd][1],adx.size);
+ getimage((gm / 2)*320+gd*40+1,20+(gm % 2)*40+1,
+ (gm / 2)*320+gd*40+adx.xl,20+(gm % 2)*40+adx.yl,
+ adxpic[gm*6+gd][1]);
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,""); fillchar(adxpic,sizeof(adxpic),'\261');
+ load("v:avalots.avd");
+/* getmem(adxpic[1,1,1],adx.size); getimage(40,20,75,60,adxpic[1,1,1]^);
+ putimage(100,100,adxpic[1,1,1]^,0); */
+ {;
+ adx.name="Avalot";
+ adx.num=24; adx.seq=6;
+ adx.xl=32; adx.yl=35; /* 35,40 */
+
+ adx.size=imagesize(40,20,40+adx.xl,60+adx.yl);
+ }
+ silhouette();
+ standard();
+ x=string("Sprite file for Avvy - Trippancy IV. Subject to copyright.")+'\32';
+ assign(f,"v:sprite1.avd");
+ rewrite(f,1);
+ blockwrite(f,x[1],59);
+ blockwrite(f,adx,sizeof(adx));
+ for( gd=1; gd <= adx.num; gd ++)
+ for( gm=0; gm <= 1; gm ++)
+ blockwrite(f,adxpic[gd][gm],adx.size); /* next image */
+ close(f);
+ closegraph();
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/andexor2.cpp b/engines/avalanche/andexor2.cpp
new file mode 100644
index 0000000000..41f27af209
--- /dev/null
+++ b/engines/avalanche/andexor2.cpp
@@ -0,0 +1,133 @@
+#include "ptoc.h"
+
+ /* Trippancy IV - original file */
+#include "graph.h"
+
+const integer taboo = cyan;
+
+struct adxtype {
+ varying_string<12> name; /* name of character */
+ byte num; /* number of pictures */
+ byte xl,yl; /* x & y lengths of pictures */
+ byte seq; /* how many in one stride */
+ word size; /* the size of all the pictures */
+ byte fgc,bgc; /* foreground & background bubble colours */
+};
+
+
+integer gd,gm;
+adxtype adx;
+array<0,1,pointer> adxpic; /* the pictures themselves */
+untyped_file f; string x; byte n; integer side2; word bigsize;
+
+void load(string n)
+{
+ byte z;
+ array<1,4,pointer> a;
+ untyped_file f; word s;
+ varying_string<40> xxx;
+ string check;
+
+;
+ assign(f,n);
+ reset(f,1);
+ blockread(f,xxx,41);
+ blockread(f,check,13);
+ blockread(f,check,31);
+ s=imagesize(0,0,getmaxx(),75);
+ for( z=1; z <= 2; z ++)
+ {;
+ getmem(a[z],s);
+ blockread(f,a[z],s);
+ putimage(0,15+(z-1)*75,a[z],0);
+ freemem(a[z],s);
+ }
+ close(f);
+}
+
+void silhouette()
+{
+ byte x,y,c;
+;
+ setvisualpage(1); setactivepage(1); setfillstyle(1,15);
+ {;
+ for( gm=0; gm <= 3; gm ++)
+ for( gd=1; gd <= 6; gd ++)
+ {; /* 26,15 */
+ side2=adx.xl*6;
+ for( y=1; y <= adx.yl; y ++)
+ for( x=1; x <= adx.xl; x ++)
+ {;
+ setactivepage(0);
+ c=getpixel((gm / 2)*320+gd*40+x,20+(gm % 2)*40+y);
+ setactivepage(1);
+ if (c==taboo)
+ putpixel((gm / 2)*side2+gd*adx.xl+x,20+(gm % 2)*adx.yl+y,15);
+ }
+ }
+ bigsize=imagesize(adx.xl+1,21,adx.xl*13,20+adx.yl*2);
+ getmem(adxpic[0],bigsize);
+ getimage(adx.xl+1,21,adx.xl*13,20+adx.yl*2,adxpic[0]);
+ putimage(adx.xl+1,21,adxpic[0],notput);
+ }
+}
+
+void standard()
+{
+ byte x,y,c;
+;
+ setvisualpage(2); setactivepage(2);
+ {;
+ for( gm=0; gm <= 3; gm ++)
+ for( gd=1; gd <= 6; gd ++)
+ {; /* 26,15 */
+ for( y=1; y <= adx.yl; y ++)
+ for( x=1; x <= adx.xl; x ++)
+ {;
+ setactivepage(0);
+ c=getpixel((gm / 2)*320+gd*40+x,20+(gm % 2)*40+y);
+ setactivepage(2);
+ if (c!=taboo)
+ putpixel((gm / 2)*side2+gd*adx.xl+x,20+(gm % 2)*adx.yl+y,c);
+ }
+/* getmem(adxpic[gm*6+gd,1],adx.size);
+ getimage((gm div 2)*side2+gd*xl+x,20+(gm mod 2)*yl+y,
+ (gm div 2)*side2+gd*xl*2+x,20+(gm mod 2)*yl*2+y,
+ adxpic[gm*6+gd,1]^); */
+ }
+ getmem(adxpic[1],bigsize);
+ getimage(adx.xl+1,21,adx.xl*13,20+adx.yl*2,adxpic[1]);
+ putimage(adx.xl+1,21,adxpic[1],notput);
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,""); fillchar(adxpic,sizeof(adxpic),'\261');
+ load("v:avalots.avd");
+ {;
+ adx.name="Avalot";
+ adx.num=24; adx.seq=6;
+ adx.xl=33; adx.yl=35; /* 35,40 */
+ adx.fgc=yellow; adx.bgc=red;
+
+ adx.size=imagesize(40,20,40+adx.xl,60+adx.yl);
+ }
+ silhouette();
+ standard();
+ x=string("Sprite file for Avvy - Trippancy IV. Subject to copyright.")+'\32';
+ assign(f,"v:sprite1.avd");
+ rewrite(f,1);
+ blockwrite(f,x[1],59);
+ blockwrite(f,adx,sizeof(adx));
+ blockwrite(f,bigsize,2);
+ for( gm=0; gm <= 1; gm ++)
+ {;
+ putimage(0,0,adxpic[gm],0);
+ blockwrite(f,adxpic[gm],bigsize); /* next image */
+ }
+ close(f);
+ closegraph();
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/andextst.cpp b/engines/avalanche/andextst.cpp
new file mode 100644
index 0000000000..8aff7172d3
--- /dev/null
+++ b/engines/avalanche/andextst.cpp
@@ -0,0 +1,64 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+
+typedef matrix<1,24,0,1,pointer> adxtype;
+
+integer gd,gm;
+word s; untyped_file f; byte n,anim,cp,t;
+array<0,0,adxtype> adx;
+array<0,1,pointer> back;
+integer x;
+array<0,1,integer> ox;
+
+void andex(integer x,integer y, byte n,byte num)
+{;
+ putimage(x,y,adx[num][n][0],andput);
+ putimage(x,y,adx[num][n][1],xorput);
+}
+
+void loadadx(byte num, string x)
+{
+ byte n;
+;
+ assign(f,x);
+ reset(f,1); seek(f,59);
+ blockread(f,n,1); /* No. of images... */
+ for( gd=1; gd <= n; gd ++)
+ for( gm=0; gm <= 1; gm ++)
+ {;
+ blockread(f,s,2); /* size of next image... */
+ getmem(adx[num][gd][gm],s);
+ blockread(f,adx[num][gd][gm],s); /* next image */
+ }
+ close(f);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ loadadx(0,"d:sprite0.avd");
+ loadadx(1,"d:sprite0.avd");
+ gd=3; gm=0; initgraph(gd,gm,"");
+ for( gd=0; gd <= 1; gd ++)
+ {;
+ setactivepage(gd); setfillstyle(6,1); bar(0,0,640,200);
+ getmem(back[gd],s);
+ }
+ x=0; anim=1; cp=0; t=2; setactivepage(0);
+ do {
+ setactivepage(cp); setvisualpage(1-cp);
+ for( gm=0; gm <= 1; gm ++)
+ {;
+ if (t>0) t -= 1; else
+ putimage(ox[cp],77,back[cp],copyput);
+ getimage(x,77,x+31,77+35,back[cp]);
+ andex(x,177,anim+6,gm);
+ ox[gm][cp]=x; x += 5;
+ }
+ anim += 1; if (anim==7) anim=1;cp=1-cp;
+ } while (!false);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/arch.cpp b/engines/avalanche/arch.cpp
new file mode 100644
index 0000000000..1ff2f1fd2d
--- /dev/null
+++ b/engines/avalanche/arch.cpp
@@ -0,0 +1,122 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ ENID Edna's manager. */
+
+#define __arch_implementation__
+ /* Loads/ saves files. */
+
+#include "arch.h"
+
+
+/*#include "Dos.h"*/
+#include "scrolls.h"
+
+
+struct ednahead { /* Edna header */
+ /* This header starts at byte offset 177 in the .ASG file. */
+ array<1,9,char> id; /* signature */
+ word revision; /* EDNA revision, here 2 (1=dna256) */
+ varying_string<50> game; /* Long name, eg Lord Avalot D'Argent */
+ varying_string<15> shortname; /* Short name, eg Avalot */
+ word number; /* Game's code number, here 2 */
+ word ver; /* Version number as integer (eg 1.00 = 100) */
+ varying_string<5> verstr; /* Vernum as string (eg 1.00 = "1.00" */
+ varying_string<12> filename; /* Filename, eg AVALOT.EXE */
+ byte os; /* Saving OS (here 1=DOS. See below for others.) */
+
+ /* Info on this particular game */
+
+ varying_string<8> fn; /* Filename (not extension ('cos that's .ASG)) */
+ byte d,m; /* D, M, Y are the Day, Month & Year this game was... */
+ word y; /* ...saved on. */
+ varying_string<40> desc; /* Description of game (same as in Avaricius!) */
+ word len; /* Length of DNA (it's not going to be above 65535!) */
+
+ /* Quick reference & miscellaneous */
+
+ word saves; /* no. of times this game has been saved */
+ integer cash; /* contents of your wallet in numerical form */
+ varying_string<20> money; /* ditto in string form (eg 5/-, or 1 denarius)*/
+ word points; /* your score */
+
+ /* DNA values follow, then footer (which is ignored) */
+};
+ /* Possible values of edhead.os:
+ 1 = DOS 4 = Mac
+ 2 = Windows 5 = Amiga
+ 3 = OS/2 6 = ST */
+const string crlf = string('\15')+'\12';
+
+const array<1,177,char> ednafirst =
+ string("This is an EDNA-based file, saved by a Thorsoft game. Good luck!")+crlf+
+ '\32'+ /* 67 bytes... */
+ crlf+crlf+ /* 71 bytes... */
+ "12345678901234567890123456789012345678901234567890"+
+ "12345678901234567890123456789012345678901234567890"+
+ "123456";
+
+const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
+const string ednaid = string("TT")+'\261'+'\60'+'\1'+'\165'+'\261'+'\231'+'\261';
+
+const integer ttage = 18;
+const char ttwashere[] = "Thomas was here ";
+
+void save(string name)
+{
+ untyped_file f;
+ edhead eh;
+ word groi;
+ string groi2;
+;
+ fillchar(eh,sizeof(eh),'\261'); /* Fill up the edhead */
+
+ dna.saves += 1; /* It's been saved one more time... */
+
+ {;
+
+ /* Info about this program */
+
+ id=ednaid; /* Edna's signature */
+ revision=2; /* Second revision of .ASG format */
+ game="Lord Avalot d'Argent"; /* Title of game */
+ shortname="Avalot";
+ number=2; /* Second Avvy game */
+ ver=100; /* Version 1.00 */
+ verstr="1.00"; /* ditto */
+ filename="AVALOT.EXE"; /* program's filename */
+ os=1; /* Saved under DOS */
+
+ /* Info on this particular game */
+
+ fsplit(name,groi2,fn,groi2); /* fn = filename of this game */
+ getdate(d,m,y,groi); /* Day, month & year when the game was saved */
+ desc=roomname; /* Description of game (same as in Avaricius!) */
+ len=sizeof(dna); /* Length of DNA (it's not going to be above 65535!) */
+
+ /* Quick reference & miscellaneous */
+
+ saves=dna.saves; /* no. of times this game has been saved */
+ cash=dna.pence; /* contents of your wallet in numerical form */
+ money=lsd(); /* ditto in string form (eg 5/-, or 1 denarius)*/
+ points=dna.score; /* your score */
+ }
+
+ assign(f,name);
+ rewrite(f,1);
+
+ blockwrite(f,ednafirst,177);
+ blockwrite(f,eh,sizeof(eh));
+ blockwrite(f,dna,sizeof(dna));
+
+ for( groi=1; groi <= ttage; groi ++)
+ blockwrite(f,ttwashere,sizeof(ttwashere));
+
+ close(f);
+}
+
+
diff --git a/engines/avalanche/arch.h b/engines/avalanche/arch.h
new file mode 100644
index 0000000000..cb0960f9dd
--- /dev/null
+++ b/engines/avalanche/arch.h
@@ -0,0 +1,10 @@
+#ifndef __arch_h__
+#define __arch_h__
+
+
+#include "gyro.h"
+
+
+void save(string name);
+
+#endif
diff --git a/engines/avalanche/avalot9.cpp b/engines/avalanche/avalot9.cpp
new file mode 100644
index 0000000000..a439f87455
--- /dev/null
+++ b/engines/avalanche/avalot9.cpp
@@ -0,0 +1,114 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ AVALOT The kernel of the program. */
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+/*#include "Trip5.h"*/
+/*#include "Gyro.h"*/
+/*#include "Lucerna.h"*/
+/*#include "Scrolls.h"*/
+/*#include "Basher.h"*/
+/*#include "Dropdown.h"*/
+/*#include "Pingo.h"*/
+/*#include "Logger.h"*/
+/*#include "Timeout.h"*/
+/*#include "Celer.h"*/
+/*#include "Enid.h"*/
+/*#include "Incline.h"*/
+/*#include "Closing.h"*/
+/*#include "Visa.h"*/
+
+
+void setup()
+{
+ integer gd,gm;
+
+ checkbreak=false; visible=m_no; to_do=0; lmo=false; resetscroll;
+ Randomize(); setup_vmc; on_virtual;
+ gd=3; gm=0; initgraph(gd,gm,"");
+ holdthedawn=true; dusk;
+ cmp=177; mouse_init; /*on;*/ dropsok=true; ctrl=ckey; oldjw=177;
+ mousetext=""; c=999; settextjustify(0,0); ddmnow=false; load_digits;
+ cheat=false; cp=0; curpos=1;
+ quote=true; ledstatus=177; defaultled=2;
+/* TSkellern:=0; { Replace with a more local variable sometime }*/
+ dna.rw=stopped; enid_filename=""; /* undefined. */
+ toolbar; state(2); copy03; lastscore="TJA";
+
+/* for gd:=0 to 1 do
+ begin
+ setactivepage(gd); outtextxy(7,177,chr(48+gd));
+ end;*/
+
+ loadtrip;
+
+ if ((filetoload=="") & (~ reloaded))
+ newgame; /* no game was requested- load the default */
+ else {
+ if (~ reloaded) avvy_background;
+ standard_bar; sprite_run;
+ if (reloaded) edna_reload; else
+ { /* Filename given on the command line (or loadfirst) */
+ edna_load(filetoload);
+ if (there_was_a_problem)
+ {
+ display("So let's start from the beginning instead...");
+ holdthedawn=true; dusk; newgame;
+ }
+ }
+ }
+
+ if (~ reloaded)
+ {
+ soundfx=~ soundfx; fxtoggle;
+ thinkabout(money,a_thing);
+ }
+
+ get_back_loretta; gm=getpixel(0,0); setcolor(7);
+ holdthedawn=false; dawn; cursoron=false; cursor_on; newspeed;
+
+ if (~ reloaded)
+ dixi('q',83); /* Info on the game, etc. */
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ setup();
+
+ do {
+
+ clock;
+ keyboard_link;
+ menu_link;
+ readstick;
+ force_numlock;
+ get_back_loretta;
+ trippancy_link;
+ pics_link;
+ checkclick;
+
+ if (visible==m_virtual) plot_vmc(mx,my,cp);
+ flip_page; /* <<<! */
+ slowdown;
+ if (visible==m_virtual) wipe_vmc(cp);
+
+ one_tick;
+
+ } while (!lmo);
+
+ restorecrtmode();
+ if (logging) close(logfile);
+
+ end_of_program;
+ return EXIT_SUCCESS;
+}
+
+/* typein; commanded; last:=current; */
diff --git a/engines/avalanche/avbkgrnd.cpp b/engines/avalanche/avbkgrnd.cpp
new file mode 100644
index 0000000000..13e6ceaef8
--- /dev/null
+++ b/engines/avalanche/avbkgrnd.cpp
@@ -0,0 +1,88 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+integer gd,gm;
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ /* Screen size: Starts at $A000:$320 (coords 0,10).
+ Length: 12000 (150*80) bytes.
+ If we divide it into sets of 5 lines (400 bytes) each, there are 30.
+ There are 40 words on a line.
+
+ Patterns:
+ 4AAA = "AVVY"
+ AAAE
+ EAA4
+ A444
+
+ A4AA = "YAVV"
+ AEAA
+ 4EAA
+ 4A44 */
+/*
+ asm
+ mov bx,$A000;
+ 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 @sameline; { Print "AVVY" }
+ mov ax,$AEAA; call @sameline;
+ mov ax,$A4EA; call @sameline;
+ mov ax,$44A4; call @sameline;
+
+ mov cx,9;
+ mov ax,$AAA4; call @sameline; { Print "YAVV" }
+ mov ax,$AAEA; call @sameline;
+ mov ax,$AA4E; call @sameline;
+ mov ax,$444A; call @sameline;
+
+ mov ax,$4AAA; call @sameline; { Print "VYAV" }
+ mov ax,$AAAE; call @sameline;
+ mov ax,$EAA4; call @sameline;
+ mov ax,$A444; call @sameline;
+
+ mov ax,$A4AA; call @sameline; { Print "VVYA" }
+ mov ax,$EAAA; call @sameline;
+ mov ax,$4EAA; call @sameline;
+ mov ax,$4A44; call @sameline;
+
+ jmp @the_end;
+
+ { 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;
+*/
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/avmenu.cpp b/engines/avalanche/avmenu.cpp
new file mode 100644
index 0000000000..3cfff7d8b6
--- /dev/null
+++ b/engines/avalanche/avmenu.cpp
@@ -0,0 +1,312 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+/*#include "Tommys.h"*/
+
+typedef matrix<'\0','\377',0,15,byte> fonttype;
+
+fonttype font;
+word storage_seg,storage_ofs;
+byte result;
+string registrant;
+
+void icons()
+{
+ untyped_file f;
+ word gd,gm; byte bit;
+ byte v;
+
+ assign(f,"menu.avd");
+ reset(f,1);
+
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( gd=70; gd <= 266; gd ++)
+ blockread(f,mem[0xa000*gd*80+6],9);
+
+ for( gd=0; gd <= 32; gd ++)
+ {
+ blockread(f,v,1);
+ for( gm=0; gm <= 5; gm ++)
+ mem[0xa000*73+((70+gd+gm*33)*80)]=v; /* 79 */
+ }
+
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ setfillstyle(1, 7); for( gd=0; gd <= 5; gd ++) bar(114, 73+gd*33,583, 99+gd*33);
+ setfillstyle(1,15); for( gd=0; gd <= 5; gd ++) bar(114, 70+gd*33,583, 72+gd*33);
+ setfillstyle(1, 8); for( gd=0; gd <= 5; gd ++) bar(114,100+gd*33,583,102+gd*33);
+
+}
+
+void load_regi_info();
+
+
+static char decode1(char c)
+{
+ byte b;
+
+ char decode1_result;
+ b=ord(c)-32;
+ decode1_result=chr(( (b & 0xf) << 3) + ((cardinal)(b & 0x70) >> 4));
+ return decode1_result;
+}
+
+
+
+static char decode2(char c)
+{
+ char decode2_result;
+ decode2_result=chr( ((ord(c) & 0xf) << 2) + 0x43);
+ return decode2_result;
+}
+
+
+
+static boolean checker(string proper,string check)
+{
+ byte fv; boolean ok;
+
+ boolean checker_result;
+ ok=true;
+ for( fv=1; fv <= length(proper); fv ++)
+ if ((ord(proper[fv]) & 0xf)!=((cardinal)(ord(check[fv])-0x43) >> 2))
+ ok=false;
+
+ checker_result=ok;
+ return checker_result;
+}
+
+void load_regi_info()
+{
+ text t;
+ byte fv;
+ string x;
+ byte namelen,numlen;
+ string namechk,numchk;
+ string reginum;
+
+
+ /*$I-*/
+ assign(t,"register.dat"); reset(t);
+ /*$I+*/
+
+ if (ioresult!=0)
+ {
+ registrant="(Unregistered evaluation copy.)";
+ return;
+ }
+
+ for( fv=1; fv <= 53; fv ++) t >> NL;
+ t >> x >> NL;
+ close(t);
+
+ namelen=107-ord(x[1]); numlen=107-ord(x[2]);
+
+ registrant=copy(x,3,namelen);
+ reginum=copy(x,4+namelen,numlen);
+ namechk=copy(x,4+namelen+numlen,namelen);
+ numchk=copy(x,4+namelen+numlen+namelen,numlen);
+
+ for( fv=1; fv <= namelen; fv ++) registrant[fv]=decode1(registrant[fv]);
+ for( fv=1; fv <= numlen; fv ++) reginum[fv]=decode1(reginum[fv]);
+
+ if ((! checker(registrant,namechk)) || (! checker(reginum,numchk)))
+ registrant="\?\"!\? ((.)";
+ else
+ registrant=registrant+" ("+reginum+").";
+
+}
+
+void flesh_colours() {; /* assembler;
+asm
+ mov ax,$1012;
+ mov bx,21; { 21 = light pink (why?) */
+ /* mov cx,1;
+ mov dx,seg @flesh;
+ mov es,dx;
+ mov dx,offset @flesh;
+ int $10;
+
+ mov dx,seg @darkflesh;
+ mov es,dx;
+ mov dx,offset @darkflesh;
+ mov bx,5; { 5 = dark pink. */
+ /*int $10;
+
+ jmp @TheEnd;
+
+ @flesh:
+ db 56,35,35;
+
+ @darkflesh:
+ db 43,22,22;
+
+ @TheEnd: */
+ }
+
+void setup()
+{
+ integer gd,gm;
+ file<fonttype> ff;
+
+ if (paramstr(1)!="jsb") exit(255);
+ checkbreak=false;
+ val(paramstr(2),storage_seg,gd);
+ val(paramstr(3),storage_ofs,gd);
+
+ assign(ff,"avalot.fnt");
+ reset(ff); ff >> font; close(ff);
+
+ gd=3; gm=1; initgraph(gd,gm,"");
+ setvisualpage(1);
+
+ icons();
+}
+
+void big(word x,word y, string z, boolean notted);
+static word start,image;
+
+
+static void generate(byte from, boolean& notted)
+{
+ byte fv;
+
+ image=0;
+ for( fv=0; fv <= 7; fv ++)
+ image += (from & (1 << fv)) << fv;
+
+ image += image << 1;
+ image=hi(image)+lo(image)*256;
+ if (notted) image=~ image;
+}
+
+void big(word x,word y, string z, boolean notted)
+{
+ byte fv,ff;byte bit;
+
+ start=x+y*80;
+
+ for( fv=1; fv <= length(z); fv ++)
+ {
+ for( ff=1; ff <= 12; ff ++)
+ {
+ generate(font[z[fv]][ff+1], notted);
+ for( bit=0; bit <= 2; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ memw[0xa000*start+ ff*160]=image;
+ memw[0xa000*start+80+ff*160]=image;
+ }
+ }
+ start += 2;
+ }
+ bit=getpixel(0,0);
+}
+
+void centre(integer y, string z)
+{
+ big(40-(length(z)),y,z,false);
+}
+
+void option(byte which, string what)
+{
+ big(16,41+which*33,string((char)(which+48))+')',true);
+ big(24,41+which*33,what,true);
+}
+
+void invert(integer x1,integer y1,integer x2,integer y2)
+{
+ word s; pointer p;
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+ putimage(x1,y1,p,4);
+ sound(y1); delay(30);
+ sound(600-y2); delay(20);
+ nosound; delay(200);
+ putimage(x1,y1,p,0);
+ delay(250);
+}
+
+void wait()
+{
+ word x; char r; boolean pressed;
+
+ x=0; pressed=false;
+ do {
+ setfillstyle(6,15); bar(x ,330,x-1,337);
+ setfillstyle(1, 0); bar(x-2,330,x-3,337);
+ delay(40); x += 1;
+
+ if (keypressed())
+ {
+ r=readkey();
+ if (r=='\0')
+ {
+ r=readkey(); /* and...? */
+ } else
+ { /* Not an extended keystroke. */
+ if (set::of(range('1','6'),cspace,cescape,creturn, eos).has(r)) pressed=true;
+ }
+ }
+
+ } while (!((x==640) || pressed));
+
+ if ((r==cspace) || (r==creturn)) r='1';
+ if (r==cescape) r='6';
+ if (pressed)
+ {
+ result=ord(r)-48;
+ invert(48,37+result*33,114,69+result*33);
+ } else result=177;
+}
+
+void show_up()
+{
+ setvisualpage(0);
+}
+
+void loadmenu()
+{
+ untyped_file f; byte bit;
+
+ assign(f,"mainmenu.avd");
+ reset(f,1);
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,mem[0xa000*0],59*80);
+ }
+ close(f);
+ bit=getpixel(0,0);
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ setup();
+ loadmenu();
+ load_regi_info();
+ option(1,"Play the game.");
+ option(2,"Read the background.");
+ option(3,"Preview... perhaps...");
+ option(4,"View the documentation.");
+ option(5,"Registration info.");
+ option(6,"Exit back to DOS.");
+ centre(275,registrant);
+ centre(303,"Make your choice, or wait for the demo.");
+
+ show_up();
+ wait();
+ mem[storage_seg*storage_ofs]=result;
+ closegraph();
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/avvyans.cpp b/engines/avalanche/avvyans.cpp
new file mode 100644
index 0000000000..68756874a8
--- /dev/null
+++ b/engines/avalanche/avvyans.cpp
@@ -0,0 +1,84 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+integer gd,gm;
+untyped_file f;
+array<1,16000,byte> aa;
+matrix<0,27,0,35,byte> cols;
+text t;
+string x;
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ fillchar(cols,sizeof(cols),'\0');
+ assign(f,"v:avvypic.ptx");
+ reset(f,1);
+ blockread(f,aa,filesize(f));
+ close(f);
+ putimage(0,0,aa,0);
+ for( gd=0; gd <= 27; gd ++)
+ for( gm=0; gm <= 34; gm ++)
+ cols[gd][gm+1]=getpixel(gd,gm);
+
+ restorecrtmode();
+/*
+ asm
+ mov ax,$1003
+ mov bl,0
+ int $10
+ end;
+*/
+ for( gm=0; gm <= 17; gm ++)
+ for( gd=0; gd <= 27; gd ++)
+ {;
+ gotoxy(gd+1,gm+1);
+ if (cols[gd][2*gm]==cols[gd][2*gm+1])
+ {;
+ textattr=cols[gd][2*gm]; output << 'Û';
+ } else
+ if ((cols[gd][2*gm]>7) && (cols[gd][2*gm+1]<8))
+ {;
+ textattr=cols[gd][2*gm]+cols[gd][2*gm+1]*16;
+ output << 'ß';
+ } else
+ {;
+ textattr=cols[gd][2*gm]*16+cols[gd][2*gm+1];
+ if (textattr>blink) textattr -= blink;
+ output << 'Ü';
+ }
+ }
+ gotoxy(23,5); textattr=red; output << 'ß';
+
+ assign(t,"v:avalot.txt"); reset(t);
+ textattr=9; gm=2;
+ do {
+ gm += 1;
+ t >> x >> NL;
+ gotoxy(30,gm);
+ output << x << NL;
+ } while (!(eof(t)));
+
+ textattr=7; gotoxy(35,2); output << "Back in good old A.D. ";
+ textattr=15; output << "1176"; textattr=7; output << "...";
+ textattr=9; gotoxy(40,4); output << "Lord";
+ gotoxy(67,9); output << "d'Argent";
+ textattr=yellow;
+ gotoxy(37,12); output << "He's back...";
+ gotoxy(47,14); output << "And this time,";
+ gotoxy(52,15); output << "he's wearing tights...";
+ textattr=4;
+ gotoxy(36,17); output << "A Thorsoft of Letchworth game. * Requires EGA";
+ gotoxy(38,18); output << "and HD. * By Mike, Mark and Thomas Thurman.";
+ gotoxy(40,19); output << "Sfx archive- ";
+ textattr=9; output << "Download ";
+ textattr=14; output << "AVLT10.EXE";
+ textattr=9; output << " now!";
+ gotoxy(1,1);
+ input >> NL;
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/avvyans2.cpp b/engines/avalanche/avvyans2.cpp
new file mode 100644
index 0000000000..915a33d372
--- /dev/null
+++ b/engines/avalanche/avvyans2.cpp
@@ -0,0 +1,185 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+/*#include "Ansi.h"*/
+
+integer gd,gm;
+untyped_file f;
+array<1,16000,byte> aa;
+matrix<0,27,0,35,byte> cols;
+text t;
+string x;
+byte n;
+byte spaces;
+byte cfg,cbg; /* Current foreground & background. */
+byte ofg,obg; /* Old fg & bg. */
+
+void do_spaces()
+{;
+ if (spaces==0) return;
+ along(spaces);
+ spaces=0;
+}
+
+void finishline();
+static byte wx,wy;
+
+static void jumpto(byte xx)
+{;
+ along(xx-wx);
+}
+
+void finishline()
+{;
+ wx=29-spaces; wy=gm+1;
+ switch (wy) {
+ case 1: {;
+ sgr(7); jumpto(35); output << "Back in good old A.D. ";
+ sgr(15); output << "1189"; sgr(7); output << "..." << NL; cfg=7;
+ }
+ break;
+ case RANGE_5(3,7): {;
+ t >> x >> NL;
+ while (x[length(x)]=='\40') x[0] -= 1;
+ if (x!="")
+ {;
+ jumpto(30);
+ sgr(9);
+ spaces=0;
+ while (x!="")
+ {;
+ if (x[1]==' ')
+ spaces += 1;
+ else
+ {;
+ do_spaces();
+ output << x[1];
+ }
+ Delete(x,1,1);
+ }
+ if (wy==7) close(t);
+ output << NL;
+ }
+ }
+ break;
+ case 8: {;
+ jumpto(67); sgr(9); output << "d'Argent" << NL; cfg=9;
+ }
+ break;
+ case 11: {;
+ jumpto(37); sgr(14); output << "He's back..." << NL;
+ }
+ break;
+ case 13: {;
+ jumpto(47); sgr(14); output << "And this time," << NL;
+ }
+ break;
+ case 14: {;
+ jumpto(52); sgr(14); output << "he's wearing tights..." << NL;
+ }
+ break;
+ case 16: {;
+ jumpto(35); sgr(4);
+ output << "A Thorsoft of Letchworth game. * Requires EGA" << NL;
+ }
+ break;
+ case 17: {;
+ jumpto(37); sgr(4);
+ output << "and HD. * By Mike, Mark and Thomas Thurman." << NL;
+ }
+ break;
+ case 18: {;
+ jumpto(39);
+ sgr( 4); output << "Sfx archive- ";
+ sgr( 9); output << "Download ";
+ sgr(14); output << "AVLT10.EXE";
+ sgr( 9); output << " now!";
+ }
+ break;
+ default: output << NL;
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ fillchar(cols,sizeof(cols),'\0');
+ assign(f,"v:avvypic.ptx");
+ reset(f,1);
+ blockread(f,aa,filesize(f));
+ close(f);
+ putimage(0,0,aa,0);
+ for( gd=0; gd <= 27; gd ++)
+ for( gm=0; gm <= 34; gm ++)
+ cols[gd][gm+1]=getpixel(gd,gm);
+
+ restorecrtmode();
+
+ assign(output,"v:avalot.ans"); rewrite(output); normal; ed;
+/* assign(output,''); rewrite(output); normal; ed;*/
+ assign(t,"v:avalot.txt"); reset(t);
+
+ for( gm=0; gm <= 17; gm ++)
+ {;
+ spaces=0;
+ for( gd=0; gd <= 27; gd ++)
+ {;
+ if ((gd==22) && (gm==4))
+ {;
+ do_spaces();
+ sgr(red); output << 'ß';
+ } else
+ {;
+ if (cols[gd][2*gm]==cols[gd][2*gm+1])
+ {;
+ if (cols[gd][2*gm]==0)
+ spaces += 1; /* a blank space */
+ else {;
+ do_spaces();
+
+ if (cfg==cols[gd][2*gm]) output << 'Û'; else
+ if (cbg==cols[gd][2*gm]) output << ' '; else
+ {;
+ sgr((cols[gd][2*gm])+(cbg*16));
+ cfg=cols[gd][2*gm];
+ output << 'Û';
+ }
+ }
+ } else
+ if ((cols[gd][2*gm]>7) && (cols[gd][2*gm+1]<8))
+ {;
+ do_spaces();
+ sgr(cols[gd][2*gm]+cols[gd][2*gm+1]*16);
+ cfg=cols[gd][2*gm]; cbg=cols[gd][2*gm+1]*16;
+ output << 'ß';
+ } else
+ {;
+ do_spaces();
+
+ ofg=cfg; obg=cbg;
+ cbg=cols[gd][2*gm]; cfg=cols[gd][2*gm+1];
+
+ if ((cbg==ofg) && (cfg==obg))
+ {;
+ n=cfg*16+cbg;
+ if (n>128) n -= 128;
+ output << 'ß';
+ } else
+ {;
+ n=cbg*16+cfg;
+ if (n>128) n -= 128;
+ if ((cfg!=ofg) || (cbg!=obg)) sgr(n);
+ output << 'Ü';
+ }
+
+ }
+ }
+ } finishline();
+ }
+ output << NL;
+ normal;
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/avvymonk.cpp b/engines/avalanche/avvymonk.cpp
new file mode 100644
index 0000000000..5a4b70c818
--- /dev/null
+++ b/engines/avalanche/avvymonk.cpp
@@ -0,0 +1,72 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+integer gd,gm;
+byte z;
+array<1,4,pointer> a;
+untyped_file f; word s;
+string check;
+integer x,y;
+void savesc()
+{
+ varying_string<40> adf; untyped_file f; byte z; array<1,2,pointer> c; word s;
+varying_string<14> nam; varying_string<30> screenname;
+;
+ nam="v:avvymonk.avd";
+ adf=string("aved as a stuff file, so there! TJAT.")+'\15'+'\12'+'\32';
+ adf[0]='S';
+ screenname="Avalot in a monk's costume";
+ assign(f,nam); /* not scrambled */
+ rewrite(f,1);
+ blockwrite(f,adf,41);
+ blockwrite(f,nam,13);
+ blockwrite(f,screenname,31);
+ s=imagesize(0,0,getmaxx(),75);
+ for( z=1; z <= 2; z ++)
+ {;
+ getmem(c[z],s);
+ getimage(0,15+(z-1)*75,getmaxx(),15+(z)*75,c[z]);
+ blockwrite(f,c[z],s);
+ freemem(c[z],s);
+ }
+}
+void loadscreen(string nam)
+{;
+ assign(f,nam);
+ reset(f,1);
+ blockread(f,check,41);
+ blockread(f,check,13);
+ blockread(f,check,31);
+ s=imagesize(0,0,getmaxx(),75);
+ for( z=1; z <= 2; z ++)
+ {;
+ getmem(a[z],s);
+ blockread(f,a[z],s);
+ setactivepage(0);
+ putimage(0,15+(z-1)*75,a[z],0);
+ freemem(a[z],s);
+ }
+ close(f);
+}
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0;
+ x=0; y=0;
+ initgraph(gd,gm,"o:");
+ loadscreen("v:legion.avd");
+ while (y<100)
+ {;
+ switch (getpixel(x,y)) {
+ case 7: putpixel(x,y,0); break;
+ case 8: putpixel(x,y,0); break;
+ case 9: putpixel(x,y,15); break;
+ }
+ x += 1;
+ if (x>640) {; y += 1; x=0; }
+ }
+ savesc();
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/bakchunk.cpp b/engines/avalanche/bakchunk.cpp
new file mode 100644
index 0000000000..5cea62db12
--- /dev/null
+++ b/engines/avalanche/bakchunk.cpp
@@ -0,0 +1,28 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Celer.h"*/
+/*#include "Lucerna.h"*/
+
+integer gd,gm;
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ gd=3; gm=0; initgraph(gd,gm,"");
+ setvisualpage(3);
+ load_chunks('1');
+
+ for( gd=0; gd <= num_chunks; gd ++)
+ show_one_at(gd,0,gd*40);
+
+ mblit(0,0,79,200,3,0);
+
+ gd=getpixel(0,0);
+ setvisualpage(0); setactivepage(0);
+
+ settextstyle(0,0,4); setcolor(15);
+ outtextxy(100,50,"Chunk1");
+ input >> NL;
+ return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/basher.cpp b/engines/avalanche/basher.cpp
new file mode 100644
index 0000000000..56cfcca023
--- /dev/null
+++ b/engines/avalanche/basher.cpp
@@ -0,0 +1,385 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ BASHER Handles the keyboard. */
+
+#define __basher_implementation__
+
+
+ /* Note: this unit can record keystrokes, for the demo. If you want it
+ to do this, define the o.c.c. RECORD. Setting gyro.demo to True will
+ cause them to be played back. */
+
+#include "basher.h"
+
+
+#include "enhanced.h"
+#include "lucerna.h"
+#include "Graph.h"
+#include "scrolls.h"
+#include "acci.h"
+#include "trip5.h"
+#include "pingo.h"
+#include "dropdown.h"
+#include "logger.h"
+#include "Sticks.h"
+#include "enid.h"
+
+
+boolean entering_filename;
+byte left_margin;
+
+void plottext()
+{
+ const array<0,2,byte> p = {{0,1,3}};
+ byte x,y,n;
+
+ x=0; if (mouse_near_text()) super_off();
+ cursor_off();
+ for( n=0; n <= 2; n ++)
+ for( y=0; y <= 7; y ++)
+ {
+ for( x=1; x <= length(current); x ++)
+ mem[0xa000*p[n]*pagetop+12882+y*80+x]=little[current[x]][y];
+ fillchar(mem[0xa000*p[n]*pagetop+12883+y*80+x],77-x,'\0');
+ }
+ cursor_on();
+ super_on();
+}
+
+void wipetext()
+{
+ const array<0,2,byte> n = {{0,1,3}};
+ byte y,p;
+
+ if (mouse_near_text()) super_off();
+ cursor_off();
+ for( y=0; y <= 7; y ++)
+ for( p=0; p <= 2; p ++)
+ fillchar(mem[0xa000*n[p]*pagetop+12883+y*80],77,'\0');
+ quote=true; curpos=1; cursor_on();
+ super_on();
+}
+
+/*procedure cursor;
+begin
+ if curflash=0 then
+ begin
+ if mouse_near_text then Super_Off;
+ cursoron:=not cursoron;
+ mem[$A000*13442+curpos]:=not mem[$A000*13442+curpos];
+ mem[$A000*pagetop+13442+curpos]:=not mem[$A000*pagetop+13442+curpos];
+ curflash:=17;
+ Super_On;
+ end else dec(curflash);
+end;*/
+
+void do_cursor()
+{
+ bytefield bf;
+ byte fv;
+
+ mem[0xac00*13442+curpos]=~ mem[0xac00*13442+curpos];
+ {
+ bf.x1=curpos+1; bf.x2=curpos+2; bf.y1=168; bf.y2=168;
+ }
+ for( fv=0; fv <= 1; fv ++) getset[fv].remember(bf);
+}
+
+void cursor_on()
+{
+ if (cursoron) return;
+ do_cursor(); cursoron=true;
+}
+
+void cursor_off()
+{
+ if (! cursoron) return;
+ do_cursor(); cursoron=false;
+}
+
+
+void get_demorec()
+{
+ demofile >> demo_rec;
+ inchar=demo_rec.key;
+ extd=demo_rec.extd;
+ demo_rec.delay -= 1;
+}
+
+#ifdef RECORD
+ void record_one()
+ {
+ demo_rec.delay=count;
+ demo_rec.key=inchar;
+ demo_rec.extd=extd;
+
+ demofile << demo_rec;
+ count=0;
+ }
+#endif
+/*
+procedure storeline(whatwhat:string);
+var
+ fv:byte;
+ what:string[77];
+ ok:boolean;
+
+ function upline(x:string):string;
+ var fv:byte; n:string[77];
+ begin
+ for fv:=1 to length(x) do n[fv]:=upcase(x[fv]);
+ n[0]:=x[0]; upline:=n;
+ end;
+begin
+
+ what:=upline(whatwhat); ok:=false;
+ for fv:=1 to 20 do
+ if what=upline(previous^[fv]) then
+ begin { it already exists, in string "fv" }
+ move(previous^[fv+1],previous^[fv],(20-fv)*78);
+ previous^[20]:=whatwhat; ok:=true;
+ end;
+ if ok then exit;
+ { it's not on the list, so add it }
+ move(previous^[2],previous^[1],1482); { shove up }
+ previous^[20]:=whatwhat;
+end;
+*/
+void typein();
+
+static char firstchar(string x) { char firstchar_result;
+ firstchar_result=x[1]; return firstchar_result;
+ }
+
+
+static void try_dd() /* This asks the Parsekey proc in Dropdown if it knows it. */
+{
+ parsekey(inchar,extd);
+}
+
+void typein()
+{
+ byte w;
+
+ inkey();
+ #ifdef RECORD record_one(); #endif
+
+ switch (inchar) {
+ case RANGE_15('\40','\56'):case '\60' ... '\337':case '\341' ... '\377': if (ddm_o.menunow)
+ {
+ parsekey(inchar,extd);
+ } else
+ {
+ if (length(current)<76)
+ {
+ if ((inchar=='"') || (inchar=='`'))
+ {
+ if (quote) inchar='`'; else inchar='"';
+ quote=! quote; /* Quote- Unquote... */
+ }
+ insert(inchar,current,curpos);
+ curpos += 1;
+ plottext();
+ } else blip();
+ }
+ break;
+ case '\10': if (! ddm_o.menunow)
+ {
+ if (curpos>left_margin)
+ {
+ curpos -= 1;
+ if (set::of('"','`', eos).has(current[curpos])) quote=! quote;
+ Delete(current,curpos,1);
+ plottext();
+ } else blip();
+ }
+ break;
+ case '\0':case '\340': {
+ switch (extd) {
+ /* Function keys: */
+ case cf1: callverb(vb_help); break; /* f1 - help (obviously) */
+ case cf2: fxtoggle(); break; /* f2 - sound */
+ case ccf2:case cf11: { clearwords(); callverb(vb_save); } break; /* ^f2 - save */
+ case cf3: if (length(current)<length(/*previous^[20]*/last)) /* f3 - rec last */
+ {
+ current=current+copy( /*previous^[20]*/last,length(current)+1,255);
+ curpos=length(current)+1;
+ plottext();
+ }
+ break;
+ case ccf3:case cf12: { clearwords(); callverb(vb_load); } break; /* ^f3 - load */
+ case cf4: callverb(vb_restart); break; /* f4 - restart game */
+ case cf5: {
+ person=pardon; thing=pardon;
+ callverb(firstchar(f5_does())); /* f5 - get up/ whatever */
+ }
+ break;
+ case cf6: callverb(vb_pause); break; /* f6 - pause */
+ case cf7: callverb(vb_open); break; /* f7 - open door */
+ case cf8: callverb(vb_look); break; /* f8 - look */
+ case cf9: callverb(vb_score); break; /* f9 - score */
+ case ccf7: major_redraw(); break; /* ^f7 - open door */
+ case cf10:case c_ax:case caf4: {
+ #ifdef RECORD
+ display("Hi. You have just finished recording. GIED.");
+ close(demofile); exit(0);
+ #endif
+ callverb(vb_quit); /* f10, alt-X, alt-f4 - quit */
+ }
+ break;
+ case ccf5: back_to_bootstrap(2); break; /* ^f5 - Dos shell. */
+ case csf10: callverb(vb_info); break; /* sf10 - version */
+
+ case c_ab: callverb(vb_boss); break; /* alt-B */
+ case c_ad: display("Wrong game!"); break; /* alt-D */
+ case ccleft: if (curpos>left_margin)
+ { cursor_off(); curpos -= 1; cursor_on(); }
+ break; /* ^left */
+ case ccright: if (curpos<=length(current)) /* ^right */
+ { cursor_off(); curpos += 1; cursor_on(); }
+ break;
+ case cchome: { cursor_off(); curpos=1; cursor_on(); } break; /* ^home */
+ case ccend: { cursor_off(); curpos=length(current)+1; cursor_on(); } break; /* ^end */
+ case c_ar: oh=177; break; /* alt-R = repeater (re-chime) */
+ case cup:case cdown:case cleft:case cright:case cpgup:case cpgdn:case chome:case cend: if (ddm_o.menunow) try_dd();
+ else tripkey(extd);
+ break; /* Up/Down/Left/Right/PgUp/PgDn */
+ case cnum5: tripkey(extd); break; /* Numeric 5 */
+ case cdel: if (! ddm_o.menunow)
+ {
+ if (curpos<=length(current))
+ {
+ if (set::of('"','`', eos).has(current[curpos])) quote=! quote;
+ Delete(current,curpos,1);
+ plottext();
+ } else blip();
+ }
+ break;
+ default: try_dd();
+ }
+ }
+ break;
+ case cescape:case '/': if (ddm_o.menunow) /* Escape */
+ { ddm_o.wipe(); } else
+ if (entering_filename)
+ { normal_edit(); wipetext(); } else
+ ddm_m.getcertain(ddm_o.menunum);
+ break;
+ case creturn: if (ddm_o.menunow) try_dd(); /* Return */
+ else {
+ log_command(current);
+ if (entering_filename)
+ {
+ edna_save(copy(current,24,255));
+ normal_edit(); wipetext();
+ } else
+ {
+ if (current!="") last=current;
+ parse(); do_that();
+ if (! entering_filename)
+ {
+ current="";
+ wipetext();
+ }
+ }
+ }
+ break;
+ case '\11': callverb(vb_inv); break; /* Ctrl-I= inventory */
+ case '\7': errorled(); break;
+ case '\25': {
+ current="";
+ wipetext();
+ }
+ break;
+
+ case '\27': { tr[1].xs=walk; newspeed(); } break;
+ case '\22': { tr[1].xs=run; newspeed(); } break;
+
+ case '\2': bosskey(); break;
+ case '\12': ctrl=cjoy; break; /* Joystick */
+ case '\13': ctrl=ckey; break; /* Keyboard */
+ case '\3': callverb(vb_quit); break; /* Ctrl-C= request to quit */
+
+ }
+ showrw();
+
+ if (demo) get_demorec();
+}
+
+/* 'x'..'z': begin setvisualpage(ord(extd)-63); write(#7); inkey; end;
+ '': begin setvisualpage(0); write(#7); inkey; end;*/
+
+void keyboard_link()
+{
+ state(defaultled); /* if defaultled=1 then on; { For the menus }*/
+ joykeys(); /* Test joystick buttons- I know that's not keyboard. */
+
+ if (demo)
+ {
+ if (keypressede()) exit(0);
+ if (demo_rec.delay>0)
+ demo_rec.delay -= 1;
+ else typein();
+ return;
+ }
+
+ #ifdef RECORD count += 1; #endif
+
+ if (! keypressede()) return;
+ if (keyboardclick) click();
+ typein();
+}
+
+boolean demo_ready()
+{
+ boolean demo_ready_result;
+ if (demo_rec.delay>0)
+ {
+ slowdown();
+ demo_rec.delay -= 1;
+ }
+ demo_ready_result=demo_rec.delay==0;
+ return demo_ready_result;
+}
+
+void filename_edit()
+{
+ entering_filename=true;
+ current="Filename\? (Esc=cancel):";
+ left_margin=24; curpos=24;
+ plottext();
+}
+
+void normal_edit()
+{
+ entering_filename=false;
+ current="";
+ left_margin=1; curpos=1;
+}
+
+class unit_basher_initialize {
+ public: unit_basher_initialize();
+};
+static unit_basher_initialize basher_constructor;
+
+unit_basher_initialize::unit_basher_initialize() {
+/* new(previous);*/ last=""; normal_edit();
+
+ if (demo)
+ {
+ assign(demofile,"demo.avd");
+ reset(demofile);
+ }
+
+ #ifdef RECORD
+ count=0;
+ assign(demofile,"demo.avd");
+ rewrite(demofile);
+ #endif
+
+}
diff --git a/engines/avalanche/basher.h b/engines/avalanche/basher.h
new file mode 100644
index 0000000000..1afecae441
--- /dev/null
+++ b/engines/avalanche/basher.h
@@ -0,0 +1,40 @@
+#ifndef __basher_h__
+#define __basher_h__
+
+
+#include "gyro.h"
+/*#include "Tommys.h"*/
+
+
+#ifdef RECORD
+
+#ifdef __basher_implementation__
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN word count;
+#undef EXTERN
+#define EXTERN extern
+
+#endif
+
+ void plottext();
+
+ void keyboard_link();
+
+ void cursor_on();
+
+ void get_demorec();
+
+ boolean demo_ready();
+
+ void cursor_off();
+
+ void filename_edit();
+ void normal_edit();
+#ifdef RECORD
+ void record_one();
+#endif
+
+#endif
diff --git a/engines/avalanche/bootstrp.cpp b/engines/avalanche/bootstrp.cpp
new file mode 100644
index 0000000000..a903679a90
--- /dev/null
+++ b/engines/avalanche/bootstrp.cpp
@@ -0,0 +1,349 @@
+#include "ptoc.h"
+
+
+/*#include "Dos.h"*/
+
+
+/*$M 8192,0,$6000, S-*/
+
+enum elm {normal, musical, elmpoyten, regi, last_elm};
+
+const integer run_shootemup = 1;
+const integer run_dosshell = 2;
+const integer run_ghostroom = 3;
+const integer run_golden = 4;
+
+const array<false,true,varying_string<2> > runcodes = {{"et","Go"}};
+
+const integer reset_ = 0;
+
+const boolean jsb = true; const boolean no_jsb = false;
+const boolean bflight = true; const boolean no_bflight = false;
+
+
+struct {
+ byte operation;
+ word skellern;
+ array<1,10000,byte> contents;
+} storage;
+
+string arguments,demo_args,args_with_no_filename;
+
+boolean first_time;
+
+byte original_mode;
+pointer old_1c;
+
+string segofs;
+
+boolean zoomy;
+
+longint soundcard,speed,baseaddr,irq,dma;
+
+void cursor_off() /*assembler; */
+{;
+/* asm
+ mov ah,01; { Change cursor size. */
+/* mov cx,8224; { CH & CL are now 32. */
+/* int $10; { Call the Bios */
+
+} /* That's all. */
+
+void cursor_on() /*assembler; */
+{;
+/*
+asm
+ mov ah,01; { Change cursor size. */
+/* mov ch,5; { Top line is 5. */
+/* mov cl,7; { Bottom line is 7. */
+/* int $10; { Call the Bios. */
+
+}
+
+void quit()
+{
+ cursor_on();
+ exit(0);
+}
+
+string strf(longint x)
+{
+ string q;
+string strf_result;
+;
+ str(x,q); strf_result=q;
+return strf_result;
+}
+
+string command_com()
+{
+ string temp;
+
+ string command_com_result;
+ temp=getenv("comspec");
+ if (temp=="")
+ output << "avvy_bootstrap: COMSPEC not defined, => cannot run Dos shell." << NL;
+ command_com_result=temp;
+ return command_com_result;
+}
+
+void explain(byte error)
+{
+ output << " (";
+ switch (error) {
+ case 2: output << "it's not there"; break;
+ case 8: output << "out of memory"; break;
+ default: output << "error " << error;
+ }
+ output << ")." << NL;
+}
+
+/*$F+*/
+
+void b_flight() /*interrupt;*/
+{
+ storage.skellern += 1;
+}
+
+/*$F-*/
+
+void bflight_on()
+{
+ storage.skellern=reset_;
+ setintvec(0x1c,&b_flight);
+}
+
+void bflight_off()
+{
+ setintvec(0x1c,old_1c);
+}
+
+void run(string what, boolean with_jsb,boolean with_bflight, elm how);
+
+
+static string elm2str(elm how)
+{
+ string elm2str_result;
+ switch (how) {
+ case normal: case musical: elm2str_result="jsb"; break;
+ case regi: elm2str_result="REGI"; break;
+ case elmpoyten: elm2str_result="ELMPOYTEN"; break;
+ }
+ return elm2str_result;
+}
+
+void run(string what, boolean with_jsb,boolean with_bflight, elm how)
+{
+ string which_dir,args;
+ integer error;
+
+
+ if (what=="") return;
+
+ getdir(0,which_dir);
+
+ if (with_jsb)
+ {
+ if (how==musical)
+ args=elm2str(how)+' '+args_with_no_filename; /* FN is NOT given if musical*/
+ else
+ args=elm2str(how)+' '+arguments;
+ } else args="";
+
+ if (how==musical) args=args+strf(soundcard)+' '+strf(speed)+' '+
+ strf(baseaddr)+' '+strf(dma)+' '+strf(irq);
+ if (with_bflight) bflight_on();
+
+ swapvectors;
+ exec(what,args);
+ swapvectors;
+ cursor_off();
+
+ error=doserror;
+
+ if (with_bflight) bflight_off();
+
+ chdir(which_dir);
+
+ if (error!=0)
+ {
+ output << "avvy_bootstrap: cannot execute " << what << '!';
+ explain(error);
+ output << "Press Enter:"; input >> NL; quit();
+ }
+}
+
+void run_avalot()
+{
+ integer error;
+
+
+ bflight_on();
+
+ swapvectors;
+ exec("avalot.avx",runcodes[first_time]+arguments);
+ swapvectors;
+
+ error=doserror;
+
+ bflight_off();
+
+ if (error!=0)
+ {
+ output << "avvy_bootstrap: error in loading AVALOT.AVX!";
+ explain(error);
+ quit();
+ }
+
+ first_time=false;
+}
+
+void run_the_demo()
+{
+ string args;
+
+ args=arguments;
+ arguments=demo_args; /* Force the demo. */
+
+ run_avalot();
+
+ arguments=args; /* Put all back to normal again. */
+ first_time=true;
+}
+
+void get_arguments()
+{
+ byte fv;
+
+ arguments="";
+
+ for( fv=1; fv <= paramcount; fv ++)
+ arguments=arguments+paramstr(fv)+' ';
+
+ arguments[0] -= 1; /* Get rid of the trailing space. */
+
+ segofs=string(' ')+strf(seg(storage))+' '+strf(ofs(storage));
+
+ arguments=segofs+' '+arguments;
+}
+
+void dos_shell()
+{
+ registers r;
+
+ r.ax=original_mode; intr(0x10,r);
+ output << NL;
+ output << "The Avalot Dos Shell." << NL;
+ output << "---------------------" << NL;
+ output << NL;
+ output << "Type EXIT to return to Avalot." << NL;
+ output << NL;
+
+ cursor_on();
+ run(command_com(),no_jsb,no_bflight,normal);
+ cursor_off();
+
+ output << "Please wait, restoring your game..." << NL;
+}
+
+boolean keypressed1() {
+ registers r;
+
+ boolean keypressed1_result;
+ r.ah=0xb;
+ msdos(r);
+ keypressed1_result=r.al==0xff;
+ return keypressed1_result;
+ }
+
+void flush_buffer() {
+ registers r; r.ah=7;
+ while (keypressed1()) msdos(r); }
+
+void demo()
+{
+ run_the_demo(); if (keypressed1()) return;
+ run("intro.avx",jsb,bflight,musical); if (keypressed1()) return;
+ run("stars.avx",jsb,no_bflight,musical); if (keypressed1()) return;
+
+ flush_buffer();
+}
+
+void call_menu()
+{
+ run("stars.avx",jsb,no_bflight,musical);
+ flush_buffer();
+ do {
+ run("avmenu.avx",jsb,no_bflight,normal);
+
+ switch (storage.operation) {
+ case 1: return; break; /* Play the game. */
+ case 2: run("intro.avx",jsb,bflight,musical); break;
+ case 3: run("preview1.avd",jsb,no_bflight,normal); break;
+ case 4: run("viewdocs.avx",jsb,bflight,elmpoyten); break;
+ case 5: run("viewdocs.avx",jsb,bflight,regi); break;
+ case 6: quit(); break;
+ case 177: demo(); break;
+ }
+
+ flush_buffer();
+ } while (!false);
+}
+
+void get_slope()
+{
+ run("slope.avx",jsb,no_bflight,normal);
+ if (dosexitcode!=0)
+ {
+ cursor_on();
+ exit(0);
+ }
+
+ move(storage.contents,arguments,sizeof(arguments));
+ move(storage.contents[4998],soundcard,4);
+ move(storage.contents[5002],baseaddr,4);
+ move(storage.contents[5006],irq,4);
+ move(storage.contents[5010],dma,4);
+ move(storage.contents[5014],speed,4);
+
+ zoomy=(arguments[8]=='y') || (arguments[2]=='y');
+ demo_args=arguments; demo_args[7]='y';
+ arguments=segofs+' '+arguments;
+ demo_args=segofs+' '+demo_args;
+
+ args_with_no_filename=arguments;
+ if (arguments[length(arguments)]!=' ')
+ { /* Filename was given */
+ args_with_no_filename=arguments;
+ while ((args_with_no_filename!="")
+ && (args_with_no_filename[length(args_with_no_filename)]!=' '))
+ args_with_no_filename[0] -= 1; /* Strip off the filename. */
+ }
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ original_mode=mem[seg0040*0x49]; getintvec(0x1c,old_1c);
+ first_time=true; cursor_off();
+
+ get_arguments();
+ get_slope();
+
+ if (! zoomy) call_menu(); /* Not run when zoomy. */
+
+ do {
+ run_avalot();
+
+ if (dosexitcode!=77) quit(); /* Didn't stop for us. */
+
+ switch (storage.operation) {
+ case run_shootemup: run("seu.avx",jsb,bflight,normal); break;
+ case run_dosshell: dos_shell(); break;
+ case run_ghostroom: run("g-room.avx",jsb,no_bflight,normal); break;
+ case run_golden: run("golden.avx",jsb,bflight,musical); break;
+ }
+
+ } while (!false);
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/cadburys.cpp b/engines/avalanche/cadburys.cpp
new file mode 100644
index 0000000000..b891123af5
--- /dev/null
+++ b/engines/avalanche/cadburys.cpp
@@ -0,0 +1,109 @@
+#include "ptoc.h"
+
+#define __cadburys_implementation__
+
+
+#include "cadburys.h"
+
+
+#include "graph.h"
+
+
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {;
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {;
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=((realx-ch.x*8)+(x2-x1)+7) / 8;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {;
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+
diff --git a/engines/avalanche/cadburys.h b/engines/avalanche/cadburys.h
new file mode 100644
index 0000000000..65e7bd7c8b
--- /dev/null
+++ b/engines/avalanche/cadburys.h
@@ -0,0 +1,41 @@
+#ifndef __cadburys_h__
+#define __cadburys_h__
+
+
+const integer arraysize = 12000;
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+
+#ifdef __cadburys_implementation__
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN array<0,arraysize,byte> aa;
+EXTERN byte num_chunks,this_chunk;
+EXTERN integer gd,gm;
+EXTERN array<1,30,longint> offsets;
+EXTERN untyped_file f;
+#undef EXTERN
+#define EXTERN extern
+
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat);
+
+#endif
diff --git a/engines/avalanche/celer.cpp b/engines/avalanche/celer.cpp
new file mode 100644
index 0000000000..61357f567b
--- /dev/null
+++ b/engines/avalanche/celer.cpp
@@ -0,0 +1,472 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ CELER The unit for updating the screen pics. */
+
+#define __celer_implementation__
+
+
+#include "celer.h"
+
+
+#include "Graph.h"
+#include "trip5.h"
+#include "lucerna.h"
+/*#include "Crt.h"*/
+
+
+untyped_file f; /* Private variable- not accessible from elsewhere. */
+
+const integer on_disk = -1; /* Value of memos[fv].x when it's not in memory. */
+
+void pics_link()
+{
+ byte xx;
+
+ if (ddmnow) return; /* No animation when the menus are up. */
+
+ { dnatype& with = dna;
+ switch (with.room) {
+
+ case r__outsideargentpub: {
+ if ((roomtime % longint(12))==0)
+ show_one(longint(1)+(roomtime / longint(12)) % longint(4));
+ }
+ break;
+
+ case r__brummieroad: if ((roomtime % longint(2))==0)
+ show_one(longint(1)+(roomtime / longint(2)) % longint(4));
+ break;
+
+ case r__bridge: if ((roomtime % longint(2))==0)
+ show_one(longint(4)+(roomtime / longint(2)) % longint(4));
+ break;
+
+ case r__yours: if ((! with.avvy_is_awake) && ((roomtime % longint(4))==0))
+ show_one(longint(1)+(roomtime / longint(12)) % longint(2));
+ break;
+
+ case r__argentpub: {
+ if (((roomtime % longint(7))==1) && (dna.malagauche!=177))
+ { /* Malagauche cycle */
+ dna.malagauche += 1;
+ switch (dna.malagauche) {
+ case 1:case 11:case 21: show_one(12); break; /* Looks forwards. */
+ case 8:case 18:case 28:case 32: show_one(11); break; /* Looks at you. */
+ case 30: show_one(13); break; /* Winks. */
+ case 33: dna.malagauche=0; break;
+ }
+ }
+
+ switch (roomtime % longint(200)) {
+ case 179:case 197: show_one(5); break; /* Dogfood's drinking cycle */
+ case 182:case 194: show_one(6); break;
+ case 185: show_one(7); break;
+ case 199: dna.dogfoodpos=177; break; /* Impossible value for this. */
+ case 0 ... 178: { /* Normally. */
+ switch (bearing(2)) {/* Bearing of Avvy from Dogfood. */
+ case 1 ... 90:case RANGE_3(358,360): xx=3; break;
+ case 293 ... 357: xx=2; break;
+ case 271 ... 292: xx=4; break;
+ }
+ if (xx!=dna.dogfoodpos) /* Only if it's changed.*/
+ {
+ show_one(xx);
+ dna.dogfoodpos=xx;
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case r__westhall: if ((roomtime % longint(3))==0)
+ switch ((roomtime / longint(3)) % longint(6)) {
+ case 4: show_one(1); break;
+ case 1:case 3:case 5: show_one(2); break;
+ case 0:case 2: show_one(3); break;
+ }
+ break;
+ case r__lustiesroom: if (! (dna.lustie_is_asleep)) {
+ if ((roomtime % longint(45))>42) xx=4; /* du Lustie blinks */
+ else
+ switch (bearing(2)) {/* Bearing of Avvy from du Lustie. */
+ case 0 ... 45:case 315 ... 360: xx=1; break; /* Middle. */
+ case 45 ... 180: xx=2; break; /* Left. */
+ case 181 ... 314: xx=3; break; /* Right. */
+ }
+ if (xx!=dna.dogfoodpos) /* Only if it's changed.*/
+ {
+ show_one(xx);
+ dna.dogfoodpos=xx; /* We use DogfoodPos here too- why not? */
+ }
+ }
+ break;
+
+ case r__aylesoffice: if ((! dna.ayles_is_awake) && (roomtime % longint(14)==0))
+ {
+ switch ((roomtime / longint(14)) % longint(2)) {
+ case 0: show_one(1); break; /* Frame 2: EGA. */
+ case 1: show_one(3); break; /* Frame 1: Natural. */
+ }
+ }
+ break;
+
+ case r__robins: if (dna.tied_up)
+ switch (roomtime % longint(54)) {
+ case 20: show_one(4); break; /* Frame 4: Avalot blinks. */
+ case 23: show_one(2); break; /* Frame 1: Back to normal. */
+ }
+ break;
+
+ case r__nottspub: {
+ switch (bearing(5)) { /* Bearing of Avvy from Port. */
+ case 0 ... 45:case 315 ... 360: xx=2; break; /* Middle. */
+ case 45 ... 180: xx=6; break; /* Left. */
+ case 181 ... 314: xx=8; break; /* Right. */
+ }
+
+ if ((roomtime % longint(60))>57) xx -= 1; /* Blinks */
+
+ if (xx!=dna.dogfoodpos) /* Only if it's changed.*/
+ {
+ show_one(xx);
+ dna.dogfoodpos=xx; /* We use DogfoodPos here too- why not? */
+ }
+
+ switch (roomtime % longint(50)) {
+ case 45 : show_one(9); break; /* Spurge blinks */
+ case 49 : show_one(10); break;
+ }
+ }
+ break;
+
+ case r__ducks: {
+ if ((roomtime % longint(3))==0) /* The fire flickers */
+ show_one(longint(1)+(roomtime / longint(3)) % longint(3));
+
+ switch (bearing(2)) {/* Bearing of Avvy from Duck. */
+ case 0 ... 45:case 315 ... 360: xx=4; break; /* Middle. */
+ case 45 ... 180: xx=6; break; /* Left. */
+ case 181 ... 314: xx=8; break; /* Right. */
+ }
+
+ if ((roomtime % longint(45))>42) xx += 1; /* Duck blinks */
+
+ if (xx!=dna.dogfoodpos) /* Only if it's changed.*/
+ {
+ show_one(xx);
+ dna.dogfoodpos=xx; /* We use DogfoodPos here too- why not? */
+ }
+ }
+ break;
+
+ }}
+
+ if ((dna.ringing_bells) && (flagset('B')))
+ /* They're ringing the bells. */
+ switch (roomtime % longint(4)) {
+ case 1: {
+ dnatype& with = dna;
+
+ if (with.nextbell<5) with.nextbell=12;
+ with.nextbell -= 1;
+ note(notes[with.nextbell]);
+ }
+ break;
+ case 2: nosound; break;
+ }
+
+}
+
+void load_chunks(string xx)
+{
+ chunkblocktype ch;
+ byte fv;
+
+ /*$I-*/
+ assign(f,string("chunk")+xx+".avd"); /* strf is done for us by Lucerna. */
+ reset(f,1);
+ if (ioresult!=0) return; /* no Chunk file. */
+ seek(f,44);
+ blockread(f,num_chunks,1);
+ blockread(f,offsets,num_chunks*4);
+
+ for( fv=1; fv <= num_chunks; fv ++)
+ {
+ seek(f,offsets[fv]);
+ blockread(f,ch,sizeof(ch));
+ {
+ if (ch.memorise)
+ {
+
+ {
+ memotype& with1 = memos[fv];
+
+ with1.x=ch.x; with1.xl=ch.xl;
+ with1.y=ch.y; with1.yl=ch.yl;
+ with1.flavour=ch.flavour;
+ with1.size=ch.size;
+ }
+
+ getmem(memory[fv],ch.size);
+
+ if (ch.natural)
+ {
+ getimage(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl,memory[fv]);
+ } else
+ blockread(f,memory[fv],ch.size);
+ } else memos[fv].x=on_disk;
+ }
+ }
+
+ close(f);
+ /*$I+*/
+}
+
+void forget_chunks()
+{
+ byte fv;
+
+ for( fv=1; fv <= num_chunks; fv ++)
+ if (memos[fv].x>on_disk)
+ freemem(memory[fv],memos[fv].size);
+ fillchar(memos,sizeof(memos),'\377'); /* x=-1, => on disk. */
+}
+
+void mdrop(integer x,integer y,integer xl,integer yl, pointer p) /* assembler;
+asm
+ push ds; { Strictly speaking, we shouldn't modify DS, so we'll save it.}
+ push bp; { Nor BP! }
+
+
+ { DI holds the offset on this page. It starts at the top left-hand corner. }
+ { (It should equal ch.y*80+ch.x. }
+
+ mov ax,y;
+ mov dl,80;
+ mul dl; { Line offset now calculated. }
+ mov di,ax; { Move it into DI. }
+ mov ax,x;
+ add di,ax; { Full offset now calculated. }
+
+ mov bx,yl; { No. of times to repeat lineloop. }
+ inc bx; { "loop" doesn't execute the zeroth time. }
+ mov bh,bl; { Put it into BH. }
+
+ { BP holds the length of the string to copy. It's equal to ch.xl.}
+
+ mov ax,word(p); { Data is held at DS:SI. }
+ mov si,ax;
+ mov ax,word(p+2); { This will be moved over into ds in just a tick... }
+
+ mov bp,xl;
+
+ mov ds,ax;
+
+
+ cld; { We're allowed to hack around with the flags! }
+
+ mov ax,$AC00; { Top of the first EGA page. }
+ mov es,ax; { Offset on this page is calculated below... }
+
+
+{ port[$3c4]:=2; port[$3ce]:=4; }
+
+ mov dx,$3c4;
+ mov al,2;
+ out dx,al;
+ mov dx,$3ce;
+ mov al,4;
+ out dx,al;
+
+ mov cx,4; { This loop executes for 3, 2, 1, and 0. }
+ mov bl,0;
+
+
+ @mainloop:
+
+ push di;
+ push cx;
+
+{ port[$3C5]:=1 shl bit; }
+ mov dx,$3C5;
+ mov al,1;
+ mov cl,bl; { BL = bit. }
+ shl al,cl;
+ out dx,al;
+{ port[$3CF]:=bit; }
+ mov dx,$3CF;
+ mov al,bl; { BL = bit. }
+ out dx,al;
+
+ xor ch,ch;
+ mov cl,bh; { BH = ch.yl. }
+
+ @lineloop:
+
+ push cx;
+
+ mov cx,bp;
+
+ repz movsb; { Copy the data. }
+
+ sub di,bp;
+ add di,80;
+
+ pop cx;
+
+ loop @lineloop;
+
+ inc bl; { One more on BL. }
+
+ pop cx;
+ pop di;
+
+ loop @mainloop;
+
+ pop bp;
+ pop ds; { Get DS back again. }
+*/
+{;
+}
+
+void show_one(byte which);
+
+static bytefield r;
+
+static void display_it(integer x,integer y,integer xl,integer yl, flavourtype flavour, pointer p)
+{
+ {
+ switch (flavour) {
+ case ch_bgi : {
+ putimage(x*8,y,p,0);
+ r.x1=x; r.y1=y;
+ r.x2=x+xl+1; r.y2=y+yl;
+ }
+ break;
+ case ch_ega : {
+ mdrop(x,y,xl,yl,p); blitfix();
+ r.x1=x; r.y1=y; r.x2=x+xl; r.y2=y+yl;
+ }
+ break;
+ }
+}
+}
+
+void show_one(byte which)
+{
+ chunkblocktype ch;
+ pointer p;
+ byte fv;
+
+
+ setactivepage(3);
+
+ {
+ memotype& with = memos[which];
+
+ if (with.x>on_disk)
+ {
+ display_it(with.x,with.y,with.xl,with.yl,with.flavour,memory[which]);
+ } else
+ {
+ reset(f,1);
+ seek(f,offsets[which]);
+ blockread(f,ch,sizeof(ch));
+
+ {
+ getmem(p,ch.size);
+ blockread(f,p,ch.size);
+
+ display_it(ch.x,ch.y,ch.xl,ch.yl,ch.flavour,p);
+ freemem(p,ch.size);
+
+ close(f);
+ }
+
+ }
+
+ setactivepage(1-cp);
+
+ for( fv=0; fv <= 1; fv ++)
+ getset[fv].remember(r);
+ }
+
+}
+
+void show_one_at(byte which, integer xxx,integer yyy);
+
+static bytefield r1;
+
+static void display_it1(integer xl,integer yl, flavourtype flavour, pointer p, integer& xxx, integer& yyy)
+{
+ {
+ switch (flavour) {
+ case ch_bgi : {
+ putimage(xxx,yyy,p,0);
+ r1.x1=xxx; r1.y1=yyy;
+ r1.x2=xxx+xl+1; r1.y2=yyy+yl;
+ }
+ break;
+ case ch_ega : {
+ mdrop(xxx / 8,yyy,xl,yl,p); blitfix();
+ r1.x1=xxx / 8; r1.y1=yyy; r1.x2=(xxx / 8)+xl; r1.y2=yyy+yl;
+ }
+ break;
+ }
+}
+}
+
+void show_one_at(byte which, integer xxx,integer yyy)
+{
+ chunkblocktype ch;
+ pointer p;
+ byte fv;
+
+
+ setactivepage(3);
+
+ {
+ memotype& with = memos[which];
+
+ if (with.x>on_disk)
+ {
+ display_it1(with.xl,with.yl,with.flavour,memory[which], xxx, yyy);
+ } else
+ {
+ reset(f,1);
+ seek(f,offsets[which]);
+ blockread(f,ch,sizeof(ch));
+
+ {
+ getmem(p,ch.size);
+ blockread(f,p,ch.size);
+
+ display_it1(ch.xl,ch.yl,ch.flavour,p, xxx, yyy);
+ freemem(p,ch.size);
+
+ close(f);
+ }
+
+ }
+
+ setactivepage(1-cp);
+
+ for( fv=0; fv <= 1; fv ++)
+ getset[fv].remember(r1);
+ }
+}
+
+class unit_celer_initialize {
+ public: unit_celer_initialize();
+};
+static unit_celer_initialize celer_constructor;
+
+unit_celer_initialize::unit_celer_initialize() {
+ num_chunks=0;
+}
diff --git a/engines/avalanche/celer.h b/engines/avalanche/celer.h
new file mode 100644
index 0000000000..f6ad52ffb1
--- /dev/null
+++ b/engines/avalanche/celer.h
@@ -0,0 +1,53 @@
+#ifndef __celer_h__
+#define __celer_h__
+
+
+#include "closing.h"
+#include "incline.h"
+#include "gyro.h"
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+struct memotype {
+ integer x,y;
+ integer xl,yl;
+ flavourtype flavour;
+ word size;
+};
+
+
+#ifdef __celer_implementation__
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN array<1,40,longint> offsets;
+EXTERN byte num_chunks;
+EXTERN array<1,40,memotype> memos;
+EXTERN array<1,40,pointer> memory;
+#undef EXTERN
+#define EXTERN extern
+
+
+ void pics_link();
+
+ void load_chunks(string xx);
+
+ void forget_chunks();
+
+ void show_one(byte which);
+
+ void show_one_at(byte which, integer xxx,integer yyy);
+
+#endif
diff --git a/engines/avalanche/ch_egats.cpp b/engines/avalanche/ch_egats.cpp
new file mode 100644
index 0000000000..a27c2612c1
--- /dev/null
+++ b/engines/avalanche/ch_egats.cpp
@@ -0,0 +1,155 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+untyped_file f;
+longint offset;
+chunkblocktype ch;
+integer gd,gm;
+byte bit;
+pointer p;
+
+void mdrop(integer x,integer y,integer xl,integer yl, pointer p) /* assembler;
+asm
+ push ds; { Strictly speaking, we shouldn't modify DS, so we'll save it.}
+ push bp; { Nor BP! }
+
+
+ { DI holds the offset on this page. It starts at the top left-hand corner. }
+ { (It should equal ch.y*80+ch.x. }
+
+ mov ax,y;
+ mov dl,80;
+ mul dl; { Line offset now calculated. }
+ mov di,ax; { Move it into DI. }
+ mov ax,x;
+ add di,ax; { Full offset now calculated. }
+
+ mov bx,yl; { No. of times to repeat lineloop. }
+ inc bx; { "loop" doesn't execute the zeroth time. }
+ mov bh,bl; { Put it into BH. }
+
+ { BP holds the length of the string to copy. It's equal to ch.xl.}
+
+ mov ax,word(p); { Data is held at DS:SI. }
+ mov si,ax;
+ mov ax,word(p+2); { This will be moved over into ds in just a tick... }
+
+ mov bp,xl;
+
+ mov ds,ax;
+
+
+ cld; { We're allowed to hack around with the flags! }
+
+ mov ax,$A000; { Top of the first EGA page. }
+ mov es,ax; { Offset on this page is calculated below... }
+
+
+{ port[$3c4]:=2; port[$3ce]:=4; }
+
+ mov dx,$3c4;
+ mov al,2;
+ out dx,al;
+ mov dx,$3ce;
+ mov al,4;
+ out dx,al;
+
+ mov cx,4; { This loop executes for 3, 2, 1, and 0. }
+ mov bl,0;
+
+
+ @mainloop:
+
+ push di;
+ push cx;
+
+{ port[$3C5]:=1 shl bit; }
+ mov dx,$3C5;
+ mov al,1;
+ mov cl,bl; { BL = bit. }
+ shl al,cl;
+ out dx,al;
+{ port[$3CF]:=bit; }
+ mov dx,$3CF;
+ mov al,bl; { BL = bit. }
+ out dx,al;
+
+ xor ch,ch;
+ mov cl,bh; { BH = ch.yl. }
+
+ @lineloop:
+
+ push cx;
+
+ mov cx,bp;
+
+ repz movsb; { Copy the data. }
+
+ sub di,bp;
+ add di,80;
+
+ pop cx;
+
+ loop @lineloop;
+
+ inc bl; { One more on BL. }
+
+ pop cx;
+ pop di;
+
+ loop @mainloop;
+
+ pop bp;
+ pop ds; { Get DS back again. }
+*/
+{;
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ assign(f,"chunk21.avd");
+ reset(f,1);
+
+ seek(f,49);
+ blockread(f,offset,4);
+
+ seek(f,offset);
+
+ blockread(f,ch,sizeof(ch));
+
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+
+ getmem(p,ch.size);
+ blockread(f,p,ch.size);
+/* putimage(0,0,p^,0);*/
+
+
+/* with ch do
+ for bit:=0 to 3 do
+ begin;
+ port[$3c4]:=2; port[$3ce]:=4; port[$3C5]:=1 shl bit; port[$3CF]:=bit;
+ for gm:=0 to yl do
+ blockread(f,mem[$A000*gm*80],(ch.xl+7) div 8);
+ end;*/
+
+ mdrop(ch.x,ch.y,ch.xl,ch.yl,p);
+
+ close(f);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/charmap.cpp b/engines/avalanche/charmap.cpp
new file mode 100644
index 0000000000..8b38f8ad62
--- /dev/null
+++ b/engines/avalanche/charmap.cpp
@@ -0,0 +1,30 @@
+#include "ptoc.h"
+
+
+/*#include "Dos.h"*/
+
+struct infotype {
+ matrix<128,255,1,8,byte> chars;
+ string data;
+};
+infotype table;
+pointer where;
+byte w,fv,ff,num;
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ getintvec(0x1f,where); move(where,table,1024);
+ for( w=128; w <= 255; w ++)
+ {; output << w << NL;
+ for( fv=1; fv <= 8; fv ++)
+ {;
+ num=table.chars[w][fv];
+ for( ff=1; ff <= 8; ff ++)
+ {;
+ if ((num & 128)==0) output << " "; else output << "ÛÛ";
+ num=num << 1;
+ }
+ output << NL;
+ } }
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/chunker.cpp b/engines/avalanche/chunker.cpp
new file mode 100644
index 0000000000..6d48054a2e
--- /dev/null
+++ b/engines/avalanche/chunker.cpp
@@ -0,0 +1,86 @@
+#include "ptoc.h"
+
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+untyped_file f;
+string fn;
+byte num_chunks,fv;
+longint offset;
+chunkblocktype ch;
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ output << NL;
+ output << "CHUNKER 12/3/1995 TT" << NL;
+ output << NL;
+
+ if (paramcount!=1)
+ {
+ output << "which chunk file?" << NL;
+ exit(0);
+ }
+
+ fn=paramstr(1);
+ assign(f,fn);
+ reset(f,1);
+ output << "----- In chunk file " << fn << ", there are: -----" << NL;
+
+ seek(f,44);
+ blockread(f,num_chunks,1);
+ output << format(num_chunks,4) << " chunks:" << NL;
+
+ output << " No Hdr Offset Flvr Mem Nat X Y Width Height Size of image" << NL;
+
+ for( fv=1; fv <= num_chunks; fv ++)
+ {
+
+ output << "Ch" << format(fv,2) << ':';
+
+ seek(f,41+fv*4);
+
+ output << format(41+fv*4,4);
+ blockread(f,offset,4);
+ output << format(offset,10);
+
+ seek(f,offset);
+ blockread(f,ch,sizeof(ch));
+ {
+ if (ch.flavour==ch_bgi)
+ output << " ch_BGI";
+ else
+ output << " ch_EGA";
+
+ if (ch.memorise)
+ output << " yes";
+ else
+ output << " no ";
+
+ if (ch.natural)
+ output << " yes";
+ else
+ output << " no ";
+
+ output << format(ch.x,7) << format(ch.y,7) << format(ch.xl,7) << format(ch.yl,7) << format(ch.size,10);
+ }
+
+ output << NL;
+ }
+
+ output << "---ENDS---" << NL;
+
+ close(f);
+ return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/chunkxf1.cpp b/engines/avalanche/chunkxf1.cpp
new file mode 100644
index 0000000000..dce3722837
--- /dev/null
+++ b/engines/avalanche/chunkxf1.cpp
@@ -0,0 +1,259 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+#include "cadburys.h"
+
+
+/*type
+ flavourtype = (ch_EGA,ch_BGI);
+
+ chunkblocktype = record
+ flavour:flavourtype;
+ x,y:integer;
+ xl,yl:integer;
+ size:longint;
+ natural:boolean;
+
+ memorise:boolean; { Hold it in memory? }
+ end;*/
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+/* arraysize = 12000;*/
+
+/* offsets:array[1..30] of longint;*/
+byte num_chunks/*,this_chunk*/;
+integer gd,gm;
+/* f:file;*/
+/* aa:array[0..arraysize] of byte;*/
+
+void load()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+ assign(f,"chunkbit.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ assign(f,"place21.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk21.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+/*
+procedure mgrab(x1,y1,x2,y2:integer; size:word);
+var yy:integer; aapos:word; length,bit:byte;
+begin;
+ if size>arraysize then
+ begin;
+ writeln('*** SORRY! *** Increase the arraysize constant to be greater');
+ writeln(' than ',size,'.');
+ halt;
+ end;
+
+ aapos:=0;
+
+ length:=x2-x1;
+
+ for bit:=0 to 3 do
+ begin;
+ port[$3c4]:=2; port[$3ce]:=4; port[$3C5]:=1 shl bit; port[$3CF]:=bit;
+ for yy:=y1 to y2 do
+ begin;
+ move(mem[$A400*yy*80+x1],aa[aapos],length);
+ move(aa[aapos],mem[$A400*yy*80],length);
+(* fillchar(mem[$A400:yy*80+x1],length,#177);*)
+ inc(aapos,length);
+ end;
+ end;
+ bit:=getpixel(0,0);
+
+end;
+*/
+/*procedure grab(x1,y1,x2,y2,realx,realy:integer; flav:flavourtype;
+ mem,nat:boolean);
+ { yes, I *do* know how to spell "really"! }
+var
+ s:word;
+ p:pointer;
+ ch:chunkblocktype;
+begin;
+ inc(this_chunk);
+ offsets[this_chunk]:=filepos(f);
+
+
+ s:=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p^);
+
+ with ch do
+ begin;
+ flavour:=flav;
+ x:=realx; y:=realy;
+
+ xl:=x2-x1;
+ yl:=y2-y1;
+ size:=s;
+ memorise:=mem;
+ natural:=nat;
+ end;
+
+ setvisualpage(1);
+ setactivepage(1);
+ readln;
+ putimage(ch.x,ch.y,p^,0);
+
+ if flav=ch_EGA then
+ begin;
+ freemem(p,s);
+ s:=4*((x2-x1+7) div 8)*(y2-y1+1);
+ with ch do
+ begin;
+ size:=s;
+ x:=x div 8;
+ xl:=(xl+7) div 8;
+ mgrab(x,y,x+xl,y+yl,s);
+ end;
+ end;
+
+ readln;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ case flav of
+ ch_EGA : if not nat then blockwrite(f,aa,s);
+ ch_BGI : begin;
+ if not nat then blockwrite(f,p^,s);
+ freemem(p,s);
+ end;
+ end;
+{ rectangle(x1,y1,x2,y2);}
+end;*/
+
+/*procedure grab(x1,y1,x2,y2,realx,realy:integer; flav:flavourtype;
+ mem,nat:boolean);*/
+ /* yes, I *do* know how to spell "really"! */
+/*var
+ s:word;
+ p:pointer;
+ ch:chunkblocktype;
+begin;
+(* rectangle(x1,y1,x2,y2); exit;*)
+ inc(this_chunk);
+ offsets[this_chunk]:=filepos(f);
+
+
+ s:=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p^);
+
+ with ch do
+ begin;
+ flavour:=flav;
+ x:=realx; y:=realy;
+
+ xl:=x2-x1;
+ yl:=y2-y1;
+ size:=s;
+ memorise:=mem;
+ natural:=nat;
+ end;
+
+ setvisualpage(1);
+ setactivepage(1);
+ readln;
+ putimage(ch.x,ch.y,p^,0);
+
+ if flav=ch_EGA then
+ begin;
+ freemem(p,s);
+ s:=4*(((x2 div 8)-(x1 div 8))+2)*(y2-y1+1);
+ with ch do
+ begin;
+ size:=s;
+ x:=x div 8;
+ xl:=(xl div 8)+2;
+ mgrab(x,y,x+xl,y+yl,s);
+ end;
+ end else
+ with ch do { For BGI pictures. *//*
+ begin;
+ x:=x div 8;
+ xl:=(xl+7) div 8;
+ size:=imagesize(x*8,y,(x+xl)*8,y+yl);
+ end;
+
+ readln;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ case flav of
+ ch_EGA : if not nat then blockwrite(f,aa,s);
+ ch_BGI : begin;
+ if not nat then blockwrite(f,p^,s);
+ freemem(p,s);
+ end;
+ end;
+(* rectangle(x1,y1,x2,y2);*)
+end;*/
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ setwritemode(xorput);
+
+ num_chunks=7;
+
+ open_chunk();
+
+ grab( 98,10,181,41,247,82,ch_ega,false,false); /* Drawbridge... */
+ grab(223,10,320,41,233,82,ch_ega,false,false);
+ grab(361,10,458,64,233,82,ch_ega,false,false);
+
+ grab( 11,10, 39,22,172,17,ch_bgi,true,true);
+ grab( 11,38, 39,50,172,17,ch_ega,true,false); /* Flag. */
+ grab( 11,24, 39,36,172,17,ch_ega,true,false);
+ grab( 11,10, 39,22,172,17,ch_ega,true,false);
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxf2.cpp b/engines/avalanche/chunkxf2.cpp
new file mode 100644
index 0000000000..5d77d298d2
--- /dev/null
+++ b/engines/avalanche/chunkxf2.cpp
@@ -0,0 +1,192 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 32000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void load()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"place9.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+}
+
+void load_temp(string which)
+{
+ byte a0 /*absolute $A000:800*/;
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+ assign(f,which); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+ bit=getpixel(0,0);
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk9.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2, integer realx, integer realy, boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ if (nat)
+ ch.flavour=ch_bgi;
+ else ch.flavour=ch_ega; /* At the moment, Celer can't handle natural ch_EGAs. */
+ ch.x=realx;
+ ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ putimage(ch.x,ch.y,p,0);
+
+ freemem(p,s);
+ {;
+ if (ch.flavour==ch_bgi) s=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ else s=4*((x2-x1+7) / 8)*(y2-y1+1);
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ if (! nat) blockwrite(f,aa,s);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ load_temp("d:chunkbit.avd");
+ setwritemode(xorput);
+
+ num_chunks=7;
+
+ open_chunk();
+
+ grab( 78, 78,232,102,212, 10,true,false); /* 154 across */
+ grab(235, 78,389,102,212, 10,true,false);
+ grab(392, 78,546,102,212, 10,true,false);
+ grab(392, 78,546,102,212, 10,true,true);
+
+ load_temp("d:chunkbi3.avd");
+
+ grab(437, 51,475, 78,147,120,false,false); /* 5 = door half-open. */
+ grab(397, 51,435, 78,147,120,false,false); /* 6 = door open. */
+ grab(397, 51,435, 78,147,120,true,true); /* 7 = door shut. */
+
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxf3.cpp b/engines/avalanche/chunkxf3.cpp
new file mode 100644
index 0000000000..220d07b563
--- /dev/null
+++ b/engines/avalanche/chunkxf3.cpp
@@ -0,0 +1,250 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+#include "cadburys.h"
+
+
+/*type
+ flavourtype = (ch_EGA,ch_BGI);
+
+ chunkblocktype = record
+ flavour:flavourtype;
+ x,y:integer;
+ xl,yl:integer;
+ size:longint;
+ natural:boolean;
+
+ memorise:boolean; { Hold it in memory? }
+ end;
+
+const
+ chunkheader : array[1..44] of char =
+ 'Chunk-type AVD file, for an Avvy game.'+#26+#177+#$30+#$01+#$75+#177;
+
+ arraysize = 12000;
+
+var
+ offsets:array[1..30] of longint;
+ num_chunks,this_chunk:byte;
+ gd,gm:integer;
+ f:file;
+ aa:array[0..arraysize] of byte;*/
+
+string strf(longint x)
+{
+ string q;
+string strf_result;
+;
+ str(x,q); strf_result=q;
+return strf_result;
+}
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void loadtemp(string n)
+{
+ byte a0 /*absolute $A000:800*/;
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+ assign(f,n); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+ bit=getpixel(0,0);
+ finder();
+}
+
+void load()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+ assign(f,"place22.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setactivepage(1); setvisualpage(1); finder();
+ setactivepage(0); setvisualpage(0);
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk22.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+/*procedure mgrab(x1,y1,x2,y2:integer; size:word);
+var yy:integer; aapos:word; length,bit:byte;
+begin;
+ if size>arraysize then
+ begin;
+ writeln('*** SORRY! *** Increase the arraysize constant to be greater');
+ writeln(' than ',size,'.');
+ halt;
+ end;
+
+ aapos:=0;
+
+ length:=x2-x1;
+
+ for bit:=0 to 3 do
+ begin;
+ port[$3c4]:=2; port[$3ce]:=4; port[$3C5]:=1 shl bit; port[$3CF]:=bit;
+ for yy:=y1 to y2 do
+ begin;
+ move(mem[$A400*yy*80+x1],aa[aapos],length);
+ inc(aapos,length);
+ end;
+ end;
+ bit:=getpixel(0,0);
+
+end;
+
+procedure grab(x1,y1,x2,y2,realx,realy:integer; flav:flavourtype;
+ mem,nat:boolean);
+ { yes, I *do* know how to spell "really"! }
+var
+ s:word;
+ p:pointer;
+ ch:chunkblocktype;
+begin;
+ inc(this_chunk);
+ offsets[this_chunk]:=filepos(f);
+
+
+ s:=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p^);
+
+ with ch do
+ begin;
+ flavour:=flav;
+ x:=realx; y:=realy;
+
+ xl:=x2-x1;
+ yl:=y2-y1;
+ size:=s;
+ memorise:=mem;
+ natural:=nat;
+ end;
+
+ setvisualpage(1);
+ setactivepage(1);
+ readln;
+ putimage(ch.x,ch.y,p^,0);
+
+ if flav=ch_EGA then
+ begin;
+ freemem(p,s);
+ s:=4*((x2-x1+7) div 8)*(y2-y1+1);
+ with ch do
+ begin;
+ size:=s;
+ x:=x div 8;
+ xl:=(xl+7) div 8;
+ mgrab(x,y,x+xl,y+yl,s);
+ end;
+ end;
+
+ readln;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ case flav of
+ ch_EGA : if not nat then blockwrite(f,aa,s);
+ ch_BGI : begin;
+ if not nat then blockwrite(f,p^,s);
+ freemem(p,s);
+ end;
+ end;
+{ rectangle(x1,y1,x2,y2);}
+end;*/
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ loadtemp("chunkbit.avd"); load();
+ setwritemode(xorput);
+
+ num_chunks=9;
+
+ open_chunk();
+
+ grab( 0,103,169,159, 72,86,ch_ega,false,false); /* Stairs... */
+ grab(172,103,341,159, 72,86,ch_ega,false,false);
+
+ loadtemp("chunkbi3.avd");
+
+ grab( 0,130, 79,157,341,94,ch_bgi,true ,true );
+ grab( 0,130, 79,157,341,94,ch_ega,false,false);
+ grab( 0,102, 79,129,341,94,ch_ega,false,false);
+ grab( 0, 74, 79,101,341,94,ch_ega,false,false); /* Far door. */
+
+ loadtemp("chunkbi2.avd");
+
+ grab(393, 92,451,137,512,98,ch_bgi,true ,true ); /* Right-hand door. */
+ grab(393, 92,451,137,512,98,ch_ega,false,false);
+ grab(453, 92,511,137,512,98,ch_ega,false,false);
+
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxf4.cpp b/engines/avalanche/chunkxf4.cpp
new file mode 100644
index 0000000000..2dfa34dc27
--- /dev/null
+++ b/engines/avalanche/chunkxf4.cpp
@@ -0,0 +1,285 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+enum kind {walled,unwalled, last_kind};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+const kind w = walled; const kind uw = unwalled;
+
+array<1,50,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void rdln()
+{
+ char r;
+ return;
+ do { r=readkey(); } while (!(! keypressed()));
+}
+
+void load(kind k)
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+
+
+ if (k==unwalled) assign(f,"place29.avd");
+ else assign(f,"walled.avd");
+
+ reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+}
+
+void finder()
+{
+ char r; integer x,y;
+ return;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void loadtemp(string which)
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+
+
+ assign(f,string("corr")+which+"tmp.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ finder();
+}
+
+void open_chunk()
+{
+ assign(f,"chunk29.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+
+ if (size>arraysize)
+ {
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat, kind k)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ load(k);
+
+ setvisualpage(1);
+ setactivepage(1);
+ rdln();
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=((realx-ch.x*8)+(x2-x1)+7) / 8;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ rdln();
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ setwritemode(xorput);
+
+ loadtemp("2");
+
+ num_chunks=32;
+
+ open_chunk();
+
+ grab( 0, 11,100,104,260,41,ch_ega,false,false,uw); /*1 Geida's door. */
+ grab(103, 12,203, 55,207,61,ch_ega,false,false,uw); /*2 "Ite mingite" sign. */
+ grab(123, 59,185,103,254,90,ch_ega,false,false,uw); /*3 Normal N door (rt handle)*/
+ grab(227, 10,289, 56,254,88,ch_ega,false,false,uw); /*4 Normal N door (lt handle)*/
+ grab(207, 63,294,105, 9,47,ch_ega,false,false, w); /*5 Window in left wall. */
+ grab(312, 10,416, 56,233,88,ch_ega,false,false,uw); /*6 North archway */
+ grab(331, 78,384,101, 32,64,ch_ega,false,false, w); /*7 2 torches, L wall. */
+ grab(607,142,621,157,233,88,ch_ega,false,false,uw); /*8 1 torch, N wall. */
+ grab(417, 11,577, 59,311,61,ch_ega,false,false,uw); /*9 "The Wrong Way!" sign. */
+
+ loadtemp("3");
+
+ grab( 0, 11, 62, 63,557,108,ch_ega,false,false, w); /*10 Near right candle */
+ grab( 64, 11,120, 63, 18,108,ch_ega,false,false, w); /*11 Near left candle */
+ grab(122, 11,169, 55, 93,100,ch_ega,false,false, w); /*12 Far left candle */
+ grab(171, 11,222, 52,500,100,ch_ega,false,false, w); /*13 Far right candle */
+ grab( 32, 68, 84,104,285, 70,ch_ega,false,false,uw); /*14 Far window */
+ grab(138, 65,190, 92,233, 88,ch_ega,false,false,uw); /*15 Baron du Lustie pic 1 */
+ grab(244, 65,296, 92,103, 51,ch_ega,false,false,uw); /*16 Baron du Lustie pic 2 */
+ grab(172, 54,280, 63,233, 88,ch_ega,false,false,uw); /*17 "Art Gallery" sign */
+ grab(341, 18,402, 47,563, 48,ch_ega,false,false, w); /*18 Right wall torches */
+ grab(528, 10,639,160,528, 10,ch_ega,false,false,uw); /*19 Right wall */
+ grab(430, 50,526, 88,543, 50,ch_ega,false,false, w); /*20 Window in right wall */
+ grab(451, 91,494,152,566, 91,ch_ega,false,false, w); /*21 Door in right wall */
+ grab(238, 10,307, 14,484,156,ch_ega,false,false, w); /*22 Near wall door: right */
+ grab(239, 16,300, 20,300,156,ch_ega,false,false, w); /*23 Near wall door: middle */
+ grab(234, 22,306, 26,100,156,ch_ega,false,false, w); /*24 Near wall door: left */
+ grab( 25,113, 87,156,254, 90,ch_ega,false,false, w); /*25 Far door opening stage 1 */
+ grab(131,113,193,156,254, 90,ch_ega,false,false, w); /*26 Far door opening stage 2 */
+ grab(237,113,299,156,254, 90,ch_ega,false,false, w); /*27 Far door opening stage 3 */
+
+ loadtemp("4");
+
+ grab( 0, 11,112,160, 0, 11,ch_ega,false,false,uw); /*28 Left wall */
+ grab(144, 44,197, 76, 30, 44,ch_ega,false,false, w); /*29 Shield on L wall. */
+ grab(149, 90,192,152, 35, 90,ch_ega,false,false, w); /*30 Door in L wall. */
+ grab(463, 28,527, 43,252,100,ch_ega,false,false, w); /*31 Archway x 2 */
+ grab(463, 79,527, 94,252,100,ch_ega,false,false, w); /*32 Archway x 3 */
+
+ close_chunk();
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxf5.cpp b/engines/avalanche/chunkxf5.cpp
new file mode 100644
index 0000000000..c9766830ae
--- /dev/null
+++ b/engines/avalanche/chunkxf5.cpp
@@ -0,0 +1,244 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"v:place1.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+
+ setvisualpage(1); setactivepage(1);
+ finder();
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"chunkbi9.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ setvisualpage(0); setactivepage(0);
+ finder();
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk1.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ if (! nat) putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {;
+ freemem(p,s);
+ s=4*(((x2+7) / 8)-(x1 / 8))*(y2-y1+1);
+ {;
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ {;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {;
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=9;
+
+ open_chunk();
+
+ grab( 48, 42, 94, 66,400,105,ch_ega, true,false); /*1 Avvy asleep. */
+ grab(100, 42,146, 66,400,105,ch_ega, true,false); /*2 Avvy asleep again. */
+ grab(152, 42,198, 66,400,105,ch_ega,false,false); /*3 Avvy awake in bed. */
+ grab(106,113,152,137,400,105,ch_bgi,true ,true ); /*4 No Avvy in bed. */
+
+ grab(206, 42,279, 75,150, 91,ch_ega,false,false); /*5 Open trunk. */
+ grab(206, 42,287, 75,150, 91,ch_bgi,true, true); /*6 Shut trunk. */
+
+ grab( 69, 70,102, 88,431,100,ch_ega,false,false); /*7 Arkata 1. */
+ grab(118, 70,151, 88,431,100,ch_ega,false,false); /*8 Arkata 2. */
+ grab(167, 70,200, 88,431,100,ch_ega,false,false); /*9 Arkata 3. */
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxf6.cpp b/engines/avalanche/chunkxf6.cpp
new file mode 100644
index 0000000000..665222252a
--- /dev/null
+++ b/engines/avalanche/chunkxf6.cpp
@@ -0,0 +1,251 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+const integer x_ofs = 165;
+const integer y_ofs = 58;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"v:place19.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+ finder();
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"d:temp1.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+/* finder;*/
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk19.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+ x1 -= x_ofs; x2 -= x_ofs;
+ y1 -= y_ofs; y2 -= y_ofs;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+/* readln;*/
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {;
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {;
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl / 8)+2;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+/* readln;*/
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {;
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=13;
+
+ open_chunk();
+
+ grab(165, 68,207, 87,127,105,ch_ega,false,false); /*1 The settle with no lute*/
+ grab(209, 68,255, 96,159, 84,ch_bgi, true, true); /*2 Dogfood looks right. */
+ grab(209, 68,255, 96,159, 84,ch_ega, true,false); /*3 Dogfood- straight ahead. */
+ grab(257, 68,303, 96,159, 84,ch_ega, true,false); /*4 Dogfood- left. */
+ grab(305, 68,351, 96,159, 84,ch_ega, true,false); /*5 DF drinks: stage 1. */
+ grab(353, 68,399, 96,159, 84,ch_ega, true,false); /*6 DF drinks: stage 2. */
+ grab(401, 68,447, 96,159, 84,ch_ega, true,false); /*7 DF drinks: stage 3. */
+ grab(449, 84,465, 94,392, 87,ch_ega, true,false); /*8 Ibythneth smiles. */
+ grab(449, 75,488, 82,341,123,ch_ega, true,false); /*9 No habit under the settle. */
+ grab(508, 68,580,106,485,105,ch_ega, true,false); /*10 M gets your drink. */
+ grab(508, 68,580,106,485,105,ch_bgi, true, true); /*11 M gets up again. */
+ grab(470, 84,486, 91,510,108,ch_ega, true,false); /*12 M looks right. */
+ grab(488, 84,504, 91,510,108,ch_ega, true,false); /*13 M winks. */
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxf7.cpp b/engines/avalanche/chunkxf7.cpp
new file mode 100644
index 0000000000..97bacb5967
--- /dev/null
+++ b/engines/avalanche/chunkxf7.cpp
@@ -0,0 +1,236 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"place25.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+ finder();
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"chunkbi3.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ finder();
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk25.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {;
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {;
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl / 8)+2;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {;
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=3;
+
+ open_chunk();
+
+ grab( 16, 24,101, 45,448,116,ch_ega, true,false); /*2 The fire again. */
+ grab(118, 20,203, 45,448,112,ch_bgi, true, true); /*1 The natural fire. */
+ grab(118, 20,203, 45,448,112,ch_ega, true,false); /*3 Third stage of the fire. */
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxf8.cpp b/engines/avalanche/chunkxf8.cpp
new file mode 100644
index 0000000000..4435ee48bd
--- /dev/null
+++ b/engines/avalanche/chunkxf8.cpp
@@ -0,0 +1,243 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"place23.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+ finder();
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp(string x)
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,x); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ finder();
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk23.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {;
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {;
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl / 8)+2;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {;
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp("chunkbi3.avd");
+ setwritemode(xorput);
+
+ num_chunks=6;
+
+ open_chunk();
+
+ grab(226, 21,242, 29,348, 96,ch_bgi, true,true ); /*1 Looking forwards. */
+ grab(226, 21,242, 29,348, 96,ch_ega, true,false); /*2 Looking left. */
+ grab(253, 21,269, 29,348, 96,ch_ega, true,false); /*3 Looking right. */
+ grab(240, 11,256, 19,348, 96,ch_ega, true,false); /*4 Blinking. */
+
+ loadtemp("chunkbi4.avd");
+
+ grab( 48, 83,110,126,324, 96,ch_ega,false,false); /*5 Eyes shut... */
+ grab(112, 83,173,126,325, 96,ch_ega,false,false); /*6 Asleep. */
+
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxf9.cpp b/engines/avalanche/chunkxf9.cpp
new file mode 100644
index 0000000000..96241d1487
--- /dev/null
+++ b/engines/avalanche/chunkxf9.cpp
@@ -0,0 +1,237 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"place42.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+ finder();
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"a:chunkbi3.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ finder();
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk42.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {;
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {;
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl / 8)+2;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {;
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=4;
+
+ open_chunk();
+
+ grab(276, 36,329, 73, 94, 97,ch_bgi, true,true ); /*1 Not tied to the tree.*/
+ grab(276, 36,329, 73, 94, 97,ch_ega,false,false); /*2 Tied to the tree. */
+ grab(182, 80,226, 88,311,132,ch_ega,false,false); /*3 Mushrooms have gone! */
+ grab(253, 75,267, 82,114, 98,ch_ega,false,false); /*4 Avalot blinks. */
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxfa.cpp b/engines/avalanche/chunkxfa.cpp
new file mode 100644
index 0000000000..6493e5241f
--- /dev/null
+++ b/engines/avalanche/chunkxfa.cpp
@@ -0,0 +1,240 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"place7.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+/* finder;*/
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"chunkbi3.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+/* finder;*/
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk7.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {;
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {;
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl / 8)+2;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {;
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=7;
+
+ open_chunk();
+
+ grab(220, 32,269, 62,370,115,ch_ega,false,false); /*1 Jacques awake... */
+ grab(400, 12,450, 48,369,112,ch_ega,false,false); /*2 Jacques gone! */
+ grab(116, 47,176, 98,393, 87,ch_ega,false,false); /*3 Jacques going... */
+ grab(333, 31,393, 82,393, 87,ch_ega,false,false); /*4 The open door. */
+ grab(396, 80,452,135, 39, 91,ch_ega,false,false); /*5 The left door opening. */
+ grab(455, 80,510,135, 39, 91,ch_ega,false,false); /*6 The left door open. */
+ grab(455, 80,510,135, 39, 91,ch_bgi,true ,true ); /*7 The left door shut. */
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxfb.cpp b/engines/avalanche/chunkxfb.cpp
new file mode 100644
index 0000000000..7fda96c375
--- /dev/null
+++ b/engines/avalanche/chunkxfb.cpp
@@ -0,0 +1,238 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"place71.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+ finder();
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"d:chunkbi2.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ finder();
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk71.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {;
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {;
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl / 8)+2;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {;
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=5;
+
+ open_chunk();
+
+ grab( 54, 57,124,116,188, 94,ch_ega,false,false); /*1 Door half-shut. */
+ grab(144, 57,203,116,188, 94,ch_ega,false,false); /*2 Door shut. */
+ grab(513, 92,572,151,188, 94,ch_ega,false,false); /*3 Door with arrow. */
+ grab(610, 94,627,106,367,122,ch_ega,false,false); /*4 Holder with no pen. */
+ grab( 54, 57,124,116,188, 94,ch_bgi,true ,true ); /*5 Door wide open. */
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxfc.cpp b/engines/avalanche/chunkxfc.cpp
new file mode 100644
index 0000000000..aefb15f8a2
--- /dev/null
+++ b/engines/avalanche/chunkxfc.cpp
@@ -0,0 +1,236 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"place2.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+ finder();
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"d:chunkbi2.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ finder();
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk2.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {;
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {;
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl / 8)+2;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {;
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=3;
+
+ open_chunk();
+
+ grab( 59, 15,166, 55,226, 86,ch_ega,false,false); /*1 Door half-shut. */
+ grab(171, 15,278, 55,226, 86,ch_ega,false,false); /*2 Door half-open. */
+ grab(283, 15,390, 55,226, 86,ch_ega,false,false); /*3 Door open. */
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxfd.cpp b/engines/avalanche/chunkxfd.cpp
new file mode 100644
index 0000000000..e87fbbabb1
--- /dev/null
+++ b/engines/avalanche/chunkxfd.cpp
@@ -0,0 +1,236 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"place15.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+ finder();
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"d:chunkbi3.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ finder();
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk15.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {;
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {;
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl / 8)+2;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {;
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=3;
+
+ open_chunk();
+
+ grab(535, 11,633, 74, 46, 97,ch_ega,false,false); /*1 Door half-open. */
+ grab(539, 76,637,139, 46, 97,ch_ega,false,false); /*2 Door open. */
+ grab(539, 76,637,139, 46, 97,ch_bgi,true ,true ); /*3 Door shut. */
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxfe.cpp b/engines/avalanche/chunkxfe.cpp
new file mode 100644
index 0000000000..adb7f8628e
--- /dev/null
+++ b/engines/avalanche/chunkxfe.cpp
@@ -0,0 +1,236 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"place5.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+ finder();
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"chunkbi2.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ finder();
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk5.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {;
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {;
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl / 8)+2;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {;
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=3;
+
+ open_chunk();
+
+ grab(252, 57,375,132,501, 85,ch_ega,false,false); /*1 Door half-open. */
+ grab(418, 15,553, 90,504, 85,ch_ega,false,false); /*2 Door open. */
+ grab(252, 57,375,132,504, 85,ch_bgi,true ,true ); /*3 Door shut. */
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxff.cpp b/engines/avalanche/chunkxff.cpp
new file mode 100644
index 0000000000..9fb2a2ed59
--- /dev/null
+++ b/engines/avalanche/chunkxff.cpp
@@ -0,0 +1,236 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"place13.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+ finder();
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"chunkbi3.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ finder();
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk13.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {;
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {;
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl / 8)+2;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {;
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=3;
+
+ open_chunk();
+
+ grab(323, 84,393,123,266, 72,ch_ega,false,false); /*1 Door half-open. */
+ grab(251, 84,321,123,266, 72,ch_ega,false,false); /*2 Door open. */
+ grab(251, 84,321,123,266, 72,ch_bgi,true ,true ); /*3 Door shut. */
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxfg.cpp b/engines/avalanche/chunkxfg.cpp
new file mode 100644
index 0000000000..077a330afe
--- /dev/null
+++ b/engines/avalanche/chunkxfg.cpp
@@ -0,0 +1,236 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"place16.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+ finder();
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"chunkbi3.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ finder();
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk16.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {;
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {;
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl / 8)+2;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {;
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=3;
+
+ open_chunk();
+
+ grab(336, 12,365, 28,187, 89,ch_ega,false,false); /*1 Ayles asleep frame 2. */
+ grab(368, 12,397, 28,187, 89,ch_ega,false,false); /*2 Ayles awake. */
+ grab(336, 12,365, 28,187, 89,ch_bgi,true ,true ); /*3 Ayles asleep frame 1. */
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxfh.cpp b/engines/avalanche/chunkxfh.cpp
new file mode 100644
index 0000000000..163ae51219
--- /dev/null
+++ b/engines/avalanche/chunkxfh.cpp
@@ -0,0 +1,237 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"place46.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+ finder();
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"d:chunkbi4.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ finder();
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk46.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {;
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {;
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl / 8)+2;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {;
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=4;
+
+ open_chunk();
+
+ grab(136, 11,216, 49,288,104,ch_ega,false,false); /*1 Door opening, frame 1.*/
+ grab( 45, 11,124, 49,289,104,ch_ega,false,false); /*2 Door opening, frame 2.*/
+ grab(227, 11,306, 49,289,104,ch_ega,false,false); /*3 Door opening, frame 3.*/
+ grab(227, 11,306, 49,289,104,ch_bgi,true ,true ); /*4 Natural frame. */
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxfi.cpp b/engines/avalanche/chunkxfi.cpp
new file mode 100644
index 0000000000..84157a84c5
--- /dev/null
+++ b/engines/avalanche/chunkxfi.cpp
@@ -0,0 +1,246 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"place47.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+ finder();
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+;
+
+ assign(f,"chunkbi9.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ finder();
+}
+
+void open_chunk()
+{;
+ assign(f,"chunk47.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{;
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+;
+ if (size>arraysize)
+ {;
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+;
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {;
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {;
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {;
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl / 8)+2;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {;
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {;
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=10;
+
+ open_chunk();
+
+ grab(323, 35,340, 43,337, 93,ch_ega,true ,false); /*1 Port blinks */
+ grab(323, 35,340, 43,337, 93,ch_bgi,true ,true ); /*2 Port normally */
+ grab(421, 22,511, 71,474,101,ch_ega,false,false); /*3 Avalot & Spurge */
+ grab(421, 22,511, 71,474,101,ch_bgi,true ,true ); /*4 Just Spurge. */
+
+ grab(524, 40,540, 47,337, 93,ch_ega,true ,false); /*5 Port L blinks */
+ grab(524, 22,540, 29,337, 93,ch_ega,true ,false); /*6 Port L */
+ grab(563, 40,579, 47,337, 93,ch_ega,true ,false); /*7 Port R blinks */
+ grab(563, 22,579, 29,337, 93,ch_ega,true ,false); /*8 Port R */
+
+ grab(307, 38,310, 38,493,104,ch_ega,true ,false); /*9 Spurge blinks */
+ grab(307, 38,310, 38,493,104,ch_bgi,true ,true ); /*10 Spurge doesn't blink */
+
+ close_chunk();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxfj.cpp b/engines/avalanche/chunkxfj.cpp
new file mode 100644
index 0000000000..34a7109acc
--- /dev/null
+++ b/engines/avalanche/chunkxfj.cpp
@@ -0,0 +1,237 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+
+
+ assign(f,"place20.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+ finder();
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+
+
+ assign(f,"chunkbit.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ finder();
+}
+
+void open_chunk()
+{
+ assign(f,"chunk20.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+
+ if (size>arraysize)
+ {
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=((realx-ch.x*8)+(x2-x1)+7) / 8;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=4;
+
+ open_chunk();
+
+ grab( 57, 11, 72, 18,399, 13,ch_ega,true ,false); /* 1 - all numbers are */
+ grab( 57, 21, 72, 28,399, 13,ch_ega,true ,false); /* 2 flags. */
+ grab( 56, 31, 71, 38,399, 13,ch_ega,true ,false); /* 3 */
+ grab( 56, 31, 71, 38,399, 13,ch_bgi,true ,true ); /* 4, the natural one. */
+ close_chunk();
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxfk.cpp b/engines/avalanche/chunkxfk.cpp
new file mode 100644
index 0000000000..70748b9a5f
--- /dev/null
+++ b/engines/avalanche/chunkxfk.cpp
@@ -0,0 +1,237 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+
+enum flavourtype {ch_ega,ch_bgi, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+ boolean natural;
+
+ boolean memorise; /* Hold it in memory? */
+};
+
+const array<1,44,char> chunkheader =
+string("Chunk-type AVD file, for an Avvy game.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer arraysize = 12000;
+
+array<1,30,longint> offsets;
+byte num_chunks,this_chunk;
+integer gd,gm;
+untyped_file f;
+array<0,arraysize,byte> aa;
+
+void finder()
+{
+ char r; integer x,y;
+
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+
+
+ assign(f,"place50.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+ finder();
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+
+
+ assign(f,"chunkbi4.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ finder();
+}
+
+void open_chunk()
+{
+ assign(f,"chunk50.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+void mgrab(integer x1,integer y1,integer x2,integer y2, word size)
+{
+ integer yy; word aapos; byte length,bit;
+
+ if (size>arraysize)
+ {
+ restorecrtmode();
+ output << "*** SORRY! *** Increase the arraysize constant to be greater" << NL;
+ output << " than " << size << '.' << NL;
+ exit(0);
+ }
+
+ aapos=0;
+
+ length=x2-x1;
+
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( yy=y1; yy <= y2; yy ++)
+ {
+ move(mem[0xa400*yy*80+x1],aa[aapos],length);
+ aapos += length;
+ }
+ }
+ bit=getpixel(0,0);
+
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2,integer realx,integer realy, flavourtype flav,
+ boolean mem,boolean nat)
+ /* yes, I *do* know how to spell "really"! */
+{
+ word s;
+ pointer p;
+ chunkblocktype ch;
+
+/* rectangle(x1,y1,x2,y2); exit;*/
+ this_chunk += 1;
+ offsets[this_chunk]=filepos(f);
+
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+
+ {
+ ch.flavour=flav;
+ ch.x=realx; ch.y=realy;
+
+ ch.xl=x2-x1;
+ ch.yl=y2-y1;
+ ch.size=s;
+ ch.memorise=mem;
+ ch.natural=nat;
+ }
+
+ setvisualpage(1);
+ setactivepage(1);
+ input >> NL;
+ putimage(ch.x,ch.y,p,0);
+
+ if (flav==ch_ega)
+ {
+ freemem(p,s);
+ s=4*(((x2 / 8)-(x1 / 8))+2)*(y2-y1+1);
+ {
+ ch.size=s;
+ ch.x=ch.x / 8;
+ ch.xl=((realx-ch.x*8)+(x2-x1)+7) / 8;
+ mgrab(ch.x,ch.y,ch.x+ch.xl,ch.y+ch.yl,s);
+ }
+ } else
+ /* For BGI pictures. */
+ {
+ ch.x=ch.x / 8;
+ ch.xl=(ch.xl+7) / 8;
+ ch.size=imagesize(ch.x*8,ch.y,(ch.x+ch.xl)*8,ch.y+ch.yl);
+ }
+
+ input >> NL;
+ setvisualpage(0);
+ setactivepage(0);
+
+ blockwrite(f,ch,sizeof(ch));
+
+ switch (flav) {
+ case ch_ega : if (! nat) blockwrite(f,aa,s); break;
+ case ch_bgi : {
+ if (! nat) blockwrite(f,p,s);
+ freemem(p,s);
+ }
+ break;
+ }
+/* rectangle(x1,y1,x2,y2);*/
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=4;
+
+ open_chunk();
+
+ grab( 46, 53,107, 81,246, 88,ch_ega,false,false); /*1 - all numbers are */
+ grab(115, 53,175, 81,248, 88,ch_ega,false,false); /*2 door stages. */
+ grab(180, 53,241, 81,246, 88,ch_ega,false,false); /*3 */
+ grab(180, 53,246, 84,246, 88,ch_bgi,true ,true ); /*4 */
+ close_chunk();
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/chunkxfl.cpp b/engines/avalanche/chunkxfl.cpp
new file mode 100644
index 0000000000..01a05509b6
--- /dev/null
+++ b/engines/avalanche/chunkxfl.cpp
@@ -0,0 +1,127 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+#include "cadburys.h"
+
+
+void finder()
+{
+ char r; integer x,y;
+
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void load()
+{
+ byte a1 /*absolute $A400:800*/;
+ byte bit;
+ untyped_file f;
+
+
+ assign(f,"place51.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a1,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+ setvisualpage(1); setactivepage(1);
+ finder();
+ setvisualpage(0); setactivepage(0);
+}
+
+void loadtemp()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+
+
+ assign(f,"chunkbi4.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+
+ bit=getpixel(0,0);
+
+ finder();
+}
+
+void open_chunk()
+{
+ assign(f,"chunk51.avd");
+ rewrite(f,1);
+ blockwrite(f,chunkheader,sizeof(chunkheader));
+ blockwrite(f,num_chunks,1);
+ blockwrite(f,offsets,num_chunks*4);
+
+ this_chunk=0;
+}
+
+void close_chunk()
+{
+ seek(f,45);
+ blockwrite(f,offsets,num_chunks*4); /* make sure they're right! */
+ close(f);
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+ loadtemp();
+ setwritemode(xorput);
+
+ num_chunks=9;
+
+ open_chunk();
+
+ grab(346,119,404,154,539,116,ch_ega,true ,false); /*1 fire */
+ grab(435,119,490,154,541,116,ch_ega,true ,false); /*2 fire */
+ grab(435,119,490,154,541,116,ch_bgi,true ,true ); /*3 natural fire */
+
+ grab(300, 58,315, 68,258, 95,ch_ega,true ,false); /*6 Duck's head 2 */
+ grab(246, 52,259, 62,258, 95,ch_ega,true ,false); /*5 Duck blinks 1 */
+
+ grab(300, 58,315, 68,258, 95,ch_bgi,true ,true ); /*4 Duck's head 1 */
+ grab(262, 52,278, 62,257, 95,ch_ega,true ,false); /*7 Duck blinks 2 */
+
+ grab(333, 58,347, 68,258, 95,ch_ega,true ,false); /*8 Duck's head 3 */
+ grab(250, 63,265, 73,258, 95,ch_ega,true ,false); /*9 Duck blinks 3 */
+
+ close_chunk();
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/clock.cpp b/engines/avalanche/clock.cpp
new file mode 100644
index 0000000000..16ec6f552b
--- /dev/null
+++ b/engines/avalanche/clock.cpp
@@ -0,0 +1,60 @@
+#include "ptoc.h"
+
+
+/*#include "Dos.h"*/
+#include "graph.h"
+/*#include "Crt.h"*/
+
+const integer xm = 511; const integer ym = 184;
+integer gd,gm;
+word oh,om,/*os,*/h,m,s,s1; char r;
+
+void hand(word ang,word length, byte colour)
+{
+ arccoordstype a;
+;
+ if (ang>900) return;
+ setcolor(colour);
+ arc(xm,ym,449-ang,450-ang,length);
+ getarccoords(a);
+ line(xm,ym,a.xend,a.yend); /* "With a do-line???!", Liz said */
+}
+
+void chime()
+{
+ integer gd,gm,fv;
+;
+ if (oh>177) return; /* too high- must be first time around */
+ fv=h / 30; if (fv==0) fv=12;
+ for( gd=1; gd <= fv; gd ++)
+ {;
+ for( gm=1; gm <= 3; gm ++)
+ {;
+ sound(140-gm*30); delay(50-gm*3);
+ }
+ nosound; if ((cardinal)gd!=oh) delay(100);
+ }
+}
+
+void plothands()
+{;
+ hand(oh,17,brown);
+ hand(h,17,yellow);
+ hand(om*6,20,brown);
+ hand(m*6,20,yellow);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"");
+ setfillstyle(1,6); bar(0,0,640,200); oh=17717; om=17717;
+ do {
+ gettime(h,m,s,s1);
+ h=(h % 12)*30+m / 2;
+ if (oh!=h) {; plothands(); chime(); }
+ if (om!=m) plothands();
+ oh=h; om=m;
+ } while (!false);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/closing.cpp b/engines/avalanche/closing.cpp
new file mode 100644
index 0000000000..b2af98740f
--- /dev/null
+++ b/engines/avalanche/closing.cpp
@@ -0,0 +1,119 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ CLOSING The closing screen and error handler. */
+
+#define __closing_implementation__
+
+
+#include "closing.h"
+
+
+#include "gyro.h"
+#include "Graph.h"
+/*#include "Crt.h"*/
+#include "lucerna.h"
+
+
+typedef array<1,3840,char> scrtype;
+
+scrtype q /*absolute $B8FA:0*/; /* Nobody's using the graphics memory now. */
+file<scrtype> f;
+pointer exitsave;
+
+void get_screen(byte which)
+{;
+ closegraph();
+ textattr=0; clrscr;
+ assign(f,string("text")+strf(which)+".scr"); reset(f); f >> q; close(f);
+}
+
+void show_screen()
+{
+ byte fv,ff,fq, tl,bl;
+ scrtype a /*absolute $B800:0*/;
+;
+ for( fv=1; fv <= 40; fv ++)
+ {;
+ if (fv>36) {; tl=1; bl=24; }
+ else {; tl=12-fv / 3; bl=12+fv / 3; }
+ for( fq=tl; fq <= bl; fq ++)
+ for( ff=80-fv*2; ff <= 80+fv*2; ff ++)
+ a[fq*160-ff]=q[fq*160-ff];
+ delay(5);
+ }
+ gotoxy(1,25); textattr=31; clreol; gotoxy(1,24);
+}
+
+void quit_with(byte which,byte errorlev)
+{;
+ dusk();
+ get_screen(which);
+ show_screen(); /* No changes. */
+ exit(errorlev);
+}
+
+void put_in(string x, word where)
+{
+ word fv;
+;
+ for( fv=1; fv <= length(x); fv ++)
+ q[1+(where+fv)*2]=x[fv];
+}
+
+void end_of_program()
+
+{
+ const array<0,11,varying_string<11> > nouns =
+ {{"sackbut","harpsichord","camel","conscience","ice-cream","serf",
+ "abacus","castle","carrots","megaphone","manticore","drawbridge"}};
+
+ const array<0,11,varying_string<9> > verbs =
+ {{"haunt","daunt","tickle","gobble","erase","provoke","surprise",
+ "ignore","stare at","shriek at","frighten","quieten"}};
+
+ string result;
+;
+ nosound;
+ get_screen(scr_nagscreen);
+ result=nouns[Random(12)]+" will "+verbs[Random(12)]+" you";
+ put_in(result,1628);
+ show_screen(); /* No halt- it's already set up. */
+}
+
+/*$F+*/
+
+void bug_handler()
+{;
+ exitproc=exitsave;
+
+ if (erroraddr!=nil)
+ {; /* An error occurred! */
+ if (exitcode==203)
+ get_screen(scr_ramcram);
+ else
+ {;
+ get_screen(scr_bugalert);
+ put_in(strf(exitcode),678); /* 678 = [38,8]. */
+ put_in(strf(seg(erroraddr))+':'+strf(ofs(erroraddr)),758); /* 758 = [38,9]. */
+ }
+ show_screen();
+ erroraddr=nil;
+ }
+}
+
+/*$F-*/
+
+class unit_closing_initialize {
+ public: unit_closing_initialize();
+};
+static unit_closing_initialize closing_constructor;
+
+unit_closing_initialize::unit_closing_initialize() {;
+ exitsave=exitproc;
+ exitproc=&bug_handler;
+}
diff --git a/engines/avalanche/closing.h b/engines/avalanche/closing.h
new file mode 100644
index 0000000000..97dd37e0c3
--- /dev/null
+++ b/engines/avalanche/closing.h
@@ -0,0 +1,15 @@
+#ifndef __closing_h__
+#define __closing_h__
+
+
+const integer scr_bugalert = 1;
+const integer scr_ramcram = 2;
+const integer scr_nagscreen = 3;
+const integer scr_twocopies = 5;
+
+
+void quit_with(byte which,byte errorlev);
+
+void end_of_program();
+
+#endif
diff --git a/engines/avalanche/convert.cpp b/engines/avalanche/convert.cpp
new file mode 100644
index 0000000000..08639eecd7
--- /dev/null
+++ b/engines/avalanche/convert.cpp
@@ -0,0 +1,79 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+integer gd,gm;
+string fn1,fn2;
+varying_string<30> desc;
+
+void loadscreen(string nam)
+{
+ byte z;
+ array<1,4,pointer> a;
+ untyped_file f; word s;
+ string check;
+;
+ assign(f,nam);
+ reset(f,1);
+ blockread(f,check,41);
+ blockread(f,check,13);
+ blockread(f,check,31);
+ s=imagesize(0,0,getmaxx(),75);
+ for( z=1; z <= 2; z ++)
+ {;
+ getmem(a[z],s);
+ blockread(f,a[z],s);
+ setactivepage(0);
+ putimage(0,15+(z-1)*75,a[z],0);
+ freemem(a[z],s);
+ }
+ close(f);
+}
+
+void load2(string name)
+{
+ byte a /*absolute $A000:1200*/;
+ byte bit;
+ untyped_file f;
+;
+ assign(f,name); reset(f,1); seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a,12080);
+ }
+ close(f);
+}
+
+void save2(string name)
+{
+ const string header =
+ string("This is a file from an Avvy game, and its contents are subject to ")+
+ "copyright."+'\15'+'\12'+'\15'+'\12'+"Have fun!"+'\32';
+ byte a /*absolute $A000:1200*/;
+ byte bit;
+ untyped_file f;
+;
+ assign(f,name); rewrite(f,1); blockwrite(f,header[1],146); /* really 90 */
+ blockwrite(f,desc,31);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockwrite(f,a,12080);
+ }
+ close(f);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ output << "Filename?"; input >> fn1 >> NL;
+ output << "New name?"; input >> fn2 >> NL;
+ output << "Describe?"; input >> desc >> NL;
+ gd=3; gm=0; initgraph(gd,gm,"");
+ loadscreen(fn1);
+ save2(fn2);
+ closegraph();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/convmous.cpp b/engines/avalanche/convmous.cpp
new file mode 100644
index 0000000000..c607b11e22
--- /dev/null
+++ b/engines/avalanche/convmous.cpp
@@ -0,0 +1,80 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Binu.h"*/
+/*#include "Crt.h"*/
+
+
+ /* ...gogogoch */struct cursor {
+ matrix<0,1,0,15,word> mask;
+ integer horzhotspot,verthotspot;
+ };
+typedef /* ha ha */matrix<0,1,0,15,varying_string<16> > precursor;
+
+const array<0,3,byte> colours = {{darkgray,blue,white,green}};
+
+cursor c_current;
+boolean usepointer;
+precursor cpc;
+byte hhs,vhs;
+string fn,desc;
+integer gd,gm;
+
+void recalc()
+{
+ byte a,b;
+;
+ {;
+ for( a=0; a <= 1; a ++)
+ for( b=0; b <= 15; b ++)
+ c_current.mask[a][b]=bintoword(cpc[a][b]);
+ c_current.horzhotspot=hhs; c_current.verthotspot=vhs;
+ }
+}
+
+void load()
+{
+ text t; string x; byte a,b;
+;
+ assign(t,fn);
+ reset(t);
+ do { t >> x >> NL; } while (!(x=='|')); /* bypass junk */
+ t >> desc >> NL;
+ for( a=0; a <= 1; a ++)
+ for( b=0; b <= 15; b ++)
+ t >> cpc[a][b] >> NL;
+ t >> hhs >> NL; t >> vhs >> NL;
+ close(t); recalc();
+}
+
+void display()
+{
+ const integer o0 = ord('0'); const integer o1 = ord('1');
+ byte x,y,p1,p2;
+;
+ for( y=0; y <= 15; y ++)
+ {;
+ for( x=1; x <= 16; x ++)
+ {;
+ switch (ord(cpc[0][y][x])*2+ord(cpc[1][y][x])) {
+ case o0*2+o0: {; p1= 0; p2= 0; } break; /* p1= silhouette, p2= real */
+ case o0*2+o1: {; p1= 0; p2=15; } break;
+ case o1*2+o0: {; p1=15; p2= 0; } break;
+ case o1*2+o1: {; p1= 9; p2= 9; } break; /* invalid- can't use this */
+ }
+ putpixel(x-1,y,p1); putpixel(x+99,y,p2);
+ }
+ output << NL;
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=1; initgraph(gd,gm,"");
+ fn="d:screwdri.inc";
+ load();
+ display();
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/credits.cpp b/engines/avalanche/credits.cpp
new file mode 100644
index 0000000000..7669c85eaa
--- /dev/null
+++ b/engines/avalanche/credits.cpp
@@ -0,0 +1,88 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+/*$R+*/
+
+typedef matrix<'\0','\377',0,15,byte> fonttype;
+
+integer gd,gm;
+text t;
+array<1,2,fonttype> f;
+file<fonttype> ff;
+array<1,80,byte> l;
+varying_string<80> x;
+
+void do_one(byte z)
+{
+ byte a /*absolute $A000:0*/;
+ byte aa /*absolute $A000:80*/;
+ byte az /*absolute $A000:27921*/;
+;
+ a=getpixel(0,0);
+ move(l,az,z);
+
+ port[0x3c5]=8; port[0x3cf]=0;
+ move(aa,a,27920);
+}
+
+void background()
+{
+ byte y;
+;
+ for( y=1; y <= 15; y ++)
+ {;
+ setcolor(y);
+ outtextxy(17,y*12,"Jesus is Lord!");
+ }
+}
+
+void scroll(string z)
+{
+ byte x,y,lz; char c;
+;
+ fillchar(l,80,'\0');
+ if (z=="")
+ for( y=1; y <= 12; y ++) do_one(0);
+ c=z[1]; Delete(z,1,1);
+ lz=length(z);
+ switch (c) {
+ case '*': for( y=0; y <= 15; y ++)
+ {;
+ for( x=1; x <= lz; x ++)
+ l[x]=f[2][z[x]][y];
+ do_one(lz);
+ }
+ break;
+ case '>': {;
+ lz += 7;
+ for( y=0; y <= 13; y ++)
+ {;
+ for( x=1; x <= lz; x ++)
+ l[x+7]=f[1][z[x]][y];
+ do_one(lz); do_one(lz); /* double-height characters */
+ }
+ }
+ break;
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=1; initgraph(gd,gm,"");
+ port[0x3c4]=2; port[0x3cf]=4;
+ assign(ff,"avalot.fnt"); reset(ff); ff >> f[1]; close(ff);
+ assign(ff,"avitalic.fnt"); reset(ff); ff >> f[2]; close(ff);
+ assign(t,"credits.txt"); reset(t);
+ background();
+ for( gd=8; gd <= 15; gd ++) setpalette(gd,62);
+ do {
+ t >> x >> NL;
+ scroll(x);
+ } while (!(eof(t) || keypressed()));
+ close(t);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/displtxt.cpp b/engines/avalanche/displtxt.cpp
new file mode 100644
index 0000000000..3c706dc14d
--- /dev/null
+++ b/engines/avalanche/displtxt.cpp
@@ -0,0 +1,34 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+
+
+const char fn[] = "text3.scr";
+
+typedef array<1,3840,char> atype;
+
+file<atype> f;
+word fv,ff,fq,st;
+char r;
+byte tl,bl;
+atype q;
+atype a /*absolute $B800:0*/;
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ textattr=0; clrscr;
+ assign(f,fn); reset(f); f >> q; close(f);
+ for( fv=1; fv <= 40; fv ++)
+ {;
+ if (fv>36) {; tl=1; bl=24; }
+ else {; tl=12-fv / 3; bl=12+fv / 3; }
+ for( fq=tl; fq <= bl; fq ++)
+ for( ff=80-fv*2; ff <= 80+fv*2; ff ++)
+ a[fq*160-ff]=q[fq*160-ff];
+ delay(5);
+ }
+ gotoxy(1,25); textattr=31; clreol; gotoxy(1,24);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/dropdown.cpp b/engines/avalanche/dropdown.cpp
new file mode 100644
index 0000000000..6c03a4724d
--- /dev/null
+++ b/engines/avalanche/dropdown.cpp
@@ -0,0 +1,802 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ DROPDOWN A customised version of Oopmenu (qv). */
+
+#define __dropdown_implementation__
+
+
+#include "dropdown.h"
+
+
+/*#include "Crt.h"*/
+#include "graph.h"
+/*#include "Dos.h"*/
+#include "lucerna.h"
+#include "Gyro.h"
+#include "acci.h"
+#include "trip5.h"
+#include "enid.h"
+#include "basher.h"
+
+/*$V-*/
+const integer indent = 5;
+const integer spacing = 10;
+
+/* menu_b = blue; { Morpheus }
+ menu_f = yellow;
+ menu_border = black;
+ highlight_b = lightblue;
+ highlight_f = yellow;
+ disabled = lightgray; */
+
+const integer menu_b = lightgray; /* Windowsy */
+const integer menu_f = black;
+const integer menu_border = black;
+const integer highlight_b = black;
+const integer highlight_f = white;
+const integer disabled = darkgray;
+
+char r;
+byte fv;
+
+void find_what_you_can_do_with_it()
+{;
+ switch (thinks) {
+ case wine:case ink: verbstr=string(vb_exam)+vb_drink; break;
+ case bell: verbstr=string(vb_exam)+vb_ring; break;
+ case potion:case wine: verbstr=string(vb_exam)+vb_drink; break;
+ case chastity: verbstr=string(vb_exam)+vb_wear; break;
+ case lute: verbstr=string(vb_exam)+vb_play; break;
+ case mushroom:case onion: verbstr=string(vb_exam)+vb_eat; break;
+ case clothes: verbstr=string(vb_exam)+vb_wear; break;
+ default: verbstr=vb_exam; /* anything else */
+ }
+}
+
+void chalk(integer x,integer y, char t, string z, boolean valid)
+{
+ byte fv,ff,p,bit;
+ word pageseg;
+ byte ander;
+;
+
+ pageseg=0xa000+cp*0x400;
+
+ if (valid) ander=255; else ander=170;
+
+ for( fv=1; fv <= length(z); fv ++)
+ for( ff=0; ff <= 7; ff ++)
+ for( bit=0; bit <= 2; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ mem[pageseg*x+fv-1+(y+ff)*80]=~ (little[z[fv]][ff] & ander);
+ }
+
+ for( ff=0; ff <= 8; ff ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << 3; port[0x3cf]=3;
+ fillchar(mem[pageseg*x+(y+ff)*80],length(z),'\0'); /* blank it out. */
+ }
+
+ p=pos(t,z); if (p==0) return; p -= 1;
+
+ for( bit=0; bit <= 2; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ mem[pageseg*x+p+(y+8)*80]=~ ander;
+ }
+
+ blitfix();
+}
+
+void hlchalk(integer x,integer y, char t, string z, boolean valid)
+ /* Highlighted. */
+{
+ byte fv,ff,p;
+ word pageseg;
+ byte ander;
+;
+
+ pageseg=0xa000+cp*0x400;
+
+ if (valid) ander=255; else ander=170;
+
+ for( fv=1; fv <= length(z); fv ++)
+ for( ff=0; ff <= 7; ff ++)
+ mem[pageseg*x+fv-1+(y+ff)*80]=little[z[fv]][ff] & ander;
+
+ p=pos(t,z); if (p==0) return; p -= 1;
+
+ mem[pageseg*x+p+(y+8)*80]=ander;
+ blitfix();
+}
+
+/*procedure say(x,y:integer; t:char; z:string; f,b:byte);
+begin;
+ settextjustify(0,2); setfillstyle(1,b); setcolor(f);
+ bar(x-3,y-1,x+textwidth(z)+3,y+textheight(z));
+ chalk(x,y,t,z);
+end;*/
+
+void bleep()
+{;
+ sound(177); delay(7); nosound;
+}
+
+void onemenu::start_afresh()
+{;
+ number=0; width=0; firstlix=false; oldy=0; highlightnum=0;
+}
+
+onemenu* onemenu::init()
+{;
+ menunow=false; ddmnow=false; menunum=1;
+ return this;
+}
+
+void onemenu::opt(string n, char tr, string key, boolean val)
+{
+ integer l;
+;
+ number += 1;
+ l=length(n+key)+3; if (width<l) width=l;
+ {
+ optiontype& with = oo[number];
+ ;
+ with.title=n;
+ with.trigger=tr;
+ with.shortcut=key;
+ with.valid=val;
+ }
+}
+
+void onemenu::displayopt(byte y, boolean highlit)
+{
+ string data;
+;
+ {
+ optiontype& with = oo[y];
+ ;
+
+ if (highlit)
+ setfillstyle(1,0);
+ else
+ setfillstyle(1,7);
+ bar((flx1+1)*8,3+y*10,(flx2+1)*8,12+y*10);
+
+/* settextjustify(2,2);
+ if shortcut>'' then outtextxy(flx2,4+y*10,shortcut);*/
+
+ data=with.title;
+
+ while (length(data+with.shortcut)<width)
+ data=data+' '; /* Pad with spaces. */
+
+ data=data+with.shortcut;
+
+ if (highlit)
+ hlchalk(left,4+y*10,with.trigger,data,with.valid);
+ else
+ chalk(left,4+y*10,with.trigger,data,with.valid);
+
+ }
+}
+
+void onemenu::display()
+{
+ byte y;
+;
+ off();
+ setactivepage(cp); setvisualpage(cp);
+ setfillstyle(1,menu_b); setcolor(menu_border);
+ firstlix=true;
+ flx1=left-2; flx2=left+width; fly=14+number*10;
+ menunow=true; ddmnow=true;
+
+ bar((flx1+1)*8,12,(flx2+1)*8,fly);
+ rectangle((flx1+1)*8-1,11,(flx2+1)*8+1,fly+1);
+
+ displayopt(1,true);
+ for( y=2; y <= number; y ++)
+ { optiontype& with = oo[y]; displayopt(y,false);}
+ defaultled=1; cmp=177; mousepage(cp); on(); /* 4= fletch */
+}
+
+void onemenu::wipe()
+{
+ bytefield r;
+;
+ setactivepage(cp);
+ off();
+ { headtype& with = ddm_m.ddms[ddm_o.menunum];
+ chalk(with.xpos,1,with.trigger,with.title,true);}
+/* mblit((flx1-3) div 8,11,((flx2+1) div 8)+1,fly+1,3,cp);*/
+
+/* with r do
+ begin;
+ x1:=flx1;
+ y1:=11;
+ x2:=flx2+1;
+ y2:=fly+1;
+ end;
+ getset[cp].remember(r);*/
+
+ mblit(flx1,11,flx2+1,fly+1,3,cp); blitfix();
+ menunow=false; ddmnow=false; firstlix=false; defaultled=2;
+ on_virtual();
+}
+
+void onemenu::movehighlight(shortint add)
+{
+ shortint hn;
+;
+ if (add!=0)
+ {;
+ hn=highlightnum+add;
+ if ((hn<0) || (hn>=(unsigned char)number)) return;
+ highlightnum=hn;
+ }
+ setactivepage(cp); off();
+ displayopt(oldy+1,false);
+ displayopt(highlightnum+1,true);
+ setactivepage(1-cp);
+ oldy=highlightnum; on();
+}
+
+void onemenu::lightup() /* This makes the menu highlight follow the mouse.*/
+{;
+ if ((mx<(cardinal)flx1*8) || (mx>(cardinal)flx2*8) || (my<=12) || (my>(cardinal)fly-3)) return;
+ highlightnum=(my-13) / 10;
+ if (highlightnum==oldy) return;
+ movehighlight(0);
+}
+
+void onemenu::select(byte n) /* Choose which one you want. */
+{;
+ if (! oo[n+1].valid) return;
+ choicenum=n; wipe();
+
+ if (choicenum==number) choicenum -= 1; /* Off the bottom. */
+ if (choicenum>number) choicenum=0; /* Off the top, I suppose. */
+
+ ddm_m.ddms[menunum].do_choose();
+}
+
+void onemenu::keystroke(char c)
+{
+ byte fv; boolean found;
+;
+ c=upcase(c); found=false;
+ for( fv=1; fv <= number; fv ++)
+ { optiontype& with = oo[fv];
+ if ((upcase(with.trigger)==c) && with.valid)
+ {;
+ select(fv-1);
+ found=true;
+ }}
+ if (! found) blip();
+}
+
+ headtype* headtype::init
+ (char trig,char alttrig, string name, byte p, proc dw,proc dc)
+ {;
+ trigger=trig; alttrigger=alttrig; title=name;
+ position=p; xpos=(position-1)*spacing+indent;
+ xright=position*spacing+indent;
+ do_setup=dw; do_choose=dc;
+ return this;
+ }
+
+ void headtype::display()
+ {;
+ off(); /*MT*/
+ chalk(xpos,1,trigger,title,true);
+ on(); /*MT*/
+ }
+
+ void headtype::highlight()
+ {;
+ off(); off_virtual(); nosound;
+ setactivepage(cp);
+ hlchalk(xpos,1,trigger,title,true);
+ {;
+ ddm_o.left=xpos;
+ ddm_o.menunow=true; ddmnow=true; ddm_o.menunum=position;
+ }
+ cmp=177; /* Force redraw of cursor. */
+ }
+
+ boolean headtype::extdparse(char c)
+ {boolean extdparse_result;
+ ;
+ if (c!=alttrigger) {; extdparse_result=true; return extdparse_result; }
+ extdparse_result=false;
+ return extdparse_result;
+ }
+
+ menuset* menuset::init()
+ {;
+ howmany=0;
+ return this;
+ }
+
+ void menuset::create(char t, string n, char alttrig, proc dw,proc dc)
+ {;
+ howmany += 1;
+ ddms[howmany].init(t,alttrig,n,howmany,dw,dc);
+ }
+
+ void menuset::update()
+ {
+ const bytefield menuspace = {0, 0, 80, 9};
+ byte fv,page_,savecp;
+ ;
+ setactivepage(3);
+ setfillstyle(1,menu_b); bar(0, 0,640, 9);
+ savecp=cp; cp=3;
+
+ for( fv=1; fv <= howmany; fv ++)
+ ddms[fv].display();
+
+ for( page_=0; page_ <= 1; page_ ++)
+ getset[page_].remember(menuspace);
+
+ cp=savecp;
+ }
+
+ void menuset::extd(char c)
+ {
+ byte fv;
+ ;
+ fv=1;
+ while ((fv<=howmany) && (ddms[fv].extdparse(c))) fv += 1;
+ if (fv>howmany) return; getcertain(fv);
+ }
+
+ void menuset::getcertain(byte fv)
+ {;
+ { headtype& with = ddms[fv];
+ {;
+ if (ddm_o.menunow)
+ {;
+ wipe(); /* get rid of menu */
+ if (ddm_o.menunum==with.position) return; /* clicked on own highlight */
+ }
+ highlight(); do_setup();
+ }}
+ }
+
+ void menuset::getmenu(integer x)
+ {
+ byte fv;
+ ;
+ fv=0;
+ do {
+ fv += 1;
+ if ((x>ddms[fv].xpos*8) && (x<ddms[fv].xright*8))
+ {;
+ getcertain(fv);
+ return;
+ }
+ } while (!(fv>howmany));
+ }
+
+void parsekey(char r,char re)
+{;
+ switch (r) {
+ case '\0':case '\340': {;
+ switch (re) {
+ case 'K': if (ddm_o.menunum>1) {;
+ wipe();
+ ddm_m.getcertain(ddm_o.menunum-1);
+ } else
+ {; /* Get menu on the left-hand side */
+ wipe();
+ ddm_m.getmenu((ddm_m.howmany-1)*spacing+indent);
+ }
+ break;
+ case 'M': if (ddm_o.menunum<ddm_m.howmany) {;
+ wipe();
+ ddm_m.getcertain(ddm_o.menunum+1);
+ } else
+ {; /* Get menu on the far right-hand side */
+ wipe();
+ ddm_m.getmenu(indent);
+ }
+ break;
+ case 'H': movehighlight(-1); break;
+ case 'P': movehighlight(1); break;
+ default: ddm_m.extd(re);
+ }
+ }
+ break;
+ case '\15': select(ddm_o.highlightnum); break;
+ default:
+ {;
+ if (ddm_o.menunow) keystroke(r);
+ }
+ }
+}
+
+/*$F+ *** Here follow all the ddm__ and do__ procedures for the DDM system. */
+
+void ddm__game()
+{;
+ {;
+ start_afresh();
+ opt("Help...",'H',"f1",true);
+ opt("Boss Key",'B',"alt-B",true);
+ opt("Untrash screen",'U',"ctrl-f7",true);
+ opt("Score and rank",'S',"f9",true);
+ opt("About Avvy...",'A',"shift-f10",true);
+ display();
+ }
+}
+
+void ddm__file()
+{;
+ {;
+ start_afresh();
+ opt("New game",'N',"f4",true);
+ opt("Load...",'L',"^f3",true);
+ opt("Save",'S',"^f2",alive);
+ opt("Save As...",'v',"",alive);
+ opt("DOS Shell",'D',atkey+'1',true);
+ opt("Quit",'Q',"alt-X",true);
+ display();
+ }
+}
+
+void ddm__action()
+{
+ string n;
+;
+ n=copy(f5_does(),2,255);
+
+ {;
+ start_afresh();
+ if (n=="")
+ opt("Do something",'D',"f5",false);
+ else
+ opt(copy(n,2,255),n[1],"f5",true);
+ opt("Pause game",'P',"f6",true);
+ if (dna.room==99)
+ opt("Journey thither",'J',"f7",neardoor());
+ else
+ opt("Open the door",'O',"f7",neardoor());
+ opt("Look around",'L',"f8",true);
+ opt("Inventory",'I',"Tab",true);
+ if (tr[1].xs==walk)
+ opt("Run fast",'R',"^R",true);
+ else
+ opt("Walk slowly",'W',"^W",true);
+ display();
+ }
+}
+
+void ddm__people()
+{
+ byte here; char fv;
+;
+
+ people="";
+ here=dna.room;
+
+ {;
+ start_afresh();
+ for( fv='\226'; fv <= '\262'; fv ++)
+ if (whereis[fv]==here)
+ {;
+ opt(getname(fv),getnamechar(fv),"",true);
+ people=people+fv;
+ }
+ display();
+ }
+}
+
+void ddm__objects()
+{
+ char fv;
+;
+ {;
+ start_afresh();
+ for( fv='\1'; fv <= numobjs; fv ++)
+ if (dna.obj[fv])
+ opt(get_thing(fv),get_thingchar(fv),"",true);
+ display();
+ }
+}
+
+string himher(char x) /* Returns "im" for boys, and "er" for girls.*/
+{string himher_result;
+;
+ if (x<'\257') himher_result="im"; else himher_result="er";
+return himher_result;
+}
+
+void ddm__with()
+{
+ byte fv; varying_string<7> verb; char vbchar; boolean n;
+;
+ {;
+ start_afresh();
+
+ if (thinkthing)
+ {;
+
+ find_what_you_can_do_with_it();
+
+ for( fv=1; fv <= length(verbstr); fv ++)
+ {;
+ verbopt(verbstr[fv],verb,vbchar);
+ opt(verb,vbchar,"",true);
+ }
+
+ /* We disable the "give" option if: (a), you haven't selected anybody,
+ (b), the person you've selected isn't in the room,
+ or (c), the person you've selected is YOU! */
+
+ if ((set::of(nowt,pavalot, eos).has(last_person)) ||
+ (whereis[last_person]!=dna.room))
+ opt("Give to...",'G',"",false); /* Not here. */ else
+ {;
+ opt(string("Give to ")+getname(last_person),'G',"",true);
+ verbstr=verbstr+vb_give;
+ }
+
+ } else
+ {;
+ opt("Examine",'x',"",true);
+ opt(string("Talk to h")+himher(thinks),'T',"",true);
+ verbstr=string(vb_exam)+vb_talk;
+ switch (thinks) {
+
+ case pgeida:case parkata:
+ {;
+ opt("Kiss her",'K',"",true);
+ verbstr=verbstr+vb_kiss;
+ }
+ break;
+
+ case pdogfood:
+ {;
+ opt("Play his game",'P',"",! dna.wonnim); /* True if you HAVEN'T won. */
+ verbstr=verbstr+vb_play;
+ }
+ break;
+
+ case pmalagauche:
+ {;
+ n=! dna.teetotal;
+ opt("Buy some wine",'w',"",! dna.obj[wine]);
+ opt("Buy some beer",'b',"",n);
+ opt("Buy some whisky",'h',"",n); opt("Buy some cider",'c',"",n);
+ opt("Buy some mead",'m',"",n);
+ verbstr=verbstr+'\145'+'\144'+'\146'+'\147'+'\150';
+ }
+ break;
+
+ case ptrader:
+ {;
+ opt("Buy an onion",'o',"",! dna.obj[onion]);
+ verbstr=verbstr+'\151';
+ }
+ break;
+
+ }
+ }
+ display();
+ }
+}
+
+/*procedure ddm__map;
+begin;
+ with ddm_o do
+ begin;
+ start_afresh;
+ opt('Cancel map','G','f5',true);
+ opt('Pause game','P','f6',true);
+ opt('Journey thither','J','f7',neardoor);
+ opt('Explanation','L','f8',true);
+ display;
+ end;
+end;
+
+procedure ddm__town;
+begin;
+ with ddm_o do
+ begin;
+ start_afresh;
+ opt('Argent','A','',true);
+ opt('Birmingham','B','',true);
+ opt('Nottingham','N','',true);
+ opt('Cardiff','C','',true);
+ display;
+ end;
+end;*/
+
+void do__game()
+{;
+ switch (ddm_o.choicenum) {
+ /* Help, boss, untrash screen. */
+ case 0: callverb(vb_help); break;
+ case 1: callverb(vb_boss); break;
+ case 2: major_redraw(); break;
+ case 3: callverb(vb_score); break;
+ case 4: callverb(vb_info); break;
+ }
+}
+
+void do__file()
+{;
+ switch (ddm_o.choicenum) {
+ /* New game, load, save, save as, DOS shell, about, quit. */
+ case 0: callverb(vb_restart); break;
+ case 1: {; realwords[2]=""; callverb(vb_load); } break;
+ case 2: {; realwords[2]=""; callverb(vb_save); } break;
+ case 3: filename_edit(); break;
+ case 4: back_to_bootstrap(2); break;
+ case 5: callverb(vb_quit); break;
+ }
+}
+
+void do__action()
+{
+ string n;
+;
+ switch (ddm_o.choicenum) {
+ /* Get up/pause game/open door/look/inv/walk-run */
+ case 0: {
+ person=pardon; thing=pardon;
+ n=f5_does(); callverb(n[1]);
+ }
+ break;
+ case 1: callverb(vb_pause); break;
+ case 2: callverb(vb_open); break;
+ case 3: callverb(vb_look); break;
+ case 4: callverb(vb_inv); break;
+ case 5: {
+ if (tr[1].xs==walk) tr[1].xs=run;
+ else tr[1].xs=walk;
+ newspeed();
+ }
+ break;
+ }
+}
+
+void do__objects()
+{;
+ thinkabout(objlist[ddm_o.choicenum+1],a_thing);
+}
+
+void do__people()
+{;
+ thinkabout(people[ddm_o.choicenum+1],a_person);
+ last_person=people[ddm_o.choicenum+1];
+}
+
+void do__with()
+{;
+ thing=thinks;
+
+ if (thinkthing)
+ {;
+
+ thing += 49;
+
+ if (verbstr[ddm_o.choicenum+1]==vb_give)
+ person=last_person;
+ else
+ person='\376';
+
+ } else
+ {;
+ switch (verbstr[ddm_o.choicenum+1]) {
+ case '\144': {; thing='\144'; callverb(vb_buy); return; } break; /* Beer */
+ case '\145': {; thing= '\62'; callverb(vb_buy); return; } break; /* Wine */
+ case '\146': {; thing='\146'; callverb(vb_buy); return; } break; /* Whisky */
+ case '\147': {; thing='\147'; callverb(vb_buy); return; } break; /* Cider */
+ case '\150': {; thing='\153'; callverb(vb_buy); return; } break; /* Mead */
+ case '\151': {; thing= '\103'; callverb(vb_buy); return; } break; /* Onion (trader) */
+ default:
+ {;
+ person=thing;
+ thing='\376';
+ }
+ }
+ }
+ callverb(verbstr[ddm_o.choicenum+1]);
+}
+
+/*$F- That's all. Now for the ...bar procs. */
+
+void standard_bar() /* Standard menu bar */
+{;
+ ddm_m.init(); ddm_o.init();
+ {; /* Set up menus */
+ create('F',"File",'!',ddm__file,do__file); /* same ones in map_bar, below, */
+ create('G',"Game",'\42',ddm__game,do__game); /* Don't forget to change the */
+ create('A',"Action",'\36',ddm__action,do__action); /* if you change them */
+ create('O',"Objects",'\30',ddm__objects,do__objects); /* here... */
+ create('P',"People",'\31',ddm__people,do__people);
+ create('W',"With",'\21',ddm__with,do__with);
+ update();
+ }
+}
+
+/*procedure map_bar; { Special menu bar for the map (screen 99) }
+begin;
+ ddm_m.init; ddm_o.init;
+ with ddm_m do
+ begin; { Set up menus }
+ create('G','Game','#',ddm__game,do__game);
+ create('F','File','!',ddm__file,do__test);
+ create('M','Map','2',ddm__map,do__test);
+ create('T','Town',#20,ddm__town,do__test);
+ update;
+ end;
+end;*/
+
+void checkclick() /* only for when the menu's displayed */
+{;
+ if (mpress>0)
+ {;
+ if (mpy>10)
+ {;
+ if (! ((ddm_o.firstlix) &&
+ ((mpx>=(cardinal)ddm_o.flx1*8) && (mpx<=(cardinal)ddm_o.flx2*8) &&
+ (mpy>=12) && (mpy<=(cardinal)ddm_o.fly))))
+ {; /* Clicked OUTSIDE the menu. */
+ if (ddm_o.menunow) wipe();
+ } /* No "else"- clicking on menu has no effect (only releasing) */
+ } else
+ {; /* Clicked on menu bar */
+ ddm_m.getmenu(mpx);
+ }
+ } else
+ {; /* NOT clicked button... */
+ if (mrelease>0)
+ {;
+ if ((ddm_o.firstlix) &&
+ ((mrx>=(cardinal)ddm_o.flx1*8) && (mrx<=(cardinal)ddm_o.flx2*8) &&
+ (mry>=12) && (mry<=(cardinal)ddm_o.fly)))
+ select((mry-13) / 10);
+ }
+ }
+}
+
+void menu_link()
+{;
+ {;
+ if (! ddm_o.menunow) return;
+
+ check(); /* find mouse coords & click information */
+ checkclick(); /* work out click codes */
+
+ /* Change arrow... */
+
+ switch (my) {
+ case RANGE_11(0, 10): newpointer(1);
+ break; /* up-arrow */
+ case 11 ... 169: {;
+ if ((mx>=(cardinal)ddm_o.flx1*8) && (mx<=(cardinal)ddm_o.flx2*8) && (my>10) && (my<=(cardinal)ddm_o.fly))
+ newpointer(3); /* right-arrow */
+ else newpointer(4); /* fletch */
+ }
+ break;
+ case RANGE_32(169,200): newpointer(2);
+ break; /* screwdriver */
+ }
+
+ if (! ddm_o.menunow) return;
+
+ lightup();
+ }
+}
+
+
diff --git a/engines/avalanche/dropdown.h b/engines/avalanche/dropdown.h
new file mode 100644
index 0000000000..9d32fb9705
--- /dev/null
+++ b/engines/avalanche/dropdown.h
@@ -0,0 +1,94 @@
+#ifndef __dropdown_h__
+#define __dropdown_h__
+
+
+typedef void(*proc)();
+
+class headtype {
+public:
+ varying_string<8> title;
+ char trigger,alttrigger;
+ byte position;
+ integer xpos,xright;
+ proc do_setup,do_choose;
+
+ headtype* init
+ (char trig,char alttrig, string name, byte p, proc dw,proc dc);
+ void display();
+ void highlight();
+ boolean extdparse(char c);
+};
+
+struct optiontype {
+ string title;
+ char trigger;
+ varying_string<9> shortcut;
+ boolean valid;
+};
+
+class onemenu {
+public:
+ array<1,12,optiontype> oo;
+ byte number;
+ integer width,left;
+ boolean firstlix;
+ integer flx1,flx2,fly;
+ byte oldy; /* used by Lightup */
+ boolean menunow; /* Is there a menu now? */
+ byte menunum; /* And if so, which is it? */
+ byte choicenum; /* Your choice? */
+ byte highlightnum;
+
+ void start_afresh();
+ void opt(string n, char tr, string key, boolean val);
+ void display();
+ void wipe();
+ void lightup();
+ void displayopt(byte y, boolean highlit);
+ void movehighlight(shortint add);
+ void select(byte n);
+ void keystroke(char c);
+ onemenu* init();
+};
+
+class menuset {
+public:
+ array<1,8,headtype> ddms;
+ byte howmany;
+
+ menuset* init();
+ void create(char t, string n, char alttrig, proc dw,proc dc);
+ void update();
+ void extd(char c);
+ void getcertain(byte fv);
+ void getmenu(integer x);
+};
+
+
+
+#ifdef __dropdown_implementation__
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN onemenu ddm_o;
+EXTERN menuset ddm_m;
+
+EXTERN varying_string<5> people;
+#undef EXTERN
+#define EXTERN extern
+
+
+
+ void find_what_you_can_do_with_it();
+
+ void parsekey(char r,char re);
+
+ void menu_link();
+
+ /* DDM menu-bar procs */
+
+ void standard_bar();
+ /*procedure map_bar;*/
+
+#endif
diff --git a/engines/avalanche/dwidth.cpp b/engines/avalanche/dwidth.cpp
new file mode 100644
index 0000000000..f66a417610
--- /dev/null
+++ b/engines/avalanche/dwidth.cpp
@@ -0,0 +1,20 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+
+typedef matrix<'\0','\377',0,15,byte> fonttype;
+
+integer gd,gm;
+fonttype f;
+file<fonttype> ff;
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ assign(ff,"v:avalot.fnt"); reset(ff); ff >> f; close(ff);
+ gd=3; gm=0; initgraph(gd,gm,"");
+ for( gd=0; gd <= 15; gd ++) mem[0xa000*gd*80]=f['A'][gd];
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/edhead.cpp b/engines/avalanche/edhead.cpp
new file mode 100644
index 0000000000..9fcb68583b
--- /dev/null
+++ b/engines/avalanche/edhead.cpp
@@ -0,0 +1,86 @@
+#include "ptoc.h"
+
+
+
+const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
+const string ednaid = string("TT")+'\261'+'\36'+'\1'+'\113'+'\261'+'\231'+'\261';
+
+struct edhead { /* Edna header */
+ /* This header starts at byte offset 177 in the .ASG file. */
+ array<1,9,char> id; /* signature */
+ word revision; /* EDNA revision, here 2 (1=dna256) */
+ varying_string<50> game; /* Long name, eg Lord Avalot D'Argent */
+ varying_string<15> shortname; /* Short name, eg Avalot */
+ word number; /* Game's code number, here 2 */
+ word ver; /* Version number as integer (eg 1.00 = 100) */
+ varying_string<5> verstr; /* Vernum as string (eg 1.00 = "1.00" */
+ varying_string<12> filename; /* Filename, eg AVALOT.EXE */
+ byte os; /* Saving OS (here 1=DOS. See below for others.) */
+
+ /* Info on this particular game */
+
+ varying_string<8> fn; /* Filename (not extension ('cos that's .ASG)) */
+ byte d,m; /* D, M, Y are the Day, Month & Year this game was... */
+ word y; /* ...saved on. */
+ varying_string<40> desc; /* Description of game (same as in Avaricius!) */
+ word len; /* Length of DNA (it's not going to be above 65535!) */
+
+ /* Quick reference & miscellaneous */
+
+ word saves; /* no. of times this game has been saved */
+ integer cash; /* contents of your wallet in numerical form */
+ varying_string<20> money; /* ditto in string form (eg 5/-, or 1 denarius)*/
+ word points; /* your score */
+
+ /* DNA values follow, then footer (which is ignored) */
+};
+ /* Possible values of edhead.os:
+ 1 = DOS 4 = Mac
+ 2 = Windows 5 = Amiga
+ 3 = OS/2 6 = ST */
+
+untyped_file f;
+byte fv;
+array<1,255,word> dna256;
+boolean ok;
+edhead e;
+
+void info(string x) /* info on .ASG files */
+{
+ varying_string<40> describe;
+;
+ assign(f,x);
+ /*$I-*/ reset(f,1);
+ seek(f,47);
+ blockread(f,describe,40);
+ blockread(f,dna256,sizeof(dna256));
+ close(f); /*$I+*/
+ e.revision=1;
+ game="Denarius Avaricius Sextus";
+ shortname="Avaricius";
+ number=1;
+ verstr="[?]";
+ filename="AVVY.EXE";
+ os=1;
+ fn=x;
+ d=dna256[7]; m=dna256[8]; y=dna256[9];
+ desc=describe;
+ len=512;
+ saves=dna256[6];
+ /*money:string[20]; { ditto in string form (eg 5/-, or 1 denarius)*/
+ /*points:word; { your score */
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ info("tt.asg");
+
+ output << "Filename: " << x << NL;
+ output << "Description: " << desc << NL;
+ output << "Cash: " << dna256[30] << NL;
+ output << "Score: " << dna256[36] << NL;
+ output << "Date: " << dna256[7] << ' ' << copy(months,dna256[8]*3-2,3) << ' ' << dna256[9] << NL;
+ output << "Number of saves: " << dna256[6] << NL;
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/edna.cpp b/engines/avalanche/edna.cpp
new file mode 100644
index 0000000000..74352fe9f7
--- /dev/null
+++ b/engines/avalanche/edna.cpp
@@ -0,0 +1,337 @@
+#include "ptoc.h"
+
+/*$M 10000,0,1000*/ /*$V-*/
+
+/*#include "Dos.h"*/
+/*#include "Tommys.h"*/
+
+
+struct ednahead { /* Edna header */
+ /* This header starts at byte offset 177 in the .ASG file. */
+ array<1,9,char> id; /* signature */
+ word revision; /* EDNA revision, here 2 (1=dna256) */
+ varying_string<50> game; /* Long name, eg Lord Avalot D'Argent */
+ varying_string<15> shortname; /* Short name, eg Avalot */
+ word number; /* Game's code number, here 2 */
+ word ver; /* Version number as integer (eg 1.00 = 100) */
+ varying_string<5> verstr; /* Vernum as string (eg 1.00 = "1.00" */
+ varying_string<12> filename; /* Filename, eg AVALOT.EXE */
+ byte osbyte; /* Saving OS (here 1=DOS. See below for others.*/
+ varying_string<5> os; /* Saving OS in text format. */
+
+ /* Info on this particular game */
+
+ varying_string<8> fn; /* Filename (not extension ('cos that's .ASG)) */
+ byte d,m; /* D, M, Y are the Day, Month & Year this game was... */
+ word y; /* ...saved on. */
+ varying_string<40> desc; /* Description of game (same as in Avaricius!) */
+ word len; /* Length of DNA (it's not going to be above 65535!) */
+
+ /* Quick reference & miscellaneous */
+
+ word saves; /* no. of times this game has been saved */
+ integer cash; /* contents of your wallet in numerical form */
+ varying_string<20> money; /* ditto in string form (eg 5/-, or 1 denarius)*/
+ word points; /* your score */
+
+ /* DNA values follow, then footer (which is ignored) */
+};
+
+/* Possible values of edhead.os:
+ 1 = DOS 4 = Mac
+ 2 = Windows 5 = Amiga
+ 3 = OS/2 6 = ST
+ 7 = Archimedes */
+
+typedef array<1,4,char> fourtype;
+
+struct avaricius_dna {
+ varying_string<39> desc;
+ array<1,256,integer> dna;
+};
+
+const string ednaid = string("TT")+'\261'+'\60'+'\1'+'\165'+'\261'+'\231'+'\261';
+const fourtype avaricius_file = "Avvy";
+
+string filename;
+boolean quiet,info;
+ednahead eh;
+
+boolean avaricius;
+fourtype id4;
+avaricius_dna av_eh;
+varying_string<4> av_ver;
+
+boolean ok;
+
+string first_dir;
+
+void explain()
+{
+ output << "EDNA Bucket v1.0 (c) 1993 Thomas Thurman." << NL;
+ output << " To load Avvy files." << NL;
+ output << NL;
+ output << "Associate .ASG files with EDNA.EXE to load them directly." << NL;
+ output << NL;
+ output << "Switches:" << NL;
+ output << " /q (quiet) will stop EDNA from printing text to the screen." << NL;
+ output << " /i (info) will print info about the file, but won't load it." << NL;
+ output << NL;
+ exit(1);
+}
+
+void fix_filename()
+{
+ string p,n,groi;
+
+ fsplit(filename,p,n,groi);
+ filename=p+n+".ASG";
+}
+
+void error(string x)
+{
+ output << "EDNA : " << x << NL;
+ exit(255);
+}
+
+void paramparse()
+{
+ byte fv;
+ string x;
+
+ if (paramcount==0) explain();
+
+ filename="";
+ quiet=false; info=false;
+
+ for( fv=1; fv <= paramcount; fv ++)
+ {
+ x=paramstr(fv);
+
+ if ((x[1]=='/') || (x[1]=='-'))
+ switch (upcase(x[2])) { /* Parse switches */
+ case 'Q': quiet=! quiet; break;
+ case 'I': info=! info; break;
+ default: error(string("Unknown switch! (")+x[2]+')');
+ }
+ else
+ if (filename=="") filename=x;
+ else error("Please, only one filename at a time!");
+ }
+
+ if (quiet && info) error("How can you give info quietly??");
+
+ if (filename=="") error("No filename given! Use EDNA alone for help.");
+
+ fix_filename();
+}
+
+void getfile()
+{
+ untyped_file f;
+
+ assign(f,filename);
+ /*$I-*/
+ reset(f,1);
+ /*$I+*/
+ if (ioresult!=0) error(string("Can't read file \"")+filename+"\".");
+
+ seek(f,11); blockread(f,id4,4);
+ avaricius=id4==avaricius_file;
+
+ if (avaricius)
+ {
+ seek(f,47);
+ blockread(f,av_eh,sizeof(av_eh));
+ av_ver[0]='\4'; seek(f,31); blockread(f,av_ver[1],4);
+ } else
+ {
+ seek(f,177);
+ blockread(f,eh,sizeof(eh));
+ }
+
+ close(f);
+}
+
+string plural(byte x)
+{
+ string plural_result;
+ if (x==1) plural_result=""; else plural_result='s';
+ return plural_result;
+}
+
+void show_info()
+{
+ string _game,_shortname,_verstr,_filename,_os,_fn,_desc,_money;
+ integer _revision,_number,_d,_m,_y,_saves,_points;
+ boolean readable,understandable;
+
+ output << "Info on file " << filename << ':' << NL;
+ output << NL;
+ if (avaricius)
+ { /* DNA-256 file. */
+ _verstr=av_ver;
+ _game="Denarius Avaricius Sextus"; _shortname="Avaricius";
+ _filename="AVVY.EXE"; _os="DOS"; _desc=av_eh.desc;
+ _revision=1; _number=1; _fn="(as above)";
+
+ _money=strf(av_eh.dna[30])+" denari";
+ if (av_eh.dna[30]==1) _money=_money+"us"; else _money=_money+'i';
+ _d=av_eh.dna[7]; _m=av_eh.dna[8]; _y=av_eh.dna[9];
+ _saves=av_eh.dna[6]; _points=av_eh.dna[36];
+
+ readable=true; understandable=true;
+ } else
+ {
+ if (eh.id==ednaid)
+ { /* EDNA file. */
+ _game=eh.game;
+ _shortname=eh.shortname;
+ _verstr=eh.verstr;
+ _filename=eh.filename;
+ _os=eh.os; _fn=eh.fn; _desc=eh.desc;
+ _money=eh.money; _revision=eh.revision;
+ _number=eh.number; _d=eh.d; _m=eh.m; _y=eh.y;
+ _saves=eh.saves; _points=eh.points;
+
+ readable=true; understandable=eh.revision==2;
+ } else
+ {
+ output << "Unknown format." << NL;
+ readable=false;
+ }
+ }
+
+ if (_desc=="") _desc="<none>";
+
+ if (readable)
+ {
+ output << "Signature is valid." << NL;
+ output << "Revision of .ASG format: " << _revision << NL;
+ output << NL;
+ if (understandable)
+ {
+ output << "The file was saved by " << _game << '.' << NL;
+ output << "Game number " << _number << " (" << _shortname << "), version " <<
+ _verstr << ", filename " << _filename << '.' << NL;
+ output << "Saved under " << _os << '.' << NL;
+ output << NL;
+ output << "This is " << _fn << ".ASG, saved on " << _d << '/' << _m << '/' << _y << " (d/m/y)." << NL;
+ output << "Description: " << _desc << NL;
+ output << "It has been saved " << _saves << " time" << plural(_saves) <<
+ ". You have " << _points << " point" << plural(_points) << ',' << NL;
+ output << "and " << _money << " in cash." << NL;
+ } else output << "Nothing else can be discovered." << NL;
+ }
+
+ exit(2);
+}
+
+void load_file()
+{
+ string progname,gamename,shortname,listname,exname,prog_dir;
+
+ string localdir,groi;
+
+ string x,y;
+
+ text t;
+
+ integer i,ii;
+
+ gamename=fexpand(filename);
+ fsplit(fexpand(paramstr(0)),localdir,groi,groi);
+ listname=localdir+"EDNA.DAT";
+
+ if (avaricius)
+ { shortname="Avaricius"; exname="AVVY"; }
+ else { shortname=eh.shortname; fsplit(eh.filename,groi,exname,groi); }
+
+ assign(t,listname);
+ /*$I-*/
+ reset(t);
+ /*$I+*/
+ progname="";
+ if (ioresult==0)
+ {
+ do {
+ t >> x >> NL; t >> y >> NL;
+ if (x==shortname)
+ {
+ progname=y;
+ flush();
+ }
+ } while (!(eof(t)));
+ }
+
+ if (progname=="")
+ { /* No entry in EDNA.DAT */
+ output << "This file was saved by " << shortname << '.' << NL;
+ output << "However, no entry was found in EDNA.DAT for that game." << NL;
+ output << NL;
+ output << "Please give the full path to that game, or press Enter to cancel." << NL;
+ output << string("(Example: C:\\")+exname+'\\'+exname+".EXE)" << NL;
+ output << NL;
+ input >> progname >> NL;
+ if (progname=="") exit(254); /* Quick exit! */
+
+ /*$I-*/
+ append(t);
+ if (ioresult!=0) rewrite(t);
+
+ t << shortname << NL;
+ t << progname << NL;
+
+ if (ioresult!=0)
+ {
+ output << "Strange... could not write to EDNA.DAT. (Disk read-only or full?)" << NL;
+ output << "The path will be used this time only." << NL;
+ output << "Press Enter..."; input >> NL;
+ }
+ close(t);
+ /*$I+*/
+ }
+
+ if (! quiet) output << "Running " << shortname << ": " << progname << "..." << NL;
+
+ fsplit(fexpand(progname),prog_dir,groi,groi);
+ if (prog_dir[length(prog_dir)]=='\\') prog_dir[0] -= 1;
+
+ /*$I-*/
+ chdir(prog_dir); i=ioresult;
+ swapvectors;
+ exec(progname,gamename); ii=ioresult;
+ swapvectors;
+ chdir(first_dir);
+ /*$I+*/
+
+ if ((i!=0) || (ii!=0))
+ {
+ output << "WARNING: DOS reported an error. This probably means that the entry" << NL;
+ output << "for this game in " << listname << " is wrong." << NL;
+ output << NL;
+ output << "Please edit this file, using" << NL;
+ output << NL;
+ if (lo(dosversion)<0x5)
+ output << " edlin " << listname << " (or similar)" << NL;
+ else
+ output << " edit " << listname << NL;
+ output << NL;
+ output << "and change the line after \"" << shortname << "\" to show the correct path." << NL;
+ output << NL;
+ output << "More info is in the Avvy documentation. Good luck!" << NL;
+ output << NL;
+ output << "Press Enter..."; input >> NL;
+ }
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ getdir(0,first_dir);
+ paramparse();
+ getfile();
+ if (info) show_info();
+ load_file();
+ return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/enhanced.cpp b/engines/avalanche/enhanced.cpp
new file mode 100644
index 0000000000..299aec2914
--- /dev/null
+++ b/engines/avalanche/enhanced.cpp
@@ -0,0 +1,86 @@
+#include "ptoc.h"
+
+#define __enhanced_implementation__
+
+
+/* This is the unit set up by Thomas with help from all the people on
+ CIS:BPROGA to read the *enhanced* keyboard codes (as opposed to the
+ readkey-type ones.) */
+
+#include "enhanced.h"
+
+
+/*#include "Dos.h"*/
+/*#include "Crt.h"*/
+
+
+boolean isenh()
+{
+ byte statefrom16;
+ registers r;
+
+ boolean isenh_result;
+ isenh_result = false;
+ {;
+ ah=0x12;
+ intr(0x16,r);
+ statefrom16=al;
+ }
+ if (statefrom16 != shiftstate) return isenh_result;
+ shiftstate = shiftstate ^ 0x20;
+ {;
+ ah=0x12;
+ intr(0x16,r);
+ statefrom16=al;
+ }
+ isenh_result = statefrom16 == shiftstate;
+ shiftstate = shiftstate ^ 0x20;
+ return isenh_result;
+}
+
+void readkeye()
+/* function fancystuff:word;
+ inline( $B4/ $10/ { MOV AH,10 }
+ $CD/ $16); { INT 16 }
+ function notfancystuff:word;
+ inline( $B4/ $00/ { MOV AH,0 }
+ $CD/ $16); { INT 16 }
+*/
+{
+ registers r; word fs;
+;
+ if (atbios)
+ fs=fancystuff; /* We're using an AT */
+ else fs=notfancystuff; /* ditto, an XT */
+ inchar=chr(lo(fs));
+ extd=chr(hi(fs));
+}
+
+boolean keypressede()
+/*
+ function fancystuff:boolean;
+ inline( $B4/ $11/ { MOV AH,11 }
+ $CD/ $16/ { INT 16 }
+ $B8/ $00/ $00/ { MOV AX, 0000 }
+ $74/ $01/ { JZ 0112 (or wherever- the next byte after $40, anyway) }
+ $40); { INC AX }
+*/
+{
+ registers r;
+boolean keypressede_result;
+;
+ if (atbios)
+ keypressede_result=fancystuff; /* ATs get the fancy stuff */
+ else keypressede_result=keypressed(); /* XTs get the usual primitive... */
+return keypressede_result;
+}
+
+class unit_enhanced_initialize {
+ public: unit_enhanced_initialize();
+};
+static unit_enhanced_initialize enhanced_constructor;
+
+unit_enhanced_initialize::unit_enhanced_initialize() {;
+ /* determine bios type */
+ atbios=isenh();
+}
diff --git a/engines/avalanche/enhanced.h b/engines/avalanche/enhanced.h
new file mode 100644
index 0000000000..a028648ced
--- /dev/null
+++ b/engines/avalanche/enhanced.h
@@ -0,0 +1,22 @@
+#ifndef __enhanced_h__
+#define __enhanced_h__
+
+
+
+#ifdef __enhanced_implementation__
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN byte shiftstate;/*ABSOLUTE $40:$17;*/
+EXTERN boolean atbios;
+EXTERN char inchar,extd;
+#undef EXTERN
+#define EXTERN extern
+
+
+void readkeye();
+
+boolean keypressede();
+
+#endif
diff --git a/engines/avalanche/enid.cpp b/engines/avalanche/enid.cpp
new file mode 100644
index 0000000000..89e1327191
--- /dev/null
+++ b/engines/avalanche/enid.cpp
@@ -0,0 +1,581 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ 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"
+
+
+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;
+}
+
+
diff --git a/engines/avalanche/enid.h b/engines/avalanche/enid.h
new file mode 100644
index 0000000000..abf20a27dc
--- /dev/null
+++ b/engines/avalanche/enid.h
@@ -0,0 +1,22 @@
+#ifndef __enid_h__
+#define __enid_h__
+
+
+#include "gyro.h"
+
+
+void edna_save(string name);
+
+void edna_load(string name);
+
+void edna_reload(); /* From Bootstrap's storage. */
+
+void dir(string where);
+
+void avvy_background();
+
+void back_to_bootstrap(byte what);
+
+boolean there_was_a_problem();
+
+#endif
diff --git a/engines/avalanche/filer.cpp b/engines/avalanche/filer.cpp
new file mode 100644
index 0000000000..036aa945af
--- /dev/null
+++ b/engines/avalanche/filer.cpp
@@ -0,0 +1,791 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Dos.h"*/
+/*#include "Crt.h"*/
+/*#include "Tommys.h"*/
+#include "lucerna.h"
+
+/*$V-*/
+
+struct windowtype {
+ integer x1,y1,x2,y2;
+ varying_string<20> title;
+};
+
+ struct ednahead { /* Edna header */
+ /* This header starts at byte offset 177 in the .ASG file. */
+ array<1,9,char> id; /* signature */
+ word revision; /* EDNA revision, here 2 (1=dna256) */
+ varying_string<50> game; /* Long name, eg Lord Avalot D'Argent */
+ varying_string<15> shortname; /* Short name, eg Avalot */
+ word number; /* Game's code number, here 2 */
+ word ver; /* Version number as integer (eg 1.00 = 100) */
+ varying_string<5> verstr; /* Vernum as string (eg 1.00 = "1.00" */
+ varying_string<12> filename; /* Filename, eg AVALOT.EXE */
+ byte osbyte; /* Saving OS (here 1=DOS. See below for others.*/
+ varying_string<5> os; /* Saving OS (here 1=DOS. See below for others.*/
+
+ /* Info on this particular game */
+
+ varying_string<8> fn; /* Filename (not extension ('cos that's .ASG)) */
+ byte d,m; /* D, M, Y are the Day, Month & Year this game was... */
+ word y; /* ...saved on. */
+ varying_string<40> desc; /* Description of game (same as in Avaricius!) */
+ word len; /* Length of DNA (it's not going to be above 65535!) */
+
+ /* Quick reference & miscellaneous */
+
+ word saves; /* no. of times this game has been saved */
+ integer cash; /* contents of your wallet in numerical form */
+ varying_string<20> money; /* ditto in string form (eg 5/-, or 1 denarius)*/
+ word points; /* your score */
+
+ /* DNA values follow, then footer (which is ignored) */
+ };
+
+const integer border = 1; /* size of border on shadowboxes */
+
+const array<1,4,varying_string<7> > buttons = {{"Okay","Wipe","Cancel","Info..."}};
+
+const integer files = 3;
+const integer dirs = 4;
+
+const integer drlen = 15; /* no. of drives on one line */
+
+const array<1,4,windowtype> threewins =
+ {{{155, 12, 630, 22, "Name"},
+ {15, 25, 410, 70, "Drives"},
+ {15, 83, 480, 179, "Files (*.ASG)"},
+ {490, 83, 630, 179, "Subdirectories"}}};
+
+const integer name_win = 1;
+const integer drive_win = 2;
+const integer file_win = 3;
+const integer subdir_win = 4;
+
+matrix<3,4,1,77,varying_string<12> > lists;
+array<1,77,varying_string<40> > descs;
+array<3,4,byte> nums,where,top;
+searchrec s;
+boolean loading;
+varying_string<26> drives;
+pathstr current;
+byte nowwin;
+varying_string<17> doing;
+
+pathstr filename;
+boolean filefound;
+
+void shadow(integer x1,integer y1,integer x2,integer y2, byte hc,byte sc)
+{
+ byte fv;
+;
+ for( fv=0; fv <= border; fv ++)
+ {;
+ setfillstyle(1,hc);
+ bar(x1+fv,y1+fv,x1+fv,y2-fv);
+ bar(x1+fv,y1+fv,x2-fv,y1+fv);
+
+ setfillstyle(1,sc);
+ bar(x2-fv,y1+fv,x2-fv,y2-fv);
+ bar(x1+fv,y2-fv,x2-fv,y2-fv);
+ }
+}
+
+void shbox(integer x1,integer y1,integer x2,integer y2, string t)
+{
+ const integer fc = 7;
+;
+ shadow(x1,y1,x2,y2,15,8);
+ setfillstyle(1,fc);
+ bar(x1+border+1,y1+border+1,x2-border-1,y2-border-1);
+ setcolor(1); x1=(x2-x1) / 2+x1; y1=(y2-y1) / 2+y1;
+ outtextxy(x1,y1,t);
+ if (length(t)>1)
+ {;
+ fillchar(t[2],length(t)-1,'\40'); t[1]='_';
+ outtextxy(x1-1,y1+1,t);
+ }
+}
+
+void show_drives()
+{
+ byte fv;
+;
+ settextjustify(1,1);
+ for( fv=0; fv <= length(drives)-1; fv ++)
+ shbox((fv % drlen)*25+25,(fv / drlen)*19+31,
+ (fv % drlen)*25+40,45+(fv / drlen)*19,drives[fv+1]);
+ setcolor(11);
+ settextjustify(0,2);
+}
+
+void box(integer x1,integer y1,integer x2,integer y2, string z)
+{;
+ rectangle(x1,y1,x2,y2);
+ outtextxy(x1+1,y1-10,z+':');
+ outtextxy(x1,y1-9,"_");
+}
+
+string lowstr(string x)
+{
+ byte fv;
+string lowstr_result;
+;
+ for( fv=1; fv <= length(x); fv ++)
+ if (set::of(range('A','Z'), eos).has(x[fv])) x[fv] += 32;
+ lowstr_result=x;
+return lowstr_result;
+}
+
+char lowchar(char x)
+{
+ char lowchar_result;
+ if (set::of(range('A','Z'), eos).has(x)) x -= 32;
+ lowchar_result=x;
+ return lowchar_result;
+}
+
+void getcurrent()
+{;
+ current=lowstr(fexpand("*.asg"));
+}
+
+void setup()
+{
+ integer gd,gm;
+ registers r;
+ byte floppies;
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ dusk();
+ setfillstyle(1,1); bar(2,2,637,197); shadow(0,0,639,199,15,7);
+
+ if (loading) doing="LOAD"; else doing="SAV";
+ doing=doing+"ING a file...";
+
+ /* Now... find all drives that exist. */
+ drives="";
+ intr(0x11,r); floppies=(((cardinal)r.ax >> 6) & 0x3)+1; /* useful bit of code! */
+ for( gm=1; gm <= floppies; gm ++) drives=drives+chr(64+gm);
+ /* Winchesters, etc., can be found the easy way... */
+ for( gd=3; gd <= 26; gd ++) /* C: to Z: */
+ if (disksize(gd)>-1) drives=drives+chr(64+gd);
+
+ fillchar(where,sizeof(where),'\1');
+ fillchar(top,sizeof(top),'\1');
+
+ settextstyle(0,0,0);
+ settextjustify(1,1);
+ for( gd=1; gd <= 2; gd ++)
+ for( gm=0; gm <= 1; gm ++)
+ shbox(420+gm*110,gd*25,520+gm*110,gd*25+20,buttons[gm*2+gd]);
+ shbox(15,182,350,196,"Help... (press f1)");
+ settextjustify(0,2); setcolor(11);
+ setcolor(15); outtextxy(15,5,"The Avvy Filer...");
+ setcolor(11); outtextxy(317,3,string('(')+doing+')');
+ outtextxy(357,185,"Copyright (c) 1993, Thomas Thurman.");
+
+ /* Draw the boxes and names */
+ setcolor(3);
+ for( gm=1; gm <= 4; gm ++)
+ { windowtype& with = threewins[gm];
+ box(with.x1,with.y1,with.x2,with.y2,with.title);}
+ nowwin=1; getcurrent();
+}
+
+void quicksort(byte whichlist, integer lo, integer hi);
+
+
+static void sort(integer l, integer r, byte& whichlist)
+{
+ integer i, j;
+ varying_string<12> x, y;
+
+ i = l; j = r; x = lists[whichlist][(l+r) / 2];
+ do {
+ while (lists[whichlist][i] < x) i = i + 1;
+ while (x < lists[whichlist][j]) j = j - 1;
+ if (i <= j)
+ {
+ y = lists[whichlist][i];
+ lists[whichlist][i] = lists[whichlist][j];
+ lists[whichlist][j] = y;
+ i = i + 1; j = j - 1;
+ }
+ } while (!(i > j));
+ if (l < j) sort(l, j, whichlist);
+ if (i < r) sort(i, r, whichlist);
+}
+
+void quicksort(byte whichlist, integer lo, integer hi)
+
+{ /*QuickSort*/;
+ sort(lo,hi, whichlist);
+}
+
+void scandir()
+{
+ pathstr nix;
+ namestr name;
+ untyped_file f;
+ ednahead eh;
+ array<1,4,char> dna_type;
+
+;
+ nums[files]=0;
+ findfirst("*.asg",archive+hidden+readonly,s);
+
+ while (doserror==0)
+ {;
+ fsplit(s.name,nix,name,nix);
+ nums[files] += 1;
+ lists[files][nums[files]]=lowstr(name);
+
+ assign(f,s.name);
+ reset(f,1);
+ seek(f,11);
+ blockread(f,dna_type,4);
+
+ if (dna_type=="Avvy")
+ {; /* A DNA256 file. */
+ descs[nums[files]]="* Saved by Avaricius!";
+ } else
+ {; /* EDNA-based files. */
+ if (dna_type=="EDNA")
+ {;
+ seek(f,177);
+ blockread(f,eh,sizeof(eh));
+
+ if (eh.revision!=2)
+ descs[nums[files]]="* Unknown EDNA type!";
+ else
+ {;
+
+ if (eh.number!=2)
+ descs[nums[files]]=string("* Saved by ")+eh.shortname+'!';
+ else
+ {; /* Well... everything seems to have gone OK! */
+ descs[nums[files]]=eh.desc;
+ }
+ }
+ } else
+ descs[nums[files]]="* Not an Avvy saved game!";
+ }
+ close(f);
+ findnext(s);
+ }
+ nums[dirs]=0; findfirst("*.*",directory,s);
+ while (doserror==0)
+ {;
+ if (((s.attr & directory)>0) && ((length(s.name))>1))
+ {;
+ nums[dirs] += 1;
+ lists[dirs][nums[dirs]]=lowstr(s.name);
+ }
+ findnext(s);
+ }
+
+ /* Now sort 'em! */
+
+ quicksort ( dirs,1,nums[ dirs]);
+ quicksort (files,1,nums[files]);
+
+ where[dirs]=1; where[files]=1;
+ top[dirs]=1; top[files]=1;
+}
+
+void show_file(integer x,integer y, byte which)
+{
+ varying_string<58> z;
+;
+ fillchar(z[1],13,'\40');
+ z=lists[files][which]+".asg";
+ z[0]='\15'; z=z+descs[which];
+
+ if (descs[which][1]=='*') /* Can't load these! */
+ setcolor(red);
+ else
+ setcolor(lightcyan);
+
+ outtextxy(x,y,z);
+}
+
+void showfiles()
+{
+ byte fv;
+;
+ if (loading) setcolor(11); else setcolor(3);
+ if (nums[3]==0)
+ {;
+ outtextxy(22,86,"(None here!)");
+ return;
+ }
+ for( fv=0; fv <= 8; fv ++)
+ if (where[3]+fv<=nums[3])
+ show_file(19,87+fv*10,where[3]+fv);
+}
+
+void showdirs()
+{
+ byte fv;
+;
+ setcolor(11);
+ for( fv=0; fv <= 8; fv ++)
+ if (where[4]+fv<=nums[4])
+ outtextxy(497,87+fv*10,string('[')+lists[dirs][fv+where[4]]+']');
+}
+
+void show()
+{
+ byte fv;
+ dirstr d; namestr n; extstr e;
+;
+ setfillstyle(1,1);
+ for( fv=1; fv <= 4; fv ++)
+ if (fv!=2)
+ { windowtype& with = threewins[fv];
+ bar(with.x1+1,with.y1+1,with.x2-1,with.y2-1);}
+ showfiles();
+ showdirs();
+ setcolor(7); outtextxy(159,14,current);
+}
+
+void blip()
+{;
+ sound(177); delay(77); nosound;
+}
+
+void invert(integer x1,integer y1,integer x2,integer y2)
+{
+ pointer p,restore; word s;
+;
+ s=imagesize(x1,y1,x2,y2);
+ mark(restore); getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+ putimage(x1,y1,p,notput);
+ release(restore);
+}
+
+void changedrive(char drive)
+{
+ byte fv;
+;
+ fv=pos(drive,drives);
+ if (fv==0) {; blip(); return; }
+ fv -= 1;
+ shadow((fv % drlen)*25+25,(fv / drlen)*19+31,
+ (fv % drlen)*25+40,45+(fv / drlen)*19,8,7);
+ chdir(string(drive)+':');
+ getcurrent(); scandir(); show();
+ shadow((fv % drlen)*25+25,(fv / drlen)*19+31,
+ (fv % drlen)*25+40,45+(fv / drlen)*19,15,8);
+}
+
+void highlight(byte win,byte line)
+{;
+ switch (win) {
+ case 3: invert(16,75+line*10,479,85+line*10); break;
+ case 4: invert(491,75+line*10,619,85+line*10); break;
+ }
+}
+
+void repaint(byte whichwindow)
+{
+ setfillstyle(1,1);
+ { windowtype& with = threewins[whichwindow];
+ bar(with.x1+1,with.y1+1,with.x2-1,with.y2-1);}
+ switch (whichwindow) {
+ case file_win: showfiles(); break;
+ case subdir_win: showdirs(); break;
+ }
+ highlight(whichwindow,1);
+ top[whichwindow]=where[whichwindow];
+}
+
+void fileblit(word xpos,word xlen,word y1,word y2, shortint dir, word ylen)
+{
+ word fv; byte bit;
+;
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ fv=0;
+ while (fv<ylen)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ move(mem[0xa000*(y1+fv*dir)*80+xpos],mem[0xa000*(y2+fv*dir)*80+xpos],xlen);
+ fv += 1;
+ }
+ }
+ bit=getpixel(0,0);
+}
+
+void seekthrough(byte whichlist, byte& wherenow, char whatfor)
+{
+ byte startedat;
+
+ startedat=wherenow;
+ do {
+ wherenow += 1;
+ if (wherenow>nums[whichlist]) wherenow=1;
+ } while (!((startedat==wherenow) || (lists[whichlist][wherenow][1]==whatfor)));
+ repaint(whichlist);
+}
+
+void gotohome(byte whichlist)
+{
+ where[whichlist]=1;
+ repaint(whichlist);
+}
+
+void gotoend(byte whichlist)
+{
+ where[whichlist]=nums[whichlist];
+ repaint(whichlist);
+}
+
+void pageup(byte whichlist)
+{
+ if (where[whichlist]>9)
+ {
+ where[whichlist] -= 9;
+ repaint(whichlist);
+ }
+}
+
+void pagedown(byte whichlist)
+{
+ if (where[whichlist]<nums[whichlist]-9)
+ {
+ where[whichlist] += 9;
+ repaint(whichlist);
+ }
+}
+
+void subdirparse(string r);
+
+static void movehl(byte which, shortint howmuch)
+{;
+ highlight(4,where[4]-top[4]+1);
+ if (((where[which]+howmuch)>0) && ((where[which]+howmuch)<=(unsigned char)nums[4]))
+ where[which]=where[which]+howmuch;
+ highlight(4,where[4]-top[4]+1);
+}
+
+
+
+static void change_dir()
+{;
+ dusk();
+ /*$I-*/ chdir(lists[4][where[4]]);
+ /*$I+*/
+ if (ioresult!=0) {; dawn(); blip(); return; }
+ where[4]=1; top[4]=1;
+ getcurrent(); scandir(); show();
+ highlight(4,1);
+ dawn();
+}
+
+void subdirparse(string r)
+
+{;
+ switch (r[1]) {
+ case creturn: change_dir(); break;
+
+ case '\0': switch (r[2]) {
+ case cup: if (where[4]-top[4]>0) /* Up */
+ movehl(4,-1); /* Within range */
+ else if (top[4]>1)
+ {; /* Outside range- must scroll */
+ highlight(4,1);
+ top[4] -= 1; where[4] -= 1;
+ fileblit(61,18,166,176,-1,80);
+ setfillstyle(1,1); bar(490,85,630,95); setcolor(11);
+ outtextxy(497,87,string('[')+lists[dirs][where[4]]+']');
+ highlight(4,1);
+ }
+ break;
+ case cdown:
+ if (where[4]-top[4]<8) /* Down */
+ movehl(4,1);
+ else if (top[4]+8<nums[4])
+ {;
+ highlight(4,9);
+ top[4] += 1; where[4] += 1;
+ fileblit(60,18,97,87,1,80);
+ setfillstyle(1,1); bar(490,165,630,175); setcolor(11);
+ outtextxy(497,167,string('[')+lists[dirs][where[4]]+']');
+ highlight(4,9);
+ }
+ break;
+ case chome: gotohome(4); break;
+ case cend: gotoend(4); break;
+ case cpgup: pageup(4); break;
+ case cpgdn: pagedown(4); break;
+ case c_ao: change_dir(); break;
+ }
+ break;
+ default: seekthrough(4,where[4],lowchar(r[1]));
+ }
+}
+
+void fileinfo(byte which);
+
+
+static void display(integer y, string left,string right)
+{;
+ y=17+y*12;
+ settextjustify(2,1); setcolor(11); outtextxy(315,y,left);
+ settextjustify(0,1); setcolor(15); outtextxy(325,y,right);
+}
+
+void fileinfo(byte which)
+ /* This gives information on the file whose name is in lists[files,which]. */
+{
+ ednahead eh;
+ untyped_file f;
+ varying_string<4> os;
+ char r;
+
+;
+
+ /* Firstly, we must check whether or not it's an Avalot file. This is easily
+ done, since the descriptions of all others always begin with a star. */
+
+ if ((descs[which][1]=='*') || (descs[which][1]=='('))
+ {; /* it is. */
+ blip(); /* Naaaarghh! */
+ return;
+ }
+
+ /* Anyway... it wasn't. */
+
+ assign(f,lists[files][which]+".asg");
+ reset(f,1);
+ seek(f,177);
+ blockread(f,eh,sizeof(eh));
+ close(f);
+
+ /* We now hold its EDNA record. */
+
+ setfillstyle(1,1); bar(2,2,637,197); /* Interesting information coming up! */
+
+ {;
+ display(2,"Saved by:", eh.game);
+ display(3,"version:", eh.verstr);
+
+/* display(4,'under', os);*/
+
+ display(6,"Saved on ",strf(eh.d)+'-'+strf(eh.m)+'-'+strf(eh.y));
+
+ display(9,"No. of times saved:",strf(eh.saves));
+
+ display(11,"Money:",eh.money);
+ display(12,"Score:",strf(eh.points));
+ }
+
+ shbox(500,177,650,200,"Press any key...");
+ r=readkey();
+
+ setfillstyle(1,1); bar(2,2,637,197);
+}
+
+void filer_help()
+ /* This gives general help. */
+{
+ char r;
+;
+ outtextxy(100,100,"Just general help here.");
+ shbox(500,177,650,200,"Press any key...");
+ r=readkey();
+
+ setfillstyle(1,1); bar(2,2,637,197);
+}
+
+void wipe()
+ /* This allows you to delete files. */
+{
+ char r;
+;
+ outtextxy(100,100,"Are you sure you want to delete \"foo.bar\"?");
+ shbox(500,177,650,200,"[Y/N]");
+ r=readkey();
+
+ setfillstyle(1,1); bar(2,2,637,197);
+}
+
+void filesparse(string r);
+
+static void movehl1(byte which, shortint howmuch)
+{;
+ highlight(3,where[3]-top[3]+1);
+ if (((where[which]+howmuch)>0) && ((where[which]+howmuch)<=(unsigned char)nums[3]))
+ where[which]=where[which]+howmuch;
+ highlight(3,where[3]-top[3]+1);
+}
+
+
+
+static boolean selected_file()
+{boolean selected_file_result;
+;
+ if (descs[where[file_win]][1]=='*')
+ {
+ blip();
+ selected_file_result=false;
+ } else
+ {
+ filename=lists[file_win][where[file_win]];
+ filefound=true;
+ selected_file_result=true;
+ }
+return selected_file_result;
+}
+
+void filesparse(string r)
+
+{;
+ switch (r[1]) {
+ case creturn: if (selected_file()) return; break;
+ case '\0': switch (r[2]) {
+ case cup: if (where[3]-top[3]>0) /* Up */
+ movehl1(3,-1); /* Within range */
+ else if (top[3]>1)
+ {; /* Outside range- must scroll */
+ highlight(3,1);
+ top[3] -= 1; where[3] -= 1;
+ fileblit(1,59,166,176,-1,80);
+ setfillstyle(1,1); bar( 15,85,480,95);
+ show_file( 19,87,where[3]);
+ highlight(3,1);
+ }
+ break;
+ case cdown: if (where[3]-top[3]<8) /* Down */
+ movehl1(3,1);
+ else if (top[3]+8<nums[3])
+ {;
+ highlight(3,9);
+ top[3] += 1; where[3] += 1;
+ fileblit(1,59,97,87,1,80);
+ setfillstyle(1,1); bar( 15,165,480,175);
+ show_file( 19,167,where[3]);
+ highlight(3,9);
+ }
+ break;
+ case c_ai: fileinfo(where[3]); break; /* alt-I: information. */
+ case c_ah:case c_f1: filer_help(); break; /* alt-I: information. */
+ case chome: gotohome(3); break;
+ case cend: gotoend(3); break;
+ case cpgup: pageup(3); break;
+ case cpgdn: pagedown(3); break;
+ case c_ao: if (selected_file()) return; break;
+ }
+ break;
+ default: seekthrough(3,where[3],lowchar(r[1]));
+ }
+}
+
+string playaround();
+
+static void changewin(byte i)
+{;
+ switch (nowwin) {
+ case 3:case 4: highlight(nowwin,where[nowwin]-top[nowwin]+1); break;
+ }
+ setcolor(3); { windowtype& with = threewins[nowwin]; box(with.x1,with.y1,with.x2,with.y2,with.title);}
+ nowwin=i;
+ if (nowwin<1) nowwin=4; if (nowwin>4) nowwin=1;
+ switch (nowwin) {
+ case 3:case 4: highlight(nowwin,where[nowwin]-top[nowwin]+1); break;
+ }
+}
+
+string playaround()
+{
+ char r,r2;
+string playaround_result;
+;
+ filefound=false; dawn();
+
+ do {
+ setcolor(14); { windowtype& with = threewins[nowwin]; box(with.x1,with.y1,with.x2,with.y2,with.title);}
+ r=readkey();
+ switch (r) {
+ case ctab: changewin(nowwin+1); break;
+ case cescape: {;
+ playaround_result="";
+ return playaround_result;
+ }
+ break;
+ case '\0': {; /* parse extd keystroke */
+ r2=readkey();
+ switch (r2) {
+ case cs_tab: changewin(nowwin-1); break;
+ case c_an: changewin(1); break;
+ case c_ad: changewin(2); break;
+ case c_af: changewin(3); break;
+ case c_as: changewin(4); break;
+ case c_ac: {;
+ playaround_result="";
+ return playaround_result;
+ }
+ break;
+ default:
+ switch (nowwin) {
+ case 3: filesparse(string('\0')+r2); break;
+ case 4: subdirparse(string('\0')+r2); break;
+ }
+ }
+ }
+ break;
+ default:
+ {; /* Pass keystroke to current window */
+ switch (nowwin) {
+ case 2: changedrive(upcase(r)); break;
+ case 4: subdirparse(r); break;
+ case 3: filesparse(r); break;
+ default: blip();
+ }
+ }
+
+ }
+
+ if (filefound)
+ {;
+ dusk();
+ playaround_result=filename;
+ return playaround_result;
+ }
+ } while (!false);
+return playaround_result;
+}
+
+void do_filer()
+{
+ pathstr p;
+void do_filer_result;
+;
+ loading=true;
+ setup();
+ scandir();
+ show(); show_drives();
+ p=playaround();
+ if (p!="") p=fexpand(p+".ASG");
+ do_filer_result=p;
+return do_filer_result;
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ filename=do_filer();
+ closegraph();
+ if (filename=="")
+ output << "*** CANCELLED! ***" << NL;
+ else
+ output << "Selected: " << filename << NL;
+ input >> NL;
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/fileunit.cpp b/engines/avalanche/fileunit.cpp
new file mode 100644
index 0000000000..a944fbc0a0
--- /dev/null
+++ b/engines/avalanche/fileunit.cpp
@@ -0,0 +1,1118 @@
+#include "ptoc.h"
+
+#define __fileunit_implementation__
+ /* v:filer.pas - "avvyfiler" - in unit form. */
+
+#include "fileunit.h"
+
+
+#include "graph.h"
+/*#include "Dos.h"*/
+/*#include "Crt.h"*/
+/*#include "Tommys.h"*/
+#include "lucerna.h"
+#include "pingo.h"
+#include "Gyro.h"
+
+/*$V-*/
+
+struct windowtype {
+ integer x1,y1,x2,y2;
+ varying_string<20> title;
+};
+
+const integer border = 1; /* size of border on shadowboxes */
+
+const array<1,4,string> buttons = {{"Okay","Wipe","Cancel","Info..."}};
+
+const integer files = 3;
+const integer dirs = 4;
+
+const integer drlen = 15; /* no. of drives on one line */
+
+const array<1,4,windowtype> threewins =
+ {{{155, 12, 630, 22, "Name"},
+ {15, 25, 410, 70, "Drives"},
+ {15, 83, 480, 179, "Files (*.ASG)"},
+ {490, 83, 630, 179, "Subdirectories"}}};
+
+const integer name_win = 1;
+const integer drive_win = 2;
+const integer file_win = 3;
+const integer subdir_win = 4;
+
+const integer filer_page = 3;
+
+matrix<3,4,1,77,varying_string<12> > lists;
+array<1,77,varying_string<40> > descs;
+array<3,4,byte> nums,where,top,thumb_pos,thumb_len;
+searchrec s;
+boolean loading;
+varying_string<26> drives;
+pathstr current;
+byte nowwin;
+
+pathstr filename;
+boolean filefound;
+
+boolean cancelled;
+
+void shadow(integer x1,integer y1,integer x2,integer y2, byte hc,byte sc)
+{
+ byte fv;
+
+ for( fv=0; fv <= border; fv ++)
+ {
+ setfillstyle(1,hc);
+ bar(x1+fv,y1+fv,x1+fv,y2-fv);
+ bar(x1+fv,y1+fv,x2-fv,y1+fv);
+
+ setfillstyle(1,sc);
+ bar(x2-fv,y1+fv,x2-fv,y2-fv);
+ bar(x1+fv,y2-fv,x2-fv,y2-fv);
+ }
+}
+
+void shbox(integer x1,integer y1,integer x2,integer y2, string t)
+{
+ const integer fc = 7;
+
+ shadow(x1,y1,x2,y2,15,8);
+ setfillstyle(1,fc);
+ bar(x1+border+1,y1+border+1,x2-border-1,y2-border-1);
+ setcolor(1); x1=(x2-x1) / 2+x1; y1=(y2-y1) / 2+y1;
+ outtextxy(x1,y1,t);
+ if ((t[1]!='[') && (length(t)>1))
+ {
+ fillchar(t[2],length(t)-1,'\40'); t[1]='_';
+ outtextxy(x1-1,y1+1,t);
+ }
+}
+
+void show_drives()
+{
+ byte fv;
+
+ settextjustify(1,1);
+ for( fv=0; fv <= length(drives)-1; fv ++)
+ shbox((fv % drlen)*25+25,(fv / drlen)*19+31,
+ (fv % drlen)*25+40,45+(fv / drlen)*19,drives[fv+1]);
+ setcolor(11);
+ settextjustify(0,2);
+}
+
+char which_drive(integer x,integer y)
+{
+ char which_drive_result;
+ x=(x-25) / 25; y=(y-32) / 19;
+
+ which_drive_result= drives[1+x+y*drlen];
+ return which_drive_result;
+}
+
+void box(integer x1,integer y1,integer x2,integer y2, string z)
+{
+ rectangle(x1,y1,x2,y2);
+ outtextxy(x1+1,y1-10,z+':');
+ outtextxy(x1,y1-9,"_");
+}
+
+string lowstr(string x)
+{
+ byte fv;
+
+ string lowstr_result;
+ for( fv=1; fv <= length(x); fv ++)
+ if (set::of(range('A','Z'), eos).has(x[fv])) x[fv] += 32;
+ lowstr_result=x;
+ return lowstr_result;
+}
+
+char lowchar(char x)
+{
+ char lowchar_result;
+ if (set::of(range('A','Z'), eos).has(x)) x -= 32;
+ lowchar_result=x;
+ return lowchar_result;
+}
+
+void getcurrent()
+{
+ current=lowstr(fexpand("*.asg"));
+}
+
+void firstsetup()
+{
+ integer gd,gm;
+ registers r;
+ byte floppies;
+
+ /* Now... find all drives that exist. */
+ drives="";
+ intr(0x11,r); floppies=(((cardinal)r.ax >> 6) & 0x3)+1; /* useful bit of code! */
+ for( gm=1; gm <= floppies; gm ++) drives=drives+chr(64+gm);
+ /* Winchesters, etc., can be found the easy way... */
+ for( gd=3; gd <= 26; gd ++) /* C: to Z: */
+ if (disksize(gd)>-1) drives=drives+chr(64+gd);
+
+ fillchar(where,sizeof(where),'\1');
+ fillchar(top,sizeof(top),'\1');
+
+ /* Set up mouse. */
+ off_virtual();
+ oncandopageswap=false;
+ newpointer(2);
+}
+
+void draw_scroll_bar(byte which)
+{
+ setcolor(1);
+ {
+ windowtype& with = threewins[which];
+
+ setfillstyle(1,7);
+ bar(with.x2-7,with.y1+10,with.x2-1,with.y2-10);
+ setfillstyle(1,3);
+ bar(with.x2-7,with.y1+ 1,with.x2-1,with.y1+9);
+ bar(with.x2-7,with.y2- 9,with.x2-1,with.y2-1);
+ outtextxy(with.x2-7,with.y1+2,"\30");
+ outtextxy(with.x2-7,with.y2-8,"\31");
+ }
+}
+
+void setup()
+{
+ integer gd,gm;
+ registers r;
+ byte floppies;
+
+ setactivepage(filer_page); setvisualpage(filer_page);
+ setfillstyle(1,1); bar(2,2,637,197); shadow(0,0,639,199,15,7);
+
+ settextstyle(0,0,0);
+ settextjustify(1,1);
+ for( gd=1; gd <= 2; gd ++)
+ for( gm=0; gm <= 1; gm ++)
+ shbox(420+gm*110,gd*25,520+gm*110,gd*25+20,buttons[gm*2+gd]);
+ shbox(15,182,350,196,"Help... (press f1)");
+ settextjustify(0,2); setcolor(11);
+ setcolor(15); outtextxy(15,5,"The Avvy Filer...");
+ setcolor(11); outtextxy(317,3,"Select a file to load.");
+ outtextxy(357,185,"Copyright (c) 1993, Thomas Thurman.");
+
+ /* Draw the boxes and names */
+ setcolor(3);
+ for( gm=1; gm <= 4; gm ++)
+ { windowtype& with = threewins[gm];
+ box(with.x1,with.y1,with.x2,with.y2,with.title);}
+
+ /* Draw the scroll bars. */
+
+ for( gm=3; gm <= 4; gm ++) draw_scroll_bar(gm);
+}
+
+void thumb(byte whichwin)
+{
+ word length,the_top;
+
+ if (nums[whichwin]<9)
+ {
+ length=76;
+ the_top=0;
+ } else
+ {
+ length=trunc(76*((real)(8)/nums[whichwin]));
+ the_top=trunc(((real)(where[whichwin])/nums[whichwin])*(76-length));
+ }
+
+ the_top += 93; /* Top of both the scrollbars. */
+
+ setfillstyle(1,7);
+ { windowtype& with = threewins[whichwin];
+ bar(with.x2-6,thumb_pos[whichwin],with.x2-3,thumb_pos[whichwin]+length);}
+ setfillstyle(1,1);
+ { windowtype& with = threewins[whichwin];
+ bar(with.x2-6,the_top,with.x2-3,the_top+length);}
+
+ thumb_pos[whichwin]=the_top;
+ thumb_len[whichwin]=length;
+}
+
+void quicksort(byte whichlist, integer lo, integer hi);
+
+
+static void sort(integer l, integer r, byte& whichlist)
+{
+ integer i, j;
+ varying_string<12> x, y;
+ varying_string<40> d;
+
+ i = l; j = r; x = lists[whichlist][(l+r) / 2];
+ do {
+ while (lists[whichlist][i] < x) i = i + 1;
+ while (x < lists[whichlist][j]) j = j - 1;
+ if (i <= j)
+ {
+ y = lists[whichlist][i];
+ lists[whichlist][i] = lists[whichlist][j];
+ lists[whichlist][j] = y;
+
+ d = descs[i];
+ descs[i] = descs[j];
+ descs[j] = d;
+
+ i = i + 1; j = j - 1;
+ }
+ } while (!(i > j));
+
+/* if j<1 then j:=1;
+ if r<1 then r:=1;*/
+
+ if (l < j) sort(l, j, whichlist);
+ if (i < r) sort(i, r, whichlist);
+}
+
+void quicksort(byte whichlist, integer lo, integer hi)
+
+{ /*QuickSort*/;
+ sort(lo,hi, whichlist);
+}
+
+void scandir()
+{
+ pathstr nix;
+ namestr name;
+ untyped_file f;
+ ednahead eh;
+ array<1,4,char> dna_type;
+
+
+ nums[files]=0;
+ findfirst("*.asg",archive+hidden+readonly,s);
+
+ while ((doserror==0) && (nums[files]<77))
+ {
+ fsplit(s.name,nix,name,nix);
+ nums[files] += 1;
+ lists[files][nums[files]]=lowstr(name);
+
+ assign(f,s.name);
+ reset(f,1);
+ seek(f,11);
+ blockread(f,dna_type,4);
+
+ if (dna_type=="Avvy")
+ { /* A DNA256 file. */
+ descs[nums[files]]="* Saved by Avaricius!";
+ } else
+ { /* EDNA-based files. */
+ if (dna_type=="EDNA")
+ {
+ seek(f,177);
+ blockread(f,eh,sizeof(eh));
+
+ if (eh.revision!=2)
+ descs[nums[files]]="* Unknown EDNA type!";
+ else
+ {
+
+ if (eh.number!=2)
+ descs[nums[files]]=string("% Saved by ")+eh.shortname+'!';
+ else
+ { /* Well... everything seems to have gone OK! */
+ descs[nums[files]]=eh.desc;
+ }
+ }
+ } else
+ descs[nums[files]]="* Not an Avvy saved game!";
+ }
+ close(f);
+ findnext(s);
+ }
+ nums[dirs]=0; findfirst("*.*",directory,s);
+ while ((doserror==0) && (nums[dirs]<77))
+ {
+ if (((s.attr & directory)>0) && ((length(s.name))>1))
+ {
+ nums[dirs] += 1;
+ lists[dirs][nums[dirs]]=lowstr(s.name);
+ }
+ findnext(s);
+ }
+
+ /* Now sort 'em! */
+
+ if (nums[dirs ]!=0) quicksort ( dirs,1,nums[ dirs]);
+ if (nums[files]!=0) quicksort (files,1,nums[files]);
+
+ where[dirs]=1; where[files]=1;
+ top[dirs]=1; top[files]=1;
+
+ thumb_pos[3]=93; thumb_pos[4]=93;
+}
+
+void show_file(integer x,integer y, byte which)
+{
+ varying_string<58> z;
+
+ fillchar(z[1],13,'\40');
+ z=lists[files][which]+".asg";
+ z[0]='\15'; z=z+descs[which];
+
+ if (set::of('*','%', eos).has(descs[which][1])) /* Can't load these! */
+ setcolor(red);
+ else
+ setcolor(lightcyan);
+
+ outtextxy(x,y,z);
+}
+
+void showfiles()
+{
+ byte fv;
+
+ if (loading) setcolor(11); else setcolor(3);
+ if (nums[3]==0)
+ {
+ outtextxy(22,86,"(None here!)");
+ return;
+ }
+ for( fv=0; fv <= 8; fv ++)
+ if (top[3]+fv<=nums[3])
+ show_file(19,87+fv*10,top[3]+fv);
+
+ draw_scroll_bar(files);
+}
+
+void showdirs()
+{
+ byte fv;
+
+ setcolor(11);
+ for( fv=0; fv <= 8; fv ++)
+ if (top[4]+fv<=nums[4])
+ outtextxy(497,87+fv*10,string('[')+lists[dirs][fv+top[4]]+']');
+ draw_scroll_bar(dirs);
+}
+
+void show()
+{
+ byte fv;
+ dirstr d; namestr n; extstr e;
+
+ setfillstyle(1,1);
+ for( fv=1; fv <= 4; fv ++)
+ if (fv!=2)
+ { windowtype& with = threewins[fv];
+ bar(with.x1+1,with.y1+1,with.x2-8,with.y2-1);}
+ showfiles();
+ showdirs();
+ setcolor(7); outtextxy(159,14,current);
+ for( fv=3; fv <= 4; fv ++) thumb(fv);
+}
+
+void blip()
+{
+ sound(177); delay(77); nosound;
+}
+
+void invert(integer x1,integer y1,integer x2,integer y2)
+{
+ pointer p,restore; word s;
+
+ s=imagesize(x1,y1,x2,y2);
+ mark(restore); getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+ putimage(x1,y1,p,notput);
+ release(restore);
+}
+
+void changedrive(char drive)
+{
+ byte fv;
+
+ fv=pos(drive,drives);
+ if (fv==0) { blip(); return; }
+ off();
+ fv -= 1;
+ shadow((fv % drlen)*25+25,(fv / drlen)*19+31,
+ (fv % drlen)*25+40,45+(fv / drlen)*19,8,7);
+ chdir(string(drive)+':');
+ getcurrent(); scandir(); show();
+ shadow((fv % drlen)*25+25,(fv / drlen)*19+31,
+ (fv % drlen)*25+40,45+(fv / drlen)*19,15,8);
+ on();
+}
+
+void highlight(byte win,byte line)
+{
+ switch (win) {
+ case 3: invert(16,75+line*10,470,85+line*10); break;
+ case 4: invert(491,75+line*10,620,85+line*10); break;
+ }
+ thumb(win);
+}
+
+void repaint(byte whichwindow)
+{
+ setfillstyle(1,1);
+ { windowtype& with = threewins[whichwindow];
+ bar(with.x1+1,with.y1+1,with.x2-8,with.y2-1);}
+ top[whichwindow]=where[whichwindow];
+ switch (whichwindow) {
+ case file_win: showfiles(); break;
+ case subdir_win: showdirs(); break;
+ }
+ thumb(whichwindow);
+}
+
+void fileblit(word xpos,word xlen,word y1,word y2, shortint dir, word ylen)
+{
+ word fv; byte bit;
+
+ for( bit=0; bit <= 3; bit ++)
+ {
+ fv=0;
+ while (fv<ylen)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ move(mem[0xac00*(y1+fv*dir)*80+xpos],mem[0xac00*(y2+fv*dir)*80+xpos],xlen);
+ fv += 1;
+ }
+ }
+ bit=getpixel(0,0);
+}
+
+void seekthrough(byte whichlist, byte& wherenow, char whatfor)
+{
+ byte startedat;
+
+ startedat=wherenow;
+ do {
+ wherenow += 1;
+ if (wherenow>nums[whichlist]) wherenow=1;
+ } while (!((startedat==wherenow) || (lists[whichlist][wherenow][1]==whatfor)));
+ off();
+ repaint(whichlist);
+ on();
+}
+
+void gotohome(byte whichlist)
+{
+ off();
+ where[whichlist]=1;
+ repaint(whichlist);
+ highlight(whichlist,1);
+ on();
+}
+
+void gotoend(byte whichlist)
+{
+ off();
+ where[whichlist]=nums[whichlist];
+ repaint(whichlist);
+ highlight(whichlist,1);
+ on();
+}
+
+void pageup(byte whichlist)
+{
+ off();
+ if (where[whichlist]>9)
+ {
+ where[whichlist] -= 9;
+ repaint(whichlist);
+ highlight(whichlist,1);
+ } else gotohome(whichlist);
+ on();
+}
+
+void pagedown(byte whichlist)
+{
+ off();
+ if (where[whichlist]<nums[whichlist]-9)
+ {
+ where[whichlist] += 9;
+ repaint(whichlist);
+ highlight(whichlist,1);
+ } else gotoend(whichlist);
+ on();
+}
+
+void subdirparse(string r);
+
+static void movehl(byte which, shortint howmuch)
+{
+ off();
+ highlight(4,where[4]-top[4]+1);
+ if (((where[which]+howmuch)>0) && ((where[which]+howmuch)<=(unsigned char)nums[4]))
+ where[which]=where[which]+howmuch;
+ highlight(4,where[4]-top[4]+1);
+ on();
+}
+
+
+
+static void change_dir()
+{
+ off(); dusk();
+ /*$I-*/ chdir(lists[4][where[4]]);
+ /*$I+*/
+ if (ioresult!=0) { dawn(); blip(); return; }
+ where[4]=1; top[4]=1;
+ getcurrent(); scandir(); show();
+ highlight(4,1);
+ dawn(); on();
+}
+
+void subdirparse(string r)
+
+{
+ switch (r[1]) {
+ case creturn: change_dir(); break;
+
+ case '\0': switch (r[2]) {
+ case cup: if (where[4]-top[4]>0) /* Up */
+ movehl(4,-1); /* Within range */
+ else if (top[4]>1)
+ { /* Outside range- must scroll */
+ off();
+ highlight(4,1);
+ top[4] -= 1; where[4] -= 1;
+ fileblit(61,17,166,176,-1,80);
+ setfillstyle(1,1); bar(490,85,622,95); setcolor(11);
+ outtextxy(497,87,string('[')+lists[dirs][where[4]]+']');
+ highlight(4,1);
+ on();
+ }
+ break;
+ case cdown:
+ if (where[4]-top[4]<8) /* Down */
+ movehl(4,1);
+ else if (top[4]+8<nums[4])
+ {
+ off();
+ highlight(4,9);
+ top[4] += 1; where[4] += 1;
+ fileblit(60,17,97,87,1,80);
+ setfillstyle(1,1); bar(490,165,622,175); setcolor(11);
+ outtextxy(497,167,string('[')+lists[dirs][where[4]]+']');
+ highlight(4,9);
+ on();
+ }
+ break;
+ case chome: gotohome(4); break;
+ case cend: gotoend(4); break;
+ case cpgup: pageup(4); break;
+ case cpgdn: pagedown(4); break;
+ case c_ao: change_dir(); break;
+ }
+ break;
+ default: {
+ off();
+ seekthrough(4,where[4],lowchar(r[1]));
+ highlight(4,1);
+ on();
+ }
+ }
+}
+
+void fileinfo(byte which);
+void filer_help();
+void wipe(byte which);
+
+void in_name_box(string x)
+{
+ off();
+ setfillstyle(1,1); bar(156,13,629,21);
+ setcolor(7); outtextxy(159,14,x);
+ on();
+}
+
+void filesparse(string r);
+
+static void movehl1(byte which, shortint howmuch)
+{
+ off();
+ highlight(3,where[3]-top[3]+1);
+ if (((where[which]+howmuch)>0) && ((where[which]+howmuch)<=(unsigned char)nums[3]))
+ where[which]=where[which]+howmuch;
+ highlight(3,where[3]-top[3]+1);
+ on();
+}
+
+
+
+static boolean selected_file()
+{
+ boolean selected_file_result;
+ if ((set::of('*','%', eos).has(descs[where[file_win]][1])) || (nums[3]==0))
+ {
+ blip();
+ selected_file_result=false;
+ } else
+ {
+ filename=lists[file_win][where[file_win]];
+ filefound=true;
+ selected_file_result=true;
+ }
+ return selected_file_result;
+}
+
+void filesparse(string r)
+
+{
+ switch (r[1]) {
+ case creturn: if (selected_file()) return; break;
+ case '\0': switch (r[2]) {
+ case cup: if (where[3]-top[3]>0) /* Up */
+ movehl1(3,-1); /* Within range */
+ else if (top[3]>1)
+ { /* Outside range- must scroll */
+ off();
+ highlight(3,1);
+ top[3] -= 1; where[3] -= 1;
+ fileblit(1,58,166,176,-1,80);
+ setfillstyle(1,1); bar( 15,85,472,95);
+ show_file( 19,87,where[3]);
+ highlight(3,1);
+ on();
+ }
+ break;
+ case cdown: if (where[3]-top[3]<8) /* Down */
+ movehl1(3,1);
+ else if (top[3]+8<nums[3])
+ {
+ off();
+ highlight(3,9);
+ top[3] += 1; where[3] += 1;
+ fileblit(1,58,97,87,1,80);
+ setfillstyle(1,1); bar( 15,165,472,175);
+ show_file( 19,167,where[3]);
+ highlight(3,9);
+ on();
+ }
+ break;
+ case c_ai: fileinfo(where[3]); break; /* alt-I: information. */
+ case c_aw: wipe(where[3]); break; /* alt-W: wipe. */
+ case chome: gotohome(3); break;
+ case cend: gotoend(3); break;
+ case cpgup: pageup(3); break;
+ case cpgdn: pagedown(3); break;
+ case c_ao: if (selected_file()) return; break;
+ }
+ break;
+ default: {
+ off();
+ seekthrough(3,where[3],lowchar(r[1]));
+ highlight(3,1);
+ on();
+ }
+ }
+ in_name_box(lists[files][where[3]]+".asg");
+}
+
+void entername(char r)
+{
+ switch (r) {
+ case '\10': if (filename[0]!='\0') filename[0] -= 1; break;
+ case '\15': filefound=true; break;
+ case '\40':; break; /* ignore spaces. */
+ default:
+ {
+ if (length(filename)<55) filename=filename+r;
+
+ if (length(filename)==1)
+ {
+ where[3]=1;
+ seekthrough(3,where[3],filename[1]);
+ }
+ }
+ }
+
+ in_name_box(filename+".asg");
+
+}
+
+void changewin(byte i)
+{
+ off();
+ switch (nowwin) {
+ case 3:case 4: highlight(nowwin,where[nowwin]-top[nowwin]+1); break;
+ }
+ setcolor(3); { windowtype& with = threewins[nowwin]; box(with.x1,with.y1,with.x2,with.y2,with.title);}
+ nowwin=i;
+ if (nowwin<1) nowwin=4; if (nowwin>4) nowwin=1;
+ switch (nowwin) {
+ case 3:case 4: highlight(nowwin,where[nowwin]-top[nowwin]+1); break;
+ }
+ on();
+}
+
+void checkmouse();
+
+static void relevant(string x)
+{
+ setcolor(14); off(); { windowtype& with = threewins[nowwin]; box(with.x1,with.y1,with.x2,with.y2,with.title);}
+ on(); if (nowwin==3) filesparse(x); else subdirparse(x);
+}
+
+void checkmouse()
+{
+ byte fv,new,waswin;
+
+ check();
+ if (mrelease>0)
+ { /* Where did they click? */
+ for( fv=1; fv <= 4; fv ++)
+ { windowtype& with = threewins[fv];
+ if (((cardinal)with.x1<=mx) && ((cardinal)with.x2>=mx) && ((cardinal)with.y1<=my) && ((cardinal)with.y2>=my))
+ {
+ waswin=nowwin;
+
+ if (nowwin!=fv)
+ {
+ changewin(fv);
+ off();
+ setcolor(14); { windowtype& with1 = threewins[nowwin]; box(with1.x1,with1.y1,with1.x2,with1.y2,with1.title);}
+ on();
+ }
+ /* Now... individual windows should do their own checkclicking. */
+
+ switch (fv) {
+ /* 1: no effect. */
+ case 2: changedrive(which_drive(mx,my)); break; /* Change drive w/mouse. */
+ case 3:case 4: if (my<175) { /* Click on highlight users. */
+ if (mx>(cardinal)threewins[nowwin].x2-9)
+ { /* Scroll bar. */
+ if (my<(cardinal)threewins[nowwin].y1+10)
+ relevant(null+cup); /* scroll up */
+ else if (my>(cardinal)threewins[nowwin].y2-10)
+ relevant(null+cdown); /* scroll down. */
+ else if (my<(unsigned char)thumb_pos[nowwin])
+ relevant(null+cpgup); /* above thumb-- page up. */
+ else if (my>(unsigned char)thumb_pos[nowwin]+thumb_len[nowwin])
+ relevant(null+cpgdn); /* above thumb-- page up. */
+ else { /* On the thumb. */
+ blip();
+ }
+ } else
+ {
+ new=top[fv]+(my-75) / 10-1;
+
+ if ((new==where[fv]) && (nowwin==waswin))
+ { /* Double-clicked, --> "OK" */
+ /* filefound:=true;
+ filename:=lists[fv,new];*/
+ if (fv==3) filesparse("\15"); else subdirparse("\15");
+ } else
+ { /* Single-clicked, --> move highlight */
+ off();
+ highlight(fv,where[fv]-top[fv]+1);
+ if ((new>0) && (new<=nums[fv]))
+ where[fv]=new;
+ highlight(fv,where[fv]-top[fv]+1);
+ on();
+ }
+ }
+ }
+ break;
+ }
+
+ return; /* Since they've clicked in a window... */
+ }}
+
+ /* Righto, they must have clicked on a button. Which? */
+
+ switch (my) {
+ case 25 ... 45: /* Top row: Okay, Cancel. */
+ switch (mx) {
+ case 420 ... 520: switch (nowwin) {
+ case 1: entername('\15'); break;
+ case 3: filesparse("\15"); break;
+ case 4: subdirparse("\15"); break;
+ default: blip();
+ }
+ break;
+ case 530 ... 630: cancelled=true; break;
+ }
+ break;
+ case 50 ... 95: /* Bottom row: Wipe, Info. */
+ switch (mx) {
+ case 420 ... 520: if (nowwin==3) wipe(where[3]); else blip(); break;
+ case 530 ... 630: if (nowwin==3) fileinfo(where[3]); else blip(); break;
+ }
+ break;
+ case 180 ... 200: filer_help(); break; /* The "help" button. */
+ }
+ }
+}
+
+string playaround()
+{
+ char r,r2;
+
+ string playaround_result;
+ filefound=false; dawn();
+
+ do {
+ setcolor(14); off(); { windowtype& with = threewins[nowwin]; box(with.x1,with.y1,with.x2,with.y2,with.title);} on();
+ do { checkmouse(); } while (!(keypressed() || filefound || cancelled));
+ if (! (filefound || cancelled))
+ {
+ r=readkey();
+ switch (r) {
+ case ctab: changewin(nowwin+1); break;
+ case cescape: {
+ playaround_result="";
+ return playaround_result;
+ }
+ break;
+ case '\0': { /* parse extd keystroke */
+ r2=readkey();
+ switch (r2) {
+ case cs_tab: changewin(nowwin-1); break;
+ case c_an: changewin(1); break;
+ case c_ad: changewin(2); break;
+ case c_af: changewin(3); break;
+ case c_as: changewin(4); break;
+ case c_ac: cancelled=false; break;
+ case c_ah:case cf1: filer_help(); break; /* alt-H: help. */
+ default:
+ switch (nowwin) {
+ case 3: filesparse(string('\0')+r2); break;
+ case 4: subdirparse(string('\0')+r2); break;
+ }
+ }
+ }
+ break;
+ default:
+ { /* Pass keystroke to current window */
+ switch (nowwin) {
+ case 1: entername(r); break;
+ case 2: changedrive(upcase(r)); break;
+ case 4: subdirparse(r); break;
+ case 3: filesparse(r); break;
+ default: blip();
+ }
+ }
+ }
+
+ }
+
+ if (filefound)
+ {
+ dusk();
+ playaround_result=filename;
+ return playaround_result;
+ }
+
+ if (cancelled)
+ {
+ dusk();
+ playaround_result="";
+ return playaround_result;
+ }
+ } while (!false);
+ return playaround_result;
+}
+
+void drawup()
+{
+ off();
+ loading=true;
+ setup();
+ show(); show_drives();
+ on();
+}
+
+void little_cls()
+{
+ setfillstyle(1,1); bar(2,2,637,197); /* Interesting information coming up! */
+}
+
+void wait_for_keypress_or_mouse_click()
+{
+ char r;
+
+ do { check(); } while (!((mrelease>0) || keypressed()));
+ while (keypressed()) r=readkey();
+}
+
+void fileinfo(byte which);
+
+
+static void display(integer y, string left,string right)
+{
+ y=17+y*12;
+ settextjustify(2,1); setcolor(11); outtextxy(315,y,left);
+ settextjustify(0,1); setcolor(15); outtextxy(325,y,right);
+}
+
+void fileinfo(byte which)
+ /* This gives information on the file whose name is in lists[files,which]. */
+{
+ ednahead eh;
+ untyped_file f;
+ varying_string<4> os;
+
+
+
+ /* Firstly, we must check whether or not it's an Avalot file. This is easily
+ done, since the descriptions of all others always begin with a star. */
+
+ if ((descs[which][1]=='*') || (nums[3]==0))
+ { /* it is. */
+ blip(); /* Naaaarghh! */
+ return;
+ }
+
+ /* Anyway... it wasn't. */
+
+ assign(f,lists[files][which]+".asg");
+ reset(f,1);
+ seek(f,177);
+ blockread(f,eh,sizeof(eh));
+ close(f);
+
+ /* We now hold its EDNA record. */
+
+ off();
+ little_cls(); /* Interesting information coming up! */
+
+ {
+ display(0,"File:",eh.fn);
+ display(1,"Description:",eh.desc);
+ display(2,"Saved by:", eh.game);
+ display(3,"version:", eh.verstr);
+
+ display(4,"under", eh.os);
+
+ display(6,"Saved on:",strf(eh.d)+'-'+strf(eh.m)+'-'+strf(eh.y));
+
+ display(9,"No. of times saved:",strf(eh.saves));
+
+ display(11,"Money:",eh.money);
+ display(12,"Score:",strf(eh.points));
+ }
+
+ settextjustify(1,1);
+ shbox(400,177,600,195,"[Press any key...]");
+ settextjustify(0,2); on();
+ wait_for_keypress_or_mouse_click();
+
+ off(); setfillstyle(1,1); bar(2,2,637,197);
+ drawup();
+ off(); highlight(3,where[3]-top[3]+1); on();
+}
+
+void filer_help()
+ /* Just some general help... */
+
+{
+ off(); little_cls();
+
+ setcolor(15);
+ outtextxy(10, 10,"To change to a particular pane:");
+ outtextxy(10, 50,"To choose a file:");
+ outtextxy(10,100,"To change drives:");
+ outtextxy(10,140,"Finally...");
+
+ setcolor(14);
+ outtextxy(20, 20,"Press Alt and the initial letter simultaneously.");
+ outtextxy(20, 30,"(e.g. to change to the Name pane, press Alt-N.)");
+ outtextxy(20, 60,"Either type its name in the Name pane or choose it");
+ outtextxy(20, 70,"from the list in the Files pane. You may either use");
+ outtextxy(20, 80,"a mouse or the keyboard to do this.");
+ outtextxy(20,110,"Move into the Drives pane and press the letter of the");
+ outtextxy(20,120,"drive you want.");
+ outtextxy(20,150,"Either select OK to load the file, or Cancel to back out.");
+
+ settextjustify(1,1);
+ shbox(400,177,600,195,"[Press any key...]");
+ settextjustify(0,2); on();
+ wait_for_keypress_or_mouse_click();
+
+ off(); setfillstyle(1,1); bar(2,2,637,197);
+ drawup(); off();
+ if (set::of(3,4, eos).has(nowwin)) highlight(nowwin,where[nowwin]-top[nowwin]+1);
+ on();
+}
+
+void wipe(byte which)
+ /* This wipes the file whose name is in lists[files,which]. */
+{
+ char r;
+ untyped_file f;
+
+
+ off(); little_cls();
+
+ settextjustify(1,1);
+ outtextxy(320,100,string("Are you sure you want to delete \"")+
+ lists[files][which]+".asg\"?");
+ shbox(400,177,600,195,"[Y/N]");
+
+ do {
+ r=upcase(readkey());
+ if (r=='Y')
+ {
+ assign(f,lists[files][which]+".asg"); /*$I-*/ erase(f); /*$I+*/
+
+ setcolor(14);
+ if (ioresult==0)
+ {
+ scandir();
+ outtextxy(100,140,"Deleted.");
+ } else
+ outtextxy(100,140,"Not deleted (some problem...)");
+
+ shbox(400,177,600,195,"[Press any key...]");
+ on();
+ wait_for_keypress_or_mouse_click(); off();
+ }
+ } while (!(set::of('Y','N', eos).has(r)));
+
+ settextjustify(0,2); setcolor(14);
+ setfillstyle(1,1); bar(2,2,637,197);
+ drawup();
+ off(); highlight(3,where[3]-top[3]+1); on();
+}
+
+string do_filer()
+{
+ pathstr p; byte groi; dirstr original_directory;
+
+ string do_filer_result;
+ getdir(0,original_directory);
+ dusk();
+ oncandopageswap=false; cancelled=false;
+ copypage(3,1-cp); /* Store old screen. */ groi=getpixel(0,0);
+ off();
+
+ firstsetup();
+ scandir();
+ nowwin=1; getcurrent();
+ firstsetup(); drawup();
+ on();
+ mousepage(filer_page);
+
+ p=playaround();
+ if (p!="") p=fexpand(p+".ASG");
+ do_filer_result=p;
+ filename="";
+
+ mousepage(cp);
+ dusk(); off();
+ oncandopageswap=true;
+ copypage(1-cp,3); /* Restore old screen. */ groi=getpixel(0,0);
+ on_virtual(); dawn(); fix_flashers();
+
+ setvisualpage(cp);
+ setactivepage(1-cp);
+ chdir(original_directory);
+
+ return do_filer_result;
+}
+
+
diff --git a/engines/avalanche/fileunit.h b/engines/avalanche/fileunit.h
new file mode 100644
index 0000000000..08f9262653
--- /dev/null
+++ b/engines/avalanche/fileunit.h
@@ -0,0 +1,7 @@
+#ifndef __fileunit_h__
+#define __fileunit_h__
+
+
+string do_filer(); /* Result is filename, or "" if cancelled. */
+
+#endif
diff --git a/engines/avalanche/filing.cpp b/engines/avalanche/filing.cpp
new file mode 100644
index 0000000000..f990f8c338
--- /dev/null
+++ b/engines/avalanche/filing.cpp
@@ -0,0 +1,144 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ FILING The saving and loading handler. */
+
+
+/*$R+*/
+
+/*interface*/
+
+/*#include "Gyro.h"*/
+
+
+const array<1,12,varying_string<6> > months =
+ {{"Jan*","Feb*","March","April","May","June","July","August",
+ "Sept&","Oct&","Nov&","Dec&"}};
+const string ednaid = string("TT")+'\261'+'\36'+'\1'+'\113'+'\261'+'\231'+'\261';
+const array<1,6,varying_string<7> > systems =
+ {{"DOS","Windows","OS/2","Mac","Amiga","ST"}};
+
+struct edhead { /* Edna header */
+ /* This header starts at byte offset 177 in the .ASG file. */
+ array<1,9,char> id; /* signature */
+ word revision; /* EDNA revision, here 2 (1=dna256) */
+ varying_string<50> game; /* Long name, eg Lord Avalot D'Argent */
+ varying_string<15> shortname; /* Short name, eg Avalot */
+ word number; /* Game's code number, here 2 */
+ word ver; /* Version number as integer (eg 1.00 = 100) */
+ varying_string<5> verstr; /* Vernum as string (eg 1.00 = "1.00" */
+ varying_string<12> filename; /* Filename, eg AVALOT.EXE */
+ byte os; /* Saving OS (here 1=DOS). See below for others.*/
+
+ /* Info on this particular game */
+
+ varying_string<8> fn; /* Filename (not extension ('cos that's .ASG)) */
+ byte d,m; /* D, M, Y are the Day, Month & Year this game was... */
+ word y; /* ...saved on. */
+ varying_string<40> desc; /* Description of game (same as in Avaricius!) */
+ word len; /* Length of DNA (it's not going to be above 65535!) */
+
+ /* Quick reference & miscellaneous */
+
+ word saves; /* no. of times this game has been saved */
+ integer cash; /* contents of your wallet in numerical form */
+ varying_string<20> money; /* ditto in string form (eg 5/-, or 1 denarius)*/
+ word points; /* your score */
+
+ /* DNA values follow, then footer (which is ignored) */
+};
+ /* Possible values of edhead.os:
+ 1 = DOS 4 = Mac
+ 2 = Windows 5 = Amiga
+ 3 = OS/2 6 = ST */
+
+/*implementation*/
+
+untyped_file f;
+byte fv;
+array<1,255,word> dna256;
+boolean ok;
+edhead e;
+
+void info256(string x) /* info on dna256 *.ASG files */
+{
+ varying_string<40> describe;
+;
+ assign(f,x);
+ /*$I-*/ reset(f,1);
+ seek(f,47);
+ blockread(f,describe,40);
+ blockread(f,dna256,sizeof(dna256));
+ close(f); /*$I+*/
+ {;
+ e.revision=1;
+ e.game="Denarius Avaricius Sextus";
+ e.shortname="Avaricius";
+ e.number=1;
+ e.verstr="[?]";
+ e.filename="AVVY.EXE";
+ e.os=1; /* Dos */
+ e.fn=x;
+ e.d=dna256[7]; e.m=dna256[8]; e.y=dna256[9];
+ e.desc=describe;
+ e.len=512;
+ e.saves=dna256[6];
+ e.cash=dna256[30];
+ e.money=strf(e.cash)+" denari";
+ if (e.cash==1) e.money=e.money+"us"; else e.money=e.money+'i';
+ e.points=dna256[36];
+ }
+}
+
+string enlarge(string x)
+{string enlarge_result;
+;
+ switch (x[length(x)]) {
+ case '*': {; x[0] -= 1; x=x+"uary"; } break;
+ case '&': {; x[0] -= 1; x=x+"ember"; } break;
+ }
+ enlarge_result=x;
+return enlarge_result;
+}
+
+string th(byte x)
+{
+ varying_string<4> n;
+string th_result;
+;
+ n=strf(x);
+ switch (x) {
+ case 1:case 21:case 31: n=n+"st"; break;
+ case 2:case 22: n=n+"nd"; break;
+ case 3:case 23: n=n+"rd"; break;
+ default: n=n+"th";
+ }
+ th_result=n;
+return th_result;
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ info256("t:justb4.asg");
+
+ {;
+ output << "DNA coding: ";
+ switch (e.revision) {
+ case 1: output << "dna256" << NL; break;
+ case 2: output << "E.D.N.A." << NL; break;
+ default: output << "Unknown!" << NL;
+ }
+ output << "Filename: " << e.game << " (version " << e.verstr << ')' << NL;
+ output << "Description: " << e.desc << NL;
+ output << "Cash: " << e.money << NL;
+ output << "Score: " << e.points << NL;
+ output << "Date: " << th(e.d) << ' ' << enlarge(months[e.m]) << ' ' << e.y << NL;
+ output << "Number of saves: " << e.saves << NL;
+ }
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/folktemp.cpp b/engines/avalanche/folktemp.cpp
new file mode 100644
index 0000000000..c715aa9936
--- /dev/null
+++ b/engines/avalanche/folktemp.cpp
@@ -0,0 +1,79 @@
+#include "ptoc.h"
+
+ /* Get 'em back! */
+#include "graph.h"
+
+
+const integer picsize = 966;
+const integer number_of_objects = 19;
+
+const array<1,65,char> thinks_header =
+ string("This is an Avalot file, which is subject to copyright. Have fun.")+'\32';
+
+const array<0,19,byte> order =
+ {{ 4, 19, 1, 18, 15, 9, 12, 13, 17, 10, 2, 6, 3, 5, 7, 14,
+ 16,
+
+ 0, 11, 8}};
+
+/*
+ pAvalot=#150; pSpludwick=#151; pCrapulus=#152; pDrDuck=#153;
+ pMalagauche=#154; pFriarTuck=#155; pRobinHood=#156; pCwytalot=#157;
+ pduLustie=#158; pDuke=#159; pDogfood=#160; pTrader=#161;
+ pIbythneth=#162; pAyles=#163; pPort=#164; pSpurge=#165;
+ pJacques=#166;
+
+ pArkata=#175; pGeida=#176; pWiseWoman=#178;
+*/
+
+integer gd,gm;
+untyped_file f;
+pointer p;
+byte noo;
+
+void load()
+{
+ byte a0 /*absolute $A000:1200*/;
+ byte bit;
+ untyped_file f;
+;
+ assign(f,"d:folk.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f); bit=getpixel(0,0);
+}
+
+void get_one()
+{;
+
+ gd=((order[noo] % 9)*70+10);
+ gm=((order[noo] / 9)*40+20);
+
+ getimage(gd,gm,gd+59,gm+29,p);
+ putimage(gd,gm,p,notput);
+ blockwrite(f,p,picsize);
+
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+
+ load(); noo=0;
+
+ assign(f,"folk.avd");
+ getmem(p,picsize);
+ rewrite(f,1);
+ blockwrite(f,thinks_header,65);
+
+ for( noo=0; noo <= number_of_objects; noo ++)
+ get_one();
+
+ close(f); freemem(p,picsize);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/fontslid.cpp b/engines/avalanche/fontslid.cpp
new file mode 100644
index 0000000000..4a2ceb21c6
--- /dev/null
+++ b/engines/avalanche/fontslid.cpp
@@ -0,0 +1,25 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+
+typedef matrix<'\0','\377',0,15,byte> fonttype;
+
+fonttype font1;
+byte fv;
+char r;
+file<fonttype> f;
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ assign(f,"v:avalot.fnt"); reset(f); f >> font1; close(f);
+ for( r='\0'; r <= '\377'; r ++)
+ {;
+ for( fv= 0; fv <= 3; fv ++) font1[r][fv]=(cardinal)font1[r][fv] >> 1;
+ for( fv= 7; fv <= 8; fv ++) font1[r][fv]=font1[r][fv] << 1;
+ for( fv= 9; fv <= 14; fv ++) font1[r][fv]=font1[r][fv] << 2;
+ }
+ assign(f,"v:avitalic.fnt"); rewrite(f); f << font1; close(f);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/frere.cpp b/engines/avalanche/frere.cpp
new file mode 100644
index 0000000000..b3118ddd1d
--- /dev/null
+++ b/engines/avalanche/frere.cpp
@@ -0,0 +1,102 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+
+
+typedef array<1,31,byte> tunetype;
+
+const integer lower = 0;
+ const integer same = 1;
+const integer higher = 2;
+
+const array<1,12,char> keys = "QWERTYUIOP[]";
+const array<1,12,word> notes =
+{{196,220,247,262,294,330,350,392,440,494,523,587}};
+
+const tunetype tune =
+{{higher,higher,lower,same,higher,higher,lower,higher,higher,higher,
+ lower,higher,higher,
+ same,higher,lower,lower,lower,lower,higher,higher,lower,lower,lower,
+ lower,same,lower,higher,same,lower,higher}};
+
+byte this_one,last_one;
+
+char pressed;
+
+byte value;
+
+tunetype played;
+
+void store_(byte what)
+{;
+
+ move(played[2],played[1],sizeof(played)-1);
+
+ played[31]=what;
+
+}
+
+boolean they_match()
+{
+ byte fv;
+boolean they_match_result;
+;
+
+ for( fv=1; fv <= sizeof(played); fv ++)
+ if (played[fv]!=tune[fv])
+ {;
+ they_match_result=false;
+ return they_match_result;
+ }
+
+ they_match_result=true;
+
+return they_match_result;
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+
+ textattr=30; clrscr; output << NL;
+
+ do {
+
+ pressed=upcase(readkey());
+
+ value=pos(pressed,keys);
+
+ if (value>0)
+ {;
+
+ last_one=this_one;
+ this_one=value;
+
+ sound(notes[this_one]);
+ delay(100);
+ nosound;
+
+ if (this_one<last_one)
+ store_(lower); else
+
+ if (this_one==last_one)
+ store_(same); else
+
+ store_(higher);
+
+ if (they_match())
+ {;
+ textattr=94; clrscr; output << NL;
+ output << string('\7')+"It matches!" << NL;
+ input >> NL;
+ exit(0);
+ }
+
+ }
+
+ } while (!(pressed=='\33'));
+
+ output << "*** PROGRAM STOPPED! ***" << NL;
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/g-room.cpp b/engines/avalanche/g-room.cpp
new file mode 100644
index 0000000000..fc8f47ec51
--- /dev/null
+++ b/engines/avalanche/g-room.cpp
@@ -0,0 +1,413 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+/*$R+*/
+
+const array<1,5,shortint> adjustment = {{7,0,7,7,7}};
+
+const array<0,3,byte> plane_to_use = {{2,2,2,3}};
+
+const array<1,5,byte> waveorder = {{5,1,2,3,4}};
+
+const array<1,26,byte> glerkfade =
+ {{1,1,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,4,4,3,3,3,2,2,1}};
+
+const array<1,18,byte> greldetfade = {{1,2,3,4,5,6,6,6,5,5,4,4,3,3,2,2,1,1}};
+
+enum flavourtype {ch_ega,ch_bgi,ch_natural,ch_two,ch_one, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+};
+
+typedef array<1,6,0,3,0,34,1,9,byte> glerktype;
+
+
+untyped_file f;
+chunkblocktype cb;
+array<1,5,2,3,0,65,0,25,byte> ghost;
+byte fv;
+pointer memlevel;
+byte y,yy,bit,xofs;
+
+array<0,1,pointer> eyes;
+pointer exclamation;
+array<1,6,pointer> aargh;
+array<1,3,pointer> bat;
+glerktype* glerk;
+array<1,5,pointer> green_eyes;
+matrix<1,6,false,true,pointer> greldet;
+
+array<1,6,pointtype> aargh_where;
+
+integer gd,gm; boolean gb;
+
+byte glerkstage;
+
+integer bat_x,bat_y; word bat_count; shortint aargh_count;
+
+integer greldet_x,greldet_y; byte greldet_count; boolean red_greldet;
+
+void plain_grab()
+ /* Just grabs the next one and puts it where it's told to. */
+{
+ integer xx,yy,xofs;
+;
+ blockread(f,cb,sizeof(cb));
+
+ switch (cb.flavour) {
+ case ch_one: {;
+ xofs=cb.x / 8;
+ bit=3;
+ for( yy=0; yy <= cb.yl; yy ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4;
+ port[0x3c5]=1 << bit; port[0x3cf]=bit;
+
+ blockread(f,mem[0xa000*(yy+cb.y)*80+xofs],cb.xl / 8);
+ }
+ }
+ break;
+ case ch_ega: {;
+ xofs=cb.x / 8;
+ bit=3;
+ for( bit=0; bit <= 3; bit ++)
+ for( yy=0; yy <= cb.yl; yy ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4;
+ port[0x3c5]=1 << bit; port[0x3cf]=bit;
+
+ blockread(f,mem[0xa000*(yy+cb.y)*80+xofs],cb.xl / 8);
+ }
+ }
+ break;
+ }
+}
+
+void get_me(pointer& p)
+{;
+ blockread(f,cb,sizeof(cb));
+ /* Take it for granted that cb.flavour = ch_BGI! */
+
+ {;
+ getmem(p,cb.size);
+ blockread(f,p,cb.size);
+ }
+}
+
+void get_me_aargh(byte which)
+{;
+ blockread(f,cb,sizeof(cb));
+ /* Take it for granted that cb.flavour = ch_BGI! */
+
+ {;
+ getmem(aargh[which],cb.size);
+ blockread(f,aargh[which],cb.size);
+ }
+
+ {
+ pointtype& with = aargh_where[which];
+
+ with.x=cb.x;
+ with.y=cb.y;
+ }
+}
+
+void wait(word how_long)
+{
+ word i; char r;
+
+ for( i=1; i <= how_long; i ++)
+ if (keypressed())
+ {
+ sound(6177);
+ while (keypressed()) r=readkey();
+ delay(1);
+ nosound;
+ } else
+ delay(1);
+}
+
+void do_bat();
+static byte batimage;
+static pointtype batsize;
+
+static void super_blank()
+{
+ pointtype oldsize;
+
+ move(bat[batimage-1],oldsize,4);
+ bar(bat_x+batsize.x,bat_y,bat_x+oldsize.x,bat_y+oldsize.y);
+}
+
+void do_bat()
+{
+ shortint dx,iy;
+
+ bat_count += 1;
+
+ if (odd(bat_count))
+ {
+ switch (bat_count) {
+ case 1 ... 90: { dx=2; iy=1; batimage=1; } break;
+ case 91 ... 240: { dx=1; iy=1; batimage=2; } break;
+ case 241 ... 260: { dx=1; iy=4; batimage=3; } break;
+ }
+
+ move(bat[batimage],batsize,4);
+
+ if ((bat_count==91) || (bat_count==241))
+ super_blank(); /* When the bat changes, blank out the old one. */
+
+ bar(bat_x,bat_y,bat_x+batsize.x,bat_y+iy);
+ bar(bat_x+batsize.x,bat_y,bat_x+batsize.x-dx,bat_y+batsize.y);
+
+ bat_x -= dx; bat_y += 1;
+ putimage(bat_x,bat_y,bat[batimage],0);
+ }
+}
+
+void big_green_eyes(byte how)
+{
+ putimage(330,103,green_eyes[how],0);
+ putimage(376,103,green_eyes[how],0);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ if (paramstr(1)!="jsb") exit(255);
+ gd=3; gm=0; initgraph(gd,gm,"");
+ fillchar(ghost,sizeof(ghost),'\0');
+
+ assign(f,"spooky.avd");
+ reset(f,1);
+ seek(f,44);
+
+ mark(memlevel);
+
+ for( fv=1; fv <= 5; fv ++)
+ {;
+ blockread(f,cb,sizeof(cb));
+ for( bit=2; bit <= 3; bit ++)
+ for( y=0; y <= cb.yl; y ++)
+ blockread(f,ghost[fv][bit][y],cb.xl / 8);
+ }
+
+ get_me(eyes[0]); /* Get BGI-based ones */
+ get_me(eyes[1]);
+ get_me(exclamation);
+
+ plain_grab(); /* Grabs to screen (cobweb) */
+ plain_grab(); /* Grabs to screen (Mark's signature) */
+ plain_grab(); /* Grabs to screen (open door) */
+
+ for( fv=1; fv <= 3; fv ++)
+ get_me(bat[fv]);
+
+/* new(glerk);
+ for fv:=1 to 5 do { Grab the Glerk. }
+ begin;
+ blockread(f,cb,sizeof(cb));
+ for bit:=0 to 3 do
+ for y:=0 to 34 do
+ blockread(f,glerk^[fv,bit,y],cb.xl div 8);
+ inc(gd,gm);
+ end;
+*/
+
+ glerk = new glerktype;
+
+ for( fv=1; fv <= 6; fv ++)
+ {;
+ blockread(f,cb,sizeof(cb));
+ bit=3;
+ for( bit=0; bit <= 3; bit ++)
+ for( yy=0; yy <= cb.yl; yy ++)
+/* begin;
+ port[$3c4]:=2; port[$3ce]:=4;
+ port[$3C5]:=1 shl bit; port[$3CF]:=bit;*/
+
+ blockread(f,(*glerk)[fv][bit][yy],cb.xl / 8);
+/* move(glerk^[fv,bit,yy],mem[$A000:yy*80+177],xl div 8);*/
+/* blockread(f,mem[$A000:yy*80+177],xl div 8);*/
+
+/* end;*/
+ }
+
+ for( fv=1; fv <= 6; fv ++) get_me_aargh(fv);
+ for( fv=1; fv <= 5; fv ++) get_me(green_eyes[fv]);
+ for( gb=false; gb <= true; gb ++)
+ for( fv=1; fv <= 6; fv ++) get_me(greldet[fv][gb]);
+
+ close(f);
+
+ /* Avvy walks over... */
+
+ setfillstyle(1,0);
+ glerkstage=0; bat_x=277; bat_y=40; bat_count=0;
+
+ for( gd=500; gd >= 217; gd --)
+ {;
+ if (set::of(range(22,27), eos).has((gd % 30)))
+ {;
+ if ((gd % 30)==27) bar(gd,135,gd+16,136);
+ putimage(gd,136,eyes[0],0);
+ putpixel(gd+16,137,0);
+ } else
+ {;
+ if (gd % 30==21) bar(gd,137,gd+17,138);
+
+ putimage(gd,135,eyes[0],0);
+ putpixel(gd+16,136,0); /* eyes would leave a trail 1 pixel high behind them */
+ }
+
+ /* Plot the Glerk: */
+ if (gd % 10==0)
+ {;
+ glerkstage += 1;
+ if (glerkstage>26) flush();
+
+ for( gm=0; gm <= 34; gm ++)
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4;
+ port[0x3c5]=1 << bit; port[0x3cf]=bit;
+
+ move((*glerk)[glerkfade[glerkstage]][bit][gm],
+ mem[0xa000*1177+gm*80],9);
+ }
+ bit=getpixel(0,0);
+ }
+
+ do_bat();
+
+ wait(15);
+ }
+
+ setfillstyle(1,0);
+ bar(456,14,530,50);
+
+ /* It descends... */
+
+ for( gm=-64; gm <= 103; gm ++)
+ {;
+ bit=getpixel(0,0);
+
+ if (gm>0)
+ fillchar(mem[0xa000*(gm-1)*80],26,'\0');
+
+ for( y=0; y <= 65; y ++)
+ if ((y+gm)>=0)
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4;
+ port[0x3c5]=1 << bit; port[0x3cf]=bit;
+
+ move(ghost[2+(abs(gm / 7) % 2)*3][plane_to_use[bit]][y],
+ mem[0xa000*(y+gm)*80],26);
+ }
+
+ wait(27);
+ }
+
+ /* And waves... */
+
+ aargh_count=-14;
+
+ for( gd=1; gd <= 4; gd ++)
+ for( fv=1; fv <= 5; fv ++)
+ {;
+
+ y=getpixel(0,0);
+
+ for( y=0; y <= 7; y ++)
+ fillchar(mem[0xa000*7760+y*80],26,'\0');
+
+ for( y=0; y <= 65; y ++)
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4;
+ port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ move(ghost[waveorder[fv]][plane_to_use[bit]][y],
+ mem[0xa000*7760+(y+adjustment[fv])*80],26);
+ }
+
+ aargh_count += 1;
+
+ if (aargh_count>0)
+ { pointtype& with = aargh_where[aargh_count];
+ putimage(with.x,with.y,aargh[aargh_count],0);}
+
+ wait(177);
+ }
+
+ /* ! appears */
+
+ gd=getpixel(0,0);
+ putimage(246,127,exclamation,0);
+ wait(777);
+ bar(172, 78,347,111); /* erase "aargh" */
+
+ for( gm=5; gm >= 1; gm --)
+ {
+ wait(377);
+ big_green_eyes(gm);
+ }
+ bar(246,127,251,133); /* erase the "!" */
+
+ /* He hurries back. */
+
+ glerkstage=1; greldet_count=18; red_greldet=false;
+
+ for( gd=217; gd <= 479; gd ++)
+ {;
+ if (set::of(range(22,27), eos).has((gd % 30)))
+ {;
+ if ((gd % 30)==22)
+ bar(gd+22,134,gd+38,137);
+ putimage(gd+23,136,eyes[1],0);
+ putpixel(gd+22,137,0);
+ } else
+ {;
+ if (gd % 30==28)
+ bar(gd+22,135,gd+38,138);
+
+ putimage(gd+23,135,eyes[1],0);
+ putpixel(gd+22,136,0); /* eyes would leave a trail 1 pixel high behind them */
+ }
+
+ /* Plot the Green Eyes: */
+ if (gd % 53==5)
+ {;
+ big_green_eyes(glerkstage);
+ glerkstage += 1;
+ }
+
+ /* Plot the Greldet: */
+
+ if (greldet_count==18)
+ { /* A new greldet. */
+ greldet_x=Random(600);
+ greldet_y=Random(80);
+ greldet_count=0;
+ red_greldet=! red_greldet;
+ }
+
+ greldet_count += 1;
+ putimage
+ (greldet_x,greldet_y,greldet[greldetfade[greldet_count]][red_greldet],0);
+
+ wait(10);
+ }
+
+ release(memlevel);
+ closegraph();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/golden.cpp b/engines/avalanche/golden.cpp
new file mode 100644
index 0000000000..009a828e0a
--- /dev/null
+++ b/engines/avalanche/golden.cpp
@@ -0,0 +1,437 @@
+#include "ptoc.h"
+
+
+/*$I c:\sleep5\DSMI.INC*/ #include "graph.h"
+/*#include "Crt.h"*/
+
+
+const varying_string<255> song =
+string("Golden slumbers kiss your eyes/Smiles awake you when you rise/")+
+"Sleep, pretty Baron, do not cry/And I will sing a lullaby.%Care you "+
+"know not, therefore sleep/While I o'er you watch do keep;/Sleep now, "+
+"du Lustie, do not cry/And I will leave the castle.*Bye!";
+
+const integer scardcount = 13;
+
+const array<0,scardcount-1,integer> soundcards =
+ {{1,2,6,3,4,5,8,9,10,7,7,7,7}};
+
+const array<1,5,byte> holding =
+{{ 24, /* 0 : 24 */
+64, /* 1 : 00 */
+128, /* 2 : 00 */
+152, /* 2 : 24 */
+170}}; /* 2 : 42 */
+
+integer gd,gm;
+byte fv;
+word* skellern;
+word s,o;
+boolean firstverse;
+word nexthangon;
+
+boolean nomusic;
+
+integer getsoundhardware(psoundcard scard)
+{
+ integer sc,i,autosel,select;
+ char ch;
+ integer e;
+
+
+
+integer getsoundhardware_result;
+Lagain:
+ sc=detectgus(scard);
+ if (sc!=0) sc=detectpas(scard);
+ if (sc!=0) sc=detectaria(scard);
+ if (sc!=0) sc=detectsb(scard);
+
+ /* if no sound card found, zero scard */
+ if (sc!=0) fillchar(scard,sizeof(tsoundcard),0);
+
+ autosel=-1;
+/* if sc=0 then
+ for i:=0 to scardcount-1 do
+ if scard^.ID=soundcards[i].ID then begin
+ { Set auto selection mark }
+ autosel:=i+1;
+ break;
+ end;*/
+
+ /* Print the list of sound cards */
+
+ val(paramstr(13),select,e);
+
+ /* Default entry? */
+ if (select==0) select=autosel;
+ if (select!=autosel) {
+ /* clear all assumptions */
+ sc=-1;
+ fillchar(scard,sizeof(tsoundcard),0);
+ scard->id=soundcards[select-1]; /* set correct ID */
+ }
+
+ /* Query I/O address */
+ if (scard->id==id_dac) scard->ioport=0x378;
+
+ /* Read user input */
+ val(paramstr(15),i,e);
+
+ if (i!=0) scard->ioport=i;
+ if (sc!=1) /* Not autodetected */
+ switch (scard->id) {
+ case id_sb16:
+ case id_pas16:
+ case id_wss:
+ case id_aria:
+ case id_gus : scard->samplesize=2;
+ break; /* 16-bit card */
+ case id_sbpro:
+ case id_pas:
+ case id_pasplus: scard->stereo=true;
+ break; /* enable stereo */
+ default: {
+ scard->samplesize=1;
+ scard->stereo=false;
+ }
+ }
+
+ if (scard->id!=id_dac) {
+ val(paramstr(17),i,e);
+
+ if (i!=0) scard->dmairq=i;
+
+ val(paramstr(16),i,e);
+
+ if (i!=0) scard->dmachannel=i;
+ } else {
+ /* Select correct DAC */
+ scard->maxrate=44100;
+ if (select==11) {
+ scard->stereo=true;
+ scard->dmachannel=1; /* Special 'mark' */
+ scard->maxrate=60000;
+ } else
+ if (select==12) {
+ scard->stereo=true;
+ scard->dmachannel=2;
+ scard->maxrate=60000;
+ if (scard->ioport==0) scard->ioport=0x378;
+ } else
+ if (select==13) {
+ scard->dmachannel=0;
+ scard->ioport=0x42; /* Special 'mark' */
+ scard->maxrate=44100;
+ }
+ }
+
+/* writeln('Your selection: ',select,' at ',scard^.ioPort,
+ ' using IRQ ',scard^.dmaIRQ,' and DMA channel ',scard^.dmaChannel);
+ readln;*/
+
+ getsoundhardware_result=0;
+return getsoundhardware_result;
+}
+
+byte here()
+{
+ byte here_result;
+ here_result=(ampgetpattern % 3)*64+ampgetrow;
+ return here_result;
+}
+
+void hold(word amount)
+{
+ *skellern=0;
+ do {; } while (!(*skellern>=amount));
+}
+
+void hangon(word forwhat)
+{
+ if (nomusic)
+ hold(40);
+ else
+ do {
+ if (keypressed()) exit(0);
+ } while (!(here()>=holding[forwhat]));
+}
+
+tsoundcard scard;
+tmcpstruct mcpstrc;
+tdds dds;
+pmodule module;
+tsdi_init sdi;
+integer e,
+bufsize;
+char ch;
+boolean v86,
+vdsok;
+longint a,rate,
+tempseg;
+string answer;
+pointer temp;
+word flags;
+word curch;
+byte modulevolume;
+array<0,4,tsampleinfo> sample;
+array<0,31,word> voltable;
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ for( e=1; e <= paramcount; e ++) answer=paramstr(e);
+
+ nomusic=paramstr(13)=='0';
+
+ if (! nomusic)
+ {
+ /* Read sound card information */
+ if (getsoundhardware(&scard)==-1) exit(1);
+
+
+ /* Initialize Timer Service */
+ tsinit;
+ atexit(&tsclose);
+ if (scard.id==id_gus) {
+ /* Initialize GUS player */
+ #ifndef DPMI
+ scard.extrafield[2]=1; /* GUS DMA transfer does not work in V86 */
+ #endif
+ gusinit(&scard);
+ atexit(&gusclose);
+
+ /* Initialize GUS heap manager */
+ gushminit;
+
+ /* Init CDI */
+ cdiinit;
+
+ /* Register GUS into CDI */
+ cdiregister(&cdi_gus,0,31);
+
+ /* Add GUS event player engine into Timer Service */
+ tsaddroutine(&gusinterrupt,gus_timer);
+ } else {
+ /* Initialize Virtual DMA Specification */
+ #ifndef DPMI
+ vdsok=vdsinit==0;
+ #else
+ vdsok=false;
+ #endif
+
+ fillchar(mcpstrc,sizeof(tmcpstruct),0);
+
+ /* Query for sampling rate */
+ val(paramstr(14),a,e);
+ if (a>4000) rate=a; else rate=21000;
+
+ /* Query for quality */
+ mcpstrc.options=mcp_quality;
+
+ switch (scard.id) {
+ case id_sb : {
+ sdi=sdi_sb;
+ scard.maxrate=22000;
+ }
+ break;
+ case id_sbpro : {
+ sdi=sdi_sbpro;
+ scard.maxrate=22000;
+ }
+ break;
+ case id_pas:
+ case id_pasplus:
+ case id_pas16 : {
+ sdi=sdi_pas;
+ scard.maxrate=44100;
+ }
+ break;
+ case id_sb16 : {
+ sdi=sdi_sb16;
+ scard.maxrate=44100;
+ }
+ break;
+ case id_aria : {
+ sdi=sdi_aria;
+ scard.maxrate=44100;
+ }
+ break;
+ case id_wss : {
+ sdi=sdi_wss;
+ scard.maxrate=48000;
+ }
+ break;
+ #ifndef DPMI
+ case id_dac : sdi=sdi_dac; break; /* Only available in real mode */
+ #endif
+ }
+
+ mcpinitsounddevice(sdi,&scard);
+ a=mcp_tablesize;
+ mcpstrc.reqsize=0;
+
+ /* Calculate mixing buffer size */
+ bufsize=(longint)(2800*(integer)(scard.samplesize) << (byte)(scard.stereo))*
+ (longint)(rate) / (longint)(22000);
+ mcpstrc.reqsize=0;
+ if ((mcpstrc.options & mcp_quality)>0)
+ if (scard.samplesize==1) a += mcp_qualitysize; else
+ a=mcp_tablesize16+mcp_qualitysize16;
+ if ((longint)(bufsize)+(longint)(a)>65500) bufsize=longint(65500)-a;
+
+ #ifdef DPMI
+ dpmiversion((byte)(e),(byte)(e),(byte)(e),flags);
+ v86=(flags & 2)==0;
+ #endif
+
+ /* Allocate volume table + mixing buffer */
+ #ifdef DPMI
+
+ /* In the V86 mode, the buffer must be allocated below 1M */
+ if (v86) {
+ tempseg=0;
+ dpmiallocdos((a+longint(bufsize)) / longint(16)+longint(1),flags,(word)(tempseg));
+ } else {
+ #endif
+ getmem(temp,a+longint(bufsize));
+ if (temp==nil) exit(2);
+ #ifdef DPMI
+ tempseg=seg(temp);
+ }
+ #else
+ tempseg=seg(temp)+ofs(temp) / 16+1;
+ #endif
+ mcpstrc.bufferseg=tempseg;
+ mcpstrc.bufferphysical=-1;
+
+ if (vdsok && (scard.id!=id_dac)) {
+ dds.size=bufsize;
+ dds.segment=tempseg;
+ dds.offset=0;
+
+ /* Lock DMA buffer if VDS present */
+ if (vdslockdma(&dds)==0) mcpstrc.bufferphysical=dds.address;
+ }
+ if (mcpstrc.bufferphysical==-1)
+ #ifdef DPMI
+ mcpstrc.bufferphysical=dpmigetlinearaddr(tempseg);
+ #else
+ mcpstrc.bufferphysical=(longint)(tempseg) << 4;
+ #endif
+
+ mcpstrc.buffersize=bufsize;
+ mcpstrc.samplingrate=rate;
+ /* Initialize Multi Channel Player */
+ if (mcpinit(&mcpstrc)!=0) exit(3);
+ atexit(&mcpclose);
+
+ /* Initialize Channel Distributor */
+ cdiinit;
+
+ /* Register MCP into CDI*/
+ cdiregister(&cdi_mcp,0,31);
+ }
+
+ /* Try to initialize AMP */
+ if (ampinit(0)!=0) exit(3);
+ atexit(&ampclose);
+
+ /* Hook AMP player routine into Timer Service */
+ tsaddroutine(&ampinterrupt,amp_timer);
+
+ #ifndef DPMI
+ /* If using DAC, then adjust DAC timer */
+ if (scard.id==id_dac) setdactimer(tsgettimerrate);
+ #endif
+
+ if (scard.id!=id_gus) mcpstartvoice; else gusstartvoice;
+
+ /* Load an example AMF */
+ module=amploadmod("golden.mod",0);
+ if (module==nil) exit(4);
+
+ /* Is it MCP, Quality mode and 16-bit card? */
+ if ((scard.id!=id_gus) && ((mcpstrc.options & mcp_quality)>0)
+ && (scard.samplesize==2)) {
+ /* Open module+2 channels with amplified volumetable (4.7 gain) */
+ for( a=1; a <= 32; a ++) voltable[a-longint(1)]=a*longint(150) / longint(32);
+ cdisetupchannels(0,module->channelcount+2,&voltable);
+ } else {
+ /* Open module+2 channels with regular volumetable */
+ cdisetupchannels(0,module->channelcount+2,nil);
+ }
+
+ curch=module->channelcount;
+ modulevolume=64;
+
+ /***/ ampplaymodule(module,0);
+ }
+
+ val(paramstr(2),s,e); if (e!=0) exit(0);
+ val(paramstr(3),o,e); if (e!=0) exit(0);
+ skellern=ptr(s,o+1);
+
+ gd=3; gm=0; initgraph(gd,gm,"");
+
+ if (! nomusic) do {; } while (!(ampgetrow>=10));
+
+ setcolor(9);
+ for( gd=0; gd <= 320; gd ++)
+ {
+ rectangle(320-gd,100-gd / 2,320+gd,100+gd / 2);
+ }
+
+
+ gd=50; gm=20;
+ firstverse=true;
+
+ hangon(1); nexthangon=2;
+ for( fv=1; fv <= 255; fv ++)
+ {
+ switch (song[fv]) {
+ case '/': {
+ gd=50;
+ gm += 15;
+ hangon(nexthangon);
+ nexthangon += 1;
+ }
+ break;
+
+ case '%': {
+ gd=50;
+ gm += 35;
+ if (nomusic)
+ hold(15);
+ else
+ do {; } while (!(ampgetpattern>2));
+ nexthangon=2;
+ hangon(1);
+ }
+ break;
+
+ case '*': {
+ gd += 24;
+ hangon(5);
+ }
+ break;
+
+ default: {
+ setcolor(1); outtextxy(gd+1,gm+1,song[fv]);
+ setcolor(0); outtextxy( gd , gm ,song[fv]);
+ gd += 12;
+ }
+ }
+ if (song[fv]==' ') hold(1);
+ if (keypressed()) exit(0);
+ }
+
+ if (nomusic)
+ hold(25);
+ else
+ do {; } while (!(ampgetmodulestatus!=md_playing));
+
+ setcolor(0);
+ for( gd=320; gd >= 0; gd --) rectangle(320-gd,100-gd / 2,320+gd,100+gd / 2);
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/gyro.cpp b/engines/avalanche/gyro.cpp
new file mode 100644
index 0000000000..b530e45b08
--- /dev/null
+++ b/engines/avalanche/gyro.cpp
@@ -0,0 +1,532 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ GYRO It all revolves around this bit! */
+
+#define __gyro_implementation__
+
+
+#include "gyro.h"
+
+
+#include "pingo.h"
+#include "scrolls.h"
+#include "lucerna.h"
+#include "visa.h"
+#include "acci.h"
+#include "trip5.h"
+#include "dropdown.h"
+#include "basher.h"
+
+
+const array<'\1',numobjs,varying_string<15> > things =
+ {{"Wine","Money-bag","Bodkin","Potion","Chastity belt",
+ "Crossbow bolt","Crossbow","Lute","Pilgrim's badge","Mushroom","Key",
+ "Bell","Scroll","Pen","Ink","Clothes","Habit","Onion"}};
+
+const array<'\1',numobjs,char> thingchar = "WMBParCLguKeSnIohn"; /* V=Vinegar */
+
+const array<'\1',numobjs,varying_string<17> > better =
+ {{"some wine","your money-bag","your bodkin","a potion","a chastity belt",
+ "a crossbow bolt","a crossbow","a lute","a pilgrim's badge","a mushroom",
+ "a key","a bell","a scroll","a pen","some ink","your clothes","a habit",
+ "an onion"}};
+
+const array<'\1',numobjs,char> betterchar = "WMBParCLguKeSnIohn";
+
+void newpointer(byte m)
+{
+ if (m==cmp) return; cmp=m;
+ {
+ ax=9; bx=(word)(mps[m].horzhotspot); cx=(word)(mps[m].verthotspot);
+ es=seg(mps[m].mask); dx=ofs(mps[m].mask);
+ }
+ intr(0x33,r);
+ load_a_mouse(m);
+}
+
+void wait() /* makes hourglass */
+{
+ newpointer(5);
+}
+
+void on()
+{
+ if (set_of_enum(<null>)::of(m_yes,m_virtual, eos).has(visible)) return;
+
+ r.ax=1; intr(0x33,r); visible=m_yes;
+ if (oncandopageswap)
+ {
+ r.ax=29; r.bx=cp; intr(0x33,r); /* show mouse on current page */
+ }
+}
+
+void on_virtual()
+{
+ switch (visible) {
+ case m_virtual: return; break;
+ case m_yes: off(); break;
+ }
+
+ visible=m_virtual;
+}
+
+void off()
+{
+ switch (visible) {
+ case m_no:case m_virtual : return; break;
+ case m_yes : { r.ax=2; intr(0x33,r); } break;
+ }
+ visible=m_no;
+}
+
+void off_virtual()
+{
+ byte fv;
+
+ if (visible!=m_virtual) return;
+
+ for( fv=0; fv <= 1; fv ++)
+ {
+ setactivepage(fv);
+ wipe_vmc(1-fv);
+ }
+ setactivepage(1-cp); visible=m_no;
+}
+
+void xycheck() /* only updates mx & my, not all other mouse vars */
+{
+ r.ax=3; intr(0x33,r); /* getbuttonstatus */
+ {
+ keystatus=bx;
+ mx=cx; my=dx;
+ }
+}
+
+void hopto(integer x,integer y) /* Moves mouse pointer to x,y */
+{
+ {
+ ax=4;
+ cx=x;
+ dx=y;
+ }
+ intr(0x33,r);
+}
+
+void check()
+{
+ { ax=6; bx=0; } intr(0x33,r); /* getbuttonreleaseinfo */
+ {
+ mrelease=bx;
+ mrx=cx; mry=dx;
+ }
+ { ax=5; bx=0; } intr(0x33,r); /* getbuttonpressinfo */
+ {
+ mpress=bx;
+ mpx=cx; mpy=dx;
+ }
+ xycheck(); /* just to complete the job. */
+}
+
+void note(word hertz)
+{
+ if (soundfx) sound(hertz);
+}
+
+void blip()
+{
+ byte fv;
+
+ for( fv=1; fv <= 7; fv ++) { sound(177+(fv*200) % 177); delay(1); }
+ nosound;
+}
+
+string strf(longint x)
+{
+ string q;
+
+ string strf_result;
+ str(x,q); strf_result=q;
+ return strf_result;
+}
+
+void shadow(integer x1,integer y1,integer x2,integer y2, byte hc,byte sc)
+{
+ byte fv;
+
+ for( fv=0; fv <= border; fv ++)
+ {
+ setfillstyle(1,hc);
+ bar(x1+fv,y1+fv,x1+fv,y2-fv);
+ bar(x1+fv,y1+fv,x2-fv,y1+fv);
+
+ setfillstyle(1,sc);
+ bar(x2-fv,y1+fv,x2-fv,y2-fv);
+ bar(x1+fv,y2-fv,x2-fv,y2-fv);
+ }
+}
+
+void shbox(integer x1,integer y1,integer x2,integer y2, string t)
+{
+ const integer fc = 7;
+
+ off();
+ shadow(x1,y1,x2,y2,15,8); setfillstyle(1,fc);
+ bar(x1+border+1,y1+border+1,x2-border-1,y2-border-1);
+ setcolor(1); x1=(x2-x1) / 2+x1; y1=(y2-y1) / 2+y1;
+ outtextxy(x1,y1,t);
+ if (length(t)>1)
+ {
+ fillchar(t[2],length(t)-1,'\40'); t[1]='_';
+ outtextxy(x1-1,y1+1,t);
+ }
+ on();
+}
+
+void newgame() /* This sets up the DNA for a completely new game. */
+{
+ byte gd,gm;
+
+ for( gm=1; gm <= numtr; gm ++)
+ { triptype& with = tr[gm];
+ if (with.quick) done();} /* Deallocate sprite. Sorry, beta testers! */
+
+ tr[1].init(0,true);
+ alive=true;
+
+ score=0; /*for gd:=0 to 5 do which[gd]:=1;*/
+ fillchar(dna,sizeof(dna),'\0'); natural();
+ normal_edit(); mousepage(0);
+ dna.spare_evening="answer a questionnaire";
+ dna.like2drink="beer";
+
+ {
+ dna.pence=30; /* 2/6 */ dna.rw=stopped; dna.wearing=clothes;
+ dna.obj[money]=true; dna.obj[bodkin]=true; dna.obj[bell]=true; dna.obj[clothes]=true;
+ }
+
+ thinks='\2'; objectlist();
+ ontoolbar=false; seescroll=false;
+
+ ppos[0][1]=-177; /*tr[1].appear(300,117,right);*/ gd=0;
+ for( gd=0; gd <= 30; gd ++) for( gm=0; gm <= 1; gm ++) also[gd][gm]=nil;
+/* fillchar(previous^,sizeof(previous^),#0); { blank out array } */
+ him='\376'; her='\376'; it='\376'; last_person='\376'; /* = Pardon? */
+ dna.pass_num=Random(30)+1; after_the_scroll=false;
+ dna.user_moves_avvy=false; doing_sprite_run=false;
+ dna.avvy_in_bed=true; enid_filename="";
+
+ for( gd=0; gd <= 1; gd ++) { cp=1-cp; getback(); }
+
+ enterroom(1,1); new_game_for_trippancy();
+ showscore();
+
+ standard_bar(); clock();
+ sprite_run();
+}
+
+void click() /* "Audio keyboard feedback" */
+{
+ sound(7177); delay(1); nosound;
+}
+
+void slowdown()
+{
+/* repeat until TSkellern>=howlong; TSkellern:=0;*/
+ do {; } while (!(memw[storage_seg*skellern]>=howlong));
+ memw[storage_seg*skellern]=0;
+}
+
+boolean flagset(char x)
+{
+ boolean flagset_result;
+ flagset_result=pos(x,flags)>0;
+ return flagset_result;
+}
+
+void force_numlock()
+{
+ if ((locks & num)>0) locks -= num;
+}
+
+boolean pennycheck(word howmuchby)
+{
+ boolean pennycheck_result;
+ dna.pence -= howmuchby;
+ if (dna.pence<0)
+ {
+ dixi('Q',2); /* "you are now denariusless!" */
+ pennycheck_result=false;
+ gameover();
+ } else
+ pennycheck_result=true;
+ return pennycheck_result;
+}
+
+string getname(char whose)
+{
+ string getname_result;
+ if (whose<'\257') getname_result=lads[whose]; else getname_result=lasses[whose];
+ return getname_result;
+}
+
+char getnamechar(char whose)
+{
+ char getnamechar_result;
+ if (whose<'\257') getnamechar_result=ladchar[whose-1];
+ else getnamechar_result=lasschar[whose-1];
+ return getnamechar_result;
+}
+
+string get_thing(char which)
+{
+ string get_thing_result;
+ switch (which) {
+ case wine: switch (dna.winestate) {
+ case 1:case 4: get_thing_result=things[which]; break;
+ case 3: get_thing_result="Vinegar"; break;
+ }
+ break;
+ case onion: if (dna.rotten_onion)
+ get_thing_result="rotten onion";
+ else get_thing_result=things[which];
+ break;
+ default: get_thing_result=things[which];
+ }
+ return get_thing_result;
+}
+
+char get_thingchar(char which)
+{
+ char get_thingchar_result;
+ switch (which) {
+ case wine: if (dna.winestate==3) get_thingchar_result='V'; /* Vinegar */
+ else get_thingchar_result=thingchar[which-1];
+ break;
+ default: get_thingchar_result=thingchar[which-1];
+ }
+ return get_thingchar_result;
+}
+
+string get_better(char which)
+{
+ string get_better_result;
+ if (which>'\226') which -= 149;
+ switch (which) {
+ case wine: switch (dna.winestate) {
+ case 0:case 1:case 4: get_better_result=better[which]; break;
+ case 3: get_better_result="some vinegar"; break;
+ }
+ break;
+ case onion: if (dna.rotten_onion)
+ get_better_result="a rotten onion";
+ else if (dna.onion_in_vinegar)
+ get_better_result="a pickled onion (in the vinegar)";
+ else get_better_result=better[which];
+ break;
+ default:
+ if ((which<numobjs) && (which>'\0'))
+ get_better_result=better[which]; else
+ get_better_result="";
+ }
+ return get_better_result;
+}
+
+string f5_does()
+ /* This procedure determines what f5 does. */
+{
+ string f5_does_result;
+ switch (dna.room) {
+ case r__yours:
+ {
+ if (! dna.avvy_is_awake)
+ { /* He's asleep, =>= wake up. */
+ f5_does_result=string(vb_wake)+"WWake up";
+ return f5_does_result;
+ }
+
+ if (dna.avvy_in_bed)
+ { /* In bed. => = get up. */
+ f5_does_result=string(vb_stand)+"GGet up";
+ return f5_does_result;
+ }
+
+ }
+ break;
+
+ case r__insidecardiffcastle:
+ {
+ if (dna.standing_on_dais)
+ f5_does_result=string(vb_climb)+"CClimb down";
+ else
+ f5_does_result=string(vb_climb)+"CClimb up";
+ return f5_does_result;
+ }
+ break;
+
+ case r__nottspub:
+ {
+ if (dna.sitting_in_pub)
+ f5_does_result=string(vb_stand)+"SStand up";
+ else
+ f5_does_result=string(vb_sit)+"SSit down";
+ return f5_does_result;
+ }
+ break;
+
+ case r__musicroom:
+ if (infield(7))
+ {
+ f5_does_result=string(vb_play)+"PPlay the harp";
+ return f5_does_result;
+ }
+ break;
+ }
+
+ f5_does_result=pardon; /* If all else fails... */
+ return f5_does_result;
+}
+
+void plot_vmc(integer xx,integer yy, byte page_)
+{
+ if (visible!=m_virtual) return;
+ {
+ xx=xx+vmc.ofsx; if (xx<0) xx=0;
+ yy=yy+vmc.ofsy; if (yy<0) yy=0;
+
+ setactivepage(1-cp);
+ getimage(xx,yy,xx+15,yy+15,vmc.backpic[page_]);
+ putimage(xx,yy,vmc.andpic,andput);
+ putimage(xx,yy,vmc.xorpic,xorput);
+
+/* setcolor( 0); outtextxy(xx+8,yy+16,'Û'); outtextxy(xx,yy+16,'Û');
+ setcolor(11+page);
+ outtextxy(xx+8,yy+16,chr(48+roomtime mod 10));
+ outtextxy(xx ,yy+16,chr(48+(roomtime div 10) mod 10));*/
+
+ {
+ pointtype& with1 = vmc.wherewas[page_];
+
+ with1.x=xx;
+ with1.y=yy;
+ }
+ }
+}
+
+void wipe_vmc(byte page_)
+{
+ if (visible!=m_virtual) return;
+ { pointtype& with1 = vmc.wherewas[page_];
+ if (with1.x!=maxint)
+ putimage(with1.x,with1.y,vmc.backpic[page_],0);}
+}
+
+void setup_vmc()
+{
+ byte fv;
+
+ {
+ getmem(vmc.andpic,mouse_size);
+ getmem(vmc.xorpic,mouse_size);
+
+ for( fv=0; fv <= 1; fv ++)
+ {
+ getmem(vmc.backpic[fv],mouse_size);
+ vmc.wherewas[fv].x=maxint;
+ }
+ }
+}
+
+void clear_vmc()
+{
+ byte fv;
+
+ for( fv=0; fv <= 1; fv ++) vmc.wherewas[fv].x=maxint;
+}
+
+void setminmaxhorzcurspos(word min,word max) /* phew */
+{
+ {
+ ax=7;
+ cx=min;
+ dx=max;
+ }
+ intr(0x33,r);
+}
+
+void setminmaxvertcurspos(word min,word max)
+{
+ {
+ ax=8; /* A guess. In the book, 7 */
+ cx=min;
+ dx=max;
+ }
+ intr(0x33,r);
+}
+
+void load_a_mouse(byte which)
+{
+ untyped_file f;
+
+ assign(f,"mice.avd");
+ reset(f,1);
+ seek(f,mouse_size*2*(which-1)+134);
+
+ {
+ blockread(f,vmc.andpic,mouse_size);
+ blockread(f,vmc.xorpic,mouse_size);
+ close(f);
+ {
+ mp& with1 = mps[which];
+
+ vmc.ofsx=-with1.horzhotspot;
+ vmc.ofsy=-with1.verthotspot;
+
+ setminmaxhorzcurspos(with1.horzhotspot+3,624+with1.horzhotspot);
+ setminmaxvertcurspos(with1.verthotspot,199);
+ }
+ }
+}
+
+void background(byte x) { setbkcolor(x); }
+
+void hang_around_for_a_while()
+{
+ byte fv;
+
+ for( fv=1; fv <= 28; fv ++) slowdown();
+}
+
+boolean mouse_near_text()
+{
+ boolean mouse_near_text_result;
+ mouse_near_text_result=(my>144) && (my<188);
+ return mouse_near_text_result;
+}
+
+/* Super_Off and Super_On are two very useful procedures. Super_Off switches
+ the mouse cursor off, WHATEVER it's like. Super_On restores it again
+ afterwards. */
+
+void super_off()
+{
+ super_was_off=visible==m_no;
+ if (super_was_off) return;
+
+ super_was_virtual=visible==m_virtual;
+
+ if (visible==m_virtual) off_virtual(); else off();
+}
+
+void super_on()
+{
+ if ((visible!=m_no) || (super_was_off)) return;
+
+ if (super_was_virtual) on_virtual(); else on();
+}
+
+
diff --git a/engines/avalanche/gyro.h b/engines/avalanche/gyro.h
new file mode 100644
index 0000000000..8a1fdb5c0a
--- /dev/null
+++ b/engines/avalanche/gyro.h
@@ -0,0 +1,702 @@
+#ifndef __gyro_h__
+#define __gyro_h__
+
+
+#include "graph.h"
+/*#include "Dos.h"*/
+/*#include "Crt.h"*/
+
+
+const char numobjs = '\22'; /* always preface with a # */
+const integer maxobjs = 12; /* carry limit */
+const byte howlong = 1/*8*/; /* 18 ticks. */
+
+const boolean oncandopageswap = true; /* Variable constant for overriding the
+ ability of On to switch pages. You may know better than On which page
+ to switch to. */
+
+const integer num = 32; /* Code for Num Lock */
+
+const integer mouse_size = 134;
+
+typedef void(*proc)();
+
+struct postype {
+ word x,y,datapos; byte length;
+};
+
+struct mp { /* mouse-pointer */
+ matrix<0,1,0,15,word> mask;
+ integer horzhotspot,verthotspot;
+};
+
+struct dnatype { /* here goes... */ /* Ux, uy, & ww now all belong to Trip5 */
+ byte rw; /* Realway- just for convenience! */
+ byte carrying; /* how many objects you're carrying... */
+ array<'\1',numobjs,boolean> obj; /* ...and which ones they are. */
+ integer score; /* your score, of course */
+ longint pence; /* your current amount of dosh */
+ byte room; /* your current room */
+ char wearing; /* what you're wearing */
+ byte swore; /* number of times you've sworn */
+ byte saves; /* number of times this game has been saved */
+ array<1,100,byte> rooms; /* Add one to each every time
+ you enter a room */
+ byte alcohol; /* Your blood alcohol level. */
+ byte playednim; /* How many times you've played Nim. */
+ boolean wonnim; /* Have you *won* Nim? (That's harder.) */
+ byte winestate; /* 0=good (Notts), 1=passable(Argent) ... 3=vinegar.*/
+ boolean cwytalot_gone; /* Has Cwytalot rushed off to Jerusalem yet?*/
+
+ byte pass_num; /* Number of the password for this game. */
+ boolean ayles_is_awake; /* pretty obvious! */
+ byte drawbridge_open; /* Between 0 (shut) and 4 (open). */
+ byte avaricius_talk; /* How much Avaricius has said to you. */
+ boolean bought_onion; /* Have you bought an onion yet? */
+ boolean rotten_onion; /* And has it rotted? */
+ boolean onion_in_vinegar; /* Is the onion in the vinegar? */
+
+ byte given2spludwick; /* 0 = nothing given, 1 = onion... */
+ byte brummie_stairs; /* Progression through the stairs trick. */
+ byte cardiff_things; /* Things you get asked in Cardiff. */
+
+ boolean cwytalot_in_herts; /* Have you passed Cwytalot in Herts?*/
+
+ boolean avvy_is_awake; /* Well? Is Avvy awake? (Screen 1 only.) */
+ boolean avvy_in_bed; /* True if Avvy's in bed, but awake. */
+
+ boolean user_moves_avvy; /* If this is false, the user has no
+ control over Avvy's movements. */
+
+ byte dogfoodpos; /* Which way Dogfood's looking in the pub. */
+
+ boolean givenbadgetoiby; /* Have you given the badge to Iby yet? */
+
+ boolean friar_will_tie_you_up; /* If you're going to get tied up. */
+ boolean tied_up; /* You ARE tied up! */
+
+ char box_contents; /* 0 = money (sixpence), 254 = empty, any
+ other number implies the contents of the box. */
+
+ boolean talked_to_crapulus; /* Pretty self-explanatory. */
+
+ byte jacques_awake; /* 0=asleep, 1=awake, 2=gets up, 3=gone. */
+
+ boolean ringing_bells; /* Is Jacques ringing the bells? */
+
+ boolean standing_on_dais; /* In room 71, inside Cardiff Castle. */
+ boolean taken_pen; /* Have you taken the pen (in Cardiff?) */
+ boolean arrow_triggered; /* And has the arrow been triggered? */
+ boolean arrow_in_the_door; /* Did the arrow hit the wall? */
+
+ varying_string<77> like2drink,
+ favourite_song,
+ worst_place_on_earth,
+ spare_evening; /* Personalisation str's */
+
+ longint total_time; /* Your total time playing this game, in ticks.*/
+
+ byte jumpstatus; /* Fixes how high you're jumping. */
+
+ boolean mushroom_growing; /* Is the mushroom growing in 42? */
+
+ boolean spludwicks_here; /* Is Spludwick at home? */
+
+ byte last_room;
+ byte last_room_not_map;
+
+ boolean crapulus_will_tell; /* Will Crapulus tell you about
+ Spludwick being away? */
+
+ boolean enter_catacombs_from_lusties_room;
+ boolean teetotal; /* Are we touching any more drinks? */
+ byte malagauche; /* Position of Malagauche. See Celer for more info. */
+ char drinking; /* What's he getting you? */
+
+ boolean entered_lusties_room_as_monk;
+
+ byte cat_x, cat_y; /* XY coords in the catacombs. */
+
+ boolean avvys_in_the_cupboard; /* On screen 22. */
+
+ boolean geida_follows; /* Is Geida following you? */
+
+ byte geida_spin,geida_time; /* For the making "Geida dizzy" joke. */
+
+ byte nextbell; /* For the ringing. */
+
+ boolean geida_given_potion; /* Does Geida have the potion? */
+ boolean lustie_is_asleep; /* Is BDL asleep? */
+
+ byte flip_to_where, flip_to_ped; /* For the sequencer. */
+
+ boolean been_tied_up; /* In r__Robins. */
+
+ boolean sitting_in_pub; /* Are you sitting down in the pub? */
+ byte spurge_talk; /* Count for talking to Spurge. */
+
+ boolean met_avaroid;
+
+ boolean taken_mushroom,
+ given_pen_to_ayles,
+ asked_dogfood_about_nim;
+};
+
+struct pedtype {
+ integer x,y; byte dir;
+};
+
+struct magictype {
+ byte op; /* one of the operations */
+ word data; /* data for them */
+};
+
+class fieldtype {
+public:
+ integer x1,y1,x2,y2;
+};
+
+struct bytefield {
+ byte x1,y1,x2,y2;
+};
+
+class linetype : public fieldtype {
+public:
+ byte col;
+};
+
+struct adxtype {
+ varying_string<12> name; /* name of character */
+ byte num; /* number of pictures */
+ byte xl,yl; /* x & y lengths of pictures */
+ byte seq; /* how many in one stride */
+ word size; /* the size of one picture */
+ byte fgc,bgc; /* foreground & background bubble colours */
+};
+
+typedef matrix<'\0','\377',0,15,byte> raw; /* raw_font_type */
+
+enum controllers {cjoy,ckey, last_controllers};
+
+typedef array<1,20,varying_string<77> > previoustype;
+
+struct corridor_type { /* Decarations for the corridors. */
+ word doors; /* Door styles are calc'ed from this word.
+ Assign a different number to each one! */
+};
+
+struct demo_type {
+ word delay;
+ char key,extd;
+};
+
+struct quasiped_type {
+ byte whichped,fgc,room,bgc; char who;
+};
+/* A quasiped defines how people who aren't sprites talk. For example,
+ quasiped "A" is Dogfood. The rooms aren't stored because I'm leaving
+ that to context. */
+
+typedef array<1,31,byte> tunetype;
+
+struct vmctype { /* Virtual Mouse Cursor */
+ pointer andpic,xorpic;
+ array<0,1,pointer> backpic;
+ array<0,1,pointtype> wherewas;
+ byte picnumber;
+ shortint ofsx,ofsy;
+};
+
+struct sundry { /* Things which must be saved over a backtobootstrap,
+ outside DNA. */
+ pathstr qenid_filename;
+ boolean qsoundfx;
+ char qthinks;
+ boolean qthinkthing;
+};
+
+struct joysetup {
+ word xmid,ymid,xmin,ymin,xmax,ymax;
+ byte centre; /* Size of centre in tenths */
+};
+
+struct ednahead { /* Edna header */
+ /* This header starts at byte offset 177 in the .ASG file. */
+ array<1,9,char> id; /* signature */
+ word revision; /* EDNA revision, here 2 (1=dna256) */
+ varying_string<50> game; /* Long name, eg Lord Avalot D'Argent */
+ varying_string<15> shortname; /* Short name, eg Avalot */
+ word number; /* Game's code number, here 2 */
+ word ver; /* Version number as integer (eg 1.00 = 100) */
+ varying_string<5> verstr; /* Vernum as string (eg 1.00 = "1.00" */
+ varying_string<12> filename; /* Filename, eg AVALOT.EXE */
+ byte osbyte; /* Saving OS (here 1=DOS. See below for others.*/
+ varying_string<5> os; /* Saving OS in text format. */
+
+ /* Info on this particular game */
+
+ varying_string<8> fn; /* Filename (not extension ('cos that's .ASG)) */
+ byte d,m; /* D, M, Y are the Day, Month & Year this game was... */
+ word y; /* ...saved on. */
+ varying_string<40> desc; /* Description of game (same as in Avaricius!) */
+ word len; /* Length of DNA (it's not going to be above 65535!) */
+
+ /* Quick reference & miscellaneous */
+
+ word saves; /* no. of times this game has been saved */
+ integer cash; /* contents of your wallet in numerical form */
+ varying_string<20> money; /* ditto in string form (eg 5/-, or 1 denarius)*/
+ word points; /* your score */
+
+ /* DNA values follow, then footer (which is ignored) */
+};
+
+ /* Possible values of edhead.os:
+ 1 = DOS 4 = Mac
+ 2 = Windows 5 = Amiga
+ 3 = OS/2 6 = ST
+ 7 = Archimedes */
+
+const char vernum[] = "1.30";
+const char copyright[] = "1995";
+const integer thisvercode = 130;
+ /* as "vernum", but numerically & without the ".". */
+const integer thisgamecode = 2; /* Avalot's code number */
+
+/* Objects you can hold: */
+ const char wine = '\1'; const char money = '\2'; const char bodkin = '\3'; const char potion = '\4'; const char chastity = '\5'; const char bolt = '\6';
+ const char crossbow = '\7'; const char lute = '\10'; const char badge = '\11'; const char mushroom = '\12'; const char key = '\13'; const char bell = '\14';
+ const char prescription = '\15'; const char pen = '\16'; const char ink = '\17'; const char clothes = '\20'; const char habit = '\21'; const char onion = '\22';
+
+/* People who hang around this game. */
+
+/* Boys: */
+const char pavalot = '\226'; const char pspludwick = '\227'; const char pcrapulus = '\230'; const char pdrduck = '\231';
+const char pmalagauche = '\232'; const char pfriartuck = '\233'; const char probinhood = '\234'; const char pcwytalot = '\235';
+const char pdulustie = '\236'; const char pduke = '\237'; const char pdogfood = '\240'; const char ptrader = '\241';
+const char pibythneth = '\242'; const char payles = '\243'; const char pport = '\244'; const char pspurge = '\245'; const char pjacques = '\246';
+
+/* Girls: */
+const char parkata = '\257'; const char pgeida = '\260'; const char pwisewoman = '\262';
+
+const integer xw = 30;
+const integer yw = 36; /* x width & y whatsit */
+
+const integer margin = 5;
+
+const array<1,9,mp> mps =
+{{{ /* 1 - up-arrow */
+ {{{{65151,64575,64575,63519,63519,61455,61455,57351,57351,49155,49155,64575,64575,64575,64575,64575}},
+ {{0,384,384,960,960,2016,2016,4080,4080,8184,384,384,384,384,384,0}}}},
+ 8,
+ 0},
+
+{ /* 2 - screwdriver */
+ {{{{8191,4095,2047,34815,50175,61951,63743,64543,65039,65031,65027,65281,65408,65472,65505,65523}},
+ {{0,24576,28672,12288,2048,1024,512,256,224,176,216,96,38,10,12,0}}}},
+ 0,
+ 0},
+
+{ /* 3 - right-arrow */
+ {{{{65535,65535,64639,64543,7,1,0,1,7,64543,64639,65535,65535,65535,65535,65535}},
+ {{0,0,0,384,480,32760,32766,32760,480,384,0,0,0,0,0,0}}}},
+ 15,
+ 6},
+
+{ /* 4 - fletch */
+ {{{{255,511,1023,2047,1023,4607,14591,31871,65031,65283,65281,65280,65280,65409,65473,65511}},
+ {{0,10240,20480,24576,26624,17408,512,256,128,88,32,86,72,20,16,0}}}},
+ 0,
+ 0},
+
+{ /* 5 - hourglass */
+ {{{{0,0,0,34785,50115,61455,61455,63519,63519,61839,61455,49155,32769,0,0,0}},
+ {{0,32766,16386,12300,2064,1440,1440,576,576,1056,1440,3024,14316,16386,32766,0}}}},
+ 8,
+ 7},
+
+{ /* 6 - TTHand */
+ {{{{62463,57855,57855,57855,57471,49167,32769,0,0,0,0,32768,49152,57344,61441,61443}},
+ {{3072,4608,4608,4608,4992,12912,21070,36937,36873,36865,32769,16385,8193,4097,2050,4092}}}},
+ 4,
+ 0},
+
+{ /* 7- Mark's crosshairs */
+ {{{{65535,65151,65151,65151,65151,0,65151,65151,65151,65151,65535,65535,65535,65535,65535,65535}},
+ {{0,384,384,384,384,65535,384,384,384,384,0,0,0,0,0,0}}}},
+ 8,
+ 5},
+
+{ /* 8- I-beam. */
+ {{{{65535,65535,63631,63503,63503,65087,65087,65087,65087,65087,63503,63503,63631,65535,65535,65535}},
+ {{0,0,0,864,128,128,128,128,128,128,128,864,0,0,0,0}}}},
+ 8,
+ 7},
+
+{ /* 9- Question mark. */
+ {{{{511,1023,2047,31,15,8199,32647,65415,63503,61471,61503,61695,63999,63999,61695,61695}},
+ {{65024,33792,34816,34784,40976,57224,32840,72,1936,2080,2496,2304,1536,1536,2304,3840}}}},
+ 0,
+ 0}}};
+
+const array<'\226','\246',varying_string<19> > lads =
+ {{"Avalot","Spludwick","Crapulus","Dr. Duck","Malagauche","Friar Tuck",
+ "Robin Hood","Cwytalot","du Lustie","the Duke of Cardiff","Dogfood",
+ "A trader","Ibythneth","Ayles","Port","Spurge","Jacques"}};
+
+const array<'\257','\262',varying_string<14> > lasses =
+ {{"Arkata","Geida",'±',"the Wise Woman"}};
+
+ const array<'\226','\245',char> ladchar = "ASCDMTRwLfgeIyPu";
+
+const array<'\257','\262',char> lasschar = "kG±o";
+
+const integer numtr = 2; /* current max no. of sprites */
+
+const boolean a_thing = true; const boolean a_person = false; /* for Thinkabout */
+
+/* Magic/portal commands are */
+
+/*N*/ const integer nix = 0; /* ignore it if this line is touched */
+/*B*/ const integer bounces = 1; /* bounce off this line. Not valid for portals. */
+/*E*/ const integer exclaim = 2; /* put up a chain of scrolls */
+/*T*/ const integer transport = 3; /* enter new room */
+/*U*/ const integer unfinished = 4; /* unfinished connection */
+/*S*/ const integer special = 5; /* special function. */
+/*O*/ const integer mopendoor = 6; /* opening door. */
+
+/* These following constants should be included in CFG when it's written. */
+
+ const boolean slow_computer = false; /* stops walking when mouse touches toolbar */
+
+/* --- */
+
+const integer border = 1; /* size of border on shadowboxes */
+
+const integer pagetop = 81920;
+
+ const integer up = 0;
+const integer right = 1;
+ const integer down = 2;
+ const integer left = 3;
+const integer ur = 4; const integer dr = 5; const integer dl = 6; const integer ul = 7;
+ const integer stopped = 8;
+
+const integer walk = 3;
+const integer run = 5;
+
+/*$I ROOMNUMS.INC - Room number constants (r__xxx) */
+
+const array<'\226','\262',byte> whereis =
+ /* The Lads */
+ {{r__yours, /* Avvy */
+ r__spludwicks, /* Spludwick */
+ r__outsideyours, /* Crapulus */
+ r__ducks, /* Duck - r__DucksRoom's not defined yet. */
+ r__argentpub, /* Malagauche */
+ r__robins, /* Friar Tuck. */
+ 177, /* Robin Hood - can't meet him at the start. */
+ r__brummieroad, /* Cwytalot */
+ r__lustiesroom, /* Baron du Lustie. */
+ r__outsidecardiffcastle, /* The Duke of Cardiff. */
+ r__argentpub, /* Dogfood */
+ r__outsideducks, /* Trader */
+ r__argentpub, /* Ibythneth */
+ r__aylesoffice, /* Ayles */
+ r__nottspub, /* Port */
+ r__nottspub, /* Spurge */
+ r__musicroom, /* Jacques */
+ 0,0,0,0,0,0,0,0,
+ /* The Lasses */
+ r__yours, /* Arkata */
+ r__geidas, /* Geida */
+ 177, /* nobody allocated here! */
+ r__wisewomans}}; /* The Wise Woman. */
+
+/* Art gallery at 2,1; notice about this at 2,2. */
+
+const matrix<1,8,1,8,longint> catamap =
+ /* Geida's room */
+ /* 1 2 3 | 4 5 6 7 8*/
+{{{{0x204,0x200,0xd0f0,0xf0ff,0xff,0xd20f,0xd200,0x200}},
+ {{0x50f1,0x20ff,0x2ff,0xff,0xe0ff,0x20ff,0x200f,0x7210}},
+ {{0xe3f0,0xe10f,0x72f0,0xff,0xe0ff,0xff,0xff,0x800f}},
+ {{0x2201,0x2030,0x800f,0x220,0x20f,0x30,0xff,0x23f}}, /* >> Oubliette */
+ {{0x5024,0xf3,0xff,0x200f,0x22f0,0x20f,0x200,0x7260}},
+ {{0xf0,0x2ff,0xe2ff,0xff,0x200f,0x50f0,0x72ff,0x201f}},
+ {{0xf6,0x220f,0x22f0,0x30f,0xf0,0x20f,0x8200,0x2f0}}, /* <<< In here */
+ {{0x34,0x200f,0x51f0,0x201f,0xf1,0x50ff,0x902f,0x2062}}}};
+ /* vv Stairs trap. */
+
+/* Explanation: $NSEW.
+ Nibble N: North.
+ 0 = no connection,
+ 2 = (left,) middle(, right) door with left-hand handle,
+ 5 = (left,) middle(, right) door with right-hand handle,
+ 7 = arch,
+ 8 = arch and 1 north of it,
+ 9 = arch and 2 north of it,
+ D = no connection + WINDOW,
+ E = no connection + TORCH,
+ F = recessed door (to Geida's room.)
+
+ Nibble S: South.
+ 0 = no connection,
+ 1,2,3 = left, middle, right door.
+
+ Nibble E: East.
+ 0 = no connection (wall),
+ 1 = no connection (wall + window),
+ 2 = wall with door,
+ 3 = wall with door and window,
+ 6 = wall with candles,
+ 7 = wall with door and candles,
+ F = straight-through corridor.
+
+ Nibble W: West.
+ 0 = no connection (wall),
+ 1 = no connection (wall + shield),
+ 2 = wall with door,
+ 3 = wall with door and shield,
+ 4 = no connection (window),
+ 5 = wall with door and window,
+ 6 = wall with candles,
+ 7 = wall with door and candles,
+ F = straight-through corridor. */
+
+const byte interrogation = 0;
+ /* If this is greater than zero, the next line you type is stored in
+ the DNA in a position dictated by the value. If a scroll comes up,
+ or you leave the room, it's automatically set to zero. */
+
+const boolean demo = false; /* If this is true, we're in a demo of the game. */
+
+const array<0,2,char> spludwick_order = {{onion,ink,mushroom}};
+
+const array<10,25,quasiped_type> quasipeds =
+{{{2,lightgray, 19,brown,pdogfood}, /* A: Dogfood (screen 19). */
+{3,green, 19,white,pibythneth}, /* B: Ibythneth (screen 19). */
+{3,white, 1,magenta,parkata}, /* C: Arkata (screen 1). */
+{3,black, 23,red,'\261'}, /* D: Hawk (screen 23). */
+{3,lightgreen,50,brown,ptrader}, /* E: Trader (screen 50). */
+{6,yellow, 42,red,pavalot}, /* F: Avvy, tied up (scr.42) */
+{2,blue, 16,white,payles}, /* G: Ayles (screen 16). */
+{2,brown, 7,white,pjacques}, /* H: Jacques (screen 7). */
+{2,lightgreen,47,green,pspurge}, /* I: Spurge (screen 47). */
+{3,yellow, 47,red,pavalot}, /* J: Avalot (screen 47). */
+{2,lightgray, 23,black,pdulustie}, /* K: du Lustie (screen 23). */
+{2,yellow, 27,red,pavalot}, /* L: Avalot (screen 27). */
+{3,white, 27,red,'\261'}, /* M: Avaroid (screen 27). */
+{4,lightgray, 19,darkgray,pmalagauche}, /*N: Malagauche (screen 19). */
+{5,lightmagenta,47,red,pport}, /* O: Port (screen 47). */
+{2,lightgreen, 51,darkgray,pdrduck}}}; /*P: Duck (screen 51). */
+
+ const integer lower = 0;
+ const integer same = 1;
+const integer higher = 2;
+
+const array<1,12,char> keys = "QWERTYUIOP[]";
+const array<1,12,word> notes =
+ {{196,220,247,262,294,330,350,392,440,494,523,587}};
+
+const tunetype tune =
+ {{higher,higher,lower,same,higher,higher,lower,higher,higher,higher,
+ lower,higher,higher,
+ same,higher,lower,lower,lower,lower,higher,higher,lower,lower,lower,
+ lower,same,lower,higher,same,lower,higher}};
+
+/* special run-time errors */
+
+const integer runerr_getset_overflow = 50;
+
+
+#ifdef __gyro_implementation__
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN varying_string<77> current; EXTERN byte curpos; EXTERN boolean cursoron;
+/* previous:^previoustype;*/
+EXTERN varying_string<77> last;
+EXTERN dnatype dna;
+EXTERN array<1,50,linetype> lines; /* For Also. */
+EXTERN integer c;
+EXTERN registers r;
+EXTERN enum { m_no , m_yes , m_virtual } visible;
+EXTERN boolean dropsok,screturn,soundfx,cheat;
+EXTERN word mx,my; /* mouse x & y now */
+EXTERN word mpx,mpy; /* mouse x & y when pressed */
+EXTERN word mrx,mry; /* mouse x & y when released */
+EXTERN byte mpress,mrelease; /* times left mouse button has been pressed/released */
+EXTERN byte keystatus; /* Mouse key status */
+EXTERN array<1,10,varying_string<20> > un;
+EXTERN byte unn; EXTERN string mousetext;
+/* which:array[0..5] of byte;*/
+EXTERN pointer p; EXTERN boolean weirdword;
+EXTERN byte to_do; EXTERN boolean lmo,mousemade;
+EXTERN array<1,15,varying_string<50> > scroll;
+EXTERN byte scrolln,score,whichwas; EXTERN char thinks; EXTERN boolean thinkthing;
+
+/* pp:array[1..1000] of postype;
+ bb:array[1..9000] of byte;*/
+EXTERN word pptr,bptr;
+EXTERN matrix<0,0,0,1,integer> ppos;
+EXTERN array<1,24,word> pozzes;
+EXTERN byte anim; EXTERN pointer copier;
+EXTERN integer talkx,talky; EXTERN byte talkb,talkf;
+EXTERN byte scrollbells; /* no. of times to ring the bell */
+EXTERN boolean ontoolbar,seescroll;
+
+EXTERN array<1,10,char> objlist;
+EXTERN array<'0','9',pointer> digit;
+EXTERN array<0,8,pointer> rwlite; EXTERN byte oldrw;
+EXTERN varying_string<3> lastscore; EXTERN byte cmp; /* current mouse-pointer */
+EXTERN varying_string<10> verbstr; /* what you can do with your object. :-) */
+
+EXTERN matrix<0,30,0,1,string*> also;
+EXTERN array<1,15,pedtype> peds;
+EXTERN array<1,15,magictype> magics;
+EXTERN array<9,15,magictype> portals;
+EXTERN array<1,30,fieldtype> fields; EXTERN byte numfields;
+EXTERN varying_string<26> flags; EXTERN string listen;
+
+EXTERN word oh,onh,om,h,m,s,s1;
+
+EXTERN varying_string<4> atkey; /* For XTs, set to "alt-". For ATs, set to "f1". */
+
+EXTERN byte cp,ledstatus,defaultled;
+EXTERN raw little; EXTERN boolean quote; /* 66 or 99 next? */
+EXTERN boolean alive;
+EXTERN array<1,2000,char> buffer; EXTERN word bufsize;
+
+EXTERN byte oldjw; /* Old joystick-way */
+EXTERN controllers ctrl;
+
+EXTERN integer underscroll; /* Y-coord of just under the scroll text. */
+
+/* TSkellern is only temporary, and I'll replace it
+ with a local version when it's all fixed up. */
+
+/* tskellern:longint absolute $0:244; { Over int $61 }*/
+
+EXTERN boolean ddmnow; /* Kludge so we don't have to keep referring to Dropdown */
+EXTERN varying_string<40> roomname; /* Name of this room */
+
+EXTERN text logfile; EXTERN boolean logging,log_epson;
+
+EXTERN boolean cl_override;
+
+EXTERN byte locks; /*ABSOLUTE $40:$17;*/
+
+EXTERN varying_string<20> subject; /* What you're talking to them about. */
+EXTERN byte subjnumber; /* The same thing. */
+
+EXTERN boolean keyboardclick; /* Is a keyboard click noise wanted? */
+
+EXTERN char him,her,it;
+EXTERN longint roomtime; /* Set to 0 when you enter a room, added to in every loop.*/
+
+EXTERN boolean after_the_scroll;
+
+ /* For the demo: */
+EXTERN demo_type demo_rec;
+EXTERN file<demo_type> demofile;
+
+EXTERN char last_person; /* Last person to have been selected using the People
+ menu. */
+
+EXTERN boolean doing_sprite_run; /* Only set to True if we're doing a sprite_run
+ at this moment. This stops the trippancy system from moving any of the
+ sprites. */
+
+EXTERN vmctype vmc;
+EXTERN string filetoload;
+
+EXTERN boolean holdthedawn; /* If this is true, calling Dawn will do nothing.
+ It's used, for example, at the start, to stop Load from dawning. */
+
+EXTERN word storage_seg,storage_ofs; /* Seg and ofs of the Storage area. */
+EXTERN word skellern; /* Offset of the timer variable - 1 more than storage_OFS */
+EXTERN boolean reloaded; /* Is this NOT the primary loading? */
+
+EXTERN boolean super_was_virtual,super_was_off; /* Used by Super_Off and Super_On */
+
+EXTERN pathstr enid_filename;
+
+EXTERN joysetup js;
+EXTERN word cxmin,cxmax,cymin,cymax; EXTERN boolean use_joy_a;
+#undef EXTERN
+#define EXTERN extern
+
+
+ void newpointer(byte m);
+
+ void wait(); /* makes hourglass */
+
+ void on();
+
+ void off();
+
+ void on_virtual();
+
+ void off_virtual();
+
+ void xycheck();
+
+ void hopto(integer x,integer y); /* Moves mouse pointer to x,y */
+
+ void check();
+
+ void note(word hertz);
+
+ void blip();
+
+ string strf(longint x);
+
+ void shbox(integer x1,integer y1,integer x2,integer y2, string t);
+
+ void newgame();
+
+ void click();
+
+ void slowdown();
+
+ boolean flagset(char x);
+
+ void force_numlock();
+
+ boolean pennycheck(word howmuchby);
+
+ string getname(char whose);
+
+ char getnamechar(char whose);
+
+ string get_thing(char which);
+
+ char get_thingchar(char which);
+
+ string get_better(char which);
+
+ string f5_does();
+
+ void plot_vmc(integer xx,integer yy, byte page_);
+
+ void wipe_vmc(byte page_);
+
+ void setup_vmc();
+
+ void clear_vmc();
+
+ void load_a_mouse(byte which);
+
+ void background(byte x);
+
+ void hang_around_for_a_while();
+
+ void super_off();
+
+ void super_on();
+
+ boolean mouse_near_text();
+
+#endif
diff --git a/engines/avalanche/help.cpp b/engines/avalanche/help.cpp
new file mode 100644
index 0000000000..d155263306
--- /dev/null
+++ b/engines/avalanche/help.cpp
@@ -0,0 +1,225 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Rodent.h"*/
+/*#include "Crt.h"*/
+
+typedef graphcursmasktype cursor;
+const char vernum[] = "v1ù00";
+const char copyright[] = "1992";
+const cursor questionmark =
+{
+ ((511,1023,2047,31,15,8199,32647,65415,63503,61471,61503,61695,63999,63999,61695,61695),
+ (65024,33792,34816,34784,40976,57224,32840,72,1936,2080,2496,2304,1536,1536,2304,3840)),
+ 0,
+ 0};
+
+const array<1,7,varying_string<12> > topics =
+ {{"Front page","Background","Toolbar","Menus",
+ "Keyboard","Shareware","Exit Help"}};
+
+const array<1,6,char> keys = "FBTMKS";
+
+byte page_;
+palettetype dp,dark;
+char r;
+boolean lmo;
+
+void hilight(integer x,integer y, byte c1,byte c2, string z)
+{
+ string w;
+;
+ w=z; w[1]='\40'; setcolor(c1); outtextxy(x,y,w);
+ w=z; fillchar(w[2],length(z)-1,'\40'); setcolor(c2);
+ outtextxy(x,y,w); outtextxy(x-1,y,w);
+}
+
+void showpage(byte x)
+{;
+ if (x==page_) return; /* twit */
+ if (x==7) {; lmo=true; return; }
+ setallpalette(dark); hidemousecursor; settextjustify(1,1);
+ if (page_!=177)
+ {;
+ setfillstyle(1,1); bar(507,page_*25+2,607,page_*25+22);
+ setfillstyle(1,9); bar(500,page_*25,600,page_*25+20);
+/* setcolor(11); outtextxy(550,page*25+10,topics[page]);*/
+ hilight(550,page_*25+10,11,14,topics[page_]);
+ }
+ page_=x;
+ setfillstyle(1,4); bar(507,page_*25+2,607,page_*25+22);
+ setfillstyle(1,12); bar(500,page_*25,600,page_*25+20);
+/* setcolor(14); outtextxy(550,page*25+10,topics[page]); */
+ hilight(550,page_*25+10,14,15,topics[page_]);
+ setfillstyle(1,7); bar(0,27,470,189); settextjustify(0,2); setcolor(1);
+ switch (page_) {
+ case 1: {; /* Front page */
+ setcolor(black);
+ outtextxy( 10, 40,"Thorsoft of Letchworth presents");
+ outtextxy(300, 80,vernum);
+ outtextxy( 10, 90,string("(c) ")+copyright+", Mike, Mark and Thomas Thurman.");
+ setcolor(red);
+ outtextxy(100,129,"Finding your way around it...");
+ setcolor(blue);
+ outtextxy( 10,120,"You are now using the Help System.");
+ outtextxy( 10,138,"Press the first letter of the topic that you want to");
+ outtextxy( 10,147,"read (eg T for (T)oolbar), or click on its button (on");
+ outtextxy( 10,156,"the right) using the mouse. Use \"Exit Help\" to quit.");
+ outtextxy( 10,174,"(Fastest exit- just hit Esc!)");
+ }
+ break;
+ case 2: {; /* Background */
+ setcolor(red);
+ outtextxy(300, 30,"Remember this chap?");
+ setcolor(blue);
+ outtextxy( 10, 55,"Back in good old A.D. 79, there lived a Roman");
+ outtextxy( 10, 64,"whose name was Denarius Avaricius Sextus, known");
+ outtextxy( 10, 73,"to his friends as Avvy. His wife was called Arkata,");
+ outtextxy( 10, 82,"and he had a slave named Crapulus. His grandson");
+ outtextxy( 10, 91,"joined the army, was posted to Gaul, and liked it");
+ outtextxy( 10,100,"so much that he stayed there, telling everyone the");
+ outtextxy( 10,109,"one about the centurion and the Turkish bath. His");
+ outtextxy( 10,118,"thirty-sixth male-line descendant accidentally");
+ outtextxy( 10,127,"poisoned an old enemy of William of Normandy, and");
+ outtextxy( 10,136,"to his great surprise came so much into Bill's favour");
+ outtextxy( 10,145,"that, after the Battle of Hastings a few years");
+ outtextxy( 10,154,"later, he was made the lord of a small town in");
+ outtextxy( 10,163,"Hertfordshire called Argent. It is his great-grandson");
+ outtextxy( 10,172,"who stars in this game, back in good old A.D. 1189.");
+ }
+ break;
+ case 3: {; /* ? */
+ outtextxy( 15, 30,"The Toolbar is there so that (along with the menus)");
+ outtextxy( 15, 39,"you can perform a lot of the functions contained in");
+ outtextxy( 15, 48,"the game, using the mouse.");
+ setcolor(red);
+ outtextxy( 15, 66,"COMPASS:");
+ setcolor(blue);
+ outtextxy( 90, 66,"Used to point Avvy in the right direction.");
+ setcolor(red);
+ outtextxy( 15, 75,"THINKS:");
+ setcolor(blue);
+ outtextxy( 90, 75,"Shows the person/object you're thinking of.");
+ setcolor(red);
+ outtextxy( 15, 84,"SCORE:");
+ setcolor(blue);
+ outtextxy( 90, 84,"Shows how many points you've got.");
+ setcolor(red);
+ outtextxy( 15, 93,"SPEED:");
+ setcolor(blue);
+ outtextxy( 90, 93,"Adjusts the speed of the game.");
+ setcolor(red);
+ outtextxy( 15,102,"L.E.D.s:");
+ setcolor(blue);
+ outtextxy( 90,102,"Shows whether sound is on (toggle with <F2>),");
+ outtextxy( 90,111,"the computer is ready, or there is an error.");
+ setcolor(red);
+ outtextxy( 15,120,"CLOCK:");
+ setcolor(blue);
+ outtextxy( 90,120,"Shows the time.");
+ setcolor(red);
+ outtextxy( 15,129,"'OK' box:");
+ setcolor(blue);
+ outtextxy( 90,129,"Works the same as pressing <ENTER>.");
+ setcolor(0);
+ outtextxy( 15,147,"N.B. The game action is suspended while you are");
+ outtextxy( 15,156,"using the toolbar.");
+ }
+ break;
+ case 4: {; /* menus */
+ outtextxy( 15, 60,"To use the drop-down menus, either click on the bar");
+ outtextxy( 15, 69,"at the top with the mouse, or press Alt and the first");
+ outtextxy( 15, 78,string("letter of the menu's name (eg alt-A = (A)ction.) The ")+'\3');
+ outtextxy( 15, 87,"menu is alt-H, for (H)eart.");
+ outtextxy( 15,105,"When you have a menu, either click on the option you");
+ outtextxy( 15,114,"want, or press its initial letter (eg O for \"OS Shell\").");
+ outtextxy( 15,132,"To do something to, or with, an object or person, first");
+ outtextxy( 15,141,"select them (or it) from the People or Things menu. Then");
+ outtextxy( 15,150,"select whatever you wanted to do from the Use menu.");
+ setcolor(red);
+ outtextxy(15,177,"(OK, so it sounds complicated, but then it's intuitive!)");
+ }
+ break;
+ case 5: {; /* Keyboard */
+ outtextxy(15, 60,"The keyboard interface is even simpler than the mouse");
+ outtextxy(15, 70,"interface! Just type what you want Avvy to do.");
+ outtextxy(15, 80,"For example, to open a door, type in:");
+ setcolor(red); outtextxy(100,95,"open door"); setcolor(blue);
+ outtextxy(15,110,"And to look at Crapulus, type:");
+ setcolor(red); outtextxy(100,125,"look at Crapulus");
+ setcolor(blue); outtextxy(15,140,"(Don't forget to press Enter after each command!)");
+ outtextxy(15,160,"This is a traditional command-line parser interface,");
+ outtextxy(15,170,"similar to the one in \"Avaricius\", only more advanced.");
+ }
+ break;
+ case 6: {; /* ? */
+ outtextxy(15, 30,"This game is Shareware. Most programs are sold through");
+ outtextxy(15, 40,"shops, and the authors prevent you from copying them.");
+ outtextxy(15, 50,"Shareware is different. You may copy it and give it to");
+ outtextxy(15, 60,"ANYBODY at all. You may post it on any BBS, give it to");
+ outtextxy(15, 70,"friends, etc. If you like it, we ask you to pay us for");
+ outtextxy(15, 80,"the software directly through the post. We're relying");
+ outtextxy(15, 90,"on you to register!");
+ outtextxy(99,177,"{ ETC }");
+ }
+ break;
+ }
+ setallpalette(dp); showmousecursor;
+}
+
+void helpsetup()
+{
+ integer gd,gm;
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi"); settextstyle(1,0,0); setcolor(11);
+ getpalette(dp); dark.size=dp.size; fillchar(dark.colors,dark.size,'\0');
+ setallpalette(dark); setusercharsize(3,1,8,10);
+ for( gm=1; gm <= 3; gm ++) outtextxy(gm,0,"Avalot- HELP!");
+ resetmouse; setgraphicscursor(questionmark); showmousecursor;
+ settextstyle(0,0,1); settextjustify(1,1);
+ for( gd=2; gd <= 7; gd ++)
+ {;
+ setfillstyle(1,1); bar(507,gd*25+2,607,gd*25+22);
+ setfillstyle(1,9); bar(500,gd*25,600,gd*25+20);
+/* setcolor(11); outtextxy(550,gd*25+10,topics[gd]); */
+ hilight(550,gd*25+10,11,14,topics[gd]);
+ }
+ showmousecursor;
+ page_=177; showpage(1); lmo=false; setfillstyle(1,7);
+ for( gd=1; gd <= 3; gd ++)
+ {;
+ bar( 10-gd*3,200-gd*3,490-gd*6,200-gd*3);
+ bar(490-gd*6, 37-gd*3,491-gd*6,200-gd*3);
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ helpsetup();
+ do {
+ do { getbuttonstatus; } while (!((mkey==left) || keypressed()));
+ if (keypressed())
+ {; /* keyboard choice */
+ r=upcase(readkey());
+ if (pos(r,keys)>0) showpage(pos(r,keys)); else
+ if (r=='\0')
+ switch (readkey()) { /* grab extd keystroke */
+ case 'H': if (page_>1) showpage(page_-1); break;
+ case 'P': if (page_<6) showpage(page_+1); break;
+ case 'G':case 'I': showpage(1); break;
+ case 'O':case 'Q': showpage(6); break;
+ } else
+ if (set::of('\33','Q','X','E','H', eos).has(r)) lmo=true; /* quit */
+ }
+ else
+ {; /* mouse choice */
+ if ((mousex>400) && (mousey>25))
+ {;
+ showpage(mousey / 25);
+ }
+ }
+ } while (!lmo);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/help2.cpp b/engines/avalanche/help2.cpp
new file mode 100644
index 0000000000..b062015aec
--- /dev/null
+++ b/engines/avalanche/help2.cpp
@@ -0,0 +1,244 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+typedef matrix<'\0','\377',0,15,byte> fonttype;
+
+struct hypertype {
+ char trigger;
+ byte line;
+ byte start,finish;
+ word ref;
+};
+
+integer gd,gm;
+array<1,2,fonttype> font;
+matrix<0,7,1,80,byte> current;
+array<1,250,varying_string<79> > data;
+integer fv,position,size;
+varying_string<79> title;
+array<1,20,hypertype> link;
+byte numlinks;
+char r;
+array<0,9,byte> reverse;
+array<0,9,byte> revpos;
+
+void loadfont()
+{
+ file<fonttype> fontfile;
+;
+ assign(fontfile,"c:\\thomas\\ttsmall.fnt"); reset(fontfile);
+ fontfile >> font[1]; close(fontfile);
+/* assign(fontfile,'c:\avalot\avalot.fnt'); reset(fontfile);
+ read(fontfile,font[2]); close(fontfile);*/
+ /* NB: We'll put BOTH of these fonts one after the other, in the same
+ file, in the final compilation. */
+}
+
+void scribe(byte which,byte what);
+
+static void underline(byte& x) {; x=x | 177; }
+
+void scribe(byte which,byte what)
+{
+ byte fv,ff; string x;
+;
+ x=data[what];
+ fillchar(current,sizeof(current),'\0');
+ for( ff=1; ff <= length(x); ff ++)
+ for( fv=0; fv <= 7; fv ++)
+ {;
+ current[fv][ff]=font[which][x[ff]][fv];
+ }
+
+ for( fv=1; fv <= numlinks; fv ++)
+ { hypertype& with = link[fv];
+ if (with.line==what)
+ for( ff=with.start; ff <= with.finish; ff ++)
+ underline(current[7][ff]);}
+
+}
+
+void display(word y)
+{;
+ for( fv=0; fv <= 7; fv ++)
+ move(current[fv],mem[0xa000*(y+fv)*80],79);
+}
+
+void update_link(char which, byte whence,byte whither)
+{
+ byte fv;
+;
+ for( fv=1; fv <= numlinks; fv ++)
+ { hypertype& with = link[fv];
+ if (with.trigger==which)
+ {;
+ with.line=size;
+ with.start=whence;
+ with.finish=whither;
+ }}
+}
+
+void getlinks(string& x)
+{
+ byte p,q;
+;
+ do {
+ p=pos("[",x);
+ if (p==0) return; /* lousy, huh? */
+ q=pos("]",x);
+ update_link(x[p+1],p,q-3);
+ Delete(x,q,1); Delete(x,p,2);
+ } while (!false);
+}
+
+void loaddata(byte which)
+{
+ text t;
+ string x;
+ integer e;
+;
+ revpos[9]=position;
+ fillchar(data,sizeof(data),'\0');
+ move(reverse[1],reverse[0],9);
+ move(revpos[1],revpos[0],9);
+ reverse[9]=which; revpos[9]=1;
+
+ str(which,x);
+ assign(t,string('h')+x+".raw");
+ reset(t);
+ t >> title >> NL;
+ size=0; numlinks=0;
+ while (! eof(t))
+ {;
+ t >> x >> NL;
+ if (x[1]==':')
+ {;
+ numlinks += 1;
+ {
+ hypertype& with = link[numlinks];
+ ;
+ with.trigger=x[2];
+ Delete(x,1,3);
+ Delete(x,pos(" ",x),255);
+ val(x,with.ref,e);
+ }
+ } else {;
+ size += 1;
+ getlinks(x);
+ data[size]=x;
+ }
+ }
+ position=1; size -= 15;
+ close(t);
+}
+
+void screen()
+{;
+ setbkcolor(1);
+ setfillstyle(1,1); bar(0,0,640,38);
+ setfillstyle(1,14); bar(0,39,640,39);
+}
+
+void showscreen()
+{
+ byte fv;
+;
+ if (position<1) position=1;
+ for( fv=0; fv <= 15; fv ++)
+ {;
+ scribe(1,fv+position);
+ display(41+fv*10);
+ }
+}
+
+void up()
+{
+ byte fv;
+;
+ position -= 1;
+ scribe(1,position);
+ for( fv=0; fv <= 9; fv ++)
+ {;
+ move(mem[0xa000*3200],mem[0xa000*3280],12720);
+ if (set::of(0,9, eos).has(fv)) fillchar(mem[0xa000*3200],79,'\0'); else
+ move(current[8-fv],mem[0xa000*3200],80);
+ }
+}
+
+void down()
+{
+ byte fv;
+;
+ position += 1;
+ scribe(1,position+15);
+ for( fv=0; fv <= 9; fv ++)
+ {;
+ move(mem[0xa000*3280],mem[0xa000*3200],12720);
+ if (set::of(0,9, eos).has(fv)) fillchar(mem[0xa000*15920],79,'\0'); else
+ move(current[fv-1],mem[0xa000*15920],80);
+ }
+}
+
+void newpage(char c)
+{
+ byte fv;
+;
+ for( fv=1; fv <= numlinks; fv ++)
+ { hypertype& with = link[fv];
+ if (with.trigger==c)
+ {;
+ loaddata(with.ref);
+ showscreen();
+ }}
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ loadfont();
+ screen();
+ loaddata(0);
+ showscreen();
+ fillchar(reverse,sizeof(reverse),'\0');
+ fillchar(revpos,sizeof(revpos),'\1');
+ do {
+ r=upcase(readkey());
+ switch (r) {
+ case '\0': switch (readkey()) {
+ case 'H': if (position>1) up(); break;
+ case 'P': if (position<size) down(); break;
+ case 'I': {; position -= 16; showscreen(); } break;
+ case 'Q': {; position += 16; showscreen(); } break;
+ case 'G': {; position=1; showscreen(); } break;
+ case 'O': {; position=size; showscreen(); } break;
+ }
+ break;
+ case 'B': {; /* go Back */
+ gd=reverse[8];
+ gm=revpos[8];
+ move(reverse[0],reverse[2],8);
+ move(revpos[0],revpos[2],8);
+ loaddata(gd); position=gm;
+ showscreen();
+ }
+ break;
+ case 'C': {; /* Contents */
+ loaddata(0);
+ showscreen();
+ }
+ break;
+ case 'H': {;
+ loaddata(7); /* help on help */
+ showscreen();
+ }
+ break;
+ case '\33': exit(0); break;
+ default: newpage(r);
+ }
+ } while (!false);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/helpbak.cpp b/engines/avalanche/helpbak.cpp
new file mode 100644
index 0000000000..91825236fa
--- /dev/null
+++ b/engines/avalanche/helpbak.cpp
@@ -0,0 +1,161 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ HELPER The help system unit. */
+
+#define __helper_implementation__
+
+
+#include "helpbak.h"
+
+
+/*#include "Crt.h"*/
+/*#include "Lucerna.h"*/
+
+
+struct buttontype {
+ char trigger;
+ byte whither;
+};
+
+const integer buttonsize = 930;
+
+const integer toolbar = 0; const integer nim = 1; const integer kbd = 2; const integer credits = 3; const integer joystick = 4; const integer troubleshooting = 5; const integer story = 6;
+const integer mainscreen = 7; const integer registering = 8; const integer sound = 9; const integer mouse = 10; const integer filer = 11; const integer back2game = 12;
+const integer helponhelp = 13; const integer pgdn = 14; const integer pgup = 15;
+
+array<1,10,buttontype> buttons;
+
+void plot_button(integer y, byte which)
+{
+ untyped_file f;
+ pointer p;
+
+ getmem(p,buttonsize);
+ assign(f,"buttons.avd");
+ reset(f,1);
+ seek(f,which*buttonsize);
+ blockread(f,p,buttonsize);
+ putimage(470,y,p,0);
+ close(f);
+ freemem(p,buttonsize);
+}
+
+void getme(byte which);
+
+
+static void chalk(byte y, string z)
+{
+ outtextxy(16,41+y*10,z);
+}
+
+void getme(byte which) /* Help icons are 80x20 */
+{
+ string x;
+ text t;
+ byte y,fv;
+
+
+ str(which,x);
+ assign(t,string('h')+x+".raw");
+ y=0;
+ reset(t);
+
+ t >> x >> NL;
+ setfillstyle(1,1); bar(0,0,640,200);
+ setfillstyle(1,15); bar(8,40,450,200);
+ settextjustify(1,1); setcolor(14);
+ outtextxy(320,15,x);
+ settextjustify(0,2);
+ setcolor(3); settextstyle(0,0,2);
+ outtextxy(550,0,"help!");
+ /***/ setcolor(0); settextstyle(0,0,1);
+
+ do {
+ t >> x >> NL;
+ if (x=='!') flush(); /* End of the help text is signalled with a !. */
+ chalk(y,x);
+ y += 1;
+ } while (!false);
+
+ /* We are now at the end of the text. Next we must read the icons. */
+
+ y=0; settextjustify(1,1); setcolor(3);
+ while (! eof(t))
+ {
+ y += 1;
+ t >> x >> NL; /* Get the name of this button, and... */
+ if (x!='-') /* (hyphen signals an empty button.) */
+ {
+ t >> buttons[y].trigger >> NL;
+ t >> fv >> NL; plot_button(13+y*27,fv);
+ t >> buttons[y].whither >> NL; /* this is the position to jump to */
+
+ switch (buttons[y].trigger) {
+ case 'þ' : outtextxy(580,25+y*27,"Esc"); break;
+ case 'Ö' : outtextxy(580,25+y*27,"\30"); break;
+ case 'Ø' : outtextxy(580,25+y*27,"\31"); break;
+ default:
+ outtextxy(580,25+y*27,buttons[y].trigger);
+ }
+
+ } else buttons[y].trigger='\0';
+ }
+
+ settextjustify(0,2);
+ close(t);
+}
+
+void continue_help()
+{
+ char r;
+ byte fv;
+
+ do {
+ r=upcase(readkey());
+ switch (r) {
+ case '\33' : return; break;
+ case '\0' : switch (readkey()) {
+ case '\110':case '\111': r='Ö'; break;
+ case '\120':case '\121': r='Ø'; break;
+ case '\73': r='H'; break; /* Help on help */
+ }
+ break;
+ }
+
+ for( fv=1; fv <= 10; fv ++)
+ { buttontype& with = buttons[fv];
+ if (with.trigger==r)
+ {
+ dusk;
+ getme(with.whither);
+ dawn;
+ flush();
+ }}
+
+ } while (!false);
+}
+
+void boot_help()
+{
+ setactivepage(2);
+
+ getme(0);
+
+ dusk;
+ setvisualpage(2);
+ dawn;
+
+ continue_help();
+
+ dusk;
+ setvisualpage(cp);
+ draw_also_lines;
+ setactivepage(1-cp);
+ dawn;
+}
+
diff --git a/engines/avalanche/helpbak.h b/engines/avalanche/helpbak.h
new file mode 100644
index 0000000000..12a7869092
--- /dev/null
+++ b/engines/avalanche/helpbak.h
@@ -0,0 +1,11 @@
+#ifndef __helpbak_h__
+#define __helpbak_h__
+
+
+#include "graph.h"
+/*#include "Gyro.h"*/
+
+
+void boot_help();
+
+#endif
diff --git a/engines/avalanche/helper.cpp b/engines/avalanche/helper.cpp
new file mode 100644
index 0000000000..50e6a074d8
--- /dev/null
+++ b/engines/avalanche/helper.cpp
@@ -0,0 +1,282 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ HELPER The help system unit. */
+
+#define __helper_implementation__
+
+
+#include "helper.h"
+
+
+/*#include "Crt.h"*/
+/*#include "Lucerna.h"*/
+/*#include "Pingo.h"*/
+
+
+struct buttontype {
+ char trigger;
+ byte whither;
+};
+
+const integer buttonsize = 930;
+
+const integer toolbar = 0; const integer nim = 1; const integer kbd = 2; const integer credits = 3; const integer joystick = 4; const integer troubleshooting = 5; const integer story = 6;
+const integer mainscreen = 7; const integer registering = 8; const integer sound = 9; const integer mouse = 10; const integer filer = 11; const integer back2game = 12;
+const integer helponhelp = 13; const integer pgdn = 14; const integer pgup = 15;
+
+array<1,10,buttontype> buttons;
+byte highlight_was;
+
+void plot_button(integer y, byte which)
+{
+ untyped_file f;
+ pointer p;
+
+ if (y>200)
+ { background(2); delay(10); background(0); return; } /* Silly buttons. */
+ getmem(p,buttonsize);
+ assign(f,"buttons.avd");
+ reset(f,1);
+ seek(f,which*buttonsize);
+ blockread(f,p,buttonsize);
+
+ if (y==-177)
+ putimage(229,5,p,0);
+ else
+ putimage(470,y,p,0);
+ close(f);
+ freemem(p,buttonsize);
+}
+
+void getme(byte which);
+
+static untyped_file f;
+
+
+static void chalk(byte y, string z)
+{
+ outtextxy(16,41+y*10,z);
+}
+
+
+
+static void getline(string& x)
+{
+ byte fz;
+
+ blockread(f,x[0],1);
+ blockread(f,x[1],(byte)(x[0]));
+ for( fz=1; fz <= length(x); fz ++)
+ x[fz]=chr(ord(x[fz]) ^ 177);
+}
+
+void getme(byte which) /* Help icons are 80x20 */
+{
+ string x;
+ byte y,fv;
+ word offset;
+
+
+ off;
+ assign(f,"help.avd");
+ y=0;
+ highlight_was=177; /* Forget where the highlight was. */
+ reset(f,1);
+ seek(f,which*2);
+ blockread(f,offset,2);
+ seek(f,offset);
+
+ getline(x);
+ setfillstyle(1,1); bar(0,0,640,200);
+ setfillstyle(1,15); bar(8,40,450,200);
+ settextjustify(2,2);
+ blockread(f,fv,1);
+ plot_button(-177,fv);
+
+ setcolor(0); outtextxy(629,26,x); /* Plot the title. */
+ setcolor(3); outtextxy(630,25,x);
+
+ settextjustify(0,2); settextstyle(0,0,2);
+ setcolor(0); outtextxy(549,1,"help!");
+ setcolor(3); outtextxy(550,0,"help!");
+ /***/ settextstyle(0,0,1);
+
+ do {
+ getline(x);
+ if (x=='!') flush(); /* End of the help text is signalled with a !. */
+ if (x[1]=='\\')
+ {
+ setcolor(4);
+ chalk(y,copy(x,2,255));
+ } else
+ {
+ setcolor(0);
+ chalk(y,x);
+ }
+ y += 1;
+ } while (!false);
+
+ /* We are now at the end of the text. Next we must read the icons. */
+
+ y=0; settextjustify(1,1); settextstyle(0,0,2);
+ while (! eof(f))
+ {
+ y += 1;
+ blockread(f,buttons[y].trigger,1);
+ if (buttons[y].trigger=='\261') flush();
+ blockread(f,fv,1);
+ if (buttons[y].trigger!='\0') plot_button(13+y*27,fv);
+ blockread(f,buttons[y].whither,1); /* this is the position to jump to */
+
+
+ switch (buttons[y].trigger) {
+ case 'þ' : x="Esc"; break;
+ case 'Ö' : x='\30'; break;
+ case 'Ø' : x='\31'; break;
+ default:
+ x=buttons[y].trigger;
+ }
+ setcolor(0); outtextxy(589,26+y*27,x);
+ setcolor(3); outtextxy(590,25+y*27,x);
+
+ }
+
+ settextjustify(0,2); settextstyle(0,0,1);
+ close(f); on;
+}
+
+
+byte check_mouse();
+ /* Returns clicked-on button, or 0 if none. */
+static void light(byte which,byte colour)
+{
+ if (which==177) return; /* Dummy value for "no button at all". */
+ setcolor(colour); which=which & 31;
+ rectangle(466,11+which*27,555,35+which*27);
+}
+
+byte check_mouse()
+{
+ byte h_is;
+
+ byte check_mouse_result;
+ check;
+
+ if (mrelease!=0)
+ { /* Clicked *somewhere*... */
+ if ((mx<470) || (mx>550) || (((my-13) % 27)>20))
+ check_mouse_result=0; else
+ /* Clicked on a button. */
+ check_mouse_result=((my-13) / 27);
+ } else
+ {
+ if ((mx>470) && (mx<=550) && (((my-13) % 27)<=20))
+ { /* No click, so highlight. */
+ h_is=(my-13) / 27;
+ if ((h_is<1) || (h_is>6)) h_is=177; /* In case of silly values. */
+ } else h_is=177;
+
+ if ((h_is!=177) && ((keystatus & 1)>0)) h_is += 32;
+
+ if (h_is!=highlight_was)
+ {
+ off;
+ light(highlight_was,1);
+ highlight_was=h_is;
+ if (buttons[h_is & 31].trigger!='\0')
+ {
+ if (h_is>31) light(h_is,11); else light(h_is,9);
+ }
+ on;
+ }
+
+ check_mouse_result=0;
+ }
+ return check_mouse_result;
+}
+
+void continue_help()
+{
+ char r;
+ byte fv;
+
+ do {
+ while (! keypressed())
+ {
+ fv=check_mouse();
+
+ if (fv>0)
+ switch (buttons[fv].trigger) {
+ case '\0':/*null*/; break;
+ case '\376': return; break;
+ default: {
+ dusk;
+ getme(buttons[fv].whither);
+ dawn;
+ continue_;
+ }
+ }
+
+ }
+ r=upcase(readkey());
+ switch (r) {
+ case '\33' : return; break;
+ case '\0' : switch (readkey()) {
+ case '\110':case '\111': r='Ö'; break;
+ case '\120':case '\121': r='Ø'; break;
+ case '\73': r='H'; break; /* Help on help */
+ default: continue_;
+ }
+ break;
+ }
+
+ for( fv=1; fv <= 10; fv ++)
+ { buttontype& with = buttons[fv];
+ if (with.trigger==r)
+ {
+ dusk;
+ getme(with.whither);
+ dawn;
+ flush();
+ }}
+
+ } while (!false);
+}
+
+void boot_help()
+{
+ byte groi;
+
+ dusk;
+ off;
+ oncandopageswap=false; highlight_was=177;
+ copypage(3,1-cp); /* Store old screen. */ groi=getpixel(0,0);
+
+ /* Set up mouse. */
+ off_virtual;
+ newpointer(2);
+ setactivepage(3); setvisualpage(3);
+
+ getme(0);
+ dawn;
+
+ newpointer(9); on;
+ mousepage(3);
+
+ continue_help();
+
+ mousepage(cp);
+ dusk; off;
+ oncandopageswap=true;
+ copypage(1-cp,3); /* Restore old screen. */ groi=getpixel(0,0);
+ on_virtual; dawn; fix_flashers;
+
+ setvisualpage(cp);
+ setactivepage(1-cp);
+}
+
diff --git a/engines/avalanche/helper.h b/engines/avalanche/helper.h
new file mode 100644
index 0000000000..9c1c43ca42
--- /dev/null
+++ b/engines/avalanche/helper.h
@@ -0,0 +1,11 @@
+#ifndef __helper_h__
+#define __helper_h__
+
+
+#include "graph.h"
+/*#include "Gyro.h"*/
+
+
+void boot_help();
+
+#endif
diff --git a/engines/avalanche/hibits.cpp b/engines/avalanche/hibits.cpp
new file mode 100644
index 0000000000..8dba55c3c3
--- /dev/null
+++ b/engines/avalanche/hibits.cpp
@@ -0,0 +1,27 @@
+#include "ptoc.h"
+
+
+file<char> inf,outf;
+char x;
+string q;
+byte fv;
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ assign(inf,"v:thank.you");
+ assign(outf,"d:hibits.out");
+ reset(inf); rewrite(outf);
+
+ q=string('\40')+"(Seven is a bit of a lucky number.)"+'\40'+'\215'+'\212'+'\212';
+
+ for( fv=1; fv <= length(q); fv ++) outf << q[fv];
+
+ while (! eof(inf))
+ {;
+ inf >> x;
+ if (x<'\200') x += 128;
+ outf << x;
+ }
+ close(inf); close(outf);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/highs.cpp b/engines/avalanche/highs.cpp
new file mode 100644
index 0000000000..2ffd27198b
--- /dev/null
+++ b/engines/avalanche/highs.cpp
@@ -0,0 +1,116 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ HIGHS This handles the high-scores. */
+
+#define __highs_implementation__
+
+
+#include "highs.h"
+
+
+/*#include "Gyro.h"*/
+/*#include "Scrolls.h"*/
+
+
+typedef array<1,12,struct A1 {
+ varying_string<30> name;
+ word score;
+ varying_string<12> rank;
+ }> highscoretype;
+
+highscoretype h;
+
+void get_new_highs()
+{
+ byte fv;
+;
+ for( fv=1; fv <= 12; fv ++)
+ {
+ A1& with = h[fv];
+ ;
+ with.score=32-fv*2;
+ with.rank="...";
+ }
+ h[1].name="Mike"; h[2].name="Liz"; h[3].name="Thomas"; h[4].name="Mark";
+ h[5].name="Mandy"; h[6].name="Andrew"; h[7].name="Lucy Tryphena";
+ h[8].name="Tammy the dog";
+ h[9].name="Avaricius"; h[10].name="Spellchick"; h[11].name="Caddelli";
+ h[12].name="Spludwick";
+}
+
+void show_highs()
+ /* This procedure shows the high-scores. */
+{
+ byte fv;
+ varying_string<40> x;
+ varying_string<5> y;
+;
+ display("HIGH SCORERS\3\r Name\n\nScore Rank\r \"\"\"\"\n\n\"\"\"\"\" \"\"\"\"\f\4");
+ for( fv=1; fv <= 12; fv ++)
+ {
+ A1& with = h[fv];
+ ;
+ display(string('\15')+with.name+'\4');
+ fillchar(x,sizeof(x),'\40');
+ y=strf(with.score);
+ x[0]=chr(29-(length(with.name+y)));
+ display(x+y+' '+with.rank+'\4');
+ }
+
+ display("");
+}
+
+void store_high(string who)
+ /* This procedure shows the high-scores. */
+{
+ byte fv,ff;
+;
+
+ for( fv=1; fv <= 12; fv ++)
+ if (h[fv].score<dna.score) flush();
+
+ /* Shift all the lower scores down a space. */
+ for( ff=fv; ff <= 11; ff ++)
+ h[ff+1]=h[ff];
+
+ {
+ A1& with = h[fv];
+ ;
+ with.name=who;
+ with.score=dna.score;
+ }
+
+}
+
+void get_highs()
+{
+ file<highscoretype> f;
+;
+ /*$I-*/
+ assign(f,"scores.avd");
+ reset(f);
+ /* Did we get it? */
+
+ if (ioresult!=0)
+ {; /* No. */
+ get_new_highs(); /* Invent one. */
+ } else
+ {; /* Yes. */
+ f >> h;
+ close(f);
+ }
+}
+
+class unit_highs_initialize {
+ public: unit_highs_initialize();
+};
+static unit_highs_initialize highs_constructor;
+
+unit_highs_initialize::unit_highs_initialize() {;
+ get_highs();
+} \ No newline at end of file
diff --git a/engines/avalanche/highs.h b/engines/avalanche/highs.h
new file mode 100644
index 0000000000..3d6eb65807
--- /dev/null
+++ b/engines/avalanche/highs.h
@@ -0,0 +1,9 @@
+#ifndef __highs_h__
+#define __highs_h__
+
+
+ void show_highs();
+
+ void store_high(string who);
+
+#endif
diff --git a/engines/avalanche/hiz.cpp b/engines/avalanche/hiz.cpp
new file mode 100644
index 0000000000..bcff8ab2bd
--- /dev/null
+++ b/engines/avalanche/hiz.cpp
@@ -0,0 +1,287 @@
+#include "ptoc.h"
+
+
+/*$M 6000,600,600*/
+/*$V-,I-,R-,F+*/ /* Do not change these directives. */
+#include "graph.h"
+/*#include "Crt.h"*/
+/*#include "Dos.h"*/
+/*#include "Tsru.h"*/
+
+
+ /* program's signature */
+const varying_string<20> tsr_tmark = "FISH FISH FISH!!!";
+
+integer gd,gm;
+byte a /*absolute $A000:0*/;
+matrix<1,800,0,3,byte> sv;
+byte bit; string nam;
+byte tsr_int; word tsr_ax;
+
+void grab()
+{;
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ move(a,sv[1][bit],800);
+ }
+}
+
+void drop()
+{;
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ move(sv[1][bit],a,800);
+ }
+}
+
+void say(string x)
+{;
+ grab(); output << string('\15')+x;
+}
+
+void pak(string x)
+{
+ char r;
+;
+ say(x+" (press any key...)"); r=readkey(); drop();
+}
+
+string typein()
+{
+ char r; string x;
+string typein_result;
+;
+ x="";
+ do {
+ r=readkey();
+ switch (r) {
+ case '\10': if (x[0]>'\0') {; output << string('\10')+'\40'+'\10'; x[0] -= 1; } break;
+ case '\15': {; typein_result=x; return typein_result; } break;
+ case '\33': {; typein_result=""; return typein_result; } break;
+ default: if (x[0]<'\62') {; x=x+r; output << r; }
+ }
+ } while (!false);
+return typein_result;
+}
+
+void load()
+{
+ byte a /*absolute $A000:1200*/; untyped_file f;
+;
+ say("LOAD: filename?"); nam=typein(); drop();
+ if (nam=="") return;
+ assign(f,nam); reset(f,1);
+ if (ioresult!=0)
+ {;
+ pak("LOAD: file not found."); return;
+ }
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a,12080);
+ if (ioresult!=0)
+ {;
+ pak("LOAD: error whilst loading."); close(f); return;
+ }
+ }
+ close(f);
+}
+
+void save()
+{
+ const string header =
+ string("This is a file from an Avvy game, and its contents are subject to ")+
+ "copyright."+'\15'+'\12'+'\15'+'\12'+"Have fun!"+'\32';
+ untyped_file f; varying_string<30> screenname; searchrec s; char r;
+byte a /*absolute $A000:1200*/;
+;
+ say("SAVE: filename?"); nam=typein(); drop();
+ if (nam=="") return;
+ findfirst(nam,anyfile,s); if (doserror==0)
+ {;
+ say("SAVE: That exists, are you sure\? (Y/N)");
+ do { r=upcase(readkey()); } while (!(set::of('Y','N', eos).has(r))); drop();
+ if (r=='N') return;
+ }
+ screenname="Saved with HIZ.";
+ assign(f,nam); rewrite(f,1); blockwrite(f,header[1],146);
+ blockwrite(f,screenname,31);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockwrite(f,a,12080);
+ if (ioresult!=0)
+ {;
+ pak("SAVE: error whilst saving."); close(f); return;
+ }
+ }
+}
+
+void hedges()
+{;
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ fillchar(mem[0xa000*14*80],80,'\377');
+ fillchar(mem[0xa000*166*80],80,'\377');
+ }
+}
+
+void reset_()
+{
+ registers regs;
+;
+ regs.ax=14;
+ intr(0x10,regs);
+ directvideo=false;
+}
+
+void do_pop()
+{
+ char r;
+;
+ do {
+ say("HIZ: Load Save Hedges Reset eXit?"); r=upcase(readkey()); drop();
+ switch (r) {
+ case 'L': load(); break;
+ case 'S': save(); break;
+ case 'H': hedges(); break;
+ case 'R': reset_(); break;
+ case 'X': return; break;
+ }
+ } while (!false);
+}
+
+/* Now for the TSR stuff */
+
+void mypoprtn()
+{
+ registers r;
+;
+ beginpop;
+ do_pop();
+ endpop;
+}
+/**********************/
+void stop_tsr()
+{;
+ if (tsrexit)
+ output << "HIZ stopped" << NL;
+ else
+ output << "Unable to stop HIZ - other TSR has been installed." << NL;
+}
+/**********************/
+/* This interrupt is called at program start-up. Its purpose is to provide
+ a way to communicate with an installed copy of the TSR through cmdline
+ params. The installation of the intrpt serves to prevent any attempt to
+ install a 2nd copy of the TSR */
+void tsr_intrtn(word flags,word cs,word ip,word ax,word bx,word cx,word dx,word si,word di,word ds,word es,word bp)
+/*interrupt;*/
+{;
+ tsr_ax=ax;
+ cli;
+ beginint;
+ sti;
+
+ switch (tsr_ax) {
+ case 1: {;
+ stop_tsr(); /* Terminate TSR, if poss.*/
+ }
+ break;
+ case 2: {;
+ tsroff= true; /* Suspend TSR */
+ output << "HIZ suspended." << NL;
+ }
+ break;
+ case 3: {;
+ tsroff=false;
+ output << "HIZ restarted" << NL;
+ }
+ break;
+ }
+ cli;
+ endint;
+ sti;
+}
+/*******************/
+byte i;
+registers r;
+string st;
+boolean b;
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+
+ /********************************************/
+ /* Check to see if TSR is already installed */
+ /********************************************/
+
+ tsr_int=dupcheck(tsr_tmark,&tsr_intrtn);
+
+ /*****************************************/
+ /* If it IS already installed, check for */
+ /* parameter. */
+ /*****************************************/
+
+ if (tsr_int > 0)
+ {
+ if (paramcount>0)
+ {
+ st=paramstr(1);
+ for( i=1; i <= length(st); i ++)
+ st[i]=upcase(st[i]);
+ if (st=="STOP")
+ r.ax=1;
+ else if (st=="HOLD") r.ax=2;
+ else if (st=="RSTR") r.ax=3;
+ else r.ax=4;
+
+ if (r.ax<4)
+ {;
+ intr(tsr_int,r);
+ return 0;
+ }
+ else
+ {;
+ output << "HIZ: invalid parameter " << paramstr(1) << NL;
+ output << "Syntax: HIZ stop/hold/rstr" << NL;
+ return 0;
+ }
+ }
+ else
+ {;
+ output << "HIZ already installed." << NL;
+ output << "(If you're sure it isn't, try running BLANKINT /I." << NL;
+ output << "It's in the TURBO directory.)" << NL;
+ }
+ return 0;
+ }
+
+ output << string("Wait...")+'\15'; /* tell 'em to wait...! */
+
+ /* Call PopSetUp to point to PopUp routine. Include the
+ scancode and the keymask to activate the program. In
+ this example, the scancode is $23 (H) and the
+ keymask is 08h (Alt.) */
+
+ popsetup(&mypoprtn,0x23,0x8);
+
+ directvideo=false;
+ output << "Û Û ßÛß ßßÛ v1.0, (c) 1992, Thomas Thurman." << NL;
+ output << "ÛßÛ Û Üß" << NL;
+ output << "ß ß ßßß ßßß The AVD saving/loading/hedging program." << NL;
+ output << " Use with Dr. Genius. The Hot Key is Ctrl-Alt-H." << NL;
+
+ output << NL;
+ output << " Enter \"HIZ stop\" to remove Hiz from memory" << NL;
+ output << " \"HIZ hold\" to temporarily halt Hiz" << NL;
+ output << " \"HIZ rstr\" to restart Hiz" << NL;
+ stacksw=-1;
+ install_int;
+ keep(0);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/incline.cpp b/engines/avalanche/incline.cpp
new file mode 100644
index 0000000000..4103089cf5
--- /dev/null
+++ b/engines/avalanche/incline.cpp
@@ -0,0 +1,172 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ INCLINE The command-line parser. */
+
+#define __incline_implementation__
+
+
+#include "incline.h"
+
+#include "gyro.h"
+#include "logger.h"
+
+
+byte fv;
+char t;
+string bugline;
+boolean zoomy,numlockhold;
+
+boolean filename_specified;
+
+void syntax()
+{
+ assign(output,""); rewrite(output);
+ output << NL;
+ output << string("Lord Avalot d'Argent\n\n(c) ")+copyright+" Mark, Mike and Thomas Thurman." << NL;
+ output << string("~~~~~~~~~~~~~~~~~~~~~\n\n")+vernum << NL;
+ output << NL;
+ output << "Syntax:" << NL;
+ output << "\n/?\ndisplays this screen," << NL;
+ output << "\n/O\noverrides EGA check," << NL;
+ output << "\n/L<f>\nlogs progress to <f>, default AVVY.LOG," << NL;
+ output << "\n/P<x>\nlogs with Epson codes to <x>, default PRN," << NL;
+ output << "\n/Q\ncancels sound effects," << NL;
+ output << "\n/Z\ngoes straight into the game." << NL;
+ output << NL;
+ output << "\n\n\n\n\n\n\n... Have fun!" << NL;
+ exit(177);
+}
+
+void not_through_bootstrap()
+{
+ output << "Avalot must be loaded through the bootstrap." << NL;
+ exit(0);
+}
+
+void get_storage_addr()
+{
+ integer e;
+
+ val(paramstr(2),storage_seg,e); if (e!=0) not_through_bootstrap();
+ val(paramstr(3),storage_ofs,e); if (e!=0) not_through_bootstrap();
+ skellern=storage_ofs+1;
+}
+
+longint value(string x)
+{
+ longint q; integer e;
+
+ longint value_result;
+ val(x,q,e); value_result=q;
+ return value_result;
+}
+
+void undo_js()
+{
+ {
+ joysetup& with = js;
+
+ cxmin=with.xmid-(((with.xmid-with.xmin) / 10)*with.centre);
+ cxmax=with.xmid+(((with.xmax-with.xmid) / 10)*with.centre);
+ cymin=with.ymid-(((with.ymid-with.ymin) / 10)*with.centre);
+ cymax=with.ymid+(((with.ymax-with.ymid) / 10)*with.centre);
+
+/* writeln(lst,'MID ',xmid,'x',ymid);
+ writeln(lst,'MAX ',xmax,'x',ymax);
+ writeln(lst,'MIN ',xmin,'x',ymin);
+ writeln(lst,'CENTRE ',xmid);
+ writeln(lst,cxmin);
+ writeln(lst,cxmax);
+ writeln(lst,cymin);
+ writeln(lst,cymax);*/
+ }
+}
+
+void check_slope_line();
+static string slope;
+
+static boolean yn1(byte where) { boolean yn1_result;
+ yn1_result=slope[where]=='y'; return yn1_result;
+ }
+
+void check_slope_line()
+{
+ slope=paramstr(4);
+
+/* if slope='' then fillchar(slope,sizeof(slope),'n');*/
+
+ if (slope[1]!='1') not_through_bootstrap();
+
+ if (yn1(2)) syntax();
+
+ soundfx=yn1(3);
+ cl_override=yn1(4);
+ keyboardclick=yn1(5); /* 6 - see below */
+ demo=yn1(7);
+ zoomy=yn1(8);
+ numlockhold=yn1(9);
+ use_joy_a=yn1(10);
+
+ {
+ joysetup& with = js;
+
+ with.xmid=value(paramstr( 5));
+ with.ymid=value(paramstr( 6));
+ with.xmin=value(paramstr( 7));
+ with.ymin=value(paramstr( 8));
+ with.xmax=value(paramstr( 9));
+ with.ymax=value(paramstr(10));
+ with.centre=value(paramstr(11));
+
+ undo_js();
+ }
+
+ switch (slope[6]) {
+ case 'l': log_setup(paramstr(12),false); break;
+ case 'p': log_setup(paramstr(12),true); break;
+ }
+}
+
+void get_extra_data()
+{
+ if (! reloaded) return;
+
+ move(mem[storage_seg*storage_ofs+300],js,sizeof(js));
+
+ undo_js();
+}
+
+class unit_incline_initialize {
+ public: unit_incline_initialize();
+};
+static unit_incline_initialize incline_constructor;
+
+unit_incline_initialize::unit_incline_initialize() {
+/* writeln('Load code: ',paramstr(1));
+ writeln('Seg & ofs: ',paramstr(2),':',paramstr(3));
+ writeln('Slope line: ',paramstr(4));
+ writeln('Log file: ',paramstr(5));
+ writeln('File to load: ',paramstr(6));
+ readln;*/
+
+ filetoload=paramstr(13);
+ filename_specified = filetoload != "";
+
+ logging=false;
+
+ if ((paramcount<3) ||
+ ((paramstr(1)!="Go") && (paramstr(1)!="et"))) not_through_bootstrap();
+
+ reloaded=paramstr(1)=="et";
+
+ get_storage_addr();
+
+ get_extra_data();
+
+ check_slope_line();
+}
diff --git a/engines/avalanche/incline.h b/engines/avalanche/incline.h
new file mode 100644
index 0000000000..4b252a146e
--- /dev/null
+++ b/engines/avalanche/incline.h
@@ -0,0 +1,10 @@
+#ifndef __incline_h__
+#define __incline_h__
+
+
+
+/* This unit has NO externally-callable procedures. Also note that
+ it MUST be called *first* (so if you load AVALOT.PAS and press f7
+ twice you get to the "begin" statement.) */
+
+#endif
diff --git a/engines/avalanche/initxf.cpp b/engines/avalanche/initxf.cpp
new file mode 100644
index 0000000000..964aa51422
--- /dev/null
+++ b/engines/avalanche/initxf.cpp
@@ -0,0 +1,32 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+
+struct inirex {
+ varying_string<12> a;
+ word num;
+};
+
+text i;
+file<inirex> o;
+inirex x;
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ assign(i,"v:init0.dat"); reset(i);
+ assign(o,"v:init.avd"); rewrite(o);
+
+ while (! eof(i))
+ {;
+ i >> x.a >> NL;
+ i >> x.num >> NL;
+ o << x;
+ output << '.';
+ }
+
+ close(i); close(o);
+ output << NL;
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/inputtes.cpp b/engines/avalanche/inputtes.cpp
new file mode 100644
index 0000000000..0c7300bfc8
--- /dev/null
+++ b/engines/avalanche/inputtes.cpp
@@ -0,0 +1,47 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+typedef matrix<'\0','\377',0,15,byte> fonttype;
+
+integer gd,gm;
+fonttype font;
+varying_string<79> current;
+char r;
+
+void plottext()
+{
+ byte x,y;
+;
+ for( y=0; y <= 7; y ++)
+ {;
+ for( x=1; x <= length(current); x ++)
+ mem[0xa000*12880+y*80+x]=font[current[x]][y];
+ fillchar(mem[0xa000*12881+y*80+x],79-x,'\0');
+ }
+}
+
+void loadfont()
+{
+ file<fonttype> f;
+;
+ assign(f,"c:\\thomas\\ttsmall.fnt"); reset(f);
+ f >> font; close(f);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\turbo");
+ loadfont();
+ setfillstyle(1,6); bar(0,0,640,200);
+ current="";
+ do {
+ r=readkey();
+ current=current+r;
+ plottext();
+ } while (!false);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/intro.cpp b/engines/avalanche/intro.cpp
new file mode 100644
index 0000000000..5d34d69fc9
--- /dev/null
+++ b/engines/avalanche/intro.cpp
@@ -0,0 +1,596 @@
+#include "ptoc.h"
+
+
+/*$I c:\sleep5\DSMI.INC*/
+/*#include "Dos.h"*/
+#include "graph.h"
+/*#include "Crt.h"*/
+
+ /* This is a stand-alone program. */
+
+/* 0, black, remains 0.
+ Other numbers: the bits take precedence from the left.
+ e.g. for 9 = 1001, => fourth bit.
+
+ First 1 is in:
+
+ Fourth bit: 63 (egaWhite)
+ Third bit: 57 (egaLightBlue)
+ Second bit: 7 (light grey)
+ First bit: 1 (blue). */
+
+const palettetype our_palette =
+ {16,
+ /* sic */
+{{ 0, 1, 57, 57, 7, 7, 7, 7, 63, 63, 63, 63, 63, 63, 63, 63}}};
+
+ const integer scardcount = 13;
+
+ const array<0,scardcount-1,integer> soundcards =
+ {{1,2,6,3,4,5,8,9,10,7,7,7,7}};
+
+typedef matrix<'\0','\377',1,16,byte> fonttype;
+
+fonttype f;
+matrix<0,39,1,16,byte> next_line;
+
+byte next_bitline;
+
+byte displaycounter;
+
+boolean cut_out;
+
+word cut_out_time;
+
+array<1,117,varying_string<40> > x;
+
+byte this_line;
+
+word* skellern;
+boolean nomusic;
+
+/*$L intro.obj*/
+extern void introduction();
+
+void graphmode(integer mode)
+{
+ registers regs;
+
+ regs.ax=mode;
+ intr(0x10,regs);
+}
+
+/* Firstly, port[$3C4]:=2; port[$3CF]:=4;,
+ Then port[$3C5]:=1 shl bit; port[$3CF]:=bit;. */
+
+void loadfont()
+{
+ file<fonttype> ff;
+
+ assign(ff,"avalot.fnt");
+ reset(ff);
+ ff >> f;
+ close(ff);
+}
+
+void calc_next_line()
+ /* This proc sets up next_line. */
+{
+ string l;
+ byte fv,ff;
+ boolean oddlen;
+ byte start;
+ byte this_;
+
+ fillchar(next_line,sizeof(next_line),'\0'); /* All blanks. */
+
+ if (this_line==117)
+ {
+ cut_out=true;
+ return;
+ }
+
+ l=x[this_line];
+ this_line += 1;
+
+ start=(20-length(l) / 2)-1;
+ oddlen=odd(length(l));
+
+ for( fv=1; fv <= length(l); fv ++)
+ for( ff=1; ff <= 16; ff ++)
+ {
+ this_=f[l[fv]][ff];
+ if (oddlen)
+ { /* Odd, => 4 bits shift to the right. */
+ next_line[start+fv][ff] += this_ << 4;
+ next_line[start+fv-1][ff] += (cardinal)this_ >> 4;
+ } else
+ { /* Even, => no bit shift. */
+ next_line[start+fv][ff]=this_;
+ }
+ }
+ next_bitline=1;
+}
+
+void display()
+{
+ byte fv,ff;
+
+
+ if (next_bitline == 17) calc_next_line();
+
+ if (cut_out)
+ {
+ if (nomusic)
+ cut_out_time -= 1;
+ else
+ if (ampgetmodulestatus != md_playing) cut_out_time=0;
+ return;
+ }
+
+ move(mem[0xa000*40],mem[0xa000*0],7960);
+ for( fv=0; fv <= 39; fv ++)
+ mem[0xa1f1*8+fv]=next_line[fv][next_bitline];
+ next_bitline += 1;
+
+}
+
+void plot_a_star(integer x,integer y)
+{
+ byte ofs;
+
+ ofs=x % 8;
+ x=x / 8;
+ mem[0xa000*x+y*40] += (cardinal)128 >> ofs;
+}
+
+void plot_some_stars(integer y)
+{
+ byte fv,times;
+
+ switch (Random(7)) {
+ case 1: times=1; break;
+ case 2: times=2; break;
+ case 3: times=3; break;
+ default: return;
+ }
+
+ for( fv=1; fv <= times; fv ++)
+ plot_a_star(Random(320),y);
+}
+
+void starry_starry_night()
+{
+ integer y;
+ byte bit;
+
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+
+ for( bit=0; bit <= 2; bit ++)
+ {
+ port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( y=1; y <= 200; y ++)
+ plot_some_stars(y);
+ }
+}
+
+void setupgraphics() /* Fix this proc. This prog SHOULDN'T use the
+ Graph unit. */
+{
+ integer gd,gm;
+
+ gd=3; gm=1; initgraph(gd,gm,"");
+}
+
+void shovestars()
+{
+ move(mem[0xa000*0],mem[0xa000*40],7960);
+ fillchar(mem[0xa000*0],40,'\0');
+ plot_some_stars(0);
+}
+
+void do_next_line()
+{
+ byte bit;
+
+ port[0x3c4]=2; port[0x3ce]=4;
+
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c5]=1 << bit; port[0x3cf]=bit;
+
+ switch (bit) {
+ case 0: if ((displaycounter % 10)==0) shovestars(); break;
+ case 1: if ((displaycounter % 2)==0) shovestars(); break;
+ case 2: shovestars(); break;
+ case 3: display(); break; /* The text. */
+ }
+ }
+
+ if (displaycounter==40) displaycounter=0;
+
+}
+
+void load_text()
+{
+ word fv;
+ char* c;
+ byte thisline;
+
+
+ c=addr(introduction());
+ thisline=0;
+ fillchar(x,sizeof(x),'\0');
+
+ for( fv=1; fv <= 2456; fv ++)
+ {
+ switch (*c) {
+ case '\15': thisline += 1; break;
+ case '\12':/*nop*/; break;
+ default: x[thisline]=x[thisline]+*c;
+ }
+
+ c += 1;
+ }
+}
+
+void check_params()
+{
+ word s,o; integer e;
+
+ if (paramstr(1)!="jsb") exit(0);
+ val(paramstr(2),s,e); if (e!=0) exit(0);
+ val(paramstr(3),o,e); if (e!=0) exit(0);
+ skellern=ptr(s,o+1);
+}
+
+integer getsoundhardware(psoundcard scard)
+{
+ integer sc,i,autosel,select;
+ char ch;
+ integer e;
+
+
+
+integer getsoundhardware_result;
+Lagain:
+ sc=detectgus(scard);
+ if (sc!=0) sc=detectpas(scard);
+ if (sc!=0) sc=detectaria(scard);
+ if (sc!=0) sc=detectsb(scard);
+
+ /* if no sound card found, zero scard */
+ if (sc!=0) fillchar(scard,sizeof(tsoundcard),0);
+
+ autosel=-1;
+/* if sc=0 then
+ for i:=0 to scardcount-1 do
+ if scard^.ID=soundcards[i].ID then begin
+ { Set auto selection mark }
+ autosel:=i+1;
+ break;
+ end;*/
+
+ /* Print the list of sound cards */
+
+ val(paramstr(13),select,e);
+
+ /* Default entry? */
+ if (select==0) select=autosel;
+ if (select!=autosel) {
+ /* clear all assumptions */
+ sc=-1;
+ fillchar(scard,sizeof(tsoundcard),0);
+ scard->id=soundcards[select-1]; /* set correct ID */
+ }
+
+ /* Query I/O address */
+ if (scard->id==id_dac) scard->ioport=0x378;
+
+ /* Read user input */
+ val(paramstr(15),i,e);
+
+ if (i!=0) scard->ioport=i;
+ if (sc!=1) /* Not autodetected */
+ switch (scard->id) {
+ case id_sb16:
+ case id_pas16:
+ case id_wss:
+ case id_aria:
+ case id_gus : scard->samplesize=2;
+ break; /* 16-bit card */
+ case id_sbpro:
+ case id_pas:
+ case id_pasplus: scard->stereo=true;
+ break; /* enable stereo */
+ default: {
+ scard->samplesize=1;
+ scard->stereo=false;
+ }
+ }
+
+ if (scard->id!=id_dac) {
+ val(paramstr(17),i,e);
+
+ if (i!=0) scard->dmairq=i;
+
+ val(paramstr(16),i,e);
+
+ if (i!=0) scard->dmachannel=i;
+ } else {
+ /* Select correct DAC */
+ scard->maxrate=44100;
+ if (select==11) {
+ scard->stereo=true;
+ scard->dmachannel=1; /* Special 'mark' */
+ scard->maxrate=60000;
+ } else
+ if (select==12) {
+ scard->stereo=true;
+ scard->dmachannel=2;
+ scard->maxrate=60000;
+ if (scard->ioport==0) scard->ioport=0x378;
+ } else
+ if (select==13) {
+ scard->dmachannel=0;
+ scard->ioport=0x42; /* Special 'mark' */
+ scard->maxrate=44100;
+ }
+ }
+
+/* writeln('Your selection: ',select,' at ',scard^.ioPort,
+ ' using IRQ ',scard^.dmaIRQ,' and DMA channel ',scard^.dmaChannel);
+ readln;*/
+
+ getsoundhardware_result=0;
+return getsoundhardware_result;
+}
+
+tsoundcard scard;
+tmcpstruct mcpstrc;
+tdds dds;
+pmodule module;
+tsdi_init sdi;
+integer e,
+bufsize;
+char ch;
+boolean v86,
+vdsok;
+longint a,rate,
+tempseg;
+string answer;
+pointer temp;
+word flags;
+word curch;
+byte modulevolume;
+array<0,4,tsampleinfo> sample;
+array<0,31,word> voltable;
+
+int main(int argc, const char* argv[])
+{
+
+ pio_initialize(argc, argv);
+ check_params();
+
+ nomusic=paramstr(13)=='0';
+
+ if (! nomusic)
+ {
+ /* Read sound card information */
+ if (getsoundhardware(&scard)==-1) exit(1);
+
+
+ /* Initialize Timer Service */
+ tsinit;
+ atexit(&tsclose);
+ if (scard.id==id_gus) {
+ /* Initialize GUS player */
+ #ifndef DPMI
+ scard.extrafield[2]=1; /* GUS DMA transfer does not work in V86 */
+ #endif
+ gusinit(&scard);
+ atexit(&gusclose);
+
+ /* Initialize GUS heap manager */
+ gushminit;
+
+ /* Init CDI */
+ cdiinit;
+
+ /* Register GUS into CDI */
+ cdiregister(&cdi_gus,0,31);
+
+ /* Add GUS event player engine into Timer Service */
+ tsaddroutine(&gusinterrupt,gus_timer);
+ } else {
+ /* Initialize Virtual DMA Specification */
+ #ifndef DPMI
+ vdsok=vdsinit==0;
+ #else
+ vdsok=false;
+ #endif
+
+ fillchar(mcpstrc,sizeof(tmcpstruct),0);
+
+ /* Query for sampling rate */
+ val(paramstr(14),a,e);
+ if (a>4000) rate=a; else rate=21000;
+
+ /* Query for quality */
+ mcpstrc.options=mcp_quality;
+
+ switch (scard.id) {
+ case id_sb : {
+ sdi=sdi_sb;
+ scard.maxrate=22000;
+ }
+ break;
+ case id_sbpro : {
+ sdi=sdi_sbpro;
+ scard.maxrate=22000;
+ }
+ break;
+ case id_pas:
+ case id_pasplus:
+ case id_pas16 : {
+ sdi=sdi_pas;
+ scard.maxrate=44100;
+ }
+ break;
+ case id_sb16 : {
+ sdi=sdi_sb16;
+ scard.maxrate=44100;
+ }
+ break;
+ case id_aria : {
+ sdi=sdi_aria;
+ scard.maxrate=44100;
+ }
+ break;
+ case id_wss : {
+ sdi=sdi_wss;
+ scard.maxrate=48000;
+ }
+ break;
+ #ifndef DPMI
+ case id_dac : sdi=sdi_dac; break; /* Only available in real mode */
+ #endif
+ }
+
+ mcpinitsounddevice(sdi,&scard);
+ a=mcp_tablesize;
+ mcpstrc.reqsize=0;
+
+ /* Calculate mixing buffer size */
+ bufsize=(longint)(2800*(integer)(scard.samplesize) << (byte)(scard.stereo))*
+ (longint)(rate) / (longint)(22000);
+ mcpstrc.reqsize=0;
+ if ((mcpstrc.options & mcp_quality)>0)
+ if (scard.samplesize==1) a += mcp_qualitysize; else
+ a=mcp_tablesize16+mcp_qualitysize16;
+ if ((longint)(bufsize)+(longint)(a)>65500) bufsize=longint(65500)-a;
+
+ #ifdef DPMI
+ dpmiversion((byte)(e),(byte)(e),(byte)(e),flags);
+ v86=(flags & 2)==0;
+ #endif
+
+ /* Allocate volume table + mixing buffer */
+ #ifdef DPMI
+
+ /* In the V86 mode, the buffer must be allocated below 1M */
+ if (v86) {
+ tempseg=0;
+ dpmiallocdos((a+longint(bufsize)) / longint(16)+longint(1),flags,(word)(tempseg));
+ } else {
+ #endif
+ getmem(temp,a+longint(bufsize));
+ if (temp==nil) exit(2);
+ #ifdef DPMI
+ tempseg=seg(temp);
+ }
+ #else
+ tempseg=seg(temp)+ofs(temp) / 16+1;
+ #endif
+ mcpstrc.bufferseg=tempseg;
+ mcpstrc.bufferphysical=-1;
+
+ if (vdsok && (scard.id!=id_dac)) {
+ dds.size=bufsize;
+ dds.segment=tempseg;
+ dds.offset=0;
+
+ /* Lock DMA buffer if VDS present */
+ if (vdslockdma(&dds)==0) mcpstrc.bufferphysical=dds.address;
+ }
+ if (mcpstrc.bufferphysical==-1)
+ #ifdef DPMI
+ mcpstrc.bufferphysical=dpmigetlinearaddr(tempseg);
+ #else
+ mcpstrc.bufferphysical=(longint)(tempseg) << 4;
+ #endif
+
+ mcpstrc.buffersize=bufsize;
+ mcpstrc.samplingrate=rate;
+ /* Initialize Multi Channel Player */
+ if (mcpinit(&mcpstrc)!=0) exit(3);
+ atexit(&mcpclose);
+
+ /* Initialize Channel Distributor */
+ cdiinit;
+
+ /* Register MCP into CDI*/
+ cdiregister(&cdi_mcp,0,31);
+ }
+
+ /* Try to initialize AMP */
+ if (ampinit(0)!=0) exit(3);
+ atexit(&ampclose);
+
+ /* Hook AMP player routine into Timer Service */
+ tsaddroutine(&ampinterrupt,amp_timer);
+
+ #ifndef DPMI
+ /* If using DAC, then adjust DAC timer */
+ if (scard.id==id_dac) setdactimer(tsgettimerrate);
+ #endif
+
+ if (scard.id!=id_gus) mcpstartvoice; else gusstartvoice;
+
+ /* Load an example AMF */
+ module=amploadmod("glover.mod",0);
+ if (module==nil) exit(4);
+
+ /* Is it MCP, Quality mode and 16-bit card? */
+ if ((scard.id!=id_gus) && ((mcpstrc.options & mcp_quality)>0)
+ && (scard.samplesize==2)) {
+ /* Open module+2 channels with amplified volumetable (4.7 gain) */
+ for( a=1; a <= 32; a ++) voltable[a-longint(1)]=a*longint(150) / longint(32);
+ cdisetupchannels(0,module->channelcount+2,&voltable);
+ } else {
+ /* Open module+2 channels with regular volumetable */
+ cdisetupchannels(0,module->channelcount+2,nil);
+ }
+
+ curch=module->channelcount;
+ modulevolume=64;
+
+ /***/ ampplaymodule(module,0);
+ }
+
+ setupgraphics();
+
+ randseed=177; checkbreak=false;
+
+ load_text();
+
+ this_line=1;
+
+ graphmode(0xd);
+ loadfont();
+
+ next_bitline=17;
+ displaycounter=0;
+
+ cut_out_time=333;
+
+ setallpalette(our_palette);
+
+ starry_starry_night();
+
+ while ((cut_out_time>0) && (! keypressed()))
+ {
+
+ *skellern=0;
+
+ do_next_line();
+
+ displaycounter += 1;
+
+ do {; } while (!(*skellern>0));
+ }
+
+ if (! nomusic) ampstopmodule;
+ graphmode(3);
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/ints.cpp b/engines/avalanche/ints.cpp
new file mode 100644
index 0000000000..71c2d47577
--- /dev/null
+++ b/engines/avalanche/ints.cpp
@@ -0,0 +1,29 @@
+#include "ptoc.h"
+
+ /* Avalot interrupt handler */
+/*#include "Dos.h"*/
+
+/*$F+*/
+registers r;
+void() old1b;
+
+boolean quicko;
+
+void new1b() /* interrupt; */
+{;
+ quicko=true;
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ getintvec(0x1b,&old1b);
+ setintvec(0x1b,addr(new1b()));
+ quicko=false;
+ do {; } while (!quicko);
+ setintvec(0x1b,&old1b);
+/* r.ah:=$02; intr($16,r);
+ writeln(r.al and 12); { Only checks Ctrl and Alt. Both on = 12. }
+ until false;*/
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/joysetup.cpp b/engines/avalanche/joysetup.cpp
new file mode 100644
index 0000000000..0c07a35961
--- /dev/null
+++ b/engines/avalanche/joysetup.cpp
@@ -0,0 +1,97 @@
+#include "ptoc.h"
+
+ /* Avalot joystick setup routines. To be incorporated
+ into Setup2 whenever I get a chance. */
+/*#include "Joystick.h"*/
+/*#include "Crt.h"*/
+
+
+struct joysetup {
+ word xmid,ymid,xmin,ymin,xmax,ymax;
+ byte centre; /* Size of centre in tenths */
+};
+
+joysetup js;
+file<joysetup> jf;
+
+boolean detect()
+{
+ word x,y,xo,yo;
+ byte count;
+boolean detect_result;
+;
+ count=0;
+ if (joystickpresent)
+ {;
+ detect_result=true;
+ return detect_result;
+ }
+ readjoya(xo,yo);
+ do {
+ if (count<7) count += 1; /* Take advantage of "flutter" */
+ if (count==6)
+ {;
+ output << "The Bios says you don't have a joystick. However, it's often wrong" << NL;
+ output << "about such matters. So, do you? If you do, move joystick A to" << NL;
+ output << "continue. If you don't, press any key to cancel." << NL;
+ }
+ readjoya(x,y);
+ } while (!((keypressed()) | (x!=xo) || (y!=yo)));
+ detect_result=~ keypressed();
+return detect_result;
+}
+
+void display()
+{;
+ {;
+ gotoxy(20,10); output << "X min: " << js.xmin << " ";
+ gotoxy(20,11); output << "X max: " << js.xmax << " ";
+ gotoxy(20,12); output << "Y min: " << js.ymin << " ";
+ gotoxy(20,13); output << "Y max: " << js.ymax << " ";
+ }
+}
+
+void getmaxmin()
+{
+ word x,y;
+;
+ output << "Rotate the joystick around in a circle, as far from the centre as it" << NL;
+ output << "can get. Then click a button." << NL;
+ {;
+ js.xmax=0; js.xmin=maxint;
+ js.ymax=0; js.ymin=maxint;
+ }
+ do {
+ readjoya(x,y);
+ {;
+ if (x<js.xmin) js.xmin=x;
+ if (y<js.ymin) js.ymin=y;
+ if (x>js.xmax) js.xmax=x;
+ if (y>js.ymax) js.ymax=y;
+ display();
+ }
+ } while (!(buttona1 | buttona2));
+ do {; } while (!(~ (buttona1 | buttona2)));
+ output << NL;
+ output << "Thank you. Now please centre your joystick and hit a button." << NL;
+ do {; } while (!(buttona1 | buttona2));
+ readjoya(js.xmid,js.ymid);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ textattr=2;
+ clrscr;
+ output << "Avalot joystick setup routine- by TT. Thanks go to David B. Howorth." << NL;
+ output << NL;
+ if (detect()) output << "You've got a joystick!" << NL; else return 0;
+ getmaxmin();
+ do {
+ output << "Centring factor\? (3-9)";
+ input >> js.centre >> NL;
+ } while (!(set::of(range(1,9), eos).has(js.centre)));
+ assign(jf,"v:joytmp.dat");
+ rewrite(jf); jf << js; close(jf); /* write it all out to disk. */
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/joystick.cpp b/engines/avalanche/joystick.cpp
new file mode 100644
index 0000000000..20f803ec11
--- /dev/null
+++ b/engines/avalanche/joystick.cpp
@@ -0,0 +1,183 @@
+#include "ptoc.h"
+
+#define __joystick_implementation__
+
+
+/*
+Copyright (c) 1989, 1990 David B. Howorth
+
+Requires Turbo Pascal 5.0 or later.
+
+Unit last revised May 9, 1989.
+This comment last revised October 22, 1990.
+
+This file, when compiled to disk, creates JOYSTICK.TPU, a Turbo Pascal unit
+containing all necessary routines for joystick control. The routines can
+be demonstrated by running the accompanying program JOYDEMO (after first
+compiling JOYSTICK.PAS to disk).
+
+For further information see the accompanying file, JOYSTICK.DOC.
+
+Permission is granted to distribute this file and the accompanying files
+(JOYDEMO.PAS and JOYSTICK.DOC) provided (1) all three files are distributed
+together and (2) no fee is charged.
+
+Permission is granted to include compiled versions of the routines in these
+files in any program, commercial or noncommercial, provided only that if the
+program is distributed, whether commercially or noncommercially, a copy
+(including any documentation) be sent to me; and, if you distribute your
+program as shareware, treat me as registered. My address is 01960 SW Palatine
+Hill Road, Portland, Oregon 97219.
+*/
+
+#include "joystick.h"
+
+
+/*#include "Dos.h"*/
+
+
+typedef void(*readjoyproc)(byte a,byte b,word& c,word& d);
+typedef boolean(*buttonfunc)(byte a);
+
+readjoyproc readjoy;
+buttonfunc button;
+registers reg;
+
+/*----------------------------- private routines ----------------------------*/
+
+boolean newbios()
+{
+ char decadechar /*absolute $F000:$FFFB*/;
+ char yearchar /*absolute $F000:$FFFC*/;
+
+ boolean newbios_result;
+ newbios_result = (set::of('9','0', eos).has(decadechar)) /*an optimistic view of software life*/
+ || ((decadechar == '8') && (set::of(range('4','9'), eos).has(yearchar)));
+ return newbios_result;
+}
+
+/*$F+*/
+
+void oldreadjoy(byte xbit,byte ybit, word& xaxis, word& yaxis)
+{;
+/*
+inline(
+ $BA/$01/$02/ {mov dx, 201h ;load dx with joystick port address }
+ $C4/$BE/>XAxis/ {les di, XAxis[bp] ;load es with segment and di w/offset }
+ $8A/$66/<xbit/ {mov ah, xbit[bp] ;set appropriate bit in ah }
+ $E8/$0C/$00/ {call SUBR }
+ $C4/$BE/>YAxis/ {les di, YAxis[bp] }
+ $8A/$66/<ybit/ {mov ah, ybit[bp] ;set appropriate bit in ah }
+ $E8/$02/$00/ {call SUBR }
+ $EB/$1D/ {jump short END ;we're done! }
+ {SUBR: ;first wait, if necessary, until }
+ { ; relevant bit is 0: }
+ $B9/$FF/$FF/ { mov cx, 0ffffh ;fill cx to the brim }
+ $EC/ {WAIT: in al, dx ;get input from port 201h }
+ $84/$E0/ { test al, ah ;is the relevant bit 0 yet? }
+ $E0/$FB/ { loopne WAIT ;if not, go back to wait }
+
+ $B9/$FF/$FF/ { mov cx, 0ffffh ;fill cx to the brim again }
+ $FA/ { cli ;disable interrupts }
+ $EE/ { out dx, al ;'nudge' port 201h }
+ $EC/ {AGAIN: in al, dx ;get input from port 201h }
+ $84/$E0/ { test al, ah ;is the relevant bit 0 yet? }
+ $E0/$FB/ { loopne AGAIN ;if not, go back to AGAIN }
+ $FB/ { sti ;reenable interrupts }
+ $F7/$D9/ { neg cx ;negative cx }
+ $81/$C1/$FF/$FF/{ add cx, 0ffffh ;add 0ffffh back to value in cx }
+ $26/ { es: ;segment override }
+ $89/$0D/ { mov [di], cx ;store value of cx in location }
+ { ; of relevant variable }
+ $C3); { ret }
+ {END: }
+*/
+} /* OldReadJoy */
+
+void newreadjoy(byte which, byte meaningless, word& xaxis, word& yaxis)
+{
+ reg.ah = 0x84;
+ reg.dx = 1;
+ intr(0x15,reg);
+ if (which == 1)
+ {
+ xaxis = reg.ax;
+ yaxis = reg.bx;
+ }
+ else {
+ xaxis = reg.cx;
+ yaxis = reg.dx;
+ }
+}
+
+boolean oldbutton(byte mask)
+{ boolean oldbutton_result;
+ oldbutton_result = ((port[0x201] & mask) == 0); return oldbutton_result;
+}
+
+boolean newbutton(byte mask)
+{
+ boolean newbutton_result;
+ reg.ah = 0x84;
+ reg.dx = 0;
+ intr(0x15,reg);
+ newbutton_result = ((reg.al & mask) == 0);
+ return newbutton_result;
+}
+
+/*$F-*/
+
+/*----------------------------- public routines -----------------------------*/
+
+void readjoya(word& xaxis, word& yaxis)
+{ readjoy(1,2,xaxis, yaxis); }
+
+void readjoyb(word& xaxis, word& yaxis)
+{ readjoy(4,8,xaxis, yaxis); }
+
+boolean buttona1()
+{ boolean buttona1_result;
+ buttona1_result = button(0x10); return buttona1_result;
+}
+
+boolean buttona2()
+{ boolean buttona2_result;
+ buttona2_result = button(0x20); return buttona2_result;
+}
+
+boolean buttonb1()
+{ boolean buttonb1_result;
+ buttonb1_result = button(0x40); return buttonb1_result;
+}
+
+boolean buttonb2()
+{ boolean buttonb2_result;
+ buttonb2_result = button(0x80); return buttonb2_result;
+}
+
+boolean joystickpresent()
+{
+ boolean joystickpresent_result;
+ intr(0x11,reg);
+ joystickpresent_result = ((reg.ax & 0x1000) != 0);
+ return joystickpresent_result;
+}
+
+/*------------------------------ initialization -----------------------------*/
+
+class unit_joystick_initialize {
+ public: unit_joystick_initialize();
+};
+static unit_joystick_initialize joystick_constructor;
+
+unit_joystick_initialize::unit_joystick_initialize() {
+ if (newbios())
+ { /* use BIOS routines */
+ readjoy = newreadjoy;
+ button = newbutton;
+ }
+ else { /* use work-around routines */
+ readjoy = oldreadjoy;
+ button = oldbutton;
+ }
+}
diff --git a/engines/avalanche/joystick.h b/engines/avalanche/joystick.h
new file mode 100644
index 0000000000..0a3147eda2
--- /dev/null
+++ b/engines/avalanche/joystick.h
@@ -0,0 +1,22 @@
+#ifndef __joystick_h__
+#define __joystick_h__
+
+
+void readjoya(word& xaxis, word& yaxis);
+/* Reads the X and Y coordinates of Joystick A. */
+
+void readjoyb(word& xaxis, word& yaxis);
+/* Reads the X and Y coordinates of Joystick B. */
+
+boolean buttona1();
+boolean buttona2();
+boolean buttonb1();
+boolean buttonb2();
+/* These four functions return the status (true = in; false = out) of each
+ of the buttons on joystick A and B. On most models, Button #1 is the
+ top button. */
+
+boolean joystickpresent();
+/* This function indicates whether a joystick is installed. */
+
+#endif
diff --git a/engines/avalanche/loading.cpp b/engines/avalanche/loading.cpp
new file mode 100644
index 0000000000..4e48cb50a0
--- /dev/null
+++ b/engines/avalanche/loading.cpp
@@ -0,0 +1,23 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+integer gd,gm;
+byte a /*absolute $A000:1200*/;
+byte bit;
+untyped_file f;
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"");
+ assign(f,"c:\\sleep\\test.ega"); reset(f,1);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a,12000);
+ }
+ close(f);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/logger.cpp b/engines/avalanche/logger.cpp
new file mode 100644
index 0000000000..5029dab2ab
--- /dev/null
+++ b/engines/avalanche/logger.cpp
@@ -0,0 +1,210 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ LOGGER Handles the logging. */
+
+#define __logger_implementation__
+
+
+#include "logger.h"
+
+
+/*#include "Gyro.h"*/
+/*#include "Trip5.h"*/
+
+
+const char divide[] = "--- oOo ---";
+
+/* Epson codes:
+
+ startwith='';
+ endwith='';
+ double_width = #14; { shift out (SO) }
+ double_off = #20; { device control 4 (DC4) }
+ italic = #27+'4'; { switches italics on... }
+ italic_off = #27+'5'; { and off. }
+ emph_on = #27+#69;
+ emph_off = #27+#70;
+ divide_indent = 15;
+
+*/
+
+ /* L'jet codes: */
+
+const string startwith = string('\33')+'\50'+"10J"+'\130';
+const string endwith = string('\33')+'\105';
+const string italic = string('\33')+'\50'+'\163'+'\61'+'\123'; /* switches italics on... */
+const string italic_off = string('\33')+'\50'+'\163'+'\60'+'\123'; /* and off. */
+const string emph_on = string('\33')+'\50'+'\163'+'\63'+'\102';
+const string emph_off = string('\33')+'\50'+'\163'+'\60'+'\102';
+const string double_width = emph_on; /* There IS no double-width. */
+const string double_off = emph_off; /* So we'll have to use bold. */
+const string quote = 'ª';
+const string unquote = 'º';
+const string copyright = "(c)";
+const integer divide_indent = 30;
+
+string scroll_line;
+byte scroll_line_length;
+
+void centre(byte size,byte x) /* Prints req'd number of spaces. */
+{
+ byte fv;
+;
+ if (~ logging) return;
+ for( fv=1; fv <= size-(x / 2); fv ++)
+ output << logfile << ' ';
+}
+
+void log_setup(string name, boolean printing) /* Sets up. */
+{;
+ assign(logfile,name);
+ rewrite(logfile);
+ output << logfile << startwith;
+ log_epson=printing;
+ logging=true;
+
+ if (! printing) { quote='"'; unquote='"'; copyright="(c)"; }
+}
+
+void log_divider() /* Prints the divider sign. */
+{
+ byte fv;
+;
+ if (~ logging) return;
+ if (log_epson)
+ {;
+ output << logfile << string(' ')+double_width;
+ for( fv=1; fv <= divide_indent; fv ++) output << logfile << ' ';
+ output << logfile << string(' ')+double_off;
+ } else
+ for( fv=1; fv <= 36; fv ++) output << logfile << ' ';
+ output << logfile << divide << NL;
+}
+
+void log_command(string x) /* Prints a command */
+{;
+ if (~ logging) return;
+ if (log_epson)
+ output << logfile << double_width+'>'+double_off+' '+italic+x+italic_off << NL;
+ else
+ output << logfile << string("> ")+x << NL;
+}
+
+void log_addstuff(string x)
+{;
+ if (~ logging) return;
+ scroll_line=scroll_line+x;
+}
+
+void log_scrollchar(string x) /* print one character */
+{
+ varying_string<2> z;
+;
+ if (~ logging) return;
+ switch (x[1]) {
+ case '`': z=quote; break; /* Open quotes: "66" */
+ case '"': z=unquote; break; /* Close quotes: "99" */
+ case '\357': z=copyright; break; /* Copyright sign. */
+ default: z=x;
+ }
+ log_addstuff(z);
+ scroll_line_length += length(z);
+}
+
+void log_italic()
+{;
+ if (~ logging) return;
+ if (log_epson)
+ log_addstuff(italic);
+ else
+ log_addstuff("*");
+}
+
+void log_roman()
+{;
+ if (~ logging) return;
+ if (log_epson)
+ log_addstuff(italic_off);
+ else
+ log_addstuff("*");
+}
+
+void log_epsonroman() /* This only sends the Roman code if you're on Epson.*/
+{;
+ if (~ logging) return;
+ if (log_epson) log_addstuff(italic_off);
+}
+
+void log_scrollline() /* Set up a line for the scroll driver */
+{;
+ scroll_line_length=0;
+ scroll_line="";
+}
+
+void log_scrollendline(boolean centred)
+{
+ byte x,fv;
+;
+ if (~ logging) return;
+ x=17;
+ if (centred) x += (50-scroll_line_length) / 2;
+ for( fv=1; fv <= x; fv ++) output << logfile << ' ';
+ output << logfile << scroll_line << NL;
+}
+
+void log_bubbleline(byte linenum,byte whom, string x)
+{
+ byte fv;
+;
+ if (~ logging) return;
+ if (linenum==1)
+ {;
+ for( fv=1; fv <= 15; fv ++) output << logfile << ' ';
+ output << logfile << italic+tr[whom].a.name+": "+italic_off+x << NL;
+ } else
+ {;
+ for( fv=1; fv <= 17; fv ++) output << logfile << ' ';
+ output << logfile << x << NL;
+ }
+}
+
+void log_newline()
+{;
+ if (logging) output << logfile << NL;
+}
+
+void log_newroom(string where)
+{
+ byte fv;
+;
+ if (~ logging) return;
+ for( fv=1; fv <= 20; fv ++) output << logfile << ' ';
+ if (log_epson) output << logfile << emph_on;
+ output << logfile << string('(')+where+')';
+ if (log_epson) output << logfile << emph_off;
+ output << logfile << NL;
+}
+
+void log_aside(string what)
+ /* This writes "asides" to the printer. For example, moves in Nim. */
+{;
+ if (~ logging) return;
+ output << logfile << " (" << italic << what << italic_off << ')' << NL;
+ /* "What" is what to write. */
+}
+
+void log_score(word credit,word now)
+{
+ byte fv;
+;
+ if (~ logging) return;
+ for( fv=1; fv <= 50; fv ++) output << logfile << ' ';
+ output << logfile << "Score " << italic << "credit : " << credit << italic_off << " total : " << now << NL;
+}
+
+
diff --git a/engines/avalanche/logger.h b/engines/avalanche/logger.h
new file mode 100644
index 0000000000..016bfb6258
--- /dev/null
+++ b/engines/avalanche/logger.h
@@ -0,0 +1,33 @@
+#ifndef __logger_h__
+#define __logger_h__
+
+
+void log_setup(string name, boolean printing);
+
+void log_divider(); /* Prints the divider sign. */
+
+void log_command(string x); /* Prints a command */
+
+void log_scrollchar(string x); /* print one character */
+
+void log_italic();
+
+void log_roman();
+
+void log_epsonroman();
+
+void log_scrollline(); /* Set up a line for the scroll driver */
+
+void log_scrollendline(boolean centred);
+
+void log_bubbleline(byte linenum,byte whom, string x);
+
+void log_newline();
+
+void log_newroom(string where);
+
+void log_aside(string what);
+
+void log_score(word credit,word now);
+
+#endif
diff --git a/engines/avalanche/lucerna.cpp b/engines/avalanche/lucerna.cpp
new file mode 100644
index 0000000000..e268ac9ecf
--- /dev/null
+++ b/engines/avalanche/lucerna.cpp
@@ -0,0 +1,1489 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ LUCERNA The screen, [keyboard] and mouse handler. */
+
+#define __lucerna_implementation__
+
+
+#include "lucerna.h"
+
+
+#include "Graph.h"
+/*#include "Dos.h"*/
+/*#include "Crt.h"*/
+#include "trip5.h"
+#include "Acci.h"
+#include "pingo.h"
+#include "scrolls.h"
+#include "enhanced.h"
+#include "dropdown.h"
+#include "logger.h"
+#include "visa.h"
+#include "celer.h"
+#include "timeout.h"
+#include "basher.h"
+#include "sequence.h"
+
+
+/*$V-*/ /*$S-*/
+boolean fxhidden; array<0,3,palettetype> fxpal;
+
+void callverb(char n)
+{
+ if (n==pardon)
+ {
+ display(string("The f5 key lets you do a particular action in certain ")+
+ "situations. However, at the moment there is nothing "+
+ "assigned to it. You may press alt-A to see what the "+
+ "current setting of this key is.");
+ } else
+ {
+ weirdword=false; polite=true; verb=n;
+ do_that();
+ }
+}
+
+void draw_also_lines()
+{
+ byte ff;
+ byte squeaky_code;
+
+ switch (visible) {
+ case m_virtual : { squeaky_code = 1; off_virtual(); } break;
+ case m_no : squeaky_code = 2; break;
+ case m_yes : { squeaky_code = 3; off(); } break;
+ }
+
+ setactivepage(2);
+ cleardevice();
+ setcolor(15); rectangle(0,45,639,160);
+ for( ff=1; ff <= 50; ff ++)
+ { linetype& with = lines[ff];
+ if (x1!=maxint)
+ {
+ setcolor(with.col); line(x1,y1,x2,y2);
+ }}
+
+ switch (squeaky_code) {
+ case 1 : on_virtual(); break;
+ case 2 :; break; /* zzzz, it was off anyway */
+ case 3 : on(); break;
+ }
+}
+
+void load_also(string n);
+
+static untyped_file f;
+
+
+static string nextstring()
+{
+ byte l; string x;
+
+ string nextstring_result;
+ blockread(f,l,1); blockread(f,x[1],l); x[0]=chr(l); nextstring_result=x;
+ return nextstring_result;
+}
+
+static void unscramble();
+
+static void scram1(string& x)
+{
+ byte fz;
+;
+ for( fz=1; fz <= length(x); fz ++)
+ x[fz]=chr(ord(x[fz]) ^ 177);
+}
+
+
+
+static void unscramble()
+{
+ byte fv,ff;
+
+ for( fv=0; fv <= 30; fv ++)
+ for( ff=0; ff <= 1; ff ++)
+ if (also[fv][ff]!=nil)
+ scram1(*also[fv][ff]);
+ scram1(listen);
+ scram1(flags);
+/* for fz:=1 to length(also[fv,ff]^) do
+ also[fv,ff]^[fz]:=chr(ord(also[fv,ff]^[fz]) xor 177);*/
+}
+
+void load_also(string n)
+{
+ byte minnames; byte ff,fv;
+
+
+ for( fv=0; fv <= 30; fv ++)
+ for( ff=0; ff <= 1; ff ++)
+ if (also[fv][ff]!=nil) { delete also[fv][ff]; also[fv][ff]=nil; }
+ assign(f,string("also")+n+".avd");
+/*$I-*/ reset(f,1); /*$I+*/ if (ioresult!=0) return; /* no Also file */
+ seek(f,128); blockread(f,minnames,1);
+ for( fv=0; fv <= minnames; fv ++)
+ {
+ for( ff=0; ff <= 1; ff ++)
+ {
+ also[fv][ff] = new string;
+ *also[fv][ff]=nextstring();
+ }
+ *also[fv][0]=string('\235')+*also[fv][0]+'\235';
+ }
+ fillchar(lines,sizeof(lines),0xff);
+
+ fv=getpixel(0,0); blockread(f,fv,1);
+ blockread(f,lines,sizeof(lines[1])*fv);
+ blockread(f,fv,1); fillchar(peds,sizeof(peds),'\261');
+ blockread(f,peds,sizeof(peds[1])*fv);
+ blockread(f,numfields,1); blockread(f,fields,sizeof(fields[1])*numfields);
+ blockread(f,magics,sizeof(magics));
+ blockread(f,portals,sizeof(portals));
+ blockread(f,flags,sizeof(flags));
+ blockread(f,listen[0],1);
+ blockread(f,listen[1],length(listen));
+ draw_also_lines();
+
+ setactivepage(1); close(f);
+ unscramble();
+ for( fv=0; fv <= minnames; fv ++)
+ *also[fv][0]=string(',')+*also[fv][0]+',';
+}
+
+void load(byte n) /* Load2, actually */
+{
+ byte a0; /*absolute $A000:800;*/
+ byte a1; /*absolute $A000:17184;*/
+ byte bit;
+ untyped_file f; varying_string<2> xx;
+ boolean was_virtual;
+
+ was_virtual=visible==m_virtual;
+ if (was_virtual) off_virtual(); else off();
+ clear_vmc();
+
+ xx=strf(n); flesh_colours();
+ assign(f,string("place")+xx+".avd"); reset(f,1);
+ seek(f,146); blockread(f,roomname,30);
+ /* Compression method byte follows this... */
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080); move(a0,a1,12080);
+ }
+ close(f); load_also(xx); load_chunks(xx);
+
+ copy03(); bit=getpixel(0,0);
+ log_newroom(roomname);
+
+ if (was_virtual) on_virtual(); else on();
+}
+
+void zoomout(integer x,integer y)
+{
+ integer x1,y1,x2,y2;
+ byte fv;
+
+ setcolor(white); setwritemode(xorput);
+ setlinestyle(dottedln,0,1);
+
+ for( fv=1; fv <= 20; fv ++)
+ {
+ x1=x-(x / 20)*fv;
+ y1=y-((y-10) / 20)*fv;
+ x2=x+(((639-x) / 20)*fv);
+ y2=y+(((161-y) / 20)*fv);
+
+ rectangle(x1,y1,x2,y2);
+ delay(17);
+ rectangle(x1,y1,x2,y2);
+ }
+ setwritemode(copyput); setlinestyle(0,0,1);
+}
+
+void find_people(byte room)
+{
+ char fv;
+
+ for( fv='\227'; fv <= '\262'; fv ++)
+ if (whereis[fv]==room)
+ {
+ if (fv<'\257') him=fv; else her=fv;
+ }
+}
+
+void exitroom(byte x)
+{
+ nosound;
+ forget_chunks();
+ seescroll=true; /* This stops the trippancy system working over the
+ length of this procedure. */
+
+ { dnatype& with = dna;
+ switch (x) {
+ case r__spludwicks: {
+ lose_timer(reason_avariciustalks);
+ /* He doesn't HAVE to be talking for this to work. It just deletes it IF it
+ exists. */ with.avaricius_talk=0;
+ }
+ break;
+ case r__bridge: if (with.drawbridge_open>0)
+ {
+ with.drawbridge_open=4; /* Fully open. */
+ lose_timer(reason_drawbridgefalls);
+ }
+ break;
+ case r__outsidecardiffcastle: lose_timer(reason_cardiffsurvey); break;
+
+ case r__robins: lose_timer(reason_getting_tied_up); break;
+ }}
+
+ interrogation=0; /* Leaving the room cancels all the questions automatically. */
+
+ seescroll=false; /* Now it can work again! */
+
+ dna.last_room=dna.room;
+ if (dna.room!=r__map)
+ dna.last_room_not_map=dna.room;
+}
+
+void new_town() /* You've just entered a town from the map. */
+{
+ standard_bar();
+
+ switch (dna.room) {
+ case r__outsidenottspub: /* Entry into Nottingham. */
+ if ((dna.rooms[r__robins]>0) && (dna.been_tied_up) &&
+ (! dna.taken_mushroom))
+ dna.mushroom_growing=true;
+ break;
+ case r__wisewomans: /* Entry into Argent. */
+ {
+ if (dna.talked_to_crapulus && (! dna.lustie_is_asleep))
+ {
+ dna.spludwicks_here=! ((dna.rooms[r__wisewomans] % 3)==1);
+ dna.crapulus_will_tell=! dna.spludwicks_here;
+ } else
+ {
+ dna.spludwicks_here=true;
+ dna.crapulus_will_tell=false;
+ }
+ if (dna.box_contents==wine) dna.winestate=3; /* Vinegar */
+ }
+ break;
+ }
+
+ if (dna.room!=r__outsideducks)
+ {
+ if ((dna.obj[onion]) && ! (dna.onion_in_vinegar))
+ dna.rotten_onion=true; /* You're holding the onion */
+ }
+}
+
+void enterroom(byte x,byte ped);
+
+static void put_geida_at(byte whichped, byte& ped)
+{
+ if (ped==0) return;
+ tr[2].init(5,false); /* load Geida */
+ apped(2,whichped);
+ tr[2].call_eachstep=true;
+ tr[2].eachstep=procgeida_procs;
+}
+
+void enterroom(byte x,byte ped)
+{
+
+ seescroll=true; /* This stops the trippancy system working over the
+ length of this procedure. */
+
+ find_people(x);
+ dna.room=x; if (ped!=0) dna.rooms[x] += 1;
+
+ load(x);
+
+ if ((dna.rooms[x]==0) && (! flagset('S'))) points(1);
+ whereis[pavalot]=dna.room;
+ if (dna.geida_follows) whereis[pgeida]=x;
+ roomtime=0;
+
+ { dnatype& with = dna;
+ if ((with.last_room==r__map) && (with.last_room_not_map!=with.room))
+ new_town();}
+
+ switch (x) {
+ case r__yours: if (dna.avvy_in_bed)
+ {
+ show_one(3);
+ set_up_timer(100,procarkata_shouts,reason_arkata_shouts);
+ }
+ break;
+
+ case r__outsideyours: if (ped>0)
+ {
+ if (! dna.talked_to_crapulus)
+ {
+
+ whereis[pcrapulus]=r__outsideyours;
+ tr[2].init(8,false); /* load Crapulus */
+
+ if (dna.rooms[r__outsideyours]==1)
+ {
+ apped(2,4); /* Start on the right-hand side of the screen. */
+ tr[2].walkto(5); /* Walks up to greet you. */
+ } else
+ {
+ apped(2,5); /* Starts where he was before. */
+ tr[2].face=3;
+ }
+
+ tr[2].call_eachstep=true;
+ tr[2].eachstep=procface_avvy; /* He always faces Avvy. */
+
+ } else whereis[pcrapulus]=r__nowhere;
+
+ if (dna.crapulus_will_tell)
+ {
+ tr[2].init(8,false);
+ apped(2,2);
+ tr[2].walkto(4);
+ set_up_timer(20,proccrapulus_splud_out,reason_crapulus_says_spludwick_out);
+ dna.crapulus_will_tell=false;
+ }
+ }
+ break;
+
+ case r__outsidespludwicks:
+ if ((dna.rooms[r__outsidespludwicks]==1) && (ped==1))
+ {
+ set_up_timer(20,procbang,reason_explosion);
+ dna.spludwicks_here=true;
+ }
+ break;
+
+ case r__spludwicks:
+ if (dna.spludwicks_here)
+ {
+ if (ped>0)
+ {
+ tr[2].init(2,false); /* load Spludwick */
+ apped(2,2);
+ whereis['\227']=r__spludwicks;
+ }
+
+ dna.dogfoodpos = 0; /* Also Spludwick pos. */
+
+ tr[2].call_eachstep =true;
+ tr[2].eachstep=procgeida_procs;
+ } else whereis['\227']=r__nowhere;
+ break;
+
+ case r__brummieroad:
+ {
+ if (dna.geida_follows) put_geida_at(5, ped);
+ if (dna.cwytalot_gone)
+ {
+ magics[lightred].op=nix;
+ whereis[pcwytalot]=r__nowhere;
+ } else
+ {
+ if (ped>0)
+ {
+ tr[2].init(4,false); /* 4=Cwytalot*/
+ tr[2].call_eachstep=true;
+ tr[2].eachstep=procfollow_avvy_y;
+ whereis[pcwytalot]=r__brummieroad;
+
+ if (dna.rooms[r__brummieroad]==1) /* First time here... */
+ {
+ apped(2,2); /* He appears on the right of the screen... */
+ tr[2].walkto(4); /* ...and he walks up... */
+ } else
+ { /* You've been here before. */
+ apped(2,4); /* He's standing in your way straight away... */
+ tr[2].face=left;
+ }
+ }
+ }
+ }
+ break;
+
+ case r__argentroad:
+ { dnatype& with = dna;
+ if ((with.cwytalot_gone) && (! with.cwytalot_in_herts) && (ped==2) &&
+ (dna.rooms[r__argentroad]>3))
+ {
+ tr[2].init(4,false); /* 4=Cwytalot again*/
+ apped(2,1);
+ tr[2].walkto(2);
+ tr[2].vanishifstill=true;
+ with.cwytalot_in_herts=true;
+ /*whereis[#157]:=r__Nowhere;*/ /* can we fit this in? */
+ set_up_timer(20,proc_cwytalot_in_herts,reason_cwytalot_in_herts);
+ }}
+ break;
+
+ case r__bridge:
+ {
+ if (dna.drawbridge_open==4) /*open*/
+ {
+ show_one(3); /* Position of drawbridge */
+ magics[green].op=nix; /* You may enter the drawbridge. */
+ }
+ if (dna.geida_follows) put_geida_at(ped+3, ped); /* load Geida */
+ }
+ break;
+
+ case r__robins:
+ {
+ if (ped>0)
+ {
+ if (! dna.been_tied_up)
+ { /* A welcome party... or maybe not... */
+ tr[2].init(6,false);
+ apped(2,2);
+ tr[2].walkto(3);
+ set_up_timer(36,procget_tied_up,reason_getting_tied_up);
+ }
+ }
+
+ if (dna.been_tied_up)
+ {
+ whereis[probinhood]=0; whereis[pfriartuck]=0;
+ }
+
+ if (dna.tied_up) show_one(2);
+
+ if (! dna.mushroom_growing) show_one(3);
+ }
+ break;
+
+ case r__outsidecardiffcastle:
+ {
+ if (ped>0)
+ switch (dna.cardiff_things) {
+ case 0 : { /* You've answered NONE of his questions. */
+ tr[2].init(9,false);
+ apped(2,2);
+ tr[2].walkto(3);
+ set_up_timer(47,proccardiffsurvey,reason_cardiffsurvey);
+ }
+ break;
+ case 5 : magics[2].op=nix; break; /* You've answered ALL his questions. => nothing happens. */
+ default: { /* You've answered SOME of his questions. */
+ tr[2].init(9,false);
+ apped(2,3);
+ tr[2].face=right;
+ set_up_timer(3,proccardiff_return,reason_cardiffsurvey);
+ }
+ }
+ if (dna.cardiff_things<5)
+ interrogation=dna.cardiff_things; else interrogation=0;
+ }
+ break;
+
+ case r__map:
+ { /* You're entering the map. */
+ dawn(); setactivepage(cp);
+ if (ped>0) zoomout(peds[ped].x,peds[ped].y);
+ setactivepage(1-cp);
+
+ { dnatype& with = dna;
+ if ((with.obj[wine]) && (with.winestate!=3))
+ {
+ dixi('q',9); /* Don't want to waste the wine! */
+ with.obj[wine]=false;
+ objectlist();
+ }}
+
+ dixi('q',69);
+ }
+ break;
+
+ case r__catacombs:
+ {
+ if (set::of(0,3,5,6, eos).has(ped))
+ {
+ dnatype& with = dna;
+
+ switch (ped) {
+ case 3 : { with.cat_x=8; with.cat_y=4; } break; /* Enter from oubliette */
+ case 5 : { with.cat_x=8; with.cat_y=7; } break; /* Enter from du Lustie's */
+ case 6 : { with.cat_x=4; with.cat_y=1; } break; /* Enter from Geida's */
+ }
+ dna.enter_catacombs_from_lusties_room=true;
+ catamove(ped);
+ dna.enter_catacombs_from_lusties_room=false;
+ }
+ }
+ break;
+
+ case r__argentpub: {
+ if (dna.wonnim) show_one(1); /* No lute by the settle. */
+ dna.malagauche=0; /* Ready to boot Malagauche */
+ if (dna.givenbadgetoiby)
+ { show_one(8); show_one(9); }
+ }
+ break;
+
+ case r__lustiesroom: {
+ dna.dogfoodpos=1; /* Actually, du Lustie pos. */
+ if (tr[1].whichsprite==0) /* Avvy in his normal clothes */
+ set_up_timer(3,proccallsguards,reason_du_lustie_talks);
+ else
+ if (! dna.entered_lusties_room_as_monk) /*already*/
+ /* Presumably, Avvy dressed as a monk. */
+ set_up_timer(3,procgreetsmonk,reason_du_lustie_talks);
+
+ if (dna.geida_follows)
+ {
+ put_geida_at(5, ped);
+ if (dna.lustie_is_asleep) show_one(5);
+ }
+ }
+ break;
+
+ case r__musicroom: {
+ if (dna.jacques_awake>0)
+ {
+ dna.jacques_awake=5;
+ show_one(2);
+ show_one(4);
+ magics[brown].op=nix;
+ whereis[pjacques]=0;
+ }
+ if (ped!=0)
+ {
+ show_one(6);
+ first_show(5); then_show(7);
+ start_to_close();
+ }
+ }
+ break;
+
+ case r__outsidenottspub: if (ped==2)
+ {
+ show_one(3); first_show(2);
+ then_show(1); then_show(4);
+ start_to_close();
+ }
+ break;
+
+ case r__outsideargentpub: if (ped==2) {
+ show_one(6);
+ first_show(5); then_show(7);
+ start_to_close();
+ }
+ break;
+
+ case r__wisewomans: {
+ tr[2].init(11,false);
+ if ((dna.rooms[r__wisewomans]==1) && (ped>0))
+ {
+ apped(2,2); /* Start on the right-hand side of the screen. */
+ tr[2].walkto(4); /* Walks up to greet you. */
+ } else
+ {
+ apped(2,4); /* Starts where she was before. */
+ tr[2].face=3;
+ }
+
+ tr[2].call_eachstep=true;
+ tr[2].eachstep=procface_avvy; /* She always faces Avvy. */
+ }
+ break;
+
+ case r__insidecardiffcastle:
+ if (ped>0)
+ {
+ tr[2].init(10,false); /* Define the dart. */
+ first_show(1);
+ if (dna.arrow_in_the_door) then_show(3); else then_show(2);
+ if (dna.taken_pen) show_one(4);
+ start_to_close();
+ } else
+ {
+ show_one(1);
+ if (dna.arrow_in_the_door) show_one(3); else show_one(2);
+ }
+ break;
+
+ case r__avvysgarden: if (ped==1) {
+ show_one(2);
+ first_show(1); then_show(3);
+ start_to_close();
+ }
+ break;
+
+ case r__entrancehall:case r__insideabbey: if (ped==2) {
+ show_one(2);
+ first_show(1); then_show(3);
+ start_to_close();
+ }
+ break;
+
+ case r__aylesoffice: if (dna.ayles_is_awake) show_one(2); break; /* Ayles awake. */
+
+ case r__geidas: put_geida_at(2, ped); break; /* load Geida */
+
+ case r__easthall:case r__westhall: if (dna.geida_follows) put_geida_at(ped+2, ped); break;
+
+ case r__lusties: if (dna.geida_follows) put_geida_at(ped+6, ped); break;
+
+ case r__nottspub: {
+ if (dna.sitting_in_pub) show_one(3);
+ dna.dogfoodpos=1; /* Actually, du Lustie pos. */
+ }
+ break;
+
+ case r__outsideducks: if (ped==2)
+ { /* Shut the door */
+ show_one(3);
+ first_show(2); then_show(1);
+ then_show(4); start_to_close();
+ }
+ break;
+ case r__ducks: dna.dogfoodpos=1; break; /* Actually, Duck pos. */
+
+ }
+
+ seescroll=false; /* Now it can work again! */
+
+}
+
+void thinkabout(char z, boolean th) /* Hey!!! Get it and put it!!! */
+{
+ const integer x = 205; const integer y = 170; const integer picsize = 966;
+ const bytefield thinkspace =
+ {25, 170, 32, 200};
+ untyped_file f; pointer p; byte fv;
+
+
+ thinks=z; z -= 1;
+
+ if (th)
+ { /* Things */
+ assign(f,"thinks.avd"); wait(); getmem(p,picsize);
+ reset(f,1); seek(f,ord(z)*picsize+65); blockread(f,p,picsize); off();
+ close(f);
+ } else
+ { /* People */
+ assign(f,"folk.avd");
+ wait();
+ getmem(p,picsize);
+ reset(f,1);
+
+ fv=ord(z)-149;
+ if (fv>=25) fv -= 8;
+ if (fv==20) fv -= 1; /* Last time... */
+
+ seek(f,fv*picsize+65);
+ blockread(f,p,picsize);
+ off();
+ close(f);
+ }
+
+ setactivepage(3);
+ putimage(x,y,p,0);
+ setactivepage(1-cp);
+
+ for( fv=0; fv <= 1; fv ++)
+ getset[fv].remember(thinkspace);
+
+ freemem(p,picsize);
+ on(); thinkthing=th;
+}
+
+void load_digits() /* Load the scoring digits & rwlites */
+{
+ const integer digitsize = 134;
+ const integer rwlitesize = 126;
+ untyped_file f; char fv; byte ff;
+
+ assign(f,"digit.avd"); reset(f,1);
+ for( fv='0'; fv <= '9'; fv ++)
+ {
+ getmem(digit[fv],digitsize); blockread(f,digit[fv],digitsize);
+ }
+ for( ff=0; ff <= 8; ff ++)
+ {
+ getmem(rwlite[ff],rwlitesize); blockread(f,rwlite[ff],rwlitesize);
+ }
+ close(f);
+}
+
+void toolbar()
+{
+ untyped_file f; word s; byte fv; pointer p;
+
+ assign(f,"useful.avd"); reset(f,1);
+ s=filesize(f)-40; getmem(p,s);
+ seek(f,40);
+ blockread(f,p,s);
+ close(f);
+/* off;*/
+
+ setcolor(15); /* (And sent for chrysanthemums...) Yellow and white. */
+ setfillstyle(1,6);
+ for( fv=0; fv <= 1; fv ++)
+ {
+ setactivepage(fv); putimage(5,169,p,0);
+ if (demo)
+ {
+ bar(264,177,307,190);
+ outtextxy(268,188,"Demo!"); /* well... actually only white now. */
+ }
+ }
+
+/* on;*/
+ freemem(p,s);
+ oldrw=177; showrw();
+}
+
+void showscore()
+{
+ const bytefield scorespace = {33, 177, 39, 200};
+ varying_string<3> q; byte fv;
+
+ if (demo) return;
+
+ str(dna.score,q); while (q[0]<'\3') q=string('0')+q; off();
+ setactivepage(3);
+ for( fv=1; fv <= 3; fv ++)
+ if (lastscore[fv]!=q[fv])
+ putimage(250+fv*15,177,digit[q[fv]],0);
+
+ for( fv=0; fv <= 1; fv ++)
+ getset[fv].remember(scorespace);
+
+ setactivepage(1-cp);
+ on(); lastscore=q;
+}
+
+void points(byte num) /* Add on no. of points */
+{
+ byte q,fv;
+
+ for( q=1; q <= num; q ++)
+ {
+ dna.score += 1;
+ if (soundfx) for( fv=1; fv <= 97; fv ++) sound(177+dna.score*3); nosound;
+ }
+ log_score(num,dna.score); showscore();
+}
+
+void topcheck()
+{
+ { menuset& with = ddm_m; /* Menuset */
+ getmenu(mpx);} /* Do this one */
+}
+
+void mouseway()
+{
+ byte col;
+
+ off(); col=getpixel(mx,my); on();
+ { triptype& with = tr[1];
+ { dnatype& with1 = dna;
+ switch (col) {
+ case green: { dna.rw=up; rwsp(1,up); showrw(); } break;
+ case brown: { dna.rw=down; rwsp(1,down); showrw(); } break;
+ case cyan: { dna.rw=left; rwsp(1,left); showrw(); } break;
+ case lightmagenta: { dna.rw=right; rwsp(1,right); showrw(); } break;
+ case red:case white:case lightcyan:case yellow: { stopwalking(); showrw(); } break;
+ }}}
+}
+
+void inkey()
+{
+ char r;
+
+
+ if (demo) return; /* Demo handles this itself. */
+
+ if (mousetext=="")
+ { /* read keyboard */
+ readkeye();
+ if ((inchar==' ') && ((shiftstate & 8)>0))
+ {
+ inchar='\0'; extd='#'; /* alt-spacebar = alt-H */
+ }
+ } else
+ {
+ if (mousetext[1]=='`') mousetext[1]='\15'; /* Backquote = return in a macro */
+ inchar=mousetext[1]; mousetext=copy(mousetext,2,255);
+ }
+}
+
+void posxy()
+{
+ varying_string<3> xs,ys;
+
+ setfillstyle(1,0); setcolor(10);
+ do {
+ check();
+ if (mpress==1)
+ {
+ str(mx,xs); str(my,ys);
+ off(); bar(400,160,500,168);
+ outtextxy(400,168,xs); outtextxy(440,168,string(": ")+ys); on();
+ }
+ } while (!(my==0));
+ bar(400,161,640,168);
+}
+
+void fxtoggle()
+{
+ byte page_;
+ const bytefield soundled =
+ {52, 175, 55, 177};
+
+ soundfx=! soundfx;
+ if (soundfx)
+ {
+ if (! fxhidden)
+ { /* ...but *not* when the screen's dark. */
+ sound(1770); delay(77); nosound;
+ }
+ setfillstyle(1,cyan);
+ } else
+ setfillstyle(1,black);
+ setactivepage(3); bar(419,175,438,177);
+ setactivepage(1-cp);
+ for( page_=0; page_ <= 1; page_ ++) getset[page_].remember(soundled);
+}
+
+void objectlist()
+{
+ char fv;
+
+ dna.carrying=0;
+ if (thinkthing && ! dna.obj[thinks])
+ thinkabout(money,a_thing); /* you always have money */
+ for( fv='\1'; fv <= numobjs; fv ++)
+ if (dna.obj[fv])
+ {
+ dna.carrying += 1; objlist[dna.carrying]=fv;
+ }
+}
+
+void verte()
+{
+ byte what;
+
+ if (! dna.user_moves_avvy) return;
+ {
+ triptype& with = tr[1]; /* that's the only one we're interested in here */
+
+
+ if (mx<(cardinal)with.x) what=1; else
+ if (mx>(unsigned char)(with.x+with.a.xl)) what=2; else
+ what=0; /* On top */
+
+ if (my<(cardinal)with.y) what += 3; else
+ if (my>(unsigned char)(with.y+with.a.yl)) what += 6;
+
+ switch (what) {
+ case 0: stopwalking(); break; /* Clicked on Avvy- no movement */
+ case 1: rwsp(1,left); break;
+ case 2: rwsp(1,right); break;
+ case 3: rwsp(1,up); break;
+ case 4: rwsp(1,ul); break;
+ case 5: rwsp(1,ur); break;
+ case 6: rwsp(1,down); break;
+ case 7: rwsp(1,dl); break;
+ case 8: rwsp(1,dr); break;
+ } /* no other values are possible... */
+
+ showrw();
+
+ }
+}
+
+void checkclick()
+{
+ bytefield b;
+
+ check(); ontoolbar=slow_computer && ((my>=169) || (my<=10));
+
+ if (mrelease>0) after_the_scroll=false;
+ switch (my) {
+ case RANGE_11(0,10): newpointer(1);
+ break; /* up arrow */
+ case RANGE_11(159,169): newpointer(8);
+ break; /* I-beam */
+ case 170 ... 200: newpointer(2); break; /* screwdriver */
+ default:
+ {
+ if (! ddmnow) /* Dropdown can handle its own pointers. */
+ {
+ if (((keystatus & 1)==1) && (my>=11) && (my<=158))
+ {
+ newpointer(7); /* Mark's crosshairs */
+ verte();
+ /* Normally, if you click on the picture, you're guiding Avvy around. */
+ } else
+ newpointer(4); /* fletch */
+ }
+ }
+ }
+
+ if (mpress>0)
+ {
+ switch (mpy) {
+ case RANGE_11(0,10): if (dropsok) topcheck();
+ break;
+ case 11 ... 158: if (! dropsok)
+ mousetext=string('\15')+mousetext;
+ break; /* But otherwise, it's
+ equivalent to pressing Enter. */
+ case RANGE_11(159,169): { /* Click on command line */
+ cursor_off(); curpos=(mx-16) / 8;
+ if (curpos>length(current)+1) curpos=length(current)+1;
+ if (curpos<1) curpos=1;
+ cursor_on();
+ }
+ break;
+ case 170 ... 200: switch (mpx) { /* bottom check */
+ case 0 ... 207: mouseway(); break;
+ case 208 ... 260: { /* Examine the thing */
+ do { check(); } while (!(mrelease>0));
+ if (thinkthing)
+ {
+ thing=thinks; thing += 49;
+ person=pardon;
+ } else
+ {
+ person=thinks;
+ thing=pardon;
+ }
+ callverb(vb_exam);
+ }
+ break;
+ case 261 ... 319: {
+ do { checkclick(); } while (!(mrelease>0));
+ callverb(vb_score);
+ }
+ break;
+ case 320 ... 357: { tr[1].xs=walk; newspeed(); } break;
+ case 358 ... 395: { tr[1].xs=run; newspeed(); } break;
+ case 396 ... 483: fxtoggle(); break; /* "sound" */
+/* 484..534: begin { clock }
+ off; if getpixel(mx,my)=14 then mousetext:='#'+mousetext; on;
+ end;*/
+ case 535 ... 640: mousetext=string('\15')+mousetext; break;
+ }
+ break;
+ }
+ }
+
+/* if mrelease>0 then
+ begin
+ if (cw<>177) and (mry>10) then
+ begin to_do:=(((mrx-20) div 100)*20)+(mry div 10); closewin; end;
+ end;*/
+}
+
+void mouse_init()
+{
+ r.ax=0;
+ intr(0x33,r); /* Returns- no. keys in bx and whether present in ax. */
+ wait();
+}
+
+void mousepage(word page_)
+{
+ boolean onstate,wason;
+
+ if (visible!=m_virtual)
+ {
+ onstate=oncandopageswap;
+ oncandopageswap=false;
+ wason=visible==m_yes;
+ if (wason) off();
+ {
+ void& with = r; ax=29; bx=page_; } intr(0x33,r);
+ if (wason) on();
+ oncandopageswap=onstate;
+ }
+}
+
+void errorled()
+{
+ byte fv;
+
+ state(0);
+ for( fv=0; fv <= 1; fv ++)
+ {
+ setactivepage(fv);
+ off(); setfillstyle(1,red); bar(419,184,438,186); on();
+ }
+ for( fv=177; fv >= 1; fv --)
+ {
+ sound(177+(fv*177177) / 999);
+ delay(1); nosound;
+ }
+ for( fv=0; fv <= 1; fv ++)
+ {
+ setactivepage(fv);
+ off(); setfillstyle(1,black); bar(419,184,438,186); on();
+ }
+ state(defaultled); setactivepage(1-cp);
+}
+
+shortint fades(shortint x)
+{
+ byte r,g,b;
+
+ shortint fades_result;
+ r=x / 16; x=x % 16;
+ g=x / 4; b=x % 4;
+ if (r>0) r -= 1; if (g>0) g -= 1; if (b>0) b -= 1;
+ fades_result=(16*r+4*g+b);
+/* fades:=x-1;*/
+ return fades_result;
+}
+
+void dusk();
+
+static void fadeout(byte n)
+{
+ byte fv;
+
+ getpalette(fxpal[n]);
+ for( fv=1; fv <= fxpal[n].size-1; fv ++)
+ fxpal[n].colors[fv]=fades(fxpal[n].colors[fv]);
+ setallpalette(fxpal[n]);
+ /*delay(50);*/ slowdown();
+}
+
+void dusk()
+{
+ byte fv;
+
+ setbkcolor(0);
+ if (fxhidden) return; fxhidden=true;
+ getpalette(fxpal[0]); for( fv=1; fv <= 3; fv ++) fadeout(fv);
+}
+
+void dawn();
+
+static void fadein(byte n)
+{
+ setallpalette(fxpal[n]);
+ /*delay(50);*/ slowdown();
+}
+
+void dawn()
+{
+ byte fv;
+
+ if ((holdthedawn) || (! fxhidden)) return; fxhidden=false;
+ for( fv=3; fv >= 0; fv --) fadein(fv);
+ { dnatype& with = dna;
+ if ((with.room==r__yours) && (with.avvy_in_bed) && (with.teetotal)) background(14);}
+}
+
+void showrw()
+{
+ byte page_;
+
+ {
+ dnatype& with = dna;
+
+ if (oldrw==with.rw) return;
+ oldrw=with.rw; off();
+ for( page_=0; page_ <= 1; page_ ++)
+ {
+ setactivepage(page_); putimage(0,161,rwlite[with.rw],0);
+ } on();
+ setactivepage(1-cp);
+ }
+}
+
+void mblit(byte x1,byte y1,byte x2,byte y2, byte f,byte t) /* assembler; */
+/* The Minstrel Blitter */
+/* asm
+{ ofsfr:=f*$4000+x1+y1*80;
+ ofsto:=t*$4000+x1+y1*80;}
+
+ mov bx,80; { We're multiplying by 80. }
+ mov al,y1;
+ mul bl; { AX now contains y1*80. }
+ xor cx,cx; { Zero CX. }
+ mov cl,x1; { CX now equals x1 }
+ add ax,cx; { AX now contains x1+y1*80. }
+ mov si,ax;
+ mov di,ax;
+
+ mov ax,$4000;
+ mov bl,f;
+ mul bx; { Note that this is a *word*! }
+ add si,ax;
+
+ mov ax,$4000;
+ mov bl,t;
+ mul bx; { Note that this is a *word*! }
+ add di,ax;
+
+ push ds; { *** <<<< *** WE MUST PRESERVE THIS! }
+ cld; { Clear Direction flag - we're going forwards! }
+
+ mov ax,$A000; { The screen memory. }
+ mov ds,ax;
+ mov es,ax; { The same. }
+
+ { AH stores the number of bytes to copy. }
+ { len:=(x2-x1)+1; }
+
+ mov ah,x2;
+ sub ah,x1;
+ inc ah;
+
+ { Firstly, let's decide how many times we're going round. }
+
+ mov cl,y2; { How many numbers between y1 and y2? }
+ sub cl,y1;
+ inc cl; { Inclusive reckoning (for example, from 3 to 5 is 5-3+1=3 turns. }
+
+ { We'll use SI and DI to be Ofsfr and Ofsto. }
+
+ @Y_axis_loop:
+ push cx;
+
+
+ { OK... We've changed this loop from a for-next loop. "Bit" is
+ represented by CX. }
+
+{ port[$3c4]:=2; port[$3ce]:=4; }
+ mov dx,$3c4;
+ mov al,2;
+ out dx,al;
+ mov dx,$3ce;
+ mov al,4;
+ out dx,al;
+
+ mov cx,4; { We have to copy planes 3, 2, 1 and Zero. We'll add 1 to the
+ number, because at zero it stops. }
+
+ mov bx,3; { This has a similar function to that of CX. }
+
+ @start_of_loop:
+
+ push cx;
+
+{ port[$3C5]:=1 shl bit; }
+ mov dx,$3C5;
+ mov al,1;
+ mov cl,bl; { BL = bit. }
+ shl al,cl;
+ out dx,al;
+{ port[$3CF]:=bit; }
+ mov dx,$3CF;
+ mov al,bl; { BL = bit. }
+ out dx,al;
+
+{ move(mem[$A000:ofsfr],mem[$A000:ofsto],len); }
+
+ xor ch,ch; { Clear CH. }
+ mov cl,ah;
+
+ repz movsb; { That's all we need to say! }
+
+ mov cl,ah;
+ sub si,cx; { This is MUCH, MUCH faster than pushing and popping them! }
+ sub di,cx;
+
+ pop cx; { Get the loop count back again. }
+ dec bx; { One less... }
+ loop @start_of_loop; { Until cx=0. }
+
+ add si,80; { Do the next line... }
+ add di,80;
+
+ pop cx;
+ loop @Y_axis_loop;
+
+ pop ds; { Get it back again (or we'll be in trouble with TP!) }
+*/
+{;
+}
+
+void blitfix()
+{
+ byte fv;
+
+ fv=getpixel(0,0); /* perform read & so cancel Xor effect! */
+}
+
+void clock();
+const integer xm = 510;
+const integer ym = 183;
+static arccoordstype ah,am;
+static word nh;
+
+static void calchand(word ang,word length, arccoordstype& a, byte c)
+{
+ if (ang>900) { a.xend=177; return; }
+ setcolor(c); arc(xm,ym,449-ang,450-ang,length); getarccoords(a);
+}
+
+
+static void hand(arccoordstype a, byte c)
+{
+ if (a.xend==177) return;
+ setcolor(c);
+ line(xm,ym,a.xend,a.yend); /* "With a do-line???!", Liz said. */
+}
+
+
+static void chime()
+{
+ word gd,gm,fv;
+
+ if ((oh==17717) || (! soundfx)) return; /* too high- must be first time around */
+ fv=h % 12; if (fv==0) fv=12; wait();
+ for( gd=1; gd <= fv; gd ++)
+ {
+ for( gm=1; gm <= 3; gm ++)
+ {
+ sound((gd % 3)*64+140-gm*30); delay(50-gm*12);
+ }
+ nosound; if (gd!=fv) delay(100);
+ }
+}
+
+
+
+static void refresh_hands()
+{
+ const bytefield clockspace = {61, 166, 66, 200};
+ byte page_;
+
+ for( page_=0; page_ <= 1; page_ ++)
+ getset[page_].remember(clockspace);
+}
+
+
+
+static void plothands()
+{
+/* off;*/
+ setactivepage(3);
+ calchand(onh,14,ah,yellow); calchand(om*6,17,am,yellow);
+ hand(ah,brown); hand(am,brown);
+ calchand(nh,14,ah,brown); calchand(m*6,17,am,brown);
+ hand(ah,yellow); hand(am,yellow);
+ setactivepage(1-cp);
+
+ refresh_hands();
+
+/* on;*/
+}
+
+void clock()
+{ /* ...Clock. */
+ gettime(h,m,s,s1);
+ nh=(h % 12)*30+m / 2;
+ if (oh!=h) { plothands(); chime(); }
+ if (om!=m) plothands();
+ if ((h==0) && (oh!=0) && (oh!=17717))
+ display(string("Good morning!\r\rYes, it's just past midnight. Are you having")+
+ " an all-night Avvy session? Glad you like the game that much!");
+ oh=h; onh=nh; om=m;
+}
+
+void flip_page()
+{
+ if (! ddm_o.menunow)
+ {
+ cp=1-cp;
+ setvisualpage(cp);
+ setactivepage(1-cp);
+ /*mousepage(cp);*/
+ }
+
+}
+
+void delavvy()
+{
+ byte page_;
+
+ off();
+ { triptype& with = tr[1];
+ for( page_=0; page_ <= 1; page_ ++)
+ mblit(with.x / 8,with.y,(with.x+with.a.xl) / 8+1,with.y+with.a.yl,3,page_);}
+ blitfix();
+ on();
+}
+
+void gameover()
+{
+ byte fv; integer sx,sy;
+
+ dna.user_moves_avvy=false;
+
+ sx=tr[1].x;
+ sy=tr[1].y;
+ {
+ triptype& with = tr[1];
+
+ done();
+ init(12,true); /* 12 = Avalot falls */
+ tr[1].step=0;
+ appear(sx,sy,0);
+ }
+ set_up_timer(3,procavalot_falls,reason_falling_over);
+/* display(^m^m^m^m^m^m^i^i^i^i^i^i^s'Z'^v);*/
+ alive=false;
+}
+
+/* OK. There are two kinds of redraw: Major and Minor. Minor is what happens
+ when you load a game, etc. Major redraws EVERYTHING. */
+
+void minor_redraw()
+{
+ byte fv;
+
+ dusk();
+ enterroom(dna.room,0); /* Ped unknown or non-existant. */
+
+ for( fv=0; fv <= 1; fv ++)
+ {
+ cp=1-cp;
+ getback();
+ }
+
+ {
+ dnatype& with = dna;
+
+ lastscore="TJA"; /* impossible digits */
+ showscore();
+ }
+
+ dawn();
+}
+
+void major_redraw()
+{
+ byte fv;
+
+ dusk();
+ setactivepage(0); cleardevice();
+
+ toolbar();
+ copy03();
+
+ enterroom(dna.room,0); /* 0 = ped unknown or non-existant. */
+ for( fv=0; fv <= 1; fv ++) { cp=1-cp; getback(); }
+
+ om=177;
+ clock();
+
+ thinkabout(thinks,thinkthing); standard_bar();
+ soundfx=! soundfx; fxtoggle();
+ for( fv=0; fv <= 1; fv ++) { cp=1-cp; getback(); }
+ plottext();
+ ledstatus=177; state(2);
+
+ {
+ dnatype& with = dna;
+
+ lastscore="TJA"; /* impossible digits */
+ showscore();
+ }
+
+ dawn();
+}
+
+word bearing(byte whichped)
+ /* Returns the bearing from ped Whichped to Avvy, in degrees. */
+{
+ const real rad2deg = 180/pi;
+
+ word bearing_result;
+ { pedtype& with = peds[whichped];
+ if (tr[1].x==with.x)
+ bearing_result=0; /* This would cause a division by zero if we let it through. */
+ else
+ /*
+ bearing:=trunc(((arctan((tr[1].y-y)/(tr[1].x-x)))*rad2deg)+90) mod 360*/
+ {
+ if (tr[1].x<with.x)
+ bearing_result=trunc(atan((real)((tr[1].y-with.y))/(tr[1].x-with.x))*rad2deg)+90;
+ else
+ bearing_result=trunc(atan((real)((tr[1].y-with.y))/(tr[1].x-with.x))*rad2deg)+270;
+ }}
+ return bearing_result;
+}
+
+void flesh_colours() /* assembler;
+asm
+ mov ax,$1012;
+ mov bx,21; { 21 = light pink (why?) }
+ mov cx,1;
+ mov dx,seg @flesh;
+ mov es,dx;
+ mov dx,offset @flesh;
+ int $10;
+
+ mov dx,seg @darkflesh;
+ mov es,dx;
+ mov dx,offset @darkflesh;
+ mov bx,5; { 5 = dark pink. }
+ int $10;
+
+ jmp @TheEnd;
+
+ @flesh:
+ db 56,35,35;
+
+ @darkflesh:
+ db 43,22,22;
+
+ @TheEnd: */
+{;
+}
+
+void sprite_run()
+ /* A sprite run is performed before displaying a scroll, if not all the
+ sprites are still. It performs two fast cycles, only using a few of
+ the links usually used, and without any extra animation. This should
+ make the sprites the same on both pages. */
+{
+ byte fv;
+
+
+ doing_sprite_run=true;
+
+ for( fv=0; fv <= 1; fv ++)
+ {
+ get_back_loretta();
+ trippancy_link();
+
+ flip_page();
+ }
+
+ doing_sprite_run=false;
+
+}
+
+void fix_flashers()
+{ ledstatus=177; oldrw=177; state(2); showrw(); }
+
+class unit_lucerna_initialize {
+ public: unit_lucerna_initialize();
+};
+static unit_lucerna_initialize lucerna_constructor;
+
+unit_lucerna_initialize::unit_lucerna_initialize() {
+ fxhidden=false; oh=17717; om=17717;
+ if (atbios) atkey="f1"; else atkey="alt-";
+}
diff --git a/engines/avalanche/lucerna.h b/engines/avalanche/lucerna.h
new file mode 100644
index 0000000000..a602f8c026
--- /dev/null
+++ b/engines/avalanche/lucerna.h
@@ -0,0 +1,76 @@
+#ifndef __lucerna_h__
+#define __lucerna_h__
+
+
+#include "gyro.h"
+
+
+ void callverb(char n);
+
+ void draw_also_lines();
+
+ void mouse_init();
+
+ void mousepage(word page_);
+
+ void load(byte n);
+
+ void exitroom(byte x);
+
+ void enterroom(byte x,byte ped);
+
+ void thinkabout(char z, boolean th); /* Hey!!! Get it and put it!!! */
+
+ void load_digits(); /* Load the scoring digits & rwlites */
+
+ void toolbar();
+
+ void showscore();
+
+ void points(byte num); /* Add on no. of points */
+
+ void mouseway();
+
+ void inkey();
+
+ void posxy();
+
+ void fxtoggle();
+
+ void objectlist();
+
+ void checkclick();
+
+ void errorled();
+
+ void dusk();
+
+ void dawn();
+
+ void showrw();
+
+ void mblit(byte x1,byte y1,byte x2,byte y2, byte f,byte t); /* The Minstrel Blitter */
+
+ void blitfix();
+
+ void clock();
+
+ void flip_page();
+
+ void delavvy();
+
+ void gameover();
+
+ void minor_redraw();
+
+ void major_redraw();
+
+ word bearing(byte whichped);
+
+ void flesh_colours();
+
+ void sprite_run();
+
+ void fix_flashers();
+
+#endif
diff --git a/engines/avalanche/magic2.cpp b/engines/avalanche/magic2.cpp
new file mode 100644
index 0000000000..03f54d04fe
--- /dev/null
+++ b/engines/avalanche/magic2.cpp
@@ -0,0 +1,37 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+
+const longint pagetop = 81920;
+const word nextcode = 17717;
+
+integer gd,gm;
+file<word> magic,out;
+word next,gg;
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ assign(magic,"v:magicirc.avd"); reset(magic);
+ assign(out,"v:magic2.avd"); rewrite(out);
+ move(mem[0xa000*0],mem[0xa000*pagetop],16000);
+ while (! eof(magic))
+ {;
+ magic >> next;
+ if (next!=nextcode)
+ mem[0xa000*next]=255;
+ else
+ {;
+ for( gg=0; gg <= 16000; gg ++)
+ if (mem[0xa000*gg]!=mem[0xa000*gg+pagetop])
+ out << gg;
+ out << nextcode;
+ move(mem[0xa000*0],mem[0xa000*pagetop],16000);
+ }
+ }
+ close(magic); close(out);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/magidraw.cpp b/engines/avalanche/magidraw.cpp
new file mode 100644
index 0000000000..282eb5d189
--- /dev/null
+++ b/engines/avalanche/magidraw.cpp
@@ -0,0 +1,34 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+
+const word nextcode = 17717;
+
+integer gd,gm;
+untyped_file magic; /* of word;*/
+word next;
+array<1,16401,word> buffer;
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ assign(magic,"v:magic2.avd"); reset(magic,1);
+ blockread(magic,buffer,sizeof(buffer));
+ close(magic);
+/* while not eof(magic) do*/
+ for( gd=1; gd <= 16401; gd ++)
+ {;
+/* read(magic,next);
+ if next<>nextcode then*/
+ if (buffer[gd]!=nextcode)
+ mem[0xa000*buffer[gd]]=255;
+ else
+ delay(1);
+ }
+/* close(magic);*/
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/magishuf.cpp b/engines/avalanche/magishuf.cpp
new file mode 100644
index 0000000000..09db4d286d
--- /dev/null
+++ b/engines/avalanche/magishuf.cpp
@@ -0,0 +1,60 @@
+#include "ptoc.h"
+
+
+/*#include "Dos.h"*/
+/*#include "Crt.h"*/
+
+
+const word nextcode = 17717;
+
+typedef array<1,8000,word> big;
+typedef array<1,16401,word> circle;
+
+big b;
+file<big> f;
+registers r;
+word gd;
+circle c;
+file<circle> fc;
+
+void melt(byte c)
+{;
+ for( gd=1; gd <= 8000; gd ++)
+ {;
+ mem[0xa000*b[gd]]=c;
+ if ((gd % 17)==0) delay(1);
+ }
+}
+
+void magicirc(byte cc)
+{;
+ for( gd=1; gd <= 16401; gd ++)
+ {;
+ if (c[gd]!=nextcode)
+ {;
+ if (odd(c[gd])) mem[0xa000*c[gd] / 2]=cc;
+ } else
+ delay(1);
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ r.ax=13; intr(0x10,r);
+ assign(f,"d:shuffle.avd"); reset(f); f >> b; close(f);
+ assign(fc,"v:magic2.avd"); reset(fc); fc >> c; close(fc);
+/* repeat
+ melt(170); magicirc(85);
+ magicirc(170); melt(85);
+ magicirc(170); magicirc(85);
+ melt(170); melt(85);
+ until keypressed;*/
+ do {
+ melt(255); magicirc(0);
+ magicirc(255); melt(0);
+ magicirc(255); magicirc(0);
+ melt(255); melt(0);
+ } while (!keypressed());
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/make!.cpp b/engines/avalanche/make!.cpp
new file mode 100644
index 0000000000..447f540b8a
--- /dev/null
+++ b/engines/avalanche/make!.cpp
@@ -0,0 +1,62 @@
+#include "ptoc.h"
+
+ /* Phew! */
+#include "graph.h"
+
+/*$S-*/
+integer gd,gm;
+untyped_file f;
+text t;
+string x;
+
+boolean subpix(integer x,integer y)
+{boolean subpix_result;
+;
+ subpix_result=getpixel(x,y)==15;
+return subpix_result;
+}
+
+byte pixel(integer x,integer y)
+{byte pixel_result;
+;
+ pixel_result=(byte)(
+ subpix(x*4,y*2) ||
+ subpix(x*4+1,y*2) ||
+ subpix(x*4+2,y*2) ||
+ subpix(x*4+3,y*2) ||
+ subpix(x*4,y*2+1) ||
+ subpix(x*4+1,y*2+1) ||
+ subpix(x*4+2,y*2+1) ||
+ subpix(x*4+3,y*2+1)
+ )*15;
+return pixel_result;
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=1; initgraph(gd,gm,"o:");
+ assign(f,"v:logo.avd"); reset(f,1);
+ for( gd=0; gd <= 180; gd ++)
+ blockread(f,mem[0xa000*(gd*80)],53);
+ close(f);
+ for( gd=1; gd <= 106; gd ++)
+ for( gm=0; gm <= 145; gm ++)
+ putpixel(gd,gm+181,pixel(gd,gm));
+ assign(t,"d:avalot.txt");
+ rewrite(t);
+ for( gm=1; gm <= 36; gm ++)
+ {;
+ x="";
+ for( gd=1; gd <= 106; gd ++)
+ switch (getpixel(gd,gm*2+181)*2+getpixel(gd,gm*2+182)) {
+ case 0: x=x+' '; break;
+ case 15: x=x+'Ü'; break;
+ case 30: x=x+'ß'; break;
+ case 45: x=x+'Û'; break;
+ }
+ t << x << NL;
+ }
+ close(t);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/makeregi.cpp b/engines/avalanche/makeregi.cpp
new file mode 100644
index 0000000000..574d346660
--- /dev/null
+++ b/engines/avalanche/makeregi.cpp
@@ -0,0 +1,142 @@
+#include "ptoc.h"
+
+ /* regname's name starts at $7D1 (2001). */
+
+const array<1,56,char> padding =
+"For all the Etruscan armies were ranged beneath his eye";
+
+text txi,txo;
+string x,y;
+word fv;
+file<byte> f;
+byte sum,n;
+string name,number;
+
+string chkname,chknum,regname,regnum;
+
+
+ char decode1(char c)
+ {
+ byte b;
+
+ char decode1_result;
+ b=ord(c)-32;
+ decode1_result=chr(( (b & 0xf) << 3) + ((cardinal)(b & 0x70) >> 4));
+ return decode1_result;
+ }
+
+ char encode1(char c)
+ {
+ byte b;
+
+ char encode1_result;
+ b=ord(c);
+ b=( (cardinal)(b & 0x78) >> 3) + ((b & 0x7) << 4);
+ encode1_result=chr(b+32);
+ return encode1_result;
+ }
+
+ char encode2(char c)
+ {
+ char encode2_result;
+ encode2_result=chr((((ord(c) & 0xf) << 2)+0x43));
+ return encode2_result;
+ }
+
+ string enc1(string x)
+ {
+ string y; byte fv;
+
+ string enc1_result;
+ y=x; for( fv=1; fv <= length(y); fv ++) y[fv]=encode1(y[fv]);
+ enc1_result=y;
+ return enc1_result;
+ }
+
+ string enc2(string x)
+ {
+ string y; byte fv;
+
+ string enc2_result;
+ y=x; for( fv=1; fv <= length(y); fv ++) y[fv]=encode2(y[fv]);
+ enc2_result=y;
+ return enc2_result;
+ }
+
+ boolean checker(string proper,string check)
+ {
+ byte fv; boolean ok;
+
+ boolean checker_result;
+ ok=true;
+ for( fv=1; fv <= length(proper); fv ++)
+ if ((ord(proper[fv]) & 0xf)!=((cardinal)(ord(check[fv])-0x43) >> 2))
+ ok=false;
+
+ checker_result=ok;
+ return checker_result;
+ }
+
+ void unscramble()
+ {
+ byte namelen,numlen;
+
+
+ namelen=107-ord(x[1]); numlen=107-ord(x[2]);
+
+ regname=copy(x,3,namelen);
+ regnum=copy(x,4+namelen,numlen);
+ chkname=copy(x,4+namelen+numlen,namelen);
+ chknum=copy(x,4+namelen+numlen+namelen,numlen);
+
+ for( fv=1; fv <= namelen; fv ++) regname[fv]=decode1(regname[fv]);
+ for( fv=1; fv <= numlen; fv ++) regnum[fv]=decode1(regnum[fv]);
+
+ if ((! checker(regname,chkname)) || (! checker(regnum,chknum)))
+ {
+ output << "CHECK ERROR: " << regname << '/' << chkname << ';' << regnum << '/' << chknum << '.' << NL;
+ exit(0);
+ } else output << "--- Passed both checks. ---" << NL;
+ }
+
+int main(int argc, const char* argv[])
+{
+
+ pio_initialize(argc, argv);
+ output << "Name? "; input >> name >> NL;
+ output << "Number? "; input >> number >> NL;
+
+ x=string(chr(107-ord(name[0])))+chr(107-ord(number[0]));
+
+
+ x=x+enc1(name)+'J'+enc1(number)+enc2(name)+enc2(number);
+
+ number=""; fv=1;
+ while ((length(number)+length(x))<57)
+ {
+ number=number+padding[fv-1]; fv=fv+1;
+ }
+ x=x+enc1(number);
+
+
+ output << x << NL; output << NL;
+ unscramble();
+
+ assign(txi,"v:register.raw"); reset(txi);
+ assign(txo,"a:register.dat"); rewrite(txo);
+
+ for( fv=1; fv <= 53; fv ++)
+ {
+ txi >> y >> NL; txo << y << NL;
+ }
+
+ txi >> y >> NL; txo << x << NL;
+
+ while (! eof(txi))
+ {
+ txi >> y >> NL; txo << y << NL;
+ }
+
+ close(txi); close(txo);
+ return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/makesez.cpp b/engines/avalanche/makesez.cpp
new file mode 100644
index 0000000000..50e58109e6
--- /dev/null
+++ b/engines/avalanche/makesez.cpp
@@ -0,0 +1,47 @@
+#include "ptoc.h"
+
+
+
+struct sezheader {
+ array<1,2,char> initials; /* should be "TT" */
+ word gamecode;
+ word revision; /* as 3- or 4-digit code (eg v1.00 = 100) */
+ longint chains; /* number of scroll chains */
+ longint size; /* total size of all scroll chains */
+};
+
+const string crlf = string('\15')+'\12';
+const string tabs = string('\11')+'\11'+'\11'+'\11'+'\11'+'\11'+'\11';
+const char eof_ = '\32';
+
+untyped_file sez;
+sezheader header;
+string x;
+char check;
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ fillchar(x,sizeof(x),'\261');
+ x=string("This is a Sez file for an Avvy game, and its contents are subject")+crlf+
+ "to copyright. Have fun with the game!"+crlf+crlf+tabs+"tt"+crlf+crlf+
+ "[Lord Avalot D'Argent]"+crlf+crlf+eof_+
+ crlf+crlf+"Thomas was here!";
+ {;
+ header.initials="TT";
+ header.gamecode=2; /* code for Avalot */
+ header.revision=100; /* version 1.00 */
+ header.chains=0; /* no chains */
+ header.size=0; /* empty! */
+ }
+ check='\261';
+ assign(sez,"avalot.sez");
+ rewrite(sez,1);
+ blockwrite(sez,x[1],255);
+ blockwrite(sez,header,sizeof(header));
+ blockwrite(sez,check,1);
+ x=string('\0')+'\0'+'\0'+"Thomas was here, too!"+crlf+crlf+"Good luck...";
+ blockwrite(sez,x[1],39); /* footer */
+ close(sez);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/makevmou.cpp b/engines/avalanche/makevmou.cpp
new file mode 100644
index 0000000000..5ed388531c
--- /dev/null
+++ b/engines/avalanche/makevmou.cpp
@@ -0,0 +1,270 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Squeak.h"*/
+/*#include "Crt.h"*/
+
+/*$R+*/
+
+struct mp { /* mouse-pointer */
+ matrix<0,1,0,15,word> mask;
+ integer horzhotspot,verthotspot;
+};
+
+struct vmctype { /* Virtual Mouse Cursor */
+ pointer andpic,xorpic;
+ array<0,1,pointer> backpic;
+ array<0,1,pointtype> wherewas;
+ byte picnumber;
+ shortint ofsx,ofsy;
+};
+
+const array<1,9,arrowtype> mps =
+{{{ /* 1 - up-arrow */
+ ((65151,64575,64575,63519,63519,61455,61455,57351,57351,49155,49155,64575,64575,64575,64575,64575),
+ (0,384,384,960,960,2016,2016,4080,4080,8184,384,384,384,384,384,0)),
+ 8,
+ 0},
+
+{ /* 2 - screwdriver */
+ ((8191,4095,2047,34815,50175,61951,63743,64543,65039,65031,65027,65281,65408,65472,65505,65523),
+ (0,24576,28672,12288,2048,1024,512,256,224,176,216,96,38,10,12,0)),
+ 0,
+ 0},
+
+{ /* 3 - right-arrow */
+ ((65535,65535,64639,64543,7,1,0,1,7,64543,64639,65535,65535,65535,65535,65535),
+ (0,0,0,384,480,32760,32766,32760,480,384,0,0,0,0,0,0)),
+ 15,
+ 6},
+
+{ /* 4 - fletch */
+ ((255,511,1023,2047,1023,4607,14591,31871,65031,65283,65281,65280,65280,65409,65473,65511),
+ (0,10240,20480,24576,26624,17408,512,256,128,88,32,86,72,20,16,0)),
+ 0,
+ 0},
+
+{ /* 5 - hourglass */
+ ((0,0,0,34785,50115,61455,61455,63519,63519,61839,61455,49155,32769,0,0,0),
+ (0,32766,16386,12300,2064,1440,1440,576,576,1056,1440,3024,14316,16386,32766,0)),
+ 8,
+ 7},
+
+{ /* 6 - TTHand */
+ ((62463,57855,57855,57855,57471,49167,32769,0,0,0,0,32768,49152,57344,61441,61443),
+ (3072,4608,4608,4608,4992,12912,21070,36937,36873,36865,32769,16385,8193,4097,2050,4092)),
+ 4,
+ 0},
+
+{ /* 7- Mark's crosshairs */
+ ((65535,65151,65151,65151,65151,0,65151,65151,65151,65151,65535,65535,65535,65535,65535,65535),
+ (0,384,384,384,384,65535,384,384,384,384,0,0,0,0,0,0)),
+ 8,
+ 5},
+
+{ /* 8- I-beam. */
+ ((65535,65535,63631,63503,63503,65087,65087,65087,65087,65087,63503,63503,63631,65535,65535,65535),
+ (0,0,0,864,128,128,128,128,128,128,128,864,0,0,0,0)),
+ 8,
+ 7},
+
+{ /* 9- Question mark. */
+ ((511,1023,2047,31,15,8199,32647,65415,63503,61471,61503,61695,63999,63999,61695,61695),
+ (65024,33792,34816,34784,40976,57224,32840,72,1936,2080,2496,2304,1536,1536,2304,3840)),
+ 0,
+ 0}}};
+
+const integer mouse_size = 134;
+
+const array<1,134,char> mice_header =
+ string("Mouse file copyright (c) 1993. I saw a mouse! Where? SQUEEAAAKK!!! Cheese ")+ /* 74 */
+ "cheese cheese. Cheddar, Stilton, Double Gloucester. Squeak."+'\32'; /* 60 */
+
+integer gd,gm;
+matrix<0,50,1,40,word> a /*absolute $A000:0i*/;
+byte fv;
+vmctype vmc;
+byte plot; integer plx,ply;
+
+word swapbits(word a)
+{word swapbits_result;
+;
+ swapbits_result=lo(a)*256+hi(a);
+return swapbits_result;
+}
+
+void plot_vmc(integer xx,integer yy, byte page_)
+{;
+ {;
+ xx=xx+vmc.ofsx;
+ yy=yy+vmc.ofsy;
+
+ getimage(xx,yy,xx+15,yy+15,vmc.backpic[page_]);
+ putimage(xx,yy,vmc.andpic,andput);
+ putimage(xx,yy,vmc.xorpic,xorput);
+ {
+ pointtype& with1 = vmc.wherewas[page_];
+ ;
+ with1.x=xx;
+ with1.y=yy;
+ }
+ }
+}
+
+void wipe_vmc(byte page_)
+{;
+ { pointtype& with1 = vmc.wherewas[page_];
+ if (with1.x!=maxint)
+ putimage(with1.x,with1.y,vmc.backpic[page_],0);}
+}
+
+void setup_vmc()
+{
+ byte fv;
+;
+/* gd:=imagesize(0,0,15,15);*/
+
+ {;
+ getmem(vmc.andpic,mouse_size);
+ getmem(vmc.xorpic,mouse_size);
+
+ for( fv=0; fv <= 1; fv ++)
+ {;
+ getmem(vmc.backpic[fv],mouse_size);
+ vmc.wherewas[fv].x=maxint;
+ }
+ }
+}
+
+void show_off_mouse()
+{;
+
+ setcolor(14); settextstyle(0,0,2);
+
+ for( gm=0; gm <= 1; gm ++)
+ {;
+ setactivepage(gm);
+ setfillstyle(1,blue); bar(0,0,getmaxx(),getmaxy());
+ outtextxy(400,20,chr(48+gm));
+ }
+
+ gd=0;
+ do {
+ setactivepage(gd);
+ setvisualpage(1-gd);
+ gd=1-gd;
+
+ delay(56);
+
+ getbuttonstatus;
+ wipe_vmc(gd);
+
+ if (plot>0)
+ {;
+ putpixel(plx,ply,red);
+ plot -= 1;
+ }
+
+ plot_vmc(mx,my,gd);
+
+ if ((mkey==left) && (plot==0))
+ {;
+ plot=2;
+ plx=mx;
+ ply=my;
+ }
+
+ } while (!(mkey==right));
+
+ for( gm=0; gm <= 1; gm ++)
+ {;
+ setactivepage(1-gm);
+ wipe_vmc(gm);
+ }
+
+ setvisualpage(0);
+ setactivepage(0);
+}
+
+void grab_cursor(byte n)
+{;
+ getimage(32*n-16, 0,32*n-1,15,vmc.andpic);
+ getimage(32*n-16,20,32*n-1,35,vmc.xorpic);
+}
+
+void save_mice()
+{
+ untyped_file f;
+ byte fv;
+;
+ assign(f,"v:mice.avd");
+ rewrite(f,1);
+
+ blockwrite(f,mice_header,mouse_size);
+
+ for( fv=1; fv <= 9; fv ++)
+ {;
+ grab_cursor(fv);
+ putimage(100,100,vmc.xorpic,0);
+ blockwrite(f,vmc.andpic,mouse_size);
+ blockwrite(f,vmc.xorpic,mouse_size);
+ }
+
+ close(f);
+}
+
+void load_a_mouse(byte which)
+{
+ untyped_file f;
+;
+ assign(f,"v:mice.avd");
+ reset(f,1);
+ seek(f,mouse_size*2*(which-1)+134);
+
+ {;
+ blockread(f,vmc.andpic,mouse_size);
+ blockread(f,vmc.xorpic,mouse_size);
+ close(f);
+ {
+ void& with1 = mps[which];
+ ;
+ vmc.ofsx=-horzhotspot;
+ vmc.ofsy=-verthotspot;
+
+ setminmaxhorzcurspos(horzhotspot,624+horzhotspot);
+ setminmaxvertcurspos(verthotspot,199);
+ }
+ }
+
+}
+
+void draw_mouse_cursors()
+{;
+ for( fv=1; fv <= 9; fv ++)
+ for( gm=0; gm <= 1; gm ++)
+ for( gd=0; gd <= 15; gd ++)
+ a[gd+gm*20][fv*2]=swapbits(mps[fv].mask[gm][gd]);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ resetmouse;
+ setup_vmc();
+
+ draw_mouse_cursors();
+
+
+ save_mice();
+
+/* grab_cursor(3);*/
+/* load_a_mouse(4);
+ setgraphicscursor(mps[4]);
+
+ show_off_mouse;
+ on; repeat getbuttonstatus until mkey=left; off;
+ show_off_mouse;*/
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/menuxf.cpp b/engines/avalanche/menuxf.cpp
new file mode 100644
index 0000000000..1919b118de
--- /dev/null
+++ b/engines/avalanche/menuxf.cpp
@@ -0,0 +1,48 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+integer gd,gm;
+
+void load() /* Load2, actually */
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+
+ assign(f,"maintemp.avd"); reset(f,1);
+ /* Compression method byte follows this... */
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+ bit=getpixel(0,0);
+}
+
+void save()
+{
+ byte bit; untyped_file f;
+
+ assign(f,"v:mainmenu.avd");
+ rewrite(f,1);
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockwrite(f,mem[0xa000*48*80],59*80);
+ }
+ close(f);
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ gd=3; gm=1; initgraph(gd,gm,"");
+ load(); /* Between 48 and 107. */
+
+ save();
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/minstran.cpp b/engines/avalanche/minstran.cpp
new file mode 100644
index 0000000000..824fc806bc
--- /dev/null
+++ b/engines/avalanche/minstran.cpp
@@ -0,0 +1,37 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+integer gd,gm;
+pointer p; word s;
+
+void mblit(integer x1,integer y1,integer x2,integer y2) /* Minstrel Blitter */
+{
+ integer yy,len,pp; byte bit; const integer offset = 16384;
+;
+ x1=x1 / 8; len=((x2 / 8)-x1)+1;
+ for( yy=y1; yy <= y2; yy ++)
+ {;
+ pp=yy*80+x1;
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ move(mem[0xa000*offset+pp],mem[0xa000*pp],len);
+ }
+ }
+}
+
+const integer fx1 = 100; const integer fy1 = 100; const integer fx2 = 135; const integer fy2 = 145;
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"");
+ setactivepage(1); setfillstyle(7,9); bar(0,0,640,200);
+ mblit(fx1,fy1,fx2,fy2);
+ s=imagesize(fx1,fy1,fx2,fy2); getmem(p,s);
+ getimage(fx1,fy1,fx2,fy2,p); setactivepage(0);
+ putimage(fx1+100,fy1,p,0); freemem(p,s);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/newsprit.cpp b/engines/avalanche/newsprit.cpp
new file mode 100644
index 0000000000..073e546f25
--- /dev/null
+++ b/engines/avalanche/newsprit.cpp
@@ -0,0 +1,124 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+
+const string crlf = string('\15')+'\12'; const char eof_ = '\32';
+const array<1,177,char> trip5head =
+ string("Sprite*.AVD ... data file for Trippancy Five")+crlf+crlf+
+ "[Thorsoft relocatable fiveplane sprite image format]"+crlf+crlf+
+ "Thomas Thurman was here. ... Have fun!"+crlf+crlf+eof_+
+ "±±±±±±± * G. I. E. D. ! * ";
+
+const array<1,4,char> tripid = string('\x30')+'\x1'+'\x75'+'\261';
+
+const array<1,50,char> trip5foot = crlf+crlf+
+ " and that's it! Enjoy the game. "+'\3'+crlf+crlf+
+ "\n\n\n\n\n\n\n"+"tt";
+
+struct adxotype {
+ varying_string<12> name; /* name of character */
+ byte num; /* number of pictures */
+ byte xl,yl; /* x & y lengths of pictures */
+ byte seq; /* how many in one stride */
+ word size; /* the size of one picture */
+ byte fgc,bgc; /* foreground & background bubble colours */
+};
+
+struct adxtype {
+ varying_string<12> name; /* name of character */
+ varying_string<16> comment; /* comment */
+ byte num; /* number of pictures */
+ byte xl,yl; /* x & y lengths of pictures */
+ byte seq; /* how many in one stride */
+ word size; /* the size of one picture */
+ byte fgc,bgc; /* foreground & background bubble colours */
+ byte accinum; /* the number according to Acci (1=Avvy, etc.) */
+};
+
+varying_string<2> sn;
+adxotype oa;
+adxtype a;
+matrix<1,24,0,1,pointer> pic; /* the pictures themselves */
+array<1,16000,byte> aa;
+untyped_file out;
+integer bigsize;
+
+void copyaoa()
+{;
+ {;
+ a.name=oa.name;
+ a.comment="Transferred";
+ a.num=oa.num;
+ a.xl=oa.xl;
+ a.yl=oa.yl;
+ a.seq=oa.seq;
+ a.size=oa.size;
+ a.fgc=oa.fgc;
+ a.bgc=oa.bgc;
+ }
+}
+
+void setup()
+{
+ integer gd,gm;
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+}
+
+string strf(longint x)
+{
+ string q;
+string strf_result;
+;
+ str(x,q); strf_result=q;
+return strf_result;
+}
+
+void save()
+{
+ byte sort,n;
+ word fv,ff; char r; byte xw;
+ byte nxl,nyl;
+ word soa;
+;
+ cleardevice();
+ {;
+ a.xl=45; a.yl=10; a.num=1; a.seq=1;
+ a.size=imagesize(0,0,a.xl,a.yl);
+ soa=sizeof(a);
+
+ assign(out,"v:sprite10.avd"); rewrite(out,1);
+ blockwrite(out,trip5head,177);
+ blockwrite(out,tripid,4);
+ blockwrite(out,soa,2);
+ blockwrite(out,a,soa);
+
+ nxl=a.xl; nyl=a.yl;
+ xw=nxl / 8;
+ if ((nxl % 8)>0) xw += 1;
+
+ for( n=1; n <= a.num; n ++)
+ {;
+ getimage( 0,0,a.xl,a.yl,aa);
+ for( fv=0; fv <= nyl; fv ++)
+ blockwrite(out,aa[5+fv*xw*4],xw);
+
+ getimage(100,0,100+a.xl,a.yl,aa);
+ blockwrite(out,aa[5],a.size-6);
+ }
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ setup();
+ save();
+
+ blockwrite(out,trip5foot,50);
+ close(out);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/nim.cpp b/engines/avalanche/nim.cpp
new file mode 100644
index 0000000000..e5da17adff
--- /dev/null
+++ b/engines/avalanche/nim.cpp
@@ -0,0 +1,381 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+/*#include "Dos.h"*/
+
+
+const array<false,true,varying_string<7> > names = {{"Avalot","Dogfood"}};
+
+array<1,3,byte> old,stones;
+array<0,3,0,22,1,7,byte> stonepic; /* picture of Nimstone */
+byte turns;
+boolean dogfoodsturn; byte fv; byte stonesleft;
+
+boolean clicked;
+
+byte row,number;
+
+boolean squeak;
+shortint mnum,mrow;
+
+registers r;
+
+void resetmouse()
+{;
+ r.ax=0; intr(0x33,r);
+ squeak=r.ax>0;
+}
+
+void show()
+{;
+ r.ax=1; intr(0x33,r);
+}
+
+void hide()
+{;
+ r.ax=2; intr(0x33,r);
+}
+
+void chalk(integer x,integer y, string z)
+{
+ const array<0,3,byte> greys = {{0,8,7,15}};
+ byte fv;
+;
+ for( fv=0; fv <= 3; fv ++)
+ {;
+ setcolor(greys[fv]);
+ outtextxy(x-fv,y,z);
+ sound(fv*100*length(z)); delay(3); nosound; delay(30);
+ }
+}
+
+void setup()
+{
+ untyped_file f;
+ integer gd,gm;
+ byte bit;
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+
+ assign(f,"c:\\avalot\\nim.avd");
+ reset(f,1);
+ seek(f,41);
+ for( gm=0; gm <= 22; gm ++)
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,stonepic[bit][gm],7);
+ }
+ for( gd=1; gd <= 3; gd ++)
+ for( gm=0; gm <= 22; gm ++)
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,mem[0xa000*3200+gd*2800+gm*80],7);
+ }
+ for( gm=0; gm <= 36; gm ++)
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,mem[0xa000*400+49+gm*80],30);
+ }
+ close(f);
+
+ gd=getpixel(0,0); /* clear codes */
+ setcolor(4); rectangle(394,50,634,197);
+ setfillstyle(1,6); bar(395,51,633,196);
+ rectangle(10,5,380,70); bar(11,6,379,69);
+ setcolor(15);
+ outtextxy(475,53,"SCOREBOARD:");
+ setcolor(14);
+ outtextxy(420,63,"Turn:");
+ outtextxy(490,63,"Player:");
+ outtextxy(570,63,"Move:");
+
+ for( gd=1; gd <= 3; gd ++) stones[gd]=gd+2;
+
+ turns=0; dogfoodsturn=true;
+
+ chalk(27,15,"Take pieces away with:");
+ chalk(77,25,"1) the mouse (click leftmost)");
+ chalk(53,35,"or 2) the keyboard:");
+ chalk(220,35,string('\30')+'/'+'\31'+": choose row,");
+ chalk(164,45,string("+/- or ")+'\33'+'/'+'\32'+": more/fewer,");
+ chalk(204,55,"Enter: take stones.");
+
+ row=1; number=1; fillchar(old,sizeof(old),'\0'); stonesleft=12;
+ resetmouse();
+}
+
+void plotstone(byte x,byte y)
+{
+ byte fv,bit; word ofs;
+;
+ ofs=3200+y*2800+x*8;
+ for( fv=0; fv <= 22; fv ++)
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ move(stonepic[bit][fv],mem[0xa000*ofs+fv*80],7);
+ }
+}
+
+void board()
+{
+ byte fv,ff;
+;
+ for( fv=1; fv <= 3; fv ++)
+ for( ff=1; ff <= stones[fv]; ff ++)
+ plotstone(ff,fv);
+}
+
+void startmove()
+{
+ varying_string<2> tstr; integer ypos;
+;
+ turns += 1; str(turns,2,tstr); ypos=63+turns*10;
+ dogfoodsturn=! dogfoodsturn;
+ chalk(433,ypos,tstr);
+ chalk(493,ypos,names[dogfoodsturn]);
+ old=stones;
+}
+
+void show_changes()
+{
+ byte fv,ff,fq;
+;
+ chalk(573,63+turns*10,string(chr(64+row))+chr(48+number));
+ for( fv=1; fv <= 3; fv ++)
+ if (old[fv]>stones[fv])
+ for( ff=stones[fv]+1; ff <= old[fv]; ff ++)
+ for( fq=0; fq <= 22; fq ++) fillchar(mem[0xa000*3200+fv*2800+ff*8+fq*80],7,'\0');
+ stonesleft -= number;
+}
+
+void checkmouse();
+
+static void blip() {; sound(1771); delay(3); nosound; clicked=false; }
+
+void checkmouse()
+{;
+ {; ax=5; bx=0; } intr(0x33,r);
+ clicked=r.bx>0;
+ if (clicked)
+ {; /* The mouse was clicked. Where? */
+ mrow=(dx-38) / 35;
+ if ((mrow<1) || (mrow>3)) blip();
+ mnum=stones[mrow]-(cx / 64)+1;
+ if ((mnum<1) || (mnum>(unsigned char)stones[mrow])) blip();
+ }
+}
+
+void takesome();
+
+static void less() {; if (number>1) number -= 1; }
+
+void takesome()
+{
+ char r; byte sr;
+;
+ number=1;
+ do {
+ do {
+ sr=stones[row];
+ if (sr==0) {; row=row % 3+1; number=1; }
+ } while (!(sr!=0));
+ if (number>sr) number=sr;
+ setcolor(1); rectangle(63+(sr-number)*64,38+35*row,54+sr*64,63+35*row);
+ /* Wait for choice */
+ show();
+ do { checkmouse(); } while (!(keypressed() || clicked));
+ if (keypressed()) r=upcase(readkey());
+ hide();
+
+ setcolor(0); rectangle(63+(sr-number)*64,38+35*row,54+sr*64,63+35*row);
+
+ if (clicked)
+ {;
+ number=mnum;
+ row=mrow;
+ return;
+ } else
+ {;
+ switch (r) {
+ case '\0': switch (readkey()) {
+ case 'H': if (row>1) row -= 1; break; /* Up */
+ case 'P': if (row<3) row += 1; break; /* Down */
+ case 'K': number += 1; break;
+ case 'M': less(); break;
+ case 'I': row=1; break; /* PgUp */
+ case 'Q': row=3; break; /* PgDn */
+ case 'G': number=5; break; /* Home- check routine will knock this down to size */
+ case 'O': number=1; break; /* End */
+ }
+ break;
+ case '+': number += 1; break;
+ case '-': less(); break;
+ case RANGE_3('A','C'): row=ord(r)-64;
+ break;
+ case RANGE_5('1','5'): number=ord(r)-48;
+ break;
+ case '\15': return; break; /* Enter was pressed */
+ }
+ }
+ } while (!false);
+}
+
+void endofgame()
+{
+ char rr;
+;
+ chalk(595,63+turns*10,"Wins!");
+ outtextxy(100,190,"- - - Press any key... - - -");
+ while (keypressed()) rr=readkey();
+ do { ax=5; bx=0; intr(0x33,r); } while (!(keypressed() || (bx>0)));
+ if (keypressed()) rr=readkey();
+}
+
+void dogfood();
+ /* AI procedure to play the game */
+const matrix<1,3,1,2,byte> other = {{{{2,3}},{{1,3}},{{1,2}}}};
+
+
+static byte live,fv,ff,matches,thisone,where;
+
+static array<1,3,byte> r,sr;
+static array<1,3,boolean> inap;
+
+static boolean lmo; /* Let Me Out! */
+
+static byte ooo; /* Odd one out */
+
+
+static boolean find(byte x)
+ /* This gives True if there's a pile with x stones in. */
+{
+ boolean q; byte p;
+boolean find_result;
+;
+ q=false;
+ for( p=1; p <= 3; p ++) if (stones[p]==x) {; q=true; inap[p]=true; }
+ find_result=q;
+return find_result;
+}
+
+
+
+static void find_ap(byte start,byte stepsize)
+{
+ byte ff;
+;
+ matches=0;
+ fillchar(inap,sizeof(inap),'\0'); /* blank 'em all */
+ for( ff=0; ff <= 2; ff ++) if (find(start+ff*stepsize)) matches += 1;
+ else thisone=ff;
+
+ /* Now.. Matches must be 0, 1, 2, or 3.
+ 0/1 mean there are no A.P.s here, so we'll keep looking,
+ 2 means there is a potential A.P. that we can create (ideal!), and
+ 3 means that we're already in an A.P. (Trouble!). */
+
+ switch (matches) {
+ case 2: {;
+ for( ff=1; ff <= 3; ff ++) /* find which one didn't fit the A.P. */
+ if (! inap[ff]) ooo=ff;
+ if (stones[ooo]>(start+thisone*stepsize)) /* check it's possible! */
+ {; /* create an A.P. */
+ row=ooo; /* already calculated */
+ /* Start+thisone*stepsize will give the amount we SHOULD have here. */
+ number=stones[row]-(start+thisone*stepsize); lmo=true; return;
+ }
+ }
+ break;
+ case 3: {; /* we're actually IN an A.P! Trouble! Oooh dear. */
+ row=r[3]; number=1; lmo=true; return; /* take 1 from the largest pile */
+ }
+ break;
+ }
+}
+
+void dogfood()
+{
+ boolean sorted; byte temp;
+
+;
+ live=0; lmo=false;
+ for( fv=1; fv <= 3; fv ++)
+ {;
+ if (stones[fv]>0)
+ {;
+ live += 1;
+ r[live]=fv; sr[live]=stones[fv];
+ }
+ }
+ switch (live) {
+ case 1: /* Only one is free- so take 'em all */
+ {; row=r[1]; number=stones[r[1]]; return; }
+ break;
+ case 2: /* Two are free- make them equal */
+ {;
+ if (sr[1]>sr[2])
+ {; row=r[1]; number=sr[1]-sr[2]; return; } else /* T > b */
+ if (sr[1]<sr[2])
+ {; row=r[2]; number=sr[2]-sr[1]; return; } else /* B > t */
+ {; row=r[1]; number=1; return; } /* B = t... oh no, we've lost! */
+ }
+ break;
+ case 3: /* Ho hum... this'll be difficult! */
+ {;
+ /* There are three possible courses of action when we have 3 lines left:
+ 1) Look for 2 equal lines, then take the odd one out.
+ 2) Look for A.P.s, and capitalise on them.
+ 3) Go any old where. */
+
+ for( fv=1; fv <= 3; fv ++) /* Look for 2 equal lines */
+ if (stones[other[fv][1]]==stones[other[fv][2]])
+ {;
+ row=fv; /* this row */ number=stones[fv]; /* all of 'em */ return;
+ }
+
+ do {
+ sorted=true;
+ for( fv=1; fv <= 2; fv ++)
+ if (sr[fv]>sr[fv+1])
+ {;
+ temp=sr[fv+1]; sr[fv+1]=sr[fv]; sr[fv]=temp;
+ temp= r[fv+1]; r[fv+1]= r[fv]; r[fv]=temp;
+ sorted=false;
+ }
+ } while (!sorted);
+ /* Now we look for A.P.s ... */
+ for( fv=1; fv <= 3; fv ++)
+ {;
+ find_ap(fv,1); /* there are 3 "1"s */
+ if (lmo) return; /* cut-out */
+ }
+ find_ap(1,2); /* only "2" possible */
+ if (lmo) return;
+
+ /* A.P. search must have failed- use the default move. */
+ row=r[3]; number=1; return;
+ }
+ break;
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ setup();
+ board();
+ do {
+ startmove();
+ if (dogfoodsturn) dogfood(); else takesome();
+ stones[row] -= number;
+ show_changes();
+ } while (!(stonesleft==0));
+ endofgame(); /* Winning sequence is A1, B3, B1, C1, C1, btw. */
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/nimdraw.cpp b/engines/avalanche/nimdraw.cpp
new file mode 100644
index 0000000000..afcac6d850
--- /dev/null
+++ b/engines/avalanche/nimdraw.cpp
@@ -0,0 +1,94 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+
+const string header = string("Datafile for Avalot, copyright (c) 1992.")+'\32';
+
+integer gd,gm,x,y;
+untyped_file f;
+byte bit;
+
+void plot(char ch, byte x)
+{;
+ setcolor(blue); outtextxy(x*80+4,0,ch); outtextxy(x*80+10,0,ch);
+ setcolor(lightblue); outtextxy(x*80+5,0,ch); outtextxy(x*80+9,0,ch);
+ setcolor(darkgray); outtextxy(x*80+6,0,ch); outtextxy(x*80+8,0,ch);
+ setcolor(yellow); outtextxy(x*80+7,0,ch);
+}
+
+void load()
+{
+ byte z;
+ array<1,4,pointer> a;
+ varying_string<12> check;
+ untyped_file f; word s;
+;
+ assign(f,"c:\\avalot\\nimstone.avd"); reset(f,1);
+ seek(f,85); z=3;
+ s=imagesize(0,0,getmaxx(),75);
+ getmem(a[z],s);
+ blockread(f,a[z],s);
+ putimage(0,7,a[z],0);
+ freemem(a[z],s); close(f);
+}
+
+void spludge(integer x,integer y, string z)
+{
+ shortint dx,dy;
+;
+ setcolor(15);
+ for( dx=-1; dx <= 1; dx ++)
+ for( dy=-1; dy <= 1; dy ++)
+ outtextxy(x+dx,y+dy,z);
+ setcolor(0);
+ outtextxy(x,y,z);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"");
+ load();
+ settextstyle(4,0,0); setusercharsize(2,1,1,1);
+ plot('A',1);
+ plot('B',2);
+ plot('C',3);
+/* rectangle(gd*80,7,56+gd*80,29); */
+
+ setfillstyle(1,1); setcolor(9);
+ fillellipse( 97,104,6,4); fillellipse(321,104,6,4);
+ fillellipse( 97,131,6,4); fillellipse(321,131,6,4);
+ bar(97,100,321,134);
+ bar(92,104,326,131);
+ setfillstyle(1,9);
+ bar(91,103, 91,131); bar(327,104,327,131);
+ bar(98, 99,321, 99); bar( 97,135,321,135);
+
+ settextstyle(2,0,0); setusercharsize(20,10,11,10);
+ spludge( 99,100,"The Ancient Game of");
+ settextstyle(1,0,0); setusercharsize(40,10,10,10);
+ spludge( 99,105,"NIM");
+
+ /* now save it all! */
+
+ assign(f,"c:\\avalot\\nim.avd");
+ rewrite(f,1);
+ blockwrite(f,header[1],length(header));
+ for( gd=0; gd <= 3; gd ++)
+ for( gm=7; gm <= 29; gm ++)
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockwrite(f,mem[0xa000*gd*10+gm*80],7);
+ }
+ for( gm=99; gm <= 135; gm ++)
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockwrite(f,mem[0xa000*11+gm*80],30);
+ }
+ close(f);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/nimunit.cpp b/engines/avalanche/nimunit.cpp
new file mode 100644
index 0000000000..0becd47d10
--- /dev/null
+++ b/engines/avalanche/nimunit.cpp
@@ -0,0 +1,443 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ NIM UNIT A unit version of the pub game (Nim). */
+
+#define __nimunit_implementation__
+
+
+#include "nimunit.h"
+
+
+const array<false,true,varying_string<7> > names = {{"Avalot","Dogfood"}};
+
+array<1,3,byte> old,stones;
+array<0,3,0,22,1,7,byte> stonepic; /* picture of Nimstone */
+byte turns;
+boolean dogfoodsturn; byte fv; byte stonesleft;
+
+boolean clicked;
+
+byte row,number;
+
+boolean squeak;
+shortint mnum,mrow;
+
+void chalk(integer x,integer y, string z)
+{
+ const array<0,3,byte> greys = {{0,8,7,15}};
+ byte fv;
+
+ for( fv=0; fv <= 3; fv ++)
+ {
+ setcolor(greys[fv]);
+ outtextxy(x-fv,y,z);
+ sound(fv*100*length(z)); delay(3); nosound; delay(30);
+ }
+}
+
+void setup()
+{
+ const integer page3 = 0xac00;
+ byte gd,gm;
+ untyped_file f;
+ byte bit;
+
+ setactivepage(3);
+ setvisualpage(3);
+ cleardevice();
+ dawn();
+
+ assign(f,"nim.avd");
+ reset(f,1);
+ seek(f,41);
+ for( gm=0; gm <= 22; gm ++)
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,stonepic[bit][gm],7);
+ }
+ for( gd=1; gd <= 3; gd ++)
+ for( gm=0; gm <= 22; gm ++)
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,mem[page3*3200+gd*2800+gm*80],7);
+ }
+ for( gm=0; gm <= 36; gm ++)
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,mem[page3*400+49+gm*80],30);
+ }
+ close(f);
+
+ gd=getpixel(0,0); /* clear codes */
+ setcolor(4); rectangle(394,50,634,197);
+ setfillstyle(1,6); bar(395,51,633,196);
+ rectangle(10,5,380,70); bar(11,6,379,69);
+ setcolor(15);
+ outtextxy(475,53,"SCOREBOARD:");
+ setcolor(14);
+ outtextxy(420,63,"Turn:");
+ outtextxy(490,63,"Player:");
+ outtextxy(570,63,"Move:");
+
+ for( gd=1; gd <= 3; gd ++) stones[gd]=gd+2;
+
+ turns=0; dogfoodsturn=true;
+
+ chalk(27,15,"Take pieces away with:");
+ chalk(77,25,"1) the mouse (click leftmost)");
+ chalk(53,35,"or 2) the keyboard:");
+ chalk(220,35,string('\30')+'/'+'\31'+": choose row,");
+ chalk(164,45,string("+/- or ")+'\33'+'/'+'\32'+": more/fewer,");
+ chalk(204,55,"Enter: take stones.");
+
+ row=1; number=1; fillchar(old,sizeof(old),'\0'); stonesleft=12;
+
+ /* Set up mouse. */
+ off_virtual();
+ oncandopageswap=false;
+
+ setactivepage(3);
+ setvisualpage(3);
+}
+
+void plotstone(byte x,byte y)
+{
+ byte fv,bit; word ofs;
+
+ ofs=3200+y*2800+x*8;
+ for( fv=0; fv <= 22; fv ++)
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ move(stonepic[bit][fv],mem[0xac00*ofs+fv*80],7);
+ }
+}
+
+void board()
+{
+ byte fv,ff;
+
+ for( fv=1; fv <= 3; fv ++)
+ for( ff=1; ff <= stones[fv]; ff ++)
+ plotstone(ff,fv);
+}
+
+void startmove()
+{
+ varying_string<2> tstr; integer ypos;
+
+ turns += 1; str(turns,2,tstr); ypos=63+turns*10;
+ dogfoodsturn=! dogfoodsturn;
+ chalk(433,ypos,tstr);
+ chalk(493,ypos,names[dogfoodsturn]);
+ old=stones;
+}
+
+void show_changes()
+{
+ byte fv,ff,fq; varying_string<2> move;
+
+ move=string(chr(64+row))+chr(48+number);
+ chalk(573,63+turns*10,move);
+ log_aside(names[dogfoodsturn]+" plays "+move+'.');
+
+ for( fv=1; fv <= 3; fv ++)
+ if (old[fv]>stones[fv])
+ for( ff=stones[fv]+1; ff <= old[fv]; ff ++)
+ for( fq=0; fq <= 22; fq ++) fillchar(mem[0xac00*3200+fv*2800+ff*8+fq*80],7,'\0');
+ stonesleft -= number;
+}
+
+void checkmouse();
+
+static void blip() { note(1771); delay(3); nosound; clicked=false; }
+
+void checkmouse()
+{
+ xycheck(); /* Check the mouse */
+ clicked=keystatus>0;
+ if (clicked)
+ {
+ void& with = r;
+ /* The mouse was clicked. Where? */
+ mrow=(my-38) / 35;
+ if ((mrow<1) || (mrow>3)) blip();
+ mnum=stones[mrow]-(mx / 64)+1;
+ if ((mnum<1) || (mnum>(unsigned char)stones[mrow])) blip();
+ }
+}
+
+void takesome();
+
+static void less() { if (number>1) number -= 1; }
+
+void takesome()
+{
+ char r; byte sr;
+
+ number=1;
+ do {
+ do {
+ sr=stones[row];
+ if (sr==0) { row=row % 3+1; number=1; }
+ } while (!(sr!=0));
+ if (number>sr) number=sr;
+ setcolor(1); rectangle(63+(sr-number)*64,38+35*row,54+sr*64,63+35*row);
+ /* Wait for choice */
+ on();
+ do { checkmouse(); } while (!(keypressed() || clicked));
+ if (keypressed()) r=upcase(readkey());
+ off();
+
+ setcolor(0); rectangle(63+(sr-number)*64,38+35*row,54+sr*64,63+35*row);
+
+ if (clicked)
+ {
+ number=mnum;
+ row=mrow;
+ return;
+ } else
+ {
+ switch (r) {
+ case '\0': switch (readkey()) {
+ case 'H': if (row>1) row -= 1; break; /* Up */
+ case 'P': if (row<3) row += 1; break; /* Down */
+ case 'K': number += 1; break;
+ case 'M': less(); break;
+ case 'I': row=1; break; /* PgUp */
+ case 'Q': row=3; break; /* PgDn */
+ case 'G': number=5; break; /* Home- check routine will knock this down to size */
+ case 'O': number=1; break; /* End */
+ }
+ break;
+ case '+': number += 1; break;
+ case '-': less(); break;
+ case RANGE_3('A','C'): row=ord(r)-64;
+ break;
+ case RANGE_5('1','5'): number=ord(r)-48;
+ break;
+ case '\15': return; break; /* Enter was pressed */
+ }
+ }
+ } while (!false);
+}
+
+void endofgame()
+{
+ char rr;
+
+ chalk(595,63+turns*10,"Wins!");
+ outtextxy(100,190,"- - - Press any key... - - -");
+ while (keypressed()) rr=readkey();
+ do { check(); } while (!(mpress==0));
+
+ { void& with = r; do { check(); } while (!(keypressed() || (mrelease>0)));}
+ if (keypressed()) rr=readkey();
+
+ mousepage(cp);
+ off();
+ on_virtual();
+}
+
+void dogfood();
+ /* AI procedure to play the game */
+const matrix<1,3,1,2,byte> other = {{{{2,3}},{{1,3}},{{1,2}}}};
+
+
+static byte live,fv,ff,matches,thisone,where;
+
+static array<1,3,byte> r,sr;
+static array<1,3,boolean> inap;
+
+static boolean lmo; /* Let Me Out! */
+
+static byte ooo; /* Odd one out */
+
+
+static boolean find(byte x)
+ /* This gives True if there's a pile with x stones in. */
+{
+ boolean q; byte p;
+
+ boolean find_result;
+ q=false;
+ for( p=1; p <= 3; p ++) if (stones[p]==x) { q=true; inap[p]=true; }
+ find_result=q;
+ return find_result;
+}
+
+
+
+static void find_ap(byte start,byte stepsize)
+{
+ byte ff;
+
+ matches=0;
+ fillchar(inap,sizeof(inap),'\0'); /* blank 'em all */
+ for( ff=0; ff <= 2; ff ++) if (find(start+ff*stepsize)) matches += 1;
+ else thisone=ff;
+
+ /* Now.. Matches must be 0, 1, 2, or 3.
+ 0/1 mean there are no A.P.s here, so we'll keep looking,
+ 2 means there is a potential A.P. that we can create (ideal!), and
+ 3 means that we're already in an A.P. (Trouble!). */
+
+ switch (matches) {
+ case 2: {
+ for( ff=1; ff <= 3; ff ++) /* find which one didn't fit the A.P. */
+ if (! inap[ff]) ooo=ff;
+ if (stones[ooo]>(start+thisone*stepsize)) /* check it's possible! */
+ { /* create an A.P. */
+ row=ooo; /* already calculated */
+ /* Start+thisone*stepsize will give the amount we SHOULD have here. */
+ number=stones[row]-(start+thisone*stepsize); lmo=true; return;
+ }
+ }
+ break;
+ case 3: { /* we're actually IN an A.P! Trouble! Oooh dear. */
+ row=r[3]; number=1; lmo=true; return; /* take 1 from the largest pile */
+ }
+ break;
+ }
+}
+
+void dogfood()
+{
+ boolean sorted; byte temp;
+
+
+ live=0; lmo=false;
+ for( fv=1; fv <= 3; fv ++)
+ {
+ if (stones[fv]>0)
+ {
+ live += 1;
+ r[live]=fv; sr[live]=stones[fv];
+ }
+ }
+ switch (live) {
+ case 1: /* Only one is free- so take 'em all */
+ { row=r[1]; number=stones[r[1]]; return; }
+ break;
+ case 2: /* Two are free- make them equal */
+ {
+ if (sr[1]>sr[2])
+ { row=r[1]; number=sr[1]-sr[2]; return; } else /* T > b */
+ if (sr[1]<sr[2])
+ { row=r[2]; number=sr[2]-sr[1]; return; } else /* B > t */
+ { row=r[1]; number=1; return; } /* B = t... oh no, we've lost! */
+ }
+ break;
+ case 3: /* Ho hum... this'll be difficult! */
+ {
+ /* There are three possible courses of action when we have 3 lines left:
+ 1) Look for 2 equal lines, then take the odd one out.
+ 2) Look for A.P.s, and capitalise on them.
+ 3) Go any old where. */
+
+ for( fv=1; fv <= 3; fv ++) /* Look for 2 equal lines */
+ if (stones[other[fv][1]]==stones[other[fv][2]])
+ {
+ row=fv; /* this row */ number=stones[fv]; /* all of 'em */ return;
+ }
+
+ do {
+ sorted=true;
+ for( fv=1; fv <= 2; fv ++)
+ if (sr[fv]>sr[fv+1])
+ {
+ temp=sr[fv+1]; sr[fv+1]=sr[fv]; sr[fv]=temp;
+ temp= r[fv+1]; r[fv+1]= r[fv]; r[fv]=temp;
+ sorted=false;
+ }
+ } while (!sorted);
+ /* Now we look for A.P.s ... */
+ for( fv=1; fv <= 3; fv ++)
+ {
+ find_ap(fv,1); /* there are 3 "1"s */
+ if (lmo) return; /* cut-out */
+ }
+ find_ap(1,2); /* only "2" possible */
+ if (lmo) return;
+
+ /* A.P. search must have failed- use the default move. */
+ row=r[3]; number=1; return;
+ }
+ break;
+ }
+}
+
+void play_nim() /* Plays the game. Only procedure in this unit to
+ be declared in the interface section. */
+{
+ byte groi;
+
+ if (dna.wonnim)
+ { /* Already won the game. */
+ dixi('Q',6);
+ return;
+ }
+
+ if (! dna.asked_dogfood_about_nim)
+ {
+ dixi('q',84);
+ return;
+ }
+
+ dixi('Q',3);
+ dna.playednim += 1;
+ dusk();
+ oncandopageswap=false;
+ copypage(3,1-cp); /* Store old screen. */ groi=getpixel(0,0);
+ off();
+
+ setup();
+ board();
+ on();
+ mousepage(3);
+
+ do {
+ startmove();
+ if (dogfoodsturn) dogfood(); else takesome();
+ stones[row] -= number;
+ show_changes();
+ } while (!(stonesleft==0));
+ endofgame(); /* Winning sequence is A1, B3, B1, C1, C1, btw. */
+
+ dusk(); off();
+ oncandopageswap=true;
+ copypage(1-cp,3); /* Restore old screen. */ groi=getpixel(0,0);
+ on(); dawn();
+
+ if (dogfoodsturn)
+ { /* Dogfood won - as usual */
+ log_aside("He won.");
+ if (dna.playednim==1) /* Your first game */
+ dixi('Q',4); /* Goody! Play me again? */
+ else
+ dixi('Q',5); /* Oh, look at that! I've won again! */
+ pennycheck(4); /* And you've just lost 4d! */
+ } else
+ { /* You won - strange! */
+ log_aside("You won.");
+ dixi('Q',7); /* You won! Give us a lute! */
+ dna.obj[lute]=true;
+ objectlist();
+ dna.wonnim=true;
+ show_one(1); /* Show the settle with no lute on it. */
+ points(7); /* 7 points for winning! */
+ }
+
+ if (dna.playednim==1) points(3); /* 3 points for playing your 1st game. */
+
+}
+
+ /* No init part. */
diff --git a/engines/avalanche/nimunit.h b/engines/avalanche/nimunit.h
new file mode 100644
index 0000000000..5e3386d47f
--- /dev/null
+++ b/engines/avalanche/nimunit.h
@@ -0,0 +1,18 @@
+#ifndef __nimunit_h__
+#define __nimunit_h__
+
+
+#include "gyro.h"
+ #include "Graph.h"
+ /*#include "Crt.h"*/
+#include "pingo.h"
+#include "visa.h"
+#include "lucerna.h"
+#include "logger.h"
+#include "celer.h"
+
+
+ void play_nim();
+
+
+#endif
diff --git a/engines/avalanche/oldfiler.cpp b/engines/avalanche/oldfiler.cpp
new file mode 100644
index 0000000000..c54a4696be
--- /dev/null
+++ b/engines/avalanche/oldfiler.cpp
@@ -0,0 +1,260 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+#include "graph.h"
+/*#include "Dos.h"*/
+/*#include "Rodent.h"*/
+
+/*$V-*/
+
+const char more[] = " (more) ";
+const string up = string('-')+'\30'+more+'\30';
+const string down = string('+')+'\31'+more+'\31';
+
+const graphcursmasktype fletch = /* Mask 4 in Avalot */
+ {(
+ (255,511,1023,2047,1023,4607,14591,31871,65031,65283,65281,65280,65280,65409,65473,65511),
+ (0,10240,20480,24576,26624,17408,512,256,128,88,32,86,72,20,16,0)),
+ 0,
+ 0};
+
+string cdir;
+matrix<0,2,1,18,varying_string<15> > info;
+matrix<0,2,1,100,varying_string<15> > possible;
+byte fv;
+array<0,2,byte> light,page_;
+array<0,2,boolean> blank;
+byte chtcode,where;
+string answer;
+
+void split(string x)
+{
+ byte fv;
+;
+ x=copy(x,4,255); if (x=="") {; blank[0]=true; return; }
+ x=x+'\\'; possible[0][1]="b\\"; fv=2;
+ while (pos("\\",x)!=0)
+ {;
+ possible[0][fv]=string('b')+copy(x,1,pos("\\",x)-1); fv += 1;
+ x=copy(x,pos("\\",x)+1,255);
+ }
+ possible[0][fv-1]="";
+}
+
+void block(integer x1,integer y1,integer x2,integer y2, string x)
+{;
+ bar(x1,y1,x2,y2);
+ setcolor( 9); outtextxy(x1+(x2-x1) / 2-1,y1+5,x);
+ setcolor(15); outtextxy(x1+(x2-x1) / 2+1,y1+6,x);
+}
+
+void message(string x)
+{;
+ block(5,189,640,200,x);
+}
+
+void bigbar(byte x)
+{;
+ bar(15+210*x,36,210+210*x,187);
+}
+
+void getem();
+
+
+static void sub_getem(char prefix, string spec, byte attrib,byte infonum)
+{
+ searchrec s; byte fv;
+;
+ fv=0;
+ findfirst(spec,attrib,s);
+ while ((doserror==0) && (fv<100))
+ {;
+ if (((s.attr & attrib)>0) && (s.name[1]!='.'))
+ {; /* circumvent inclusive searching! */
+ fv += 1;
+ possible[infonum][fv]=string(prefix)+s.name;
+ }
+ findnext(s);
+ }
+ if (fv==0) blank[infonum]=true;
+}
+
+void getem()
+
+{;
+ message("Please wait... scanning directory...");
+ sub_getem('a',"*.asg",archive+hidden,1); /* Scan for .ASG files */
+ sub_getem('f',"*.*",directory,2); /* Scan for sub-directories */
+}
+
+void minisc(string& x) /* Converts to lower-case */
+{
+ byte fv;
+;
+ for( fv=1; fv <= length(x); fv ++)
+ if ((x[fv]>='A') && (x[fv]<='Z')) x[fv] += 32;
+}
+
+void showall()
+{
+ byte fv,ff;
+;
+ for( fv=0; fv <= 2; fv ++)
+ {;
+ bigbar(fv); /* blank out anything else */
+ if (blank[fv])
+ {; /* nothing here at all */
+/* setcolor(14);
+ outtextxy(113+210*fv,43,'(Nothing here!)'); */
+ setcolor(14); settextstyle(0,0,2);
+ outtextxy(113+210*fv, 77,"Nothing");
+ outtextxy(113+210*fv,100,"here!");
+ settextstyle(0,0,1);
+ } else
+ {; /* something here- what? */
+ setcolor(11);
+ for( ff=0; ff <= 15; ff ++)
+ {;
+ info[fv][ff+2]=possible[fv][page_[fv]*15+ff+1]; minisc(info[fv][ff+2]);
+ }
+ if (page_[fv]>0) info[fv][1]=up; else info[fv][1]="";
+ if (possible[fv][page_[fv]*15+17]!="")
+ info[fv][18]=down; else info[fv][18]="";
+ for( ff=1; ff <= 18; ff ++)
+ {;
+ outtextxy(113+210*fv,35+ff*8,copy(info[fv][ff],2,255));
+ }
+ }
+ }
+ block(5,12,640,22,cdir);
+}
+
+void changedir(string x)
+{;
+
+ chdir(x); getdir(0,cdir);
+}
+
+void drawup()
+{
+ integer gd;
+;
+ block( 15, 0,630,10,"Choose an .ASG file to load or save.");
+ block( 15,24,210,34,"Looking back:");
+ block(225,24,420,34,"Here:");
+ block(435,24,630,34,"Looking forwards:");
+ for( gd=0; gd <= 2; gd ++) bigbar(gd); /* just to tide us over the wait... */
+ showall();
+}
+
+void setup()
+{;
+ settextjustify(1,1); setfillstyle(1,1);
+ fillchar(blank,sizeof(blank),'\0'); fillchar( info,sizeof( info),'\0');
+ fillchar(possible,sizeof(possible),'\0');
+ fillchar( page_,sizeof( page_),'\0');
+ split(cdir); getem(); drawup();
+}
+
+void setup1()
+{
+ integer gd,gm;
+;
+ gd=3; gm=0; initgraph(gd,gm,""); answer="";
+ getdir(0,cdir); resetmouse; setgraphicscursor(fletch);
+ fillchar(light,sizeof(light),'\0');
+ setup();
+}
+
+void clickwait()
+{
+ const array<1,4,varying_string<30> > msg =
+ {{"change to another drive.",
+ "return to a lower directory.",
+ "use the file named.",
+ "enter a sub-directory."}};
+ byte oldcht; /* Click Here To... code */
+;
+ showmousecursor; oldcht=177;
+ do {
+ if (mousey<38) chtcode=1; else
+ switch (mousex) {
+ case 0 ... 210: chtcode=2; break;
+ case 211 ... 421: chtcode=3; break;
+ default: chtcode=4;
+ }
+ if (oldcht!=chtcode)
+ {;
+ hidemousecursor; message(string("Click here to ")+msg[chtcode]);
+ showmousecursor; oldcht=chtcode;
+ }
+ } while (!leftmousekeypressed);
+ hidemousecursor; where=((mousey-39) / 8)+1;
+}
+
+void blip()
+{;
+ sound(32); delay(3); nosound;
+}
+
+void do_cht()
+{
+ char r; byte fv; string x;
+;
+ if (chtcode==1)
+ {; /* change drives */
+ message("Enter the drive letter (e.g. A)...");
+ r=readkey();
+ changedir(string(r)+':'); setup();
+ } else
+ {;
+ x=info[chtcode-2][where]; r=x[1]; x=copy(x,2,255);
+ switch (r) {
+ case 'b': {; /* back some dirs */
+ if (x=='\\') x="";
+ for( fv=where-1; fv >= 3; fv --)
+ x=copy(info[0][fv],2,255)+'\\'+x;
+ changedir(string('\\')+x);
+ setup();
+ }
+ break;
+ case 'f': {; /* sub-directory */
+ changedir(x);
+ setup();
+ }
+ break;
+ case '+': {; /* scroll one panel down */
+ page_[chtcode-2] += 1;
+ drawup();
+ }
+ break;
+ case '-': {; /* scroll one panel up */
+ page_[chtcode-2] -= 1;
+ drawup();
+ }
+ break;
+ case 'a': answer=x; break;
+ }
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ setup1();
+ do {
+ clickwait();
+ do_cht();
+ } while (!(answer!=""));
+ if (length(cdir)>3) cdir=cdir+'\\';
+ answer=cdir+answer;
+ closegraph();
+ output << "Routine completed." << NL;
+ output << "Answer: " << answer << NL;
+ output << "Hit Enter:"; input >> NL;
+return EXIT_SUCCESS;
+}
+
+
+
diff --git a/engines/avalanche/oldhighs.cpp b/engines/avalanche/oldhighs.cpp
new file mode 100644
index 0000000000..1aed0c5026
--- /dev/null
+++ b/engines/avalanche/oldhighs.cpp
@@ -0,0 +1,249 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+
+struct scoretype {
+ varying_string<39> name;
+ word score;
+};
+
+struct ratetype {
+ varying_string<10> rank;
+ word lowest;
+};
+
+struct tabletype {
+ array<1,12,scoretype> a;
+ byte light;
+};
+
+const array<1,9,ratetype> ratings =
+ {{{"Rubbish", 0},
+ {"Beginner", 1},
+ {"Poor", 10},
+ {"Average", 30},
+ {"Fair", 50},
+ {"Not bad", 70},
+ {"Good", 100},
+ {"Great", 200},
+ {"Fantastic!", 330}}};
+
+integer gd,gm;
+tabletype table;
+
+byte ratingname(word x)
+{
+ byte fv;
+byte ratingname_result;
+;
+ for( fv=9; fv >= 1; fv --)
+ if (x>=ratings[fv].lowest)
+ {;
+ ratingname_result=fv;
+ return ratingname_result;
+ } /* bad style */
+return ratingname_result;
+}
+
+void title();
+
+const string message = "A v a l o t : H i g h - S c o r e s";
+
+
+static void sayfast(integer x,integer y)
+{
+ integer anchor; byte fv;
+;
+ anchor=-296;
+ for( fv=1; fv <= length(message); fv ++)
+ {;
+ if (message[fv-1]!='\40') outtextxy(x+anchor,y-8,message[fv-1]);
+ anchor += 16;
+ }
+}
+
+void title()
+{
+ const array<0,6,byte> shades =
+ {{blue,lightgray,darkgray,blue,lightblue,blue,darkgray}};
+ byte x;
+ integer len;
+
+;
+ settextstyle(0,0,2); /*settextjustify(1,1);*/
+ len=textheight(message);
+ for( x=6; x >= 0; x --)
+ {;
+ setcolor(shades[x]);
+ sayfast(320-x*2,20-x);
+ if (x>0)
+ {;
+ sayfast(320+x*2,20-x);
+ sayfast(320+x*2,20+x);
+ sayfast(320-x*2,20+x);
+ }
+ }
+}
+
+void newtable()
+{
+ const array<1,12,varying_string<15> > names =
+ {{"Mike","Liz","Thomas","Mark","Mandy","Andrew","Lucy Tryphena","",
+ "Thanks to all","who helped...","","Have fun!"}};
+ byte fv;
+;
+ fillchar(table,sizeof(table),'\261');
+ for( fv=1; fv <= 12; fv ++)
+ {
+ scoretype& with = table.a[fv];
+ ;
+ with.name=names[fv];
+ with.score=193-fv*16;
+ }
+ table.light=1;
+}
+
+string strf(longint x) /* From Gyro. Delete when integrated. */
+{
+ string q;
+string strf_result;
+;
+ str(x,q); strf_result=q;
+return strf_result;
+}
+
+void sparkle(integer x,integer y, string z)
+{;
+ setcolor(cyan); outtextxy(x-1,y-1,z);
+ setcolor(blue); outtextxy(x+1,y+1,z);
+ setcolor(white); outtextxy(x ,y ,z);
+}
+
+void drawtable()
+{
+ byte fv,last,now;
+;
+ setfillstyle(1,8);
+ bar( 0, 40,105, 58); bar(110, 40,400, 58);
+ bar(405, 40,490, 58); bar(495, 40,640, 58);
+ bar( 5, 60,105,181); bar(110, 60,400,181);
+ bar(405, 60,490,181); bar(495, 60,635,181);
+ bar( 0,185,640,190);
+ setcolor(lightred); settextstyle(0,0,1); settextjustify(0,0);
+ outtextxy( 45,55,"Number:");
+ outtextxy(120,55,"Name:");
+ outtextxy(420,55,"Score:");
+ outtextxy(500,55,"Rating:");
+ setcolor(white); last=177;
+ for( fv=1; fv <= 12; fv ++)
+ {
+ scoretype& with = table.a[fv];
+ ;
+ settextjustify(righttext,bottomtext);
+ sparkle(100,60+fv*10,strf(fv)+'.');
+ sparkle(455,60+fv*10,strf(with.score));
+ if (fv==table.light) sparkle(70,60+fv*10,string("ÍÍ")+'\20');
+
+ settextjustify(lefttext,bottomtext);
+ sparkle(120,60+fv*10,with.name);
+ now=ratingname(with.score);
+ if (now!=last)
+ sparkle(510,60+fv*10,ratings[ratingname(with.score)].rank);
+ else
+ sparkle(517,57+fv*10,",,");
+ last=now;
+ }
+}
+
+void message1(string x)
+{;
+ setfillstyle(1,8); bar(0,190,640,200);
+ settextjustify(1,1); sparkle(320,195,x);
+}
+
+void sorthst()
+{
+ byte fv; boolean ok; scoretype temp;
+;
+ do {
+ ok=true;
+ for( fv=1; fv <= 11; fv ++)
+ if (table.a[fv].score<table.a[fv+1].score)
+ {;
+ temp=table.a[fv]; table.a[fv]=table.a[fv+1]; table.a[fv+1]=temp; /* swap 'em */
+ table.light=fv; /* must be- that's the only unsorted one */
+ ok=false; /* So, we try again. */
+ }
+ } while (!ok);
+}
+
+void entername();
+static integer x,y;
+
+
+static void cursor(byte col)
+{;
+ setcolor(col);
+ outtextxy(x,y,"?");
+}
+
+void entername()
+{
+ varying_string<34> i;char r; integer counter; byte flash;
+
+;
+ y=60+table.light*10; i=""; settextjustify(2,0); counter=999; flash=0;
+ do {
+ x=128+length(i)*8;
+ do {
+ counter += 1;
+ if (counter==1000)
+ {;
+ cursor(4+flash*10);
+ flash=1-flash;
+ counter=0;
+ }
+ delay(1);
+ } while (!keypressed());
+ cursor(8);
+ sound(17177); r=readkey(); nosound;
+ if (r=='\10') {;
+ if (i[0]>'\0') {;
+ bar(x-17,y-10,x-8,y);
+ i[0] -= 1; sparkle(x-16,y,i[length(i)]);
+ }
+ } else {;
+ if ((i[0]<'\42') && (r!='\15')) {;
+ sparkle(x,y,r);
+ i=i+r;
+ }
+ }
+ counter=999;
+ } while (!(r=='\15'));
+}
+
+void newscore(word sc)
+{;
+ { scoretype& with = table.a[12];
+ if (sc>with.score)
+ {;
+ with.name=""; with.score=sc; table.light=10; sorthst(); drawtable();
+ message1("Well done! Please enter your name, then press Return...");
+ entername();
+ } else drawtable();} /* too low for score */
+ message1("Press Space to continue...");
+ do {; } while (!(keypressed() && (readkey()=='\40')));
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"");
+ title();
+ newtable();
+ newscore(/*177*/0);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/oldincln.cpp b/engines/avalanche/oldincln.cpp
new file mode 100644
index 0000000000..252d8b36c3
--- /dev/null
+++ b/engines/avalanche/oldincln.cpp
@@ -0,0 +1,249 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ INCLINE The command-line parser. */
+
+#define __incline_implementation__
+
+
+#include "oldincln.h"
+
+#include "gyro.h"
+#include "logger.h"
+
+
+const integer bug_twonames = 255;
+const integer bug_pandl = 254;
+const integer bug_weirdswitch = 253;
+const integer bug_invalidini = 252;
+const integer bug_notyesorno = 251;
+
+byte fv;
+char t;
+string bugline;
+boolean usingp,usingl;
+boolean zoomy,numlockhold;
+
+boolean filename_specified;
+
+string inihead,initail; /* For reading the .INI file. */
+
+
+void linebug(byte which)
+{;
+ output << "AVALOT : ";
+ switch (which) {
+ case bug_twonames : output << "You may only specify ONE filename." << NL; break;
+ case bug_pandl : output << "/p and /l cannot be used together." << NL; break;
+ case bug_weirdswitch : output << "Unknown switch (\"" << bugline <<
+ "\"). Type AVALOT /? for a list of switches." << NL;
+ break;
+ case bug_invalidini: output << "Invalid line in AVALOT.INI (\"" << bugline << "\")" << NL; break;
+ case bug_notyesorno: output << "Error in AVALOT.INI: \"" << inihead << "\" must be \"yes\" or \"no.\"" << NL; break;
+ }
+ exit(which);
+}
+
+void syntax()
+{;
+ assign(output,""); rewrite(output);
+ output << NL;
+ output << string("Lord Avalot d'Argent\n\n(c) ")+copyright+" Mark, Mike and Thomas Thurman." << NL;
+ output << string("~~~~~~~~~~~~~~~~~~~~~\n\n")+vernum << NL;
+ output << NL;
+ output << "Syntax:" << NL;
+ output << "\n/?\ndisplays this screen," << NL;
+ output << "\n/O\noverrides EGA check," << NL;
+ output << "\n/L<f>\nlogs progress to <f>, default AVVY.LOG," << NL;
+ output << "\n/P<x>\nlogs with Epson codes to <x>, default PRN," << NL;
+ output << "\n/Q\ncancels sound effects," << NL;
+ output << "\n/S\ndisables Soundblaster," << NL;
+ output << "\n/Z\ngoes straight into the game." << NL;
+ output << NL;
+ output << "\n\n\n\n\n\n\n... Have fun!" << NL;
+ exit(177);
+}
+
+void upstr(string& x)
+{
+ byte fv;
+;
+ for( fv=1; fv <= length(x); fv ++) x[fv]=upcase(x[fv]);
+}
+
+boolean yesno()
+{boolean yesno_result;
+;
+ if (initail=="YES") yesno_result=true; else
+ if (initail=="NO") yesno_result=false; else
+ linebug(bug_notyesorno);
+return yesno_result;
+}
+
+void ini_parse()
+{;
+ upstr(inihead);
+ upstr(initail);
+
+ if (inihead=="QUIET") soundfx=! yesno(); else
+ if (inihead=="ZOOMYSTART") zoomy=yesno(); else
+ if (inihead=="NUMLOCKHOLD") numlockhold=yesno(); else
+ if (inihead=="LOADFIRST") filetoload=initail; else
+ if (inihead=="OVERRIDEEGACHECK") cl_override=yesno(); else
+ if (inihead=="KEYBOARDCLICK") keyboardclick=yesno();
+}
+
+void strip_ini()
+{
+ byte fv;
+;
+ if (inihead=="") return;
+
+ /* Firstly, delete any comments. */
+ fv=pos(";",inihead);
+ if (fv>0) Delete(inihead,fv,255);
+
+ /* Lose the whitespace... */
+
+ while (inihead[length(inihead)]==' ') inihead[0] -= 1;
+ while ((inihead!="") && (inihead[1]==' ')) Delete(inihead,1,1);
+
+ /* It's possible that now we'll end up with a blank line. */
+
+ if ((inihead=="") || (inihead[1]=='[')) return;
+
+ fv=pos("=",inihead);
+
+ if (fv==0)
+ {; /* No "="! Weird! */
+ bugline=inihead;
+ linebug(bug_invalidini);
+ }
+
+ initail=copy(inihead,fv+1,255);
+ inihead[0]=chr(fv-1);
+}
+
+void load_ini()
+{
+ text ini;
+;
+ assign(ini,"AVALOT.INI");
+ reset(ini);
+
+ while (! eof(ini))
+ {;
+ ini >> inihead >> NL;
+ strip_ini();
+ if (inihead!="") ini_parse();
+ }
+
+ close(ini);
+}
+
+void parse(string x);
+static string arg;
+
+static string getarg(string otherwis)
+{string getarg_result;
+;
+ if (arg=="") getarg_result=otherwis; else getarg_result="";
+return getarg_result;
+}
+
+void parse(string x)
+
+{;
+ switch (x[1]) {
+ case '/':case '-': {;
+ arg=copy(x,3,255);
+ switch (upcase(x[2])) {
+ case '?': syntax(); break;
+ case 'O': cl_override=true; break;
+ case 'L': if (! usingp)
+ {;
+ log_setup(getarg("avvy.log"),false);
+ usingl=true;
+ } else {; close(logfile); linebug(bug_pandl); }
+ break;
+ case 'P': if (! usingl)
+ {;
+ log_setup(getarg("prn"),true);
+ usingp=true;
+ } else {; close(logfile); linebug(bug_pandl); }
+ break;
+ case 'Q': soundfx=false; break;
+ case 'Z': zoomy=true; break;
+ case 'K': keyboardclick=true; break;
+ case 'D': demo=true; break;
+ default: {;
+ bugline=x;
+ linebug(bug_weirdswitch);
+ }
+ }
+ }
+ break;
+ case '*': {;
+ inihead=copy(x,2,255);
+ strip_ini();
+ if (inihead!="") ini_parse();
+ }
+ break;
+ default: {; /* filename */
+ if (filename_specified)
+ linebug(bug_twonames);
+ else
+ filetoload=x;
+ filename_specified=true;
+ }
+ }
+}
+
+void not_through_bootstrap()
+{
+ output << "Avalot must be loaded through the bootstrap." << NL;
+ exit(0);
+}
+
+void get_storage_addr()
+{
+ integer e;
+
+ val(paramstr(2),storage_seg,e); if (e!=0) not_through_bootstrap();
+ val(paramstr(3),storage_ofs,e); if (e!=0) not_through_bootstrap();
+ skellern=storage_ofs+1;
+}
+
+class unit_incline_initialize {
+ public: unit_incline_initialize();
+};
+static unit_incline_initialize incline_constructor;
+
+unit_incline_initialize::unit_incline_initialize() {;
+ filetoload="";
+ usingl=false;
+ usingp=false;
+ logging=false;
+ cl_override=false;
+ soundfx=true;
+ zoomy=false;
+ numlockhold=false;
+ filename_specified=false;
+ keyboardclick=false;
+
+ load_ini();
+
+ if ((paramcount<3) ||
+ ((paramstr(1)!="Go") && (paramstr(1)!="et"))) not_through_bootstrap();
+
+ reloaded=paramstr(1)=="et";
+
+ get_storage_addr();
+
+ for( fv=4; fv <= paramcount; fv ++)
+ parse(paramstr(fv));
+}
diff --git a/engines/avalanche/oldincln.h b/engines/avalanche/oldincln.h
new file mode 100644
index 0000000000..a0db659f92
--- /dev/null
+++ b/engines/avalanche/oldincln.h
@@ -0,0 +1,10 @@
+#ifndef __oldincln_h__
+#define __oldincln_h__
+
+
+
+/* This unit has NO externally-callable procedures. Also note that
+ it MUST be called *first* (so if you load AVALOT.PAS and press f7
+ twice you get to the "begin" statement.) */
+
+#endif
diff --git a/engines/avalanche/oldtrip.cpp b/engines/avalanche/oldtrip.cpp
new file mode 100644
index 0000000000..5e0fb99c4c
--- /dev/null
+++ b/engines/avalanche/oldtrip.cpp
@@ -0,0 +1,448 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ TRIP4 Trippancy IV- "Trip Oop". */
+
+#define __trip4_implementation__
+ /* Trippancy IV (Trip Oop) */
+#include "oldtrip.h"
+
+
+/*#include "Scrolls.h"*/
+/*#include "Lucerna.h"*/
+/*#include "Gyro.h"*/
+/*#include "Dropdown.h"*/
+
+
+void copier(integer x1,integer y1,integer x2,integer y2,integer x3,integer y3,integer x4,integer y4);
+
+
+static boolean dropin(integer xc,integer yc,integer x1,integer y1,integer x2,integer y2)
+/* Dropin returns True if the point xc,yc falls within the 1-2 rectangle. */
+{boolean dropin_result;
+;
+ dropin_result=((xc>=x1) && (xc<=x2) && (yc>=y1) && (yc<=y2));
+return dropin_result;
+}
+
+
+
+static integer lesser(integer a,integer b)
+{integer lesser_result;
+;
+ if (a<b) lesser_result=a; else lesser_result=b;
+return lesser_result;
+}
+
+
+
+static integer greater(integer a,integer b)
+{integer greater_result;
+;
+ if (a>b) greater_result=a; else greater_result=b;
+return greater_result;
+}
+
+void copier(integer x1,integer y1,integer x2,integer y2,integer x3,integer y3,integer x4,integer y4)
+
+{;
+ if (dropin(x3,y3,x1,y1,x2,y2)
+ || dropin(x3,y4,x1,y1,x2,y2)
+ || dropin(x4,y3,x1,y1,x2,y2)
+ || dropin(x4,y4,x1,y1,x2,y2))
+ {; /* Overlaps */
+ mblit(lesser(x1,x3),lesser(y1,y3),greater(x2,x4),greater(y2,y4),1,0);
+ } else
+ {; /* Doesn't overlap- copy both of them seperately */
+ mblit(x3,y3,x4,y4,1,0); /* backwards- why not...? */
+ mblit(x1,y1,x2,y2,1,0);
+ }
+}
+
+void loadtrip()
+{
+ byte gm;
+;
+ for( gm=1; gm <= numtr; gm ++) tr[gm].original();
+ tr[1].init(0);
+}
+
+byte checkfeet(integer x1,integer x2,integer oy,integer y, byte yl)
+{
+ byte a,c; integer fv,ff;
+byte checkfeet_result;
+;
+ a=0; setactivepage(2); if (x1<0) x1=0; if (x2>639) x2=639;
+ if (oy<y)
+ for( fv=x1; fv <= x2; fv ++)
+ for( ff=oy+yl; ff <= y+yl; ff ++)
+ {;
+ c=getpixel(fv,ff);
+ if (c>a) a=c;
+ } else
+ for( fv=x1; fv <= x2; fv ++)
+ for( ff=y+yl; ff <= oy+yl; ff ++)
+ {;
+ c=getpixel(fv,ff);
+ if (c>a) a=c;
+ }
+ checkfeet_result=a; setactivepage(1);
+return checkfeet_result;
+}
+
+void touchcol(byte tc);
+static boolean bug;
+
+static void fr(byte a,byte b) {; fliproom(a,b); bug=false; }
+
+void touchcol(byte tc)
+{;
+ bug=true; /* j.i.c. */
+ switch (dna.room) {
+ case 1: fr(2,3); break;
+ case 2: {; /* main corridor */
+ switch (tc) {
+ case 1: fr(3,1); break; /* to the other corridor */
+ case 2: fr(2,1); break; /* to this corridor! Fix this later... */
+ }
+ }
+ break;
+ case 3: {; /* turn corridor */
+ switch (tc) {
+ case 1: fr(2,1); break; /* to the other corridor */
+ case 2: fr(12,1); break; /* through Spludwick's door */
+ }
+ }
+ break;
+ case 12: fr(3,2); break;
+ }
+ if (bug)
+ {;
+ setactivepage(0);
+ display(string('\7')+"Unknown touchcolour ("+strf(tc)+')'+" in "+strf(dna.room)
+ +'.'); setactivepage(1); tr[1].bounce();
+ }
+}
+
+triptype* triptype::init(byte spritenum)
+{
+ integer gd,gm; word s; untyped_file f; varying_string<2> xx; byte sort,n;
+ word bigsize; pointer p,q;
+;
+ str(spritenum,xx); assign(f,string("c:\\avalot\\sprite")+xx+".avd");
+ reset(f,1); seek(f,59);
+ blockread(f,a,sizeof(a)); blockread(f,bigsize,2);
+ setactivepage(3);
+ for( sort=0; sort <= 1; sort ++)
+ {;
+ mark(q); getmem(p,bigsize);
+ blockread(f,p,bigsize);
+ off; putimage(0,0,p,0); release(q); n=1;
+ { adxtype& with = a;
+ for( gm=0; gm <= (with.num / with.seq)-1; gm ++) /* directions */
+ for( gd=0; gd <= with.seq-1; gd ++) /* steps */
+ {;
+ getmem(pic[n][sort],a.size); /* grab the memory */
+ getimage((gm / 2)*(with.xl*6)+gd*with.xl,(gm % 2)*with.yl,
+ (gm / 2)*(with.xl*6)+gd*with.xl+with.xl-1,(gm % 2)*with.yl+with.yl-1,
+ pic[n][sort]); /* grab the pic */
+ n += 1;
+ }} on;
+ }
+ close(f); setactivepage(0);
+
+ x=0; y=0; quick=true; visible=false; getmem(behind,a.size);
+ homing=false; ix=0; iy=0; step=0; check_me=a.name=="Avalot";
+return this;
+}
+
+void triptype::original()
+{;
+ quick=false;
+}
+
+void triptype::getback()
+{;
+ tax=x; tay=y;
+ off; /*getimage(x,y,x+a.xl,y+a.yl,behind^);*/
+ mblit(x,y,x+a.xl,y+a.yl,1,3); on;
+}
+
+void triptype::andexor()
+{
+ byte picnum; /* Picnum, Picnic, what ye heck */
+;
+ picnum=face*a.seq+step+1; off;
+ putimage(x,y,pic[picnum][0],andput);
+ putimage(x,y,pic[picnum][1],xorput); on;
+}
+
+void triptype::turn(byte whichway)
+{;
+ face=whichway;
+}
+
+void triptype::appear(integer wx,integer wy, byte wf)
+{;
+ x=(wx / 8)*8; y=wy; ox=wx; oy=wy; turn(wf); visible=true; ix=0; iy=0;
+}
+
+void triptype::walk()
+{
+ byte tc;
+;
+ ox=x; oy=y;
+ if ((ix==0) && (iy==0)) return;
+ if (homing) homestep();
+ x=x+ix; y=y+iy;
+ if (check_me) {;
+ tc=checkfeet(x,x+a.xl,oy,y,a.yl);
+ { void& with = magics[tc];
+ switch (op) {
+ case exclaim: blip; break;
+ case bounces: bounce(); break;
+ case transport: fliproom(hi(data),lo(data)); break;
+ }}
+ }
+/* if x<0 then x:=0; else if x+a.xl>640 then x:=640-a.xl;*/
+ if (y<0) y=0; /* else if y+a.yl>161 then y:=161-a.yl; */
+ step += 1; if (step==a.seq) step=0; getback();
+}
+
+void triptype::bounce()
+{; setactivepage(1); putback(); x=ox; y=oy; stopwalk(); return; }
+
+void triptype::do_it()
+{;
+ if (((ix!=0) || (iy!=0)) & (~ ddm_o.menunow))
+ {;
+ off; copier(ox,oy,ox+a.xl,oy+a.yl,x,y,x+a.xl,y+a.yl);
+ putback(); on;
+ }
+}
+
+void triptype::putback()
+{;
+/* putimage(tax,tay,behind^,0);*/ mblit(tax,tay,tax+a.xl,tay+a.yl,3,1);
+}
+
+void triptype::walkto(integer xx,integer yy)
+{;
+ speed(xx-x,yy-y); hx=xx; hy=yy; homing=true;
+}
+
+void triptype::stophoming()
+{;
+ homing=false;
+}
+
+void triptype::homestep()
+{
+ integer temp;
+;
+ if ((hx==x) && (hy==y))
+ {; /* touching the target */
+ homing=false; return;
+ }
+ ix=0; iy=0;
+ if (hy!=y)
+ {;
+ temp=hy-y; if (temp>4) iy=4; else if (temp<-4) iy=-4; else iy=temp;
+ }
+ if (hx!=x)
+ {;
+ temp=hx-x; if (temp>4) ix=4; else if (temp<-4) ix=-4; else ix=temp;
+ }
+}
+
+void triptype::speed(shortint xx,shortint yy)
+{;
+ ix=xx; iy=yy;
+ if ((ix==0) && (iy==0)) return; /* no movement */
+ if (ix==0)
+ {; /* No horz movement */
+ if (iy<0) turn(up); else turn(down);
+ } else
+ {;
+ if (ix<0) turn(left); else turn(right);
+ }
+}
+
+void triptype::stopwalk()
+{;
+ ix=0; iy=0; homing=false;
+}
+
+void triptype::chatter()
+{;
+ talkx=x+a.xl / 2; talky=y; talkf=a.fgc; talkb=a.bgc;
+}
+
+
+getsettype* getsettype::init()
+{;
+ numleft=0; /* initialise array pointer */
+ return this;
+}
+
+void remember(fieldtype r)
+{;
+ numleft += 1;
+ gs[numleft]=r;
+}
+
+void recall()
+{void recall_result;
+;
+ recall_result=gs[numleft];
+ numleft -= 1;
+return recall_result;
+}
+
+void rwsp(byte t,byte r)
+{
+ const integer xs = 4; const integer ys = 2;
+;
+ { triptype& with = tr[t]; switch (r) {
+ case up: speed( 0,-ys); break; case down: speed( 0, ys); break; case left: speed(-xs, 0); break;
+ case right: speed( xs, 0); break; case ul: speed(-xs,-ys); break; case ur: speed( xs,-ys); break;
+ case dl: speed(-xs, ys); break; case dr: speed( xs, ys); break;
+ }}
+}
+
+void apped(byte trn,byte np)
+{;
+ {
+ triptype& with = tr[trn];
+ ; { void& with1 = peds[np]; appear(with.x-with.a.xl / 2,with.y-with.a.yl,dir);}
+ rwsp(trn,tr[trn].face); }
+}
+
+void trippancy();
+
+static boolean allstill()
+{
+ boolean xxx; byte fv;
+boolean allstill_result;
+;
+ xxx=true;
+ for( fv=1; fv <= numtr; fv ++)
+ { triptype& with = tr[fv];
+ if (with.quick && ((with.ix!=0) || (with.iy!=0))) xxx=false;}
+ allstill_result=xxx;
+return allstill_result;
+}
+
+void trippancy()
+{
+ byte fv;
+;
+ if ((ddm_o.menunow) | ontoolbar | seescroll | allstill()) return;
+ setactivepage(1);
+ for( fv=1; fv <= numtr; fv ++)
+ { triptype& with = tr[fv];
+ if (with.quick)
+ {;
+ walk();
+ if (with.visible && ((with.ix!=0) || (with.iy!=0))) andexor();
+ do_it();
+ }}
+ setactivepage(0);
+}
+
+void tripkey(char dir);
+
+static void stopwalking()
+{;
+ tr[1].stopwalk(); dna.rw=stopped;
+}
+
+void tripkey(char dir)
+{;
+ { triptype& with = tr[1];
+ {;
+ switch (dir) {
+ case 'H': if (rw!=up)
+ {; rw=up; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'P': if (rw!=down)
+ {; rw=down; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'K': if (rw!=left)
+ {; rw=left; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'M': if (rw!=right)
+ {; rw=right; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'I': if (rw!=ur)
+ {; rw=ur; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'Q': if (rw!=dr)
+ {; rw=dr; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'O': if (rw!=dl)
+ {; rw=dl; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'G': if (rw!=ul)
+ {; rw=ul; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'L': stopwalking(); break;
+ }
+ }}
+}
+
+void fliproom(byte room,byte ped)
+{;
+ dusk; tr[1].putback(); dna.room=room; load(room); apped(1,ped);
+ oldrw=dna.rw; dna.rw=tr[1].face; showrw; dawn;
+}
+
+boolean infield(byte x) /* returns True if you're within field "x" */
+{
+ integer ux,uy;
+boolean infield_result;
+;
+ {
+ triptype& with = tr[1];
+ ;
+ ux=with.x;
+ uy=with.y+with.a.yl;
+ }
+ {
+ void& with = fields[x];
+ ;
+ infield_result=(ux>=x1) && (ux<=x2) && (uy>=y1) && (uy<=y2);
+ }
+return infield_result;
+}
+
+boolean neardoor() /* returns True if you're near a door! */
+{
+ integer ux,uy; byte fv; boolean nd;
+boolean neardoor_result;
+;
+ if (numfields<9)
+ {; /* there ARE no doors here! */
+ neardoor_result=false;
+ return neardoor_result;
+ }
+ {
+ triptype& with = tr[1];
+ ;
+ ux=with.x;
+ uy=with.y+with.a.yl;
+ } nd=false;
+ for( fv=9; fv <= numfields; fv ++)
+ {
+ void& with = fields[fv];
+ ;
+ if ((ux>=x1) && (ux<=x2) && (uy>=y1) && (uy<=y2)) nd=true;
+ }
+ neardoor_result=nd;
+return neardoor_result;
+}
+
diff --git a/engines/avalanche/oldtrip.h b/engines/avalanche/oldtrip.h
new file mode 100644
index 0000000000..dc36efd2d6
--- /dev/null
+++ b/engines/avalanche/oldtrip.h
@@ -0,0 +1,95 @@
+#ifndef __oldtrip_h__
+#define __oldtrip_h__
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+
+const integer maxgetset = 10;
+
+struct adxtype {
+ varying_string<12> name; /* name of character */
+ byte num; /* number of pictures */
+ byte xl,yl; /* x & y lengths of pictures */
+ byte seq; /* how many in one stride */
+ word size; /* the size of one picture */
+ byte fgc,bgc; /* foreground & background bubble colours */
+};
+
+class triptype {
+public:
+ adxtype a; /* vital statistics */
+ byte face,step;
+ integer x,y; /* current xy coords */
+ integer ox,oy; /* last xy coords */
+ integer tax,tay; /* "behind" taken at... */
+ shortint ix,iy; /* amount to move sprite by, each step */
+ matrix<1,24,0,1,pointer> pic; /* the pictures themselves */
+ boolean quick,visible,homing,check_me;
+ pointer behind; /* what's behind you */
+ integer hx,hy; /* homing x & y coords */
+
+ triptype* init(byte spritenum); /* loads & sets up the sprite */
+ void original(); /* just sets Quick to false */
+ void andexor(); /* drops sprite onto screen 1 */
+ void turn(byte whichway); /* turns him round */
+ void appear(integer wx,integer wy, byte wf); /* switches him on */
+ void bounce(); /* bounces off walls. */
+ void walk(); /* prepares for do_it, andexor, etc. */
+ void do_it(); /* Actually copies the picture over */
+ void getback(); /* gets background before sprite is drawn */
+ void putback(); /* ...and wipes sprite from screen 1 */
+ void walkto(integer xx,integer yy); /* home in on a point */
+ void stophoming(); /* self-explanatory */
+ void homestep(); /* calculates ix & iy for one homing step */
+ void speed(shortint xx,shortint yy); /* sets ix & iy, non-homing, etc */
+ void stopwalk(); /* Stops the sprite from moving */
+ void chatter(); /* Sets up talk vars */
+};
+
+class getsettype {
+public:
+ array<1,maxgetset,fieldtype> gs;
+ byte numleft;
+
+ getsettype* init();
+ void remember(fieldtype r);
+ void recall();
+};
+
+const integer up = 0;
+const integer right = 1;
+const integer down = 2;
+const integer left = 3;
+const integer ur = 4; const integer dr = 5; const integer dl = 6; const integer ul = 7;
+const integer stopped = 8;
+
+const integer numtr = 5; /* current max no. of sprites */
+
+void trippancy();
+
+void loadtrip();
+
+void tripkey(char dir);
+
+void apped(byte trn,byte np);
+
+void fliproom(byte room,byte ped);
+
+boolean infield(byte x); /* returns True if you're within field "x" */
+
+boolean neardoor(); /* returns True if you're near a door! */
+
+
+#ifdef __trip4_implementation__
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN array<1,numtr,triptype> tr;
+#undef EXTERN
+#define EXTERN extern
+
+
+#endif
diff --git a/engines/avalanche/omtest.cpp b/engines/avalanche/omtest.cpp
new file mode 100644
index 0000000000..52b1a0373e
--- /dev/null
+++ b/engines/avalanche/omtest.cpp
@@ -0,0 +1,177 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Oopmenu.h"*/
+/*#include "Rodent.h"*/
+/*#include "Crt.h"*/
+/*#include "Enhanced.h"*/
+
+varying_string<5> st;
+byte fv;
+
+void graphics()
+ {
+ integer gd,gm; ; gd=3; gm=0; initgraph(gd,gm,""); }
+
+/*$F+ ... All ddm__procs and do__procs must be compiled in Far-Call state. */
+
+void ddm__file()
+{;
+ {;
+ start_afresh;
+ opt("Load...",'L',"f3",true);
+ opt("Save...",'S',"f2",false);
+ opt("Save As...",'A',"ctrl-f2",false);
+ opt("OS Shell...",'O',"f2",true);
+ opt("Untrash screen",'U',"f11",true);
+ display;
+ }
+}
+
+void ddm__heart()
+{;
+ {;
+ start_afresh;
+ opt("About...",'A',"shift-f10",true);
+ opt("Boss Key",'B',"alt-B",true);
+ opt("Help...",'H',"f1",true);
+ opt("Status screen",'S',"f12",true);
+ opt("Quit",'Q',"f10",true);
+ display;
+ }
+}
+
+void ddm__action()
+{;
+ {;
+ start_afresh;
+ opt("Get up",'G',"",true);
+ opt("Open door",'O',"",true);
+ opt("Pause game",'P',"",true);
+ opt("Look around",'L',"",true);
+ opt("Inventory",'I',"Tab",true);
+ opt("Do the boogie",'b',"",true);
+ display;
+ }
+}
+
+void ddm__objects()
+{;
+ {;
+ start_afresh;
+ opt("Bell",'B',"",true);
+ opt("Wine",'W',"",true);
+ opt("Chastity Belt",'C',"",true);
+ opt("Crossbow Bolt",'t',"",true);
+ opt("Crossbow",'r',"",true);
+ opt("Potion",'P',"",true);
+ display;
+ }
+}
+
+void ddm__people()
+{;
+ {;
+ start_afresh;
+ opt("Avalot",'A',"",true);
+ opt("Spludwick",'S',"",true);
+ opt("Arkata",'k',"",true);
+ opt("Dogfood",'D',"",true);
+ opt("Geida",'G',"",true);
+ display;
+ }
+}
+
+void ddm__use()
+{;
+ {;
+ start_afresh;
+ opt("Drink",'D',"",true);
+ opt("Wear",'W',"",true);
+ opt("Give to [du Lustie]",'G',"",true);
+ display;
+ }
+}
+
+void do__stuff()
+{
+ varying_string<2> st;
+;
+ str(o.choicenum+1,st);
+ setfillstyle(1,6); setcolor(14);
+ bar(0,177,640,200);
+ outtextxy(320,177,string("You just chose: ")+st);
+}
+
+void do__heart()
+{;
+ switch (o.choicenum) {
+ case 0: outtextxy(100,100,"A really funny game!"); break;
+ case 1: outtextxy(100,120,"You ought to be working!"); break;
+ case 2: outtextxy(100,140,"No help available, so THERE!"); break;
+ case 3: outtextxy(100,160,"Everything's COOL and FROODY!"); break;
+ case 4: exit(0); break;
+ }
+}
+
+/*$F- ... End of ddm__procs */
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ graphics();
+ setfillstyle(6,6); bar(0,0,639,199);
+ resetmouse;
+ m.init; o.init;
+ {;
+ create('H','\3','#',ddm__heart(),do__heart());
+ create('F',"File",'!',ddm__file(),do__stuff());
+ create('A',"Action",'\36',ddm__action(),do__stuff());
+ create('O',"Objects",'\30',ddm__objects(),do__stuff());
+ create('P',"People",'\31',ddm__people(),do__stuff());
+ create('W',"With",'\21',ddm__use(),do__stuff());
+ update;
+ }
+ do {
+ showmousecursor;
+ do {
+ getbuttonpressinfo(1);
+ getbuttonreleaseinfo(1);
+ getbuttonstatus;
+ if (menunow) o.lightup;
+ } while (!((buttonpresscount>0) || (buttonreleasecount>0) | keypressede));
+ hidemousecursor;
+ if (buttonpresscount>0)
+ {;
+ if (mousey>10)
+ {;
+ if (! ((o.firstlix) &
+ ((mousex>=flx1) && (mousex<=flx2) &&
+ (mousey>=12) && (mousey<=fly))))
+ {; /* Clicked OUTSIDE the menu. */
+ if (o.menunow) wipe;
+ setcolor(2); for( fv=1; fv <= 17; fv ++) circle(mousex,mousey,fv*3);
+ setcolor(0); for( fv=1; fv <= 17; fv ++) circle(mousex,mousey,fv*3);
+ }
+ } else
+ {; /* Clicked on menu bar */
+ m.getmenu(mousex);
+ }
+ } else
+ {; /* NOT clicked button... */
+ if (buttonreleasecount>0)
+ {;
+ if ((firstlix) &
+ ((mousex>=flx1) && (mousex<=flx2) &&
+ (mousey>=12) && (mousey<=fly)))
+ select((mousey-14) / 10);
+ } else
+ {; /* NOT clicked or released button, so must be keypress */
+ readkeye;
+ parsekey(inchar,extd);
+ }
+ }
+ } while (!false);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/oopmenu.cpp b/engines/avalanche/oopmenu.cpp
new file mode 100644
index 0000000000..5c1b13f08b
--- /dev/null
+++ b/engines/avalanche/oopmenu.cpp
@@ -0,0 +1,295 @@
+#include "ptoc.h"
+
+#define __oopmenu_implementation__
+
+
+#include "oopmenu.h"
+
+
+/*#include "Crt.h"*/
+#include "graph.h"
+/*#include "Rodent.h"*/
+/*#include "Dos.h"*/
+
+
+const integer indent = 40;
+const integer spacing = 83;
+
+const integer menu_b = blue;
+const integer menu_f = yellow;
+const integer menu_border = black;
+const integer highlight_b = lightblue;
+const integer highlight_f = yellow;
+const integer disabled = lightgray;
+
+/* menu_b = lightgray;
+ menu_f = black;
+ menu_border = black;
+ highlight_b = black;
+ highlight_f = white;
+ disabled = darkgray;*/
+
+/* Built-in mouse routine */
+
+char r;
+byte fv;
+
+void chalk(integer x,integer y, char t, string z)
+{
+ byte p;
+;
+ outtextxy(x,y,z);
+ p=pos(t,z); if (p==0) return; p -= 1;
+ outtextxy(x+p*8,y+1,"_");
+}
+
+void say(integer x,integer y, char t, string z, byte f,byte b)
+{;
+ settextjustify(0,2); setfillstyle(1,b); setcolor(f);
+ bar(x-3,y-1,x+textwidth(z)+3,y+textheight(z)+1);
+ chalk(x,y,t,z);
+}
+
+void mblit(integer x1,integer y1,integer x2,integer y2, byte f,byte t) /* NOT The Minstrel Blitter */
+{
+ pointer p,q; word s;
+;
+ mark(q);
+ s=imagesize(x1,y1,x2,y2); getmem(p,s);
+ setactivepage(f); getimage(x1,y1,x2,y2,p);
+ setactivepage(t); putimage(x1,y1,p,0);
+ setactivepage(0); release(q);
+}
+
+void onemenu::start_afresh()
+{;
+ number=0; width=0; firstlix=false; oldy=0; highlightnum=0;
+}
+
+onemenu* onemenu::init()
+{;
+ menunow=false;
+ return this;
+}
+
+void onemenu::opt(string n, char tr, string key, boolean val)
+{
+ integer l;
+;
+ number += 1;
+ l=textwidth(n+key)+30; if (width<l) width=l;
+ {
+ optiontype& with = oo[number];
+ ;
+ with.title=n;
+ with.trigger=tr;
+ with.shortcut=key;
+ with.valid=val;
+ }
+}
+
+void onemenu::displayopt(byte y,byte b,byte f,byte d)
+{;
+ {
+ optiontype& with = oo[y];
+ ;
+ if (with.valid) setcolor(f); else setcolor(d);
+ if (b!=177)
+ {;
+ setfillstyle(1,b);
+ bar(flx1,3+y*10,flx2,12+y*10);
+ }
+ settextjustify(2,2);
+ if (with.shortcut>"") outtextxy(flx2,4+y*10,with.shortcut);
+ settextjustify(0,2);
+ chalk(left+3,4+y*10,with.trigger,with.title);
+ }
+}
+
+void onemenu::display()
+{
+ byte y;
+;
+ setfillstyle(1,menu_b); setcolor(menu_border);
+ firstlix=true;
+ flx1=left-2; flx2=left+width; fly=14+number*10;
+ mblit(flx1-3,11,flx2+1,fly+1,0,1);
+ menunow=true;
+
+ bar(flx1,12,flx2,fly);
+ rectangle(flx1-1,11,flx2+1,fly+1);
+
+ setcolor(menu_f); settextjustify(0,2);
+ displayopt(1,highlight_b,highlight_f,177);
+ for( y=2; y <= number; y ++)
+ { optiontype& with = oo[y]; displayopt(y,177,menu_f,disabled);}
+}
+
+void onemenu::wipe()
+{;
+ { headtype& with = m.ddms[o.menunum]; say(flx1+2,1,with.trigger,with.title,menu_f,menu_b);}
+ mblit(flx1-3,11,flx2+1,fly+1,1,0);
+ menunow=false; firstlix=false;
+}
+
+void onemenu::movehighlight(shortint add)
+{
+ shortint hn;
+;
+ if (add!=0)
+ {;
+ hn=highlightnum+add;
+ if ((hn<0) || (hn>=(unsigned char)number)) return;
+ highlightnum=hn;
+ }
+ hidemousecursor;
+ displayopt(oldy+1,menu_b,menu_f,disabled);
+ displayopt(highlightnum+1,highlight_b,highlight_f,disabled);
+ showmousecursor;
+ oldy=highlightnum;
+}
+
+void onemenu::lightup() /* This makes the menu highlight follow the mouse.*/
+{;
+ if ((mousex<flx1) || (mousex>flx2)
+ || (mousey<=12) || (mousey>fly-3)) return;
+ highlightnum=(mousey-12) / 10;
+ if (highlightnum==oldy) return;
+ movehighlight(0);
+}
+
+void onemenu::select(byte n) /* Choose which one you want. */
+{;
+ if (! oo[n+1].valid) return;
+ choicenum=n;
+ m.ddms[menunum].do_choose();
+ wipe();
+}
+
+void onemenu::keystroke(char c)
+{
+ byte fv;
+;
+ c=upcase(c);
+ for( fv=1; fv <= number; fv ++)
+ if (upcase(oo[fv].trigger)==c) select(fv-1);
+}
+
+void bleep()
+{;
+ sound(177); delay(7); nosound;
+}
+
+ headtype* headtype::init
+ (char trig,char alttrig, string name, byte p, proc dw,proc dc)
+ {;
+ trigger=trig; alttrigger=alttrig; title=name;
+ position=p; xpos=(position-1)*spacing+indent;
+ xright=xpos+textwidth(name)+3;
+ do_setup=dw; do_choose=dc;
+ return this;
+ }
+
+ void headtype::display()
+ {;
+ say(xpos,1,trigger,title,menu_f,menu_b);
+ }
+
+ void headtype::highlight()
+ {;
+ say(xpos,1,trigger,title,highlight_f,highlight_b);
+ {;
+ o.left=xpos;
+ o.menunow=true; o.menunum=position;
+ }
+ }
+
+ boolean headtype::extdparse(char c)
+ {boolean extdparse_result;
+ ;
+ if (c!=alttrigger) {; extdparse_result=true; return extdparse_result; }
+ extdparse_result=false;
+ return extdparse_result;
+ }
+
+ menuset* menuset::init()
+ {;
+ howmany=0;
+ return this;
+ }
+
+ void menuset::create(char t, string n, char alttrig, proc dw,proc dc)
+ {;
+ howmany += 1;
+ ddms[howmany].init(t,alttrig,n,howmany,dw,dc);
+ }
+
+ void menuset::update()
+ {
+ byte fv;
+ ;
+ setfillstyle(1,menu_b); bar(0,0,640,10);
+ for( fv=1; fv <= howmany; fv ++) ddms[fv].display();
+ }
+
+ void menuset::extd(char c)
+ {
+ byte fv;
+ ;
+ fv=1;
+ while ((fv<=howmany) && (ddms[fv].extdparse(c))) fv += 1;
+ if (fv>howmany) return; getmenu(fv*spacing-indent);
+ }
+
+ void menuset::getmenu(integer x)
+ {
+ byte fv;
+ ;
+ fv=0;
+ do {
+ fv += 1;
+ if ((x>ddms[fv].xpos-3) && (x<ddms[fv].xright))
+ { headtype& with = ddms[fv];
+ {;
+ if (o.menunow)
+ {;
+ wipe(); /* get rid of menu */
+ if (o.menunum==with.position) return; /* click on own highlight */
+ }
+ highlight(); do_setup();
+ return;
+ }}
+ } while (!(fv>howmany));
+ }
+
+void parsekey(char r,char re)
+{;
+ switch (r) {
+ case '\0': {;
+ switch (re) {
+ case 'K': {;
+ wipe();
+ m.getmenu((o.menunum-2)*spacing+indent);
+ }
+ break;
+ case 'M': {;
+ wipe();
+ m.getmenu((o.menunum*spacing+indent));
+ }
+ break;
+ case 'H': movehighlight(-1); break;
+ case 'P': movehighlight(1); break;
+ default: m.extd(re);
+ }
+ }
+ break;
+ case '\33': if (o.menunow) wipe(); break;
+ case '\15': select(o.highlightnum); break;
+ default:
+ {;
+ if (o.menunow) keystroke(r); else
+ kbuffer=kbuffer+r+re;
+ }
+ }
+}
+
diff --git a/engines/avalanche/oopmenu.h b/engines/avalanche/oopmenu.h
new file mode 100644
index 0000000000..ee928e2050
--- /dev/null
+++ b/engines/avalanche/oopmenu.h
@@ -0,0 +1,82 @@
+#ifndef __oopmenu_h__
+#define __oopmenu_h__
+
+
+typedef void(*proc)();
+
+class headtype {
+public:
+ varying_string<8> title;
+ char trigger,alttrigger;
+ byte position;
+ integer xpos,xright;
+ proc do_setup,do_choose;
+
+ headtype* init
+ (char trig,char alttrig, string name, byte p, proc dw,proc dc);
+ void display();
+ void highlight();
+ boolean extdparse(char c);
+};
+
+struct optiontype {
+ string title;
+ char trigger;
+ varying_string<9> shortcut;
+ boolean valid;
+};
+
+class onemenu {
+public:
+ array<1,12,optiontype> oo;
+ byte number;
+ integer width,left;
+ boolean firstlix;
+ integer flx1,flx2,fly;
+ byte oldy; /* used by Lightup */
+ boolean menunow; /* Is there a menu now? */
+ byte menunum; /* And if so, which is it? */
+ byte choicenum; /* Your choice? */
+ byte highlightnum;
+
+ void start_afresh();
+ void opt(string n, char tr, string key, boolean val);
+ void display();
+ void wipe();
+ void lightup();
+ void displayopt(byte y,byte b,byte f,byte d);
+ void movehighlight(shortint add);
+ void select(byte n);
+ void keystroke(char c);
+ onemenu* init();
+};
+
+class menuset {
+public:
+ array<1,8,headtype> ddms;
+ byte howmany;
+
+ menuset* init();
+ void create(char t, string n, char alttrig, proc dw,proc dc);
+ void update();
+ void extd(char c);
+ void getmenu(integer x);
+};
+
+
+
+#ifdef __oopmenu_implementation__
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN onemenu o;
+EXTERN menuset m;
+EXTERN string kbuffer;
+#undef EXTERN
+#define EXTERN extern
+
+
+ void parsekey(char r,char re);
+
+#endif
diff --git a/engines/avalanche/overlap.cpp b/engines/avalanche/overlap.cpp
new file mode 100644
index 0000000000..973bafb79f
--- /dev/null
+++ b/engines/avalanche/overlap.cpp
@@ -0,0 +1,53 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+integer gd,gm;
+
+void flash(integer x1,integer y1,integer x2,integer y2)
+{;
+ setcolor(14); rectangle(x1,y1,x2,y2);
+ sound(x1+x2); delay(100); nosound; delay(500);
+ setcolor( 9); rectangle(x1,y1,x2,y2); delay(500);
+}
+
+boolean dropin(integer xc,integer yc,integer x1,integer y1,integer x2,integer y2)
+/* Dropin returns True if the point xc,yc falls within the 1-2 rectangle. */
+{boolean dropin_result;
+;
+ dropin_result=((xc>=x1) && (xc<=x2) && (yc>=y1) && (yc<=y2));
+return dropin_result;
+}
+
+void test(integer x1,integer y1,integer x2,integer y2,integer x3,integer y3,integer x4,integer y4)
+{;
+ cleardevice();
+ rectangle(x1,y1,x2,y2);
+ rectangle(x3,y3,x4,y4);
+ flash(x1,y1,x2,y2);
+ flash(x3,y3,x4,y4);
+
+ if (dropin(x3,y3,x1,y1,x2,y2)
+ || dropin(x3,y4,x1,y1,x2,y2)
+ || dropin(x4,y3,x1,y1,x2,y2)
+ || dropin(x4,y4,x1,y1,x2,y2))
+ {; /* Overlaps */
+ flash(x1,y1,x4,y4);
+ } else
+ {; /* Doesn't overlap- flash 'em both again */
+ flash(x3,y3,x4,y4); /* backwards- why not...? */
+ flash(x1,y1,x2,y2);
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=1; initgraph(gd,gm,""); setcolor(9);
+ test(100,50,200,100,400,200,600,250);
+ test(100,50,200,100,120, 70,220,120);
+ test(100,50,200,100,150, 50,250,100);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/overscro.cpp b/engines/avalanche/overscro.cpp
new file mode 100644
index 0000000000..6e0b9fca7a
--- /dev/null
+++ b/engines/avalanche/overscro.cpp
@@ -0,0 +1,53 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+integer gd,gm;
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"");
+ setactivepage(1); setcolor(9);
+ settextstyle(0,0,2);
+ outtextxy(0, 0,"This is a test to see whether you can");
+ outtextxy(0, 20,"scroll text over the top of a picture.");
+ outtextxy(0, 40,"I was wondering whether it would work.");
+ outtextxy(0, 60,"Well, does it, or not?");
+ outtextxy(0, 80,"If so, it could be useful for the");
+ outtextxy(0,100,"Avalot title sequence.");
+ outtextxy(0,120,"Good, isn't it?");
+ outtextxy(0,140,"The quick brown fox jumps over the");
+ outtextxy(0,160,"lazy dog...");
+ outtextxy(0,180,"This is the last line...");
+ setactivepage(0);
+ gm=0;
+ for( gd=0; gd <= 640; gd ++)
+ {;
+ gm += 1; if (gm==8) gm=1; setcolor(gm);
+ line(gd,0,gm,350);
+ line(640-gd,0,640-gm,350);
+ }
+/* for gd:=1 to 15 do
+ begin;
+ setfillstyle(1,gd); bar(gd*20,10,gd*20+19,100);
+ end;*/
+/* setfillstyle(1,6); bar(100,100,500,100);*/ gd=getpixel(0,0);
+ for( gm=8; gm <= 15; gm ++) setpalette(gm,egayellow);
+ for( gd=0; gd <= 199; gd ++)
+ {;
+ port[0x3c4]=2; port[0x3cf]=4; port[0x3c5]=8; port[0x3cf]=0;
+ move(mem[0xa000*80],mem[0xa000*0],16000);
+ port[0x3c4]=2; port[0x3cf]=4; port[0x3c5]=8; port[0x3cf]=0;
+ move(mem[0xa000*gd*80+16384],mem[0xa000*15920],80);
+ }
+/* for gd:=0 to 199 do
+ begin;
+ port[$3C4]:=2; port[$3CF]:=4; port[$3C5]:=8; port[$3CF]:=0;
+ move(mem[$A000*160],mem[$A000*0],15920);
+ port[$3C4]:=2; port[$3CF]:=4; port[$3C5]:=8; port[$3CF]:=0;
+ move(mem[$A000*gd*80+16384],mem[$A000*15920],80);
+ move(mem[$A000*15920],mem[$A000*15840],80);
+ end;*/
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/particle.cpp b/engines/avalanche/particle.cpp
new file mode 100644
index 0000000000..e4c5b3ed91
--- /dev/null
+++ b/engines/avalanche/particle.cpp
@@ -0,0 +1,233 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+/*$R+*/
+
+typedef matrix<'\0','\377',0,15,byte> fonttype;
+
+struct markertype {
+ word length;
+ longint offset;
+ byte checksum;
+};
+
+string rawname;
+array<0,1999,char> buffer,was;
+word bufpos,bufsize;
+fonttype font;
+integer cpos;
+char r;
+boolean ok;
+
+const char marker = '\33';
+
+void cursor()
+{
+ byte fv;
+;
+ for( fv=12; fv <= 15; fv ++)
+ mem[0xa000*cpos+fv*80]=~(mem[0xa000*cpos+fv*80]);
+}
+
+void xy()
+{;
+ cpos=(bufpos / 80)*1280+(bufpos % 80);
+}
+
+void show()
+{
+ word fv,orig,y;
+;
+ for( fv=0; fv <= 1999; fv ++)
+ if (buffer[fv]!=was[fv])
+ {;
+ orig=(fv / 80)*1280+(fv % 80);
+ for( y=0; y <= 15; y ++)
+ mem[0xa000*orig+y*80]=(byte)(font[buffer[fv]][y]);
+ }
+ xy();
+ move(buffer,was,sizeof(buffer));
+}
+
+void sizeup()
+{;
+ do {
+ switch (buffer[bufsize]) {
+ case marker: return; break; /* we've found it OK! */
+ case '\0': bufsize -= 1; break;
+ default: bufsize += 1;
+ }
+ } while (!false);
+}
+
+void graphics()
+{
+ integer gd,gm;
+ file<fonttype> fontfile;
+;
+ gd=3; gm=1; initgraph(gd,gm,"c:\\bp\\bgi");
+ assign(fontfile,"c:\\thomas\\lanche.fnt");
+ reset(fontfile); fontfile >> font; close(fontfile);
+}
+
+void helpscreen();
+
+static byte l,fv;
+
+static void addon(char b, string st)
+{;
+ buffer[3+80*l]=b; b -= 64;
+ buffer[5+80*l]=b;
+ move(st[1],buffer[7+80*l],length(st));
+ l += 1;
+}
+
+void helpscreen()
+{
+ array<0,1999,char> temp;
+ char r;
+;
+ l=0; move(buffer,temp,2000); fillchar(buffer,sizeof(buffer),'\0');
+ addon('B',"Bubble");
+ addon('C',"Centre text");
+ addon('D',"Don't add \20 (at end)");
+ addon('F',"Italic Font");
+ addon('G',"Bell");
+ addon('H',"Not allocated (=backspace)");
+ addon('I',"Not allocated (=tab)");
+ addon('L',"Left-justify text");
+ addon('K',"Keyboard input");
+ addon('M',"Carriage return (same as \r key)");
+ addon('P',"Scroll (Paragraph break)");
+ addon('Q',"Yes/no scroll (question)");
+ addon('R',"Roman font");
+ addon('S',"Fix to sprite");
+ addon('U',"Money (in œsd format)");
+ addon('V',"View icon (number from ^S)");
+ show(); do { r=readkey(); } while (!(! keypressed()));
+ cleardevice();
+ fillchar(was,sizeof(was),'\0'); move(temp,buffer,2000); show();
+}
+
+void edit_it();
+
+static void legit(char r)
+{; /* it's a legit keystroke */
+ move(buffer[bufpos],buffer[bufpos+1],1999-bufpos);
+ buffer[bufpos]=r;
+ bufpos += 1; show();
+}
+
+void edit_it()
+{
+ byte fv;
+;
+ bufpos=0;
+ fillchar(was,sizeof(was),'\0'); show();
+ do {
+ cursor(); r=readkey(); cursor();
+ switch (r) {
+ case '\0': switch (readkey()) { /* extd keystrokes */
+ case 'K': if (bufpos>0) {; bufpos -= 1; xy(); } break; /* Left */
+ case 'M': if (bufpos<bufsize) {; bufpos += 1; xy(); } break; /* Right */
+ case 'H': if (bufpos>80) {; bufpos -= 80; xy(); } break; /* Up */
+ case 'P': if (bufpos<(cardinal)bufsize-79) {; bufpos += 80; xy(); } break; /* Down */
+ case 's': if (bufpos>10) {; bufpos -= 10; xy(); } break;
+ case 't': if (bufpos<(cardinal)bufsize-10) {; bufpos += 10; xy(); } break;
+ case 'G': {; bufpos=0; xy(); } break; /* Home */
+ case 'O': {; bufpos=bufsize; xy(); } break; /* End */
+ case 'S': if (bufpos<bufsize) {; /* Del */
+ move(buffer[bufpos+1],buffer[bufpos],1999-bufpos); show();
+ }
+ break;
+ case ';': helpscreen(); break;
+ case 'A': legit('\357'); break; /* copyright symbol */
+ case 'B': legit('\221'); break; /* uppercase AE */
+ case 'C': legit('\222'); break; /* lowercase AE */
+ }
+ break;
+ case '\10': if (bufpos>0) {; /* backspace */
+ bufpos -= 1;
+ move(buffer[bufpos+1],buffer[bufpos],1999-bufpos);
+ show();
+ }
+ break;
+ case '\33': {;
+ restorecrtmode();
+ return;
+ }
+ break; /* end of editing */
+ default: legit(r);
+ }
+ sizeup();
+ } while (!false);
+}
+
+void loadit()
+{
+ untyped_file f;
+;
+ if (pos(".",rawname)==0) rawname=rawname+".raw";
+ fillchar(buffer,sizeof(buffer),'\0');
+ /*$I-*/
+ assign(f,rawname);
+ reset(f,1);
+ if (ioresult!=0)
+ {;
+ output << string('\7')+"New file!"+'\7' << NL;
+ buffer[0]=marker;
+ return;
+ }
+ bufsize=filesize(f);
+ blockread(f,buffer,bufsize);
+ close(f);
+ while (buffer[bufsize]=='\0') bufsize -= 1;
+ if (buffer[bufsize]!=marker)
+ {; /* add on a marker */
+ bufsize += 1;
+ buffer[bufsize]=marker;
+ }
+}
+
+void saveit()
+{
+ untyped_file f;
+;
+ output << "Saving " << rawname << ", " << bufsize << " bytes..." << NL;
+ assign(f,rawname); rewrite(f,1);
+ blockwrite(f,buffer,bufsize);
+ close(f);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ output << "Filename of .RAW file?"; input >> rawname >> NL;
+ loadit();
+ ok=false;
+ do {
+ graphics();
+ edit_it();
+ output << "Now what?" << NL;
+ output << NL;
+ output << " Filename: " << rawname << NL;
+ output << " Size of text: " << bufsize << NL;
+ output << " Cursor position: " << bufpos << NL;
+ output << NL;
+ output << " C) Cancel this & continue edit" << NL;
+ output << " S) Save under current name" << NL;
+ output << " A) Save under a different name" << NL;
+ output << " X) Exit & lose all changes." << NL;
+ output << NL;
+ output << "Pick one!" << NL;
+ do { r=upcase(readkey()); } while (!(set::of('C','S','A','X', eos).has(r)));
+ switch (r) {
+ case 'X': ok=true; break;
+ case 'S': {; saveit(); exit(0); } break;
+ }
+ } while (!ok);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/pictemp.cpp b/engines/avalanche/pictemp.cpp
new file mode 100644
index 0000000000..144d956853
--- /dev/null
+++ b/engines/avalanche/pictemp.cpp
@@ -0,0 +1,65 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+
+const integer picsize = 966;
+
+integer gd,gm;
+untyped_file f;
+pointer p;
+
+void save()
+{
+ varying_string<40> adf; untyped_file f; byte z; array<1,2,pointer> c;
+string nam,screenname;
+ const string header =
+ string("This is a file from an Avvy game, and its contents are subject to ")+
+ "copyright."+'\15'+'\12'+'\15'+'\12'+"Have fun!"+'\32';
+ byte a /*absolute $A000:1200i*/;
+ byte bit;
+;
+ nam="d:thingtmp.avd";
+ screenname="Temp.";
+ assign(f,nam);
+
+ assign(f,nam); rewrite(f,1); blockwrite(f,header[1],146);
+ blockwrite(f,screenname,31);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockwrite(f,a,12080);
+ }
+ close(f);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+
+ assign(f,"thinks.avd");
+ getmem(p,picsize);
+ reset(f,1);
+ seek(f,65);
+ gd=10; gm=20;
+
+ while (gm<120)
+ {;
+ if (! eof(f))
+ blockread(f,p,picsize);
+ putimage(gd,gm,p,0);
+ gd += 70;
+
+ if (gd==640)
+ {;
+ gd=10; gm += 40;
+ }
+
+ }
+
+ close(f); freemem(p,picsize);
+ save();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/pictemp2.cpp b/engines/avalanche/pictemp2.cpp
new file mode 100644
index 0000000000..54e9e0dafa
--- /dev/null
+++ b/engines/avalanche/pictemp2.cpp
@@ -0,0 +1,64 @@
+#include "ptoc.h"
+
+ /* Get 'em back! */
+#include "graph.h"
+
+
+const integer picsize = 966;
+const integer number_of_objects = 17;
+
+const array<1,65,char> thinks_header =
+ string("This is an Avalot file, which is subject to copyright. Have fun.")+'\32';
+
+integer gd,gm;
+untyped_file f;
+pointer p;
+byte noo;
+
+void load()
+{
+ byte a0 /*absolute $A000:1200*/;
+ byte bit;
+ untyped_file f;
+;
+ assign(f,"d:thingtmp.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f); bit=getpixel(0,0);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+
+ load(); noo=0;
+
+ assign(f,"thinks.avd");
+ getmem(p,picsize);
+ rewrite(f,1);
+ blockwrite(f,thinks_header,65);
+ gd=10; gm=20;
+
+ while (noo<=number_of_objects)
+ {;
+ getimage(gd,gm,gd+59,gm+29,p);
+ putimage(gd,gm,p,notput);
+ blockwrite(f,p,picsize);
+ gd += 70;
+
+ if (gd==640)
+ {;
+ gd=10; gm += 40;
+ }
+
+ noo += 1;
+ }
+
+ close(f); freemem(p,picsize);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/pingo.cpp b/engines/avalanche/pingo.cpp
new file mode 100644
index 0000000000..1bb3066bff
--- /dev/null
+++ b/engines/avalanche/pingo.cpp
@@ -0,0 +1,229 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ PINGO Full-screen sub-parts of the game. */
+
+#define __pingo_implementation__
+
+
+#include "pingo.h"
+
+
+#include "graph.h"
+#include "gyro.h"
+#include "lucerna.h"
+/*#include "Crt.h"*/
+#include "trip5.h"
+#include "scrolls.h"
+
+
+void dplot(integer x,integer y, string z)
+{;
+ setcolor( 9); outtextxy(x,y ,z);
+ setcolor(11); outtextxy(x,y-1,z);
+}
+
+void bosskey()
+/*const
+ months : array[0..11] of char = 'JFMAMJJASOND';
+ title = 'Net Profits';
+ fish = #224; { à }
+var fv:byte; gd,gm:integer; r:char;
+begin;
+ dusk; delavvy;
+ setactivepage(3); mousepage(3); setvisualpage(3); off;
+ cleardevice; setfillstyle(xhatchfill,11);
+ settextstyle(1,0,4); settextjustify(1,1);
+ dplot(320,10,title);
+ settextstyle(1,0,0); setusercharsize(4,3,7,12);
+ for fv:=0 to 11 do
+ begin;
+ dplot(26+fv*52,187,months[fv]);
+ bar(fv*52,177-fv*14,51+fv*52,180);
+ rectangle(fv*52,177-fv*14,51+fv*52,180);
+ end;
+ settextstyle(0,0,1);
+ for fv:=1 to 177 do
+ begin;
+ gd:=random(630); gm:=random(160)+30;
+ setcolor(lightred); outtextxy(gd ,gm ,fish);
+ setcolor(yellow); outtextxy(gd+1,gm-1,fish);
+ end;
+ newpointer(6); { TTHand }
+ dawn; on; setbkcolor(1); repeat check until (mpress>0) or keypressed;
+ while keypressed do r:=readkey; setbkcolor(0); settextjustify(0,0);
+ dusk; setvisualpage(0); setactivepage(0); mousepage(0); dawn;
+ copy02;*/
+{
+ byte fv;
+;
+ dusk();
+ off_virtual();
+ for( fv=0; fv <= 1; fv ++)
+ {;
+ setactivepage(fv);
+ cleardevice();
+ }
+ load(98); off();
+ setactivepage(1); setvisualpage(1);
+ settextjustify(1,0); setcolor(8);
+ outtextxy(320,177,"Graph/Histo/Draw/Sample: \"JANJUN93.GRA\": (W3-AB3)");
+ outtextxy(320,190,"Press any key or click the mouse to return.");
+ settextjustify(2,0);
+ on(); mousepage(1); newpointer(1); dawn();
+ do { check(); } while (!((mpress>0) || keypressed()));
+ off(); on_virtual();
+ major_redraw();
+
+ mousepage(cp);
+}
+
+void copy02() /* taken from Wobble (below) */
+{
+ byte a0 /*absolute $A000:0*/; byte a2/*absolute $A800:0*/; byte bit;
+;
+ off();
+ for( bit=0; bit <= 3; bit ++) {;
+ port[0x3c4]=2; port[0x3ce]=4;
+ port[0x3c5]=1 << bit;
+ port[0x3cf]=bit;
+ move(a0,a2,16000);
+ } on();
+}
+
+void copy03() /* taken from Wobble (below) */
+{
+ byte a0 /*absolute $A000:0*/; byte a2/*absolute $AC00:0*/; byte bit;
+ byte squeaky_code;
+
+ switch (visible) {
+ case m_virtual : { squeaky_code = 1; off_virtual(); } break;
+ case m_no : squeaky_code = 2; break;
+ case m_yes : { squeaky_code = 3; off(); } break;
+ }
+
+ for( bit=0; bit <= 3; bit ++) {;
+ port[0x3c4]=2; port[0x3ce]=4;
+ port[0x3c5]=1 << bit;
+ port[0x3cf]=bit;
+ move(a0,a2,16000);
+ }
+
+ switch (squeaky_code) {
+ case 1 : on_virtual(); break;
+ case 2 :; break; /* zzzz, it was off anyway */
+ case 3 : on(); break;
+ }
+
+}
+
+void copypage(byte frp,byte top) /* taken from Copy02 (above) */
+{
+ byte bit;
+;
+ off();
+ for( bit=0; bit <= 3; bit ++) {;
+ port[0x3c4]=2; port[0x3ce]=4;
+ port[0x3c5]=1 << bit;
+ port[0x3cf]=bit;
+ move(mem[0xa000*frp*pagetop],mem[0xa000*top*pagetop],16000);
+ } on();
+}
+
+void wobble()
+{
+ byte bit;
+ byte a2 /*absolute $A800:80i*/;
+;
+ off();
+ setactivepage(2); bit=getpixel(0,0);
+ cleardevice();
+ for( bit=0; bit <= 3; bit ++) {;
+ port[0x3c4]=2; port[0x3ce]=4;
+ port[0x3c5]=1 << bit;
+ port[0x3cf]=bit;
+ move(mem[0xa000*cp*pagetop],a2,16000);
+ }
+ for( bit=0; bit <= 25; bit ++)
+ {;
+ setvisualpage(2); delay(bit*7);
+ setvisualpage(cp); delay(bit*7);
+ }
+ bit=getpixel(0,0);
+ draw_also_lines();
+ setactivepage(1-cp); on();
+}
+
+void zonk();
+
+static void zl(integer x1,integer y1,integer x2,integer y2)
+{;
+ setlinestyle(0,0,3); setcolor( 1); line(x1,y1,x2,y2);
+ setlinestyle(0,0,1); setcolor(11); line(x1,y1,x2,y2);
+}
+
+void zonk()
+{
+ integer xx,yy;
+/* a0:byte absolute $A000:0; a3:byte absolute $A000:245760;*/ byte bit,fv;
+;
+ off();
+ copypage(3,1-cp);
+ {
+ triptype& with = tr[1];
+ ; xx=with.x+with.a.xl / 2; yy=with.y; }
+
+ setactivepage(3); cleardevice();
+/* for bit:=0 to 3 do begin;
+ port[$3C4]:=2; port[$3CE]:=4;
+ port[$3C5]:=1 shl bit;
+ port[$3CF]:=bit;
+ move(a0,a3,16000);
+ end;*/
+ copypage(cp,3); off();
+ zl(640,0,0,yy / 4);
+ zl(0,yy / 4,640,yy / 2);
+ zl(640,yy / 2,xx,yy); setbkcolor(yellow);
+
+ for( bit=0; bit <= 255; bit ++)
+ {;
+ note(270-bit); setvisualpage(3);
+ note(2700-10*bit); delay(5); nosound;
+ note(270-bit); setvisualpage(cp);
+ note(2700-10*bit); delay(5); nosound;
+ } setactivepage(0); setbkcolor(black); on(); state(2);
+ copypage(1-cp,3);
+}
+
+void winning_pic()
+{
+ byte bit;
+ untyped_file f;
+ char r;
+
+ dusk();
+
+ assign(f,"finale.avd");
+ reset(f,1);
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4;
+ port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,mem[0xa000*0],16000);
+ }
+ close(f); blitfix();
+
+ setvisualpage(0);
+
+ dawn();
+
+ do { check(); } while (!(keypressed() || (mrelease>0)));
+ while (keypressed()) r=readkey();
+ major_redraw();
+}
+
+
diff --git a/engines/avalanche/pingo.h b/engines/avalanche/pingo.h
new file mode 100644
index 0000000000..fdb49b7048
--- /dev/null
+++ b/engines/avalanche/pingo.h
@@ -0,0 +1,19 @@
+#ifndef __pingo_h__
+#define __pingo_h__
+
+
+void bosskey();
+
+void copy02();
+
+void copy03();
+
+void copypage(byte frp,byte top);
+
+void wobble();
+
+void zonk();
+
+void winning_pic();
+
+#endif
diff --git a/engines/avalanche/plottest.cpp b/engines/avalanche/plottest.cpp
new file mode 100644
index 0000000000..80f7937ca5
--- /dev/null
+++ b/engines/avalanche/plottest.cpp
@@ -0,0 +1,42 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+integer gd,gm; byte fv;
+matrix<1,35,0,39,byte> a;
+array<0,3,0,4,1,35,byte> b;
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"");
+ for( gd=0; gd <= 39; gd ++)
+ for( gm=1; gm <= 35; gm ++)
+ a[gm][gd]=(gd+gm) % 16;
+ for( gd=0; gd <= 39; gd ++)
+ for( gm=1; gm <= 35; gm ++)
+ putpixel(gd+100,gm+100,a[gm][gd]);
+
+ fillchar(b,sizeof(b),'\0');
+ for( gm=1; gm <= 35; gm ++)
+ for( gd=0; gd <= 39; gd ++)
+ {;
+ for( fv=0; fv <= 3; fv ++)
+ {;
+ b[fv][gd / 8][gm]=(b[fv][gd / 8][gm] << 1);
+ b[fv][gd / 8][gm] += ((cardinal)(a[gm][gd] & (1 << fv)) >> fv);
+ }
+ }
+
+ for( gd=1; gd <= 35; gd ++)
+ for( gm=0; gm <= 4; gm ++)
+ {;
+ for( fv=0; fv <= 3; fv ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4;
+ port[0x3c5]=1 << fv; port[0x3cf]=fv;
+ mem[0xa000*gd*80+gm]=b[fv][gm][gd];
+ }
+ }
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/preview1.cpp b/engines/avalanche/preview1.cpp
new file mode 100644
index 0000000000..aff9f1b5e5
--- /dev/null
+++ b/engines/avalanche/preview1.cpp
@@ -0,0 +1,122 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+
+array<0,3,palettetype> fxpal;
+
+void load()
+{
+ byte a0 /*absolute $A000:800*/;
+ byte bit;
+ untyped_file f;
+
+
+ assign(f,"preview2.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+
+ settextjustify(1,1);
+ setcolor(3);
+ outtextxy(320,166,"...This is a preview of things to come...");
+ setcolor(14);
+ outtextxy(320,176,"AVAROID");
+ outtextxy(320,183,"(a space so dizzy)");
+ setcolor(9);
+ outtextxy(320,194,"the next Avvy adventure-- in 256 colours.");
+ setcolor(7);
+ outtextxy(590,195,"Any key...");
+}
+
+void setup()
+{
+ integer gd,gm;
+ palettetype p;
+
+ if (paramstr(1)!="jsb") exit(255);
+ gd=3; gm=0; initgraph(gd,gm,"");
+ getpalette(fxpal[0]);
+
+ fillchar(p.colors,sizeof(p.colors),'\0'); /* Blank out the screen. */
+ p.size=16; setallpalette(p);
+}
+
+void wait()
+{
+ word w; char r;
+
+ w=0;
+ do {
+ delay(1); w += 1;
+ } while (!(keypressed() || (w==15000)));
+
+ while (keypressed()) r=readkey(); /* Keyboard sink. */
+}
+
+void show(byte n)
+{
+ setallpalette(fxpal[n]);
+ delay(55);
+}
+
+shortint fades(shortint x)
+{
+ byte r,g,b;
+
+ shortint fades_result;
+ r=x / 16; x=x % 16;
+ g=x / 4; b=x % 4;
+ if (r>0) r -= 1; if (g>0) g -= 1; if (b>0) b -= 1;
+ fades_result=(16*r+4*g+b);
+/* fades:=x-1;*/
+ return fades_result;
+}
+
+void dawn();
+
+static void calc(byte n)
+{
+ byte fv;
+
+ fxpal[n]=fxpal[n-1];
+
+ for( fv=1; fv <= fxpal[n].size-1; fv ++)
+ fxpal[n].colors[fv]=fades(fxpal[n].colors[fv]);
+}
+
+void dawn()
+{
+ byte fv;
+
+ for( fv=1; fv <= 3; fv ++) calc(fv);
+
+ for( fv=3; fv >= 0; fv --) show(fv);
+}
+
+void dusk()
+{
+ byte fv;
+
+ for( fv=1; fv <= 3; fv ++) show(fv);
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ setup();
+ load();
+ dawn();
+ wait();
+ dusk();
+ closegraph();
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/qintro.cpp b/engines/avalanche/qintro.cpp
new file mode 100644
index 0000000000..3843d80872
--- /dev/null
+++ b/engines/avalanche/qintro.cpp
@@ -0,0 +1,277 @@
+#include "ptoc.h"
+
+
+/*#include "Dos.h"*/
+#include "graph.h"
+/*#include "Crt.h"*/
+
+ /* This is a stand-alone program. */
+
+/* 0, black, remains 0.
+ Other numbers: the bits take precedence from the left.
+ e.g. for 9 = 1001, => fourth bit.
+
+ First 1 is in:
+
+ Fourth bit: 63 (egaWhite)
+ Third bit: 57 (egaLightBlue)
+ Second bit: 7 (light grey)
+ First bit: 1 (blue). */
+
+const palettetype our_palette =
+ {16,
+ /* sic */
+{{ 0, 1, 57, 57, 7, 7, 7, 7, 63, 63, 63, 63, 63, 63, 63, 63}}};
+
+typedef matrix<'\0','\377',1,16,byte> fonttype;
+
+fonttype f;
+matrix<0,39,1,16,byte> next_line;
+
+byte next_bitline;
+
+byte displaycounter;
+
+boolean cut_out;
+
+word cut_out_time;
+
+array<1,117,varying_string<40> > x;
+
+byte this_line;
+
+word* skellern;
+
+/*$L intro.obj*/
+extern void introduction();
+
+void graphmode(integer mode)
+{
+ registers regs;
+
+ regs.ax=mode;
+ intr(0x10,regs);
+}
+
+/* Firstly, port[$3C4]:=2; port[$3CF]:=4;,
+ Then port[$3C5]:=1 shl bit; port[$3CF]:=bit;. */
+
+void loadfont()
+{
+ file<fonttype> ff;
+
+ assign(ff,"avalot.fnt");
+ reset(ff);
+ ff >> f;
+ close(ff);
+}
+
+void calc_next_line()
+ /* This proc sets up next_line. */
+{
+ string l;
+ byte fv,ff;
+ boolean oddlen;
+ byte start;
+ byte this_;
+
+ fillchar(next_line,sizeof(next_line),'\0'); /* All blanks. */
+
+ if (this_line==117)
+ {
+ cut_out=true;
+ return;
+ }
+
+ l=x[this_line];
+ this_line += 1;
+
+ start=(20-length(l) / 2)-1;
+ oddlen=odd(length(l));
+
+ for( fv=1; fv <= length(l); fv ++)
+ for( ff=1; ff <= 16; ff ++)
+ {
+ this_=f[l[fv]][ff];
+ if (oddlen)
+ { /* Odd, => 4 bits shift to the right. */
+ next_line[start+fv][ff] += this_ << 4;
+ next_line[start+fv-1][ff] += (cardinal)this_ >> 4;
+ } else
+ { /* Even, => no bit shift. */
+ next_line[start+fv][ff]=this_;
+ }
+ }
+ next_bitline=1;
+}
+
+void display()
+{
+ byte fv,ff;
+
+
+ if (next_bitline == 17) calc_next_line();
+
+ if (cut_out)
+ {
+ cut_out_time -= 1;
+ return;
+ }
+
+ move(mem[0xa000*40],mem[0xa000*0],7960);
+ for( fv=0; fv <= 39; fv ++)
+ mem[0xa1f1*8+fv]=next_line[fv][next_bitline];
+ next_bitline += 1;
+
+}
+
+void plot_a_star(integer x,integer y)
+{
+ byte ofs;
+
+ ofs=x % 8;
+ x=x / 8;
+ mem[0xa000*x+y*40] += (cardinal)128 >> ofs;
+}
+
+void plot_some_stars(integer y)
+{
+ byte fv,times;
+
+ switch (Random(7)) {
+ case 1: times=1; break;
+ case 2: times=2; break;
+ case 3: times=3; break;
+ default: return;
+ }
+
+ for( fv=1; fv <= times; fv ++)
+ plot_a_star(Random(320),y);
+}
+
+void starry_starry_night()
+{
+ integer y;
+ byte bit;
+
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+
+ for( bit=0; bit <= 2; bit ++)
+ {
+ port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( y=1; y <= 200; y ++)
+ plot_some_stars(y);
+ }
+}
+
+void setupgraphics() /* Fix this proc. This prog SHOULDN'T use the
+ Graph unit. */
+{
+ integer gd,gm;
+
+ gd=3; gm=1; initgraph(gd,gm,"");
+}
+
+void shovestars()
+{
+ move(mem[0xa000*0],mem[0xa000*40],7960);
+ fillchar(mem[0xa000*0],40,'\0');
+ plot_some_stars(0);
+}
+
+void do_next_line()
+{
+ byte bit;
+
+ port[0x3c4]=2; port[0x3ce]=4;
+
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c5]=1 << bit; port[0x3cf]=bit;
+
+ switch (bit) {
+ case 0: if ((displaycounter % 10)==0) shovestars(); break;
+ case 1: if ((displaycounter % 2)==0) shovestars(); break;
+ case 2: shovestars(); break;
+ case 3: display(); break; /* The text. */
+ }
+ }
+
+ if (displaycounter==40) displaycounter=0;
+
+}
+
+void load_text()
+{
+ word fv;
+ char* c;
+ byte thisline;
+
+
+ c=addr(introduction());
+ thisline=0;
+ fillchar(x,sizeof(x),'\0');
+
+ for( fv=1; fv <= 2456; fv ++)
+ {
+ switch (*c) {
+ case '\15': thisline += 1; break;
+ case '\12':/*nop*/; break;
+ default: x[thisline]=x[thisline]+*c;
+ }
+
+ c += 1;
+ }
+}
+
+void check_params()
+{
+ word s,o; integer e;
+
+ if (paramstr(1)!="jsb") exit(0);
+ val(paramstr(2),s,e); if (e!=0) exit(0);
+ val(paramstr(3),o,e); if (e!=0) exit(0);
+ skellern=ptr(s,o+1);
+}
+
+int main(int argc, const char* argv[])
+{
+
+ pio_initialize(argc, argv);
+ check_params();
+
+ setupgraphics();
+
+ randseed=177; checkbreak=false;
+
+ load_text();
+
+ this_line=1;
+
+ graphmode(0xd);
+ loadfont();
+
+ next_bitline=17;
+ displaycounter=0;
+
+ cut_out_time=333;
+
+ setallpalette(our_palette);
+
+ starry_starry_night();
+
+ while ((cut_out_time>0) && (! keypressed()))
+ {
+
+ *skellern=0;
+
+ do_next_line();
+
+ displaycounter += 1;
+
+ do {; } while (!(*skellern>0));
+ }
+
+ graphmode(3);
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/qstars.cpp b/engines/avalanche/qstars.cpp
new file mode 100644
index 0000000000..3a31a9e67a
--- /dev/null
+++ b/engines/avalanche/qstars.cpp
@@ -0,0 +1,237 @@
+#include "ptoc.h"
+
+ /* Demonstration of the Bigo II system. */
+#include "graph.h"
+/*#include "Crt.h"*/
+/*#include "Rodent.h"*/
+/*#include "Tommys.h"*/
+
+integer gd,gm;
+
+typedef matrix<'\0','\377',0,15,byte> fonttype;
+
+boolean reverse;
+word spinnum;
+array<0,1,fonttype> f;
+file<fonttype> ff;
+array<0,7,0,15,0,79,byte> strip;
+byte across;
+word w; byte y;
+byte charnum;
+byte cfont; /* current font. 0=roman, 1=italic. */
+
+char* c;
+
+const integer colours = 12; /* Run Workout to see possible values of these two. */
+const integer steps = 6; /* 60,30,20,15,12,10,6,5,4,3,2,1 */
+const integer gmtop = 360 / steps;
+
+/*$L credits.obj*/ extern void credits();
+
+void bigo2(string date)
+{
+ integer gd,gm;
+ byte c;
+ palettetype p;
+ untyped_file f; pointer pp; word s;
+
+
+ getpalette(p);
+ setvisualpage(1); setactivepage(0);
+ assign(f,"logo.avd"); reset(f,1);
+ for( gd=7; gd <= 194; gd ++)
+ blockread(f,mem[0xa000*(gd*80)],53);
+ close(f);
+ s=imagesize(0,7,415,194); getmem(pp,s); getimage(0,7,415,194,pp);
+
+ cleardevice();
+ for( gd=1; gd <= 64; gd ++)
+ {
+ for( gm=0; gm <= gmtop; gm ++)
+ {
+ c=(c % colours)+1;
+/* putpixel(trunc(sin(gm*steps*n)*gd*6)+320,
+ trunc(cos(gm*steps*n)*gd*3)+175,c); */
+ if (c>5) continue_;
+ setcolor(c); arc(320,175,gm*steps,gm*steps+1,gd*6);
+ }
+ if (keypressed()) { closegraph(); exit(0); }
+ }
+ settextstyle(0,0,1); setcolor(13);
+ outtextxy(550,343,"(press any key)");
+
+ putimage(112,0,pp,orput); freemem(pp,s);
+ resetmouse; setvisualpage(0);
+}
+
+void nextchar() /* Sets up charnum & cline for the next character. */
+{
+
+ c += 1;
+}
+
+void getchar()
+{
+ do {
+ nextchar();
+
+ switch (*c) {
+ case '@': { cfont=1; nextchar(); } break;
+ case '^': { cfont=0; nextchar(); } break;
+ case '%': { closegraph(); exit(0); } break;
+ }
+
+ } while (!((*c!='\15') && (*c!='\12')));
+
+ for( w=0; w <= 7; w ++)
+ for( y=0; y <= 15; y ++)
+ move(strip[w][y][1],strip[w][y][0],79);
+
+ for( w=0; w <= 7; w ++)
+ for( y=0; y <= 15; y ++)
+ strip[w][y][79]=(byte)((strip[7][y][78] << (w+1)))+
+ ((cardinal)f[cfont][*c][y] >> (7-w));
+
+ across=0;
+}
+
+void scrolltext()
+{
+ byte c,w,y;
+
+ across += 1;
+ if (across==8) getchar();
+
+ for( y=0; y <= 15; y ++)
+ for( w=0; w <= 1; w ++)
+ move(strip[across][y][0],mem[0xa000*24000+(y*2+w)*80],80);
+}
+
+void do_stuff()
+{
+ switch (spinnum) {
+ case 50 ... 110: {
+ setfillstyle(1,14);
+ bar(0,315+(spinnum-50) / 3,640,315+(spinnum-50) / 3);
+ bar(0,316-(spinnum-50) / 3,640,316-(spinnum-50) / 3);
+ if (spinnum>56)
+ {
+ setfillstyle(1,13);
+ bar(0,315+(spinnum-56) / 3,640,315+(spinnum-56) / 3);
+ bar(0,316-(spinnum-56) / 3,640,316-(spinnum-56) / 3);
+ }
+ }
+ break;
+ case 150 ... 198: {
+ setfillstyle(1,0);
+ bar(0,315+(spinnum-150) / 3,640,315+(spinnum-150) / 3);
+ bar(0,316-(spinnum-150) / 3,640,316-(spinnum-150) / 3);
+ }
+ break;
+ case 200: scrolltext(); break;
+ }
+}
+
+void setcol(byte which,byte what)
+/*var dummy:byte;*/
+{;
+/* setpalette(which,what);
+ asm
+(* mov dx,$3DA;
+ in ax,dx;
+
+ or ah,ah;
+
+ mov dx,$3C0;
+ mov al,which;
+ out dx,al;
+
+ mov dx,$3C0;
+ mov al,what;
+ out dx,al;
+ end;
+(* dummy:=port[$3DA];
+ port[$3C0]:=which; port[$3C0]:=what;*/
+}
+
+void bigo2go()
+{
+ palettetype p; byte c; boolean lmo;
+ boolean altnow,altbefore;
+
+ for( gd=0; gd <= 13; gd ++) p.colors[gd]=0;
+
+ setcol(13,24); /* murk */ setcol(14,38); /* gold */
+ setcol(15,egawhite); /* white- of course */
+ p.colors[13]=24; p.colors[14]=38; p.colors[15]=egawhite;
+
+ /***/
+
+ p.colors[5]=egawhite;
+ p.colors[4]=egalightcyan;
+ p.colors[3]=egacyan;
+ p.colors[2]=egalightblue;
+ p.colors[1]=egablue;
+
+ /***/
+
+ c=1; p.size=16; lmo=false;
+ setallpalette(p);
+
+ do {
+/* if reverse then
+ begin
+ dec(c); if c=0 then c:=colours;
+ end else
+ begin
+ inc(c); if c>colours then c:=1;
+ end;
+ for gm:=1 to colours do
+ case p.colors[gm] of
+ egaWhite: begin p.colors[gm]:=egaLightcyan; setcol(gm,egaLightCyan); end;
+ egaLightcyan: begin p.colors[gm]:=egaCyan; setcol(gm,egaCyan); end;
+ egaCyan: begin p.colors[gm]:=egaLightblue; setcol(gm,egaLightblue); end;
+ egaLightblue: begin p.colors[gm]:=egaBlue; setcol(gm,egaBlue); end;
+ egaBlue: begin p.colors[gm]:=0; setcol(gm,0); end;
+ end;
+ p.colors[c]:=egaWhite; setcol(c,egaWhite);
+
+ AltBefore:=AltNow; AltNow:=testkey(sAlt);*/
+
+ if (anymousekeypressed) lmo=true;
+ if (keypressed()) lmo=true;
+
+ /* if (AltNow=True) and (AltBefore=False) then reverse:=not reverse;*/
+
+ do_stuff();
+ if (spinnum<200) spinnum += 1;
+ } while (!lmo);
+}
+
+void parse_cline()
+{
+ integer e;
+
+ if (paramstr(1)!="jsb")
+ {
+ output << "Not a standalone program." << NL; exit(255);
+ }
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ parse_cline();
+
+ gd=3; gm=1; initgraph(gd,gm,"");
+ assign(ff,"avalot.fnt"); reset(ff); ff >> f[0]; close(ff);
+ assign(ff,"avitalic.fnt"); reset(ff); ff >> f[1]; close(ff);
+
+ c=addr(credits()); c -= 1;
+
+ fillchar(strip,sizeof(strip),'\0');
+ reverse=false; spinnum=0; across=7; charnum=1; cfont=0;
+ bigo2("1189"); /* 1189? 79? 2345? 1967? */
+ bigo2go();
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/rawupd.cpp b/engines/avalanche/rawupd.cpp
new file mode 100644
index 0000000000..a911e1d918
--- /dev/null
+++ b/engines/avalanche/rawupd.cpp
@@ -0,0 +1,71 @@
+#include "ptoc.h"
+
+
+/*#include "Dos.h"*/
+/*#include "Crt.h"*/
+
+searchrec s;
+string x,y;
+longint hash_time,s_time;
+boolean s_exists;
+
+void find_out_about_s(string name)
+{
+ searchrec ss;
+;
+ findfirst(name,anyfile,ss);
+ s_exists=doserror==0;
+
+ if (s_exists)
+ s_time=ss.time;
+}
+
+void get_y()
+{
+ y=x;
+ if (set::of(range('0','9'), eos).has(x[2]))
+ y[1]='h'; else
+ if (x[3]=='K')
+ y[1]='a'; else
+ y[1]='s';
+}
+
+void rename_it()
+{
+ untyped_file f;
+
+ output << x << " -> " << y;
+ assign(f,x); reset(f); rename(f,y); close(f);
+ output << " ...done." << NL;
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ output << NL;
+ findfirst("#*.*",anyfile,s);
+ while (doserror==0)
+ {
+ x=s.name;
+ get_y();
+ hash_time=s.time;
+ output << format(x,15); clreol;
+ find_out_about_s(y);
+ if (s_exists)
+ {
+ output << ": s exists and is ";
+ if (s_time<hash_time)
+ output << "NEWER!" << NL;
+ else if (s_time==hash_time)
+ output << string("equal.")+'\15';
+ else output << "older." << NL;
+ } else
+ {
+ output << " ... NO S FOUND! Renaming...";
+ rename_it();
+ }
+
+ findnext(s);
+ }
+ return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/readsez.cpp b/engines/avalanche/readsez.cpp
new file mode 100644
index 0000000000..744d221fd0
--- /dev/null
+++ b/engines/avalanche/readsez.cpp
@@ -0,0 +1,80 @@
+#include "ptoc.h"
+
+
+
+struct markertype {
+ word length;
+ longint offset;
+ byte checksum;
+};
+
+struct sezheader {
+ array<1,2,char> initials; /* should be "TT" */
+ word gamecode;
+ word revision; /* as 3- or 4-digit code (eg v1.00 = 100) */
+ longint chains; /* number of scroll chains */
+ longint size; /* total size of all chains */
+};
+
+untyped_file f;
+longint number;
+markertype marker;
+sezheader sezhead;
+array<0,1999,char> x;
+word fv;
+byte sum;
+
+byte sumup()
+{
+ word fv; byte total;
+byte sumup_result;
+;
+ total=0;
+ for( fv=0; fv <= marker.length; fv ++)
+ {;
+ total += ord(x[fv]);
+ }
+ sumup_result=total;
+return sumup_result;
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ output << "READ-SEZ by TT." << NL; output << NL;
+ assign(f,"avalot.sez"); reset(f,1);
+ seek(f,255); blockread(f,sezhead,sizeof(sezhead));
+ {;
+ if (sezhead.initials!="TT")
+ {;
+ output << "Not a valid Sez file!" << NL;
+ exit(0);
+ }
+ output << "Number of chains in file = " << sezhead.chains << NL;
+ output << "Total size of all chains = " << sezhead.size << " bytes." << NL;
+ }
+ output << NL;
+ output << "Number of scrollchain to display?"; input >> number >> NL;
+ seek(f,longint(262)+number*longint(7)); blockread(f,marker,7);
+ {;
+ output << "Scrollchain no. " << number << NL;
+ output << "Length: " << marker.length << NL;
+ output << "Offset: " << marker.offset << NL;
+ output << NL;
+ output << "Contents:" << NL;
+ seek(f,longint(270)+sezhead.chains*longint(7)+marker.offset);
+ blockread(f,x,marker.length+1);
+ for( fv=0; fv <= marker.length; fv ++) x[fv] -= 3+177*fv*marker.length; /* unscramble */
+ for( fv=0; fv <= marker.length; fv ++) output << x[fv];
+ output << NL; sum=sumup();
+ output << "Checksum in file: " << marker.checksum << ". Actual value: " << sum << '.' << NL;
+ output << NL;
+ if (sum!=marker.checksum)
+ {;
+ output << "Bleargh! Checksum failed!" << NL;
+ exit(0);
+ }
+ }
+ close(f);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/reginam.cpp b/engines/avalanche/reginam.cpp
new file mode 100644
index 0000000000..c85dee39a9
--- /dev/null
+++ b/engines/avalanche/reginam.cpp
@@ -0,0 +1,91 @@
+#include "ptoc.h"
+
+
+const array<1,36,char> letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+varying_string<30> name;
+varying_string<5> number;
+
+void alphanum();
+
+static string z;
+
+static byte p;
+
+
+static void replace(char what,char whatwith)
+{;
+ p=pos(what,z); if (p>0) z[p]=whatwith;
+}
+
+void alphanum()
+{
+ byte fv;
+
+;
+ z="";
+ for( fv=1; fv <= length(name); fv ++)
+ if (set::of(range('A','Z'), eos).has(name[fv]))
+ z=z+'7'+name[fv]; else
+ z=z+upcase(name[fv]);
+ replace(' ','1');
+ replace('.','2');
+ replace('-','3');
+ replace('\'','4');
+ replace('"','5');
+ replace('!','6');
+ replace(',','9');
+ replace('?','0');
+
+ for( fv=1; fv <= length(number); fv ++)
+ number[fv]=upcase(number[fv]);
+
+ name=z+'8'+number;
+}
+
+void scramble()
+{
+ byte fv,what;
+;
+ for( fv=1; fv <= length(name); fv ++)
+ {;
+ what=pos(name[fv],letters);
+ what += 177;
+ what += (fv+1)*3;
+ name[fv]=letters[(what % 36)+1-1];
+ }
+}
+
+void checks()
+{
+ byte fv,total;
+;
+ total=177;
+ for( fv=1; fv <= length(name); fv ++)
+ total += ord(name[fv]);
+ name=string('T')+name+letters[total % 36-1];
+}
+
+void negate()
+{
+ byte fv;
+;
+ name[1]='N';
+ for( fv=2; fv <= length(name); fv ++)
+ name[fv]=letters[37-pos(name[fv],letters)-1];
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ output << "Registrant's name?"; input >> name >> NL;
+ output << "And number (eg, A1)?"; input >> number >> NL;
+ alphanum();
+ output << "Name = " << name << NL;
+ scramble();
+ output << "Scrambled = " << name << NL;
+ checks();
+ output << "With checks = " << name << NL;
+ negate();
+ output << "Or, negated, = " << name << NL;
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/sackb1.cpp b/engines/avalanche/sackb1.cpp
new file mode 100644
index 0000000000..800738821c
--- /dev/null
+++ b/engines/avalanche/sackb1.cpp
@@ -0,0 +1,52 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ SACKBLASTER-1 The temporary mod player. */
+
+/* This is SackBlaster version 1.0, using Mark J. Cox's MODOBJ routines.
+ When Cameron finishes his mod player I'll use his routines, DV. However,
+ this will do for the time being. */
+
+#define __sackb1_implementation__
+
+
+#include "sackb1.h"
+
+
+/*$L v:MOD-obj.OBJ*/ /* Link in Object file */
+/*$F+*/ /* force calls to be 'far'*/
+
+extern void modvolume(integer v1,integer v2,integer v3,integer v4); /*Can do while playing*/
+extern void moddevice(integer& device);
+extern void modsetup(integer& status,integer device,integer mixspeed,integer pro,integer loop,string& stri);
+extern void modstop();
+extern void modinit();
+/*$F-*/
+
+void sb_start(string md)
+{
+ integer dev,mix,stat,pro,loop;
+
+ modinit();
+ dev=7; /* Sound Blaster */
+ mix = 10000; /*use 10000 normally */
+ pro = 0; /*Leave at 0*/
+ loop =4; /*4 means mod will play forever*/
+ modvolume (255,255,255,255); /* Full volume */
+ modsetup ( stat, dev, mix, pro, loop, md );
+}
+
+void sb_stop()
+{;
+ modstop();
+}
+
+void sb_link() /* At the moment, this does nothing. */
+{;
+}
+
+
diff --git a/engines/avalanche/sackb1.h b/engines/avalanche/sackb1.h
new file mode 100644
index 0000000000..b671da2a76
--- /dev/null
+++ b/engines/avalanche/sackb1.h
@@ -0,0 +1,14 @@
+#ifndef __sackb1_h__
+#define __sackb1_h__
+
+
+/*#include "Crt.h"*/
+
+
+void sb_start(string md);
+
+void sb_stop();
+
+void sb_link(); /* At the moment, this does nothing. */
+
+#endif
diff --git a/engines/avalanche/sackb3.cpp b/engines/avalanche/sackb3.cpp
new file mode 100644
index 0000000000..b48379d364
--- /dev/null
+++ b/engines/avalanche/sackb3.cpp
@@ -0,0 +1,23 @@
+#include "ptoc.h"
+
+/*$M 16384,0,0*/
+
+ /* to demonstrate the SBVoice Unit */
+ /* Copyright 1991 Amit K. Mathur, Windsor, Ontario */
+
+/*#include "SBVoice.h"*/
+
+
+int main(int argc, const char* argv[])
+{
+pio_initialize(argc, argv);
+if (paramcount>0) {
+ loadvoice(paramstr(1),0,0);
+ sb_output(seg(soundfile),ofs(soundfile)+26);
+ do {
+ output << "Demo of the SBVoice Unit, Copyright 1991 by Amit K. Mathur --- ";
+ } while (!(statusword==0));
+} else
+ output << "Usage: DEMO [d:\\path\\]filename.voc" << NL;
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/sackblas.cpp b/engines/avalanche/sackblas.cpp
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/engines/avalanche/sackblas.cpp
diff --git a/engines/avalanche/saving.cpp b/engines/avalanche/saving.cpp
new file mode 100644
index 0000000000..6f35a21ada
--- /dev/null
+++ b/engines/avalanche/saving.cpp
@@ -0,0 +1,48 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+integer gd,gm;
+byte a /*absolute $A000:(15*80)*/;
+byte bit;
+untyped_file f;
+
+void load(string nam)
+{
+ byte z;
+ array<1,4,pointer> a;
+ untyped_file f; word s;
+ string check;
+;
+ assign(f,nam);
+ reset(f,1);
+ blockread(f,check,41);
+ blockread(f,check,13);
+ blockread(f,check,31);
+ s=imagesize(0,0,getmaxx(),75);
+ for( z=1; z <= 2; z ++)
+ {;
+ getmem(a[z],s);
+ blockread(f,a[z],s);
+ setactivepage(0);
+ putimage(0,15+(z-1)*75,a[z],0);
+ freemem(a[z],s);
+ }
+ close(f);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"");
+ load("d:britain.avd");
+ assign(f,"c:\\sleep\\test.ega"); rewrite(f,1);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockwrite(f,a,12000);
+ }
+ close(f);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/scr_1.cpp b/engines/avalanche/scr_1.cpp
new file mode 100644
index 0000000000..5118cd8558
--- /dev/null
+++ b/engines/avalanche/scr_1.cpp
@@ -0,0 +1,89 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+
+
+const varying_string<4> codes = " ßÜÛ";
+
+typedef matrix<'\0','\377',0,15,byte> fonttype;
+
+byte x,xx,y;
+string title,fn;
+file<fonttype> f;
+fonttype font;
+byte code;
+
+
+typedef array<1,3840,byte> atype;
+
+void save()
+{
+ file<atype> f;
+ word fv;
+ atype a /*absolute $B800:0*/;
+;
+ assign(f,"TEXT1.SCR");
+ rewrite(f); f << a; close(f);
+}
+
+void centre(byte y, string z)
+{;
+ gotoxy(40-length(z) / 2,y); output << z;
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+/* write('Title?'); readln(title);
+ write('Font?'); readln(fn); */
+ textattr=0; clrscr;
+ title="Bug Alert!"; fn="";
+ for( xx=1; xx <= 77; xx ++)
+ {;
+ gotoxy(Random(80)+1,Random(24)+1);
+ switch (Random(2)) {
+ case 0: textattr=red; break;
+ case 1: textattr=lightred; break;
+ }
+ switch (Random(4)) {
+ case 0: output << '*'; break;
+ case 1: output << '\17'; break;
+ case 2: output << 'ù'; break;
+ case 3: output << 'ú'; break;
+ }
+ }
+ textattr=12;
+ assign(f,"c:\\thomas\\ttsmall.fnt");
+ reset(f); f >> font; close(f);
+ for( y=0; y <= 3; y ++)
+ {;
+ for( x=1; x <= length(title); x ++)
+ {;
+ for( xx=7; xx >= 0; xx --)
+ {;
+ code=(byte)(((1 << xx) & font[title[x]][y*2])>0)+
+ (byte)(((1 << xx) & font[title[x]][y*2+1])>0)*2;
+ gotoxy(1+x*8-xx,y+1);
+ if (code>0) output << codes[code+1-1];
+ }
+ }
+ /*if wherex<>1 then writeln;*/
+ }
+ textattr=red;
+ centre(7,"An internal error has just occurred within the program.");
+
+ textattr=white; gotoxy(26, 9); output << "Error number: ";
+ textattr=lightred; output << " ";
+ textattr=white; gotoxy(27,10); output << "at location: ";
+ textattr=lightred; output << " ";
+ centre(12,"This screen should never come up...");
+ centre(13,"but it just has!");
+ textattr=15;
+ centre(15,"So, please tell Thorsoft about this as soon as");
+ centre(16,"possible, so that we can fix it.");
+ textattr=red;
+ centre(20,"Thanks...");
+ save();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/scr_2.cpp b/engines/avalanche/scr_2.cpp
new file mode 100644
index 0000000000..7a88efce95
--- /dev/null
+++ b/engines/avalanche/scr_2.cpp
@@ -0,0 +1,113 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+
+
+const varying_string<4> codes = " ßÜÛ";
+
+typedef matrix<'\0','\377',0,15,byte> fonttype;
+
+byte x,xx,y;
+string qq;
+file<fonttype> f;
+fonttype font;
+byte code;
+
+
+typedef array<1,3840,byte> atype;
+
+void save()
+{
+ file<atype> f;
+ word fv;
+ atype a /*absolute $B800:0*/;
+;
+ assign(f,"TEXT2.SCR");
+ rewrite(f); f << a; close(f);
+}
+
+void centre(byte y, string z)
+{
+ byte fv;
+;
+ for( fv=1; fv <= length(z); fv ++)
+ {;
+ gotoxy(39-length(z) / 2+fv,y);
+ if (odd(fv+y)) textattr=2; else textattr=cyan;
+ if (z[fv]!='\40') output << z[fv];
+ }
+}
+
+void line(byte yy, string title)
+{
+ const integer offset = 5;
+;
+ for( y=1; y <= 6; y ++)
+ {;
+ qq="";
+ for( x=1; x <= length(title); x ++)
+ {;
+ for( xx=7; xx >= 0; xx --)
+ {;
+ code=(byte)(((1 << xx) & font[title[x]][y*2-offset])>0)+
+ (byte)(((1 << xx) & font[title[x]][y*2+1-offset])>0)*2;
+ qq=qq+codes[code+1-1];
+ }
+ }
+ centre(y+yy,qq);
+ }
+}
+
+void chips()
+{
+ byte fv,x,y;
+;
+ for( fv=0; fv <= 1; fv ++)
+ {;
+ textattr=120;
+ for( y=2; y <= 6; y ++)
+ {;
+ gotoxy(fv*67+3,y); output << " "; if (fv==1) output << ' ';
+ }
+ gotoxy(fv*67+4,4);
+ if (fv==0) output << "RAM"; else output << "CRAM";
+ textattr=7;
+ for( x=0; x <= 1; x ++)
+ for( y=2; y <= 6; y ++)
+ {; gotoxy(fv*67+2+x*(6+fv),y); output << 'ð'; }
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ textattr=0; clrscr;
+ chips();
+ assign(f,"c:\\thomas\\ttsmall.fnt");
+ reset(f); f >> font; close(f);
+ line(0,"Out of");
+ line(4,"memory!");
+ centre(11,"Yes, RAM cram strikes again- Avvy has just run out of RAM (not the");
+ centre(12,"hydraulic, woolly or village kinds.) Fortunately, there are a few things");
+ centre(13,"you can do about this:");
+ textattr=3;
+ for( xx=15; xx <= 17; xx ++)
+ {;
+ gotoxy(23,xx); output << '\20';
+ }
+ textattr=2;
+ gotoxy(25,15); output << "Don't run Avvy in a DOS shell.";
+ gotoxy(25,16); output << "If that fails, try un-installing your TSRs.";
+ gotoxy(25,17); output << "If you've got DOS 5ù0 or above, try using";
+ gotoxy(28,18); textattr=3; output << "dos=high";
+ textattr=2; output << ',';
+ textattr=3; output << " loadhigh";
+ textattr=2; output << " and";
+ textattr=3; output << " devicehigh";
+ textattr=2; output << '.';
+ gotoxy(28,19); output << "See your DOS manual for details...";
+ centre(23,"Sorry for any inconvenience...");
+ save();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/scr_3.cpp b/engines/avalanche/scr_3.cpp
new file mode 100644
index 0000000000..0c866fc7da
--- /dev/null
+++ b/engines/avalanche/scr_3.cpp
@@ -0,0 +1,93 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+
+
+const varying_string<4> codes = " ßÜÛ";
+
+typedef matrix<'\0','\377',0,15,byte> fonttype;
+
+byte x,xx,y;
+string qq;
+file<fonttype> f;
+fonttype font;
+byte code;
+
+
+typedef array<1,3840,byte> atype;
+
+void save()
+{
+ file<atype> f;
+ word fv;
+ atype a /*absolute $B800:0*/;
+;
+ assign(f,"TEXT3.SCR");
+ rewrite(f); f << a; close(f);
+}
+
+void centre(byte y, string z)
+{
+ byte fv;
+;
+ for( fv=1; fv <= length(z); fv ++)
+ {;
+ gotoxy(39-length(z) / 2+fv,y);
+ if (z[fv]!='\40') output << z[fv];
+ }
+}
+
+void line(byte cx,byte cy, string title)
+{;
+ for( y=0; y <= 4; y ++)
+ {;
+ qq="";
+ for( x=1; x <= length(title); x ++)
+ {;
+ for( xx=7; xx >= 0; xx --)
+ {;
+ code=(byte)(((1 << xx) & font[title[x]][y*2])>0)+
+ (byte)(((1 << xx) & font[title[x]][y*2+1])>0)*2;
+ qq=qq+codes[code+1-1];
+ }
+ }
+ gotoxy(cx,cy+y); output << qq;
+ }
+}
+
+void big_t()
+{
+ text t;
+ string x;
+ byte y;
+;
+ assign(t,"c:\\avalot\\t.txt"); reset(t); y=1;
+ while (! eof(t))
+ {;
+ t >> x >> NL;
+ gotoxy(1,y); output << x; y += 1;
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ textattr=4; clrscr;
+ assign(f,"c:\\thomas\\ttsmall.fnt");
+ reset(f); f >> font; close(f);
+ textattr=4; line(19,4,"hanks");
+ textattr=6; line(23,8,"for");
+ line(7,12,"playing"); textattr += 8;
+ line(12,16,"Avalot.");
+ textattr=12; big_t();
+ textattr=8; gotoxy(40,2); output << "(c) 1994, Mike, Mark and Thomas Thurman.";
+ textattr=11; gotoxy(50,10); output << "* Goodbyte! *";
+ textattr=10; gotoxy(9,20); output << '\20';
+ textattr=12; output << " If you'd like to see yet more of these games, then don't forget to";
+ gotoxy(12,21); output << "register, or your"; clreol;
+ gotoxy(12,22); output << "for the rest of your life!";
+ gotoxy(60,22); output << "(Only joking!)";
+ save();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/scr_4.cpp b/engines/avalanche/scr_4.cpp
new file mode 100644
index 0000000000..605a1dc51b
--- /dev/null
+++ b/engines/avalanche/scr_4.cpp
@@ -0,0 +1,89 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+
+
+const varying_string<4> codes = " ÞÝÛ";
+
+typedef matrix<'\0','\377',0,15,byte> fonttype;
+
+byte x,xx,y;
+string qq;
+file<fonttype> f;
+fonttype font;
+byte code;
+
+void centre(byte y, string z)
+{
+ byte fv;
+;
+ for( fv=1; fv <= length(z); fv ++)
+ {;
+ gotoxy(39-length(z) / 2+fv,y);
+ if (z[fv]!='\40') output << z[fv];
+ }
+}
+
+void line(byte cy, string title)
+{;
+ for( y=0; y <= 6; y ++)
+ {;
+ qq="";
+ for( x=1; x <= length(title); x ++)
+ {;
+ for( xx=3; xx >= 0; xx --)
+ {;
+ code=(byte)(((1 << (xx*2)) & font[title[x]][y])>0)+
+ (byte)(((1 << (xx*2+1)) & font[title[x]][y])>0)*2;
+ qq=qq+codes[code+1-1];
+ }
+ }
+ centre(cy+y,qq);
+ }
+}
+
+void big_t()
+{
+ text t;
+ string x;
+ byte y;
+;
+ assign(t,"c:\\avalot\\t.txt"); reset(t); y=1;
+ while (! eof(t))
+ {;
+ t >> x >> NL;
+ gotoxy(1,y); output << x; y += 1;
+ }
+}
+
+void box(byte x1,byte y1,byte x2,byte y2, string z)
+{
+ byte fv;
+;
+ gotoxy(x1,y1); output << z[1]; /* tl */
+ gotoxy(x2,y1); output << z[2]; /* tr */
+ gotoxy(x1,y2); output << z[3]; /* bl */
+ gotoxy(x2,y2); output << z[4]; /* br */
+ for( fv=y1+1; fv <= y2-1; fv ++)
+ {;
+ gotoxy(x1,fv); output << z[5]; /* verticals */
+ gotoxy(x2,fv); output << z[6];
+ }
+ gotoxy(x1+1,y1); for( fv=x1+1; fv <= x2-1; fv ++) output << z[7];
+ gotoxy(x1+1,y2); for( fv=x1+1; fv <= x2-1; fv ++) output << z[8];
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ textattr=26; clrscr;
+ assign(f,"c:\\thomas\\ttsmall.fnt");
+ reset(f); f >> font; close(f);
+ line(3,"CONGRATULATIONS!");
+ textattr=30; box(4,1,74,11,"ɻȼººÍÍ");
+ textattr=33; box(6,2,72,10,"/\\\\/°°Üß");
+ textattr=30; centre(12,"Well done!");
+ textattr=27; centre(14,"You completed the game!");
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/scr_5.cpp b/engines/avalanche/scr_5.cpp
new file mode 100644
index 0000000000..e90e55e455
--- /dev/null
+++ b/engines/avalanche/scr_5.cpp
@@ -0,0 +1,93 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+
+
+const varying_string<4> codes = " ßÜÛ";
+
+typedef matrix<'\0','\377',0,15,byte> fonttype;
+
+byte x,xx,y;
+string qq;
+file<fonttype> f;
+fonttype font;
+byte code;
+
+
+typedef array<1,3840,byte> atype;
+
+void save()
+{
+ file<atype> f;
+ word fv;
+ atype a /*absolute $B800:0*/;
+;
+ assign(f,"TEXT5.SCR");
+ rewrite(f); f << a; close(f);
+}
+
+void line(byte cx,byte cy, string title)
+{;
+ for( y=0; y <= 4; y ++)
+ {;
+ qq="";
+ for( x=1; x <= length(title); x ++)
+ {;
+ for( xx=7; xx >= 0; xx --)
+ {;
+ code=(byte)(((1 << xx) & font[title[x]][y*2])>0)+
+ (byte)(((1 << xx) & font[title[x]][y*2+1])>0)*2;
+ qq=qq+codes[code+1-1];
+ }
+ }
+ gotoxy(cx,cy+y); output << qq;
+ }
+}
+
+void uline()
+{
+ byte fv,ff;
+;
+ for( fv=1; fv <= 10; fv ++)
+ {;
+ gotoxy(16-fv,21-fv); textattr=fv;
+ for( ff=1; ff <= fv; ff ++) output << "ÄÍÍ-";
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ textattr=0; clrscr;
+ assign(f,"c:\\thomas\\ttsmall.fnt");
+ reset(f); f >> font; close(f);
+ textattr=11;
+ line( 1, 3,"Two at");
+ line( 3, 7,"once?!");
+ textattr=9; gotoxy(55,4); output << string('\4')+'\377';
+ textattr=3; output << "You're trying to run";
+ gotoxy(54,5); output << "two copies of Avalot";
+ gotoxy(54,6); output << "at once.";
+ gotoxy(57,8); output << "Although this "; textattr=9; output << "is";
+ textattr=3;
+ gotoxy(54,9); output << "usually possible, it's";
+ gotoxy(54,10); output << "probably more sensible";
+ gotoxy(54,11); output << "to type ";
+ textattr=7; output << "EXIT ";
+ textattr=3; output << "now, which";
+ gotoxy(54,12); output << "should return you to the";
+ gotoxy(54,13); output << "first copy in memory.";
+
+ textattr=11; gotoxy(55,15); output << "BUT:"; textattr=9;
+ gotoxy(40,16); output << "If you want to run two copies anyway,";
+ gotoxy(40,17); output << "or you think that I've got it wrong,";
+ gotoxy(40,18); output << "(even computers can make mistakes!) then";
+ gotoxy(40,19); output << "try running the game again, but this time";
+ gotoxy(40,20); output << "use "; textattr=7; output << "/i ";
+ textattr=9; output << "on the command line.";
+ uline();
+
+ save();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/scr_9.cpp b/engines/avalanche/scr_9.cpp
new file mode 100644
index 0000000000..e1363470fd
--- /dev/null
+++ b/engines/avalanche/scr_9.cpp
@@ -0,0 +1,21 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+
+text t;
+string x;
+byte fv;
+untyped_file f;
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ assign(f,"v:paralogo.scr");
+ clrscr;
+ reset(f,1);
+ blockread(f,mem[0xb800*0],4000);
+ close(f);
+ gotoxy(1,1); insline;
+ gotoxy(1,23); clreol;
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/scrolls.cpp b/engines/avalanche/scrolls.cpp
new file mode 100644
index 0000000000..4a2a0d9fc0
--- /dev/null
+++ b/engines/avalanche/scrolls.cpp
@@ -0,0 +1,781 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ SCROLLS The scroll driver. */
+/* $D-*/
+#define __scrolls_implementation__
+
+/*$V-*/
+
+#include "scrolls.h"
+
+#include "lucerna.h"
+ #include "Graph.h"
+ /*#include "Crt.h"*/
+#include "trip5.h"
+#include "enhanced.h"
+ /*#include "Dos.h"*/
+#include "logger.h"
+ #include "Acci.h"
+#include "basher.h"
+#include "visa.h"
+#include "timeout.h"
+
+
+const integer roman = 0;
+const integer italic = 1;
+
+const integer halficonwidth = 19; /* Half the width of an icon. */
+
+integer dix,diy;
+array<roman,italic,raw> ch;
+byte cfont; /* Current font */
+
+integer dodgex,dodgey;
+byte param; /* For using arguments code */
+
+byte use_icon;
+
+void state(byte x) /* Sets "Ready" light to whatever */
+{
+ byte page_;
+
+ if (ledstatus==x) return; /* Already like that! */
+ switch (x) {
+ case 0: setfillstyle(1,black); break; /* Off */
+ case 1: setfillstyle(9,green); break; /* Half-on (menus) */
+ case 2: setfillstyle(1,green); break; /* On (kbd) */
+ case 3: setfillstyle(6,green); break; /* Hit a key */
+ }
+ super_off();
+ for( page_=0; page_ <= 1; page_ ++)
+ { setactivepage(page_); bar(419,195,438,197); } super_on();
+ ledstatus=x;
+}
+
+void easteregg()
+{
+ word fv,ff;
+
+ background(15);
+ for( fv=4; fv <= 100; fv ++)
+ for( ff=0; ff <= 70; ff ++)
+ { sound(fv*100+ff*10); delay(1); }
+ nosound; setcolor(10);
+ settextstyle(0,0,3); settextjustify(1,1); outtextxy(320,100,"GIED");
+ settextstyle(0,0,1); settextjustify(0,2);
+ background(0);
+}
+
+void say(integer x,integer y, string z) /* Fancy FAST screenwriting */
+{
+ const integer locol = 2;
+ byte xx,yy,ox,bit,lz,t; integer yp; boolean offset;
+ matrix<1,12,1,80,byte> itw;
+
+ offset=x % 8==4; x=x / 8; lz=length(z); ox=0;
+ log_scrollline();
+
+ for( xx=1; xx <= lz; xx ++)
+ {
+ switch (z[xx]) {
+ case '\22': { cfont=roman; log_roman(); } break;
+ case '\6': { cfont=italic; log_italic(); } break;
+ default: {
+ ox += 1;
+ for( yy=1; yy <= 12; yy ++) itw[yy][ox]=~ ch[cfont][z[xx]][yy+1];
+ log_scrollchar(z[xx]);
+ }
+ }
+ }
+
+ lz=ox;
+ if (offset)
+ { /* offsetting routine */
+ lz += 1;
+ for( yy=1; yy <= 12; yy ++)
+ {
+ bit=240; itw[yy][lz]=255;
+ for( xx=1; xx <= lz; xx ++)
+ {
+ t=itw[yy][xx];
+ itw[yy][xx]=bit+t / 16;
+ bit=t << 4;
+ }
+ }
+ }
+ yp=x+y*80+(1-cp)*pagetop;
+ for( yy=1; yy <= 12; yy ++)
+ {
+ yp += 80;
+ for( bit=0; bit <= locol; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ move(itw[yy],mem[0xa000*yp],lz);
+ }
+ }
+}
+
+/* Here are the procedures that Scroll calls */ /* So they must be... */ /*$F+*/
+
+void normscroll()
+{
+ const array<1,8,char> egg = string("\20\f\25\7\b")+"***";
+ const array<1,8,char> e = "(c) 1994";
+ char r;
+ boolean oktoexit;
+
+ state(3); seescroll=true;
+ off_virtual();
+ on(); newpointer(4);
+ mousepage(1-cp);
+
+ if (demo) get_demorec();
+
+ do {
+ do {
+ check(); /* was "checkclick;" */
+
+ #ifdef RECORD slowdown(); basher::count += 1; #endif
+
+ if (demo)
+ {
+ if (demo_ready()) flush();
+ if (keypressede()) exit(0);
+ } else
+ if (keypressede()) flush();
+ } while (!((mrelease>0) || (buttona1()) || (buttonb1())));
+
+
+ if (mrelease==0)
+ {
+ inkey();
+ if (aboutscroll)
+ {
+ move(e[2-1],e[1-1],7);
+ e[8-1]=inchar;
+ if (egg==e) easteregg();
+ }
+ oktoexit=set::of('\15','\33','+','#', eos).has(inchar);
+ if (! oktoexit) errorled();
+ }
+
+ } while (!((oktoexit) || (mrelease>0)));
+ #ifdef RECORD record_one(); #endif
+ screturn=r=='#'; /* "back door" */
+ state(0); seescroll=false; mousepage(cp); off();
+}
+
+void dialogue()
+{
+ char r;
+
+ state(3); seescroll=true; r='\0';
+ newpointer(6); on();
+ mousepage(1-cp);
+ do {
+ do {
+ check();
+ if (mrelease>0)
+ {
+ if ((mx>=(cardinal)dix-65) && (my>=(cardinal)diy-24) && (mx<=(cardinal)dix- 5) && (my<=(cardinal)diy-10))
+ r='Y';
+ if ((mx>=(cardinal)dix+ 5) && (my>=(cardinal)diy-24) && (mx<=(cardinal)dix+65) && (my<=(cardinal)diy-10))
+ r='N';
+ } else
+ if (keypressede())
+ {
+ inkey();
+ r=upcase(inchar);
+ }
+ } while (!(r!='\0'));
+ } while (!(set::of('Y','N','O','J', eos).has(r))); /* Yes, Ja, Oui, or No, Non, Nein */
+ screturn=r!='N';
+ state(0); seescroll=false; mousepage(cp); off();
+}
+
+void music_scroll();
+
+
+static void store_(byte what, tunetype& played)
+{
+ move(played[2],played[1],sizeof(played)-1);
+ played[31]=what;
+}
+
+
+
+static boolean they_match(tunetype& played)
+{
+ byte fv,mistakes;
+
+ boolean they_match_result;
+ mistakes=0;
+
+ for( fv=1; fv <= sizeof(played); fv ++)
+ if (played[fv]!=tune[fv])
+ {
+ mistakes += 1;
+ }
+
+ they_match_result=mistakes<5;
+ return they_match_result;
+}
+
+void music_scroll()
+{
+ char r;
+ byte value;
+
+ byte last_one,this_one;
+
+ tunetype played;
+
+
+ state(3); seescroll=true; on();
+ newpointer(4);
+ do {
+ do {
+ check(); /* was "checkclick;" */
+ if (keypressede()) flush();
+ } while (!((mpress>0) || (buttona1()) || (buttonb1())));
+
+ if (mpress==0)
+ {
+ inkey();
+ r=upcase(inchar); if (r=='Z') r='Y'; /* Euro keyboards */
+
+ value=pos(r,keys);
+
+ if (value>0)
+ {
+
+ last_one=this_one;
+ this_one=value;
+
+ sound(notes[this_one]);
+ delay(100);
+ nosound;
+
+ if (! dna.ringing_bells)
+ { /* These handle playing the right tune. */
+
+ if (this_one<last_one)
+ store_(lower, played); else
+
+ if (this_one==last_one)
+ store_(same, played); else
+
+ store_(higher, played);
+
+ if (they_match(played))
+ {
+ screturn=true;
+ off();
+ state(0); seescroll=false;
+
+ set_up_timer(8,procjacques_wakes_up,reason_jacques_waking_up);
+ return;
+ }
+
+ }
+
+ }
+
+ }
+
+ } while (!((set::of('\15','\33','+','#', eos).has(r)) || (mpress>0)));
+ screturn=false;
+ off();
+ state(0); seescroll=false;
+}
+
+/* ThatsAll, so put us back to */ /*$F-*/
+
+void resetscrolldriver() /* phew */
+{
+ scrollbells=0; cfont=roman; log_epsonroman(); use_icon=0;
+ interrogation=0; /* always reset after a scroll comes up. */
+}
+
+void dingdongbell() /* Pussy's in the well. Who put her in? Little... */
+{
+ byte fv;
+
+ for( fv=1; fv <= scrollbells; fv ++) errorled(); /* ring the bell "x" times */
+}
+
+void dodgem() /* This moves the mouse pointer off the scroll so that
+ you can read it. */
+{
+ xycheck(); /* Mx & my now contain xy pos of mouse */
+ dodgex=mx; dodgey=my; /* Store 'em */
+ hopto(dodgex,underscroll); /* Move the pointer off the scroll. */
+}
+
+void undodgem() /* This is the opposite of Dodgem. It moves the
+ mouse pointer back, IF you haven't moved it in the meantime. */
+{
+ xycheck();
+ if ((mx==(cardinal)dodgex) && (my==(cardinal)underscroll))
+ /* No change, so restore the pointer's original position. */
+ hopto(dodgex,dodgey);
+}
+
+void geticon(integer x,integer y, byte which)
+{
+ untyped_file f;
+ pointer p;
+
+ assign(f,"icons.avd");
+ reset(f,1);
+ which -= 1;
+ seek(f,which*426);
+ getmem(p,426);
+ blockread(f,p,426);
+ putimage(x,y,p,0);
+ freemem(p,426);
+ close(f);
+}
+
+void block_drop(string fn, integer xl,integer yl,integer y)
+{
+ untyped_file f; byte bit;
+ integer fv; word st;
+
+ st=(y-1)*80+(40-xl / 2)+((1-cp)*pagetop);
+
+ assign(f,fn+".avd");
+ reset(f,1);
+
+ for( fv=1; fv <= yl; fv ++)
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,mem[0xa000*st+(fv*80)],xl);
+ }
+
+ close(f);
+ bit=getpixel(0,0);
+}
+
+void drawscroll(proc gotoit) /* This is one of the oldest procs in the game. */
+{
+ byte b,groi; integer lx,ly,mx,my,ex,ey; boolean centre;
+ byte icon_indent;
+
+ off_virtual();
+ setvisualpage(cp); setactivepage(1-cp);
+ oncandopageswap=false; /* On can now no longer swap pages. So we can
+ do what we want without its interference! */
+ log_epsonroman(); /* Scrolls always START with Roman. */
+ lx=0; ly=scrolln*6;
+ for( b=1; b <= scrolln; b ++)
+ {
+ ex=length(scroll[b])*8; if (lx<ex) lx=ex;
+ }
+ mx=320; my=100; /* Getmaxx & getmaxy div 2, both. */
+ lx=lx / 2; ly -= 2;
+
+ if (set::of(range(1,34), eos).has(use_icon)) lx += halficonwidth;
+
+ off();
+/* mblit(mx-lx-46,my-ly-6,mx+lx+15,my+ly+6,0,3);*/
+ setfillstyle(1,7);
+ setcolor(7);
+ pieslice(mx+lx,my-ly,360,90,15);
+ pieslice(mx+lx,my+ly,270,360,15);
+ setcolor(4);
+ arc(mx+lx,my-ly,360,90,15);
+ arc(mx+lx,my+ly,270,360,15);
+ bar(mx-lx-30,my+ly+6,mx+lx,my+ly);
+ bar(mx-lx-30,my-ly-6,mx+lx,my-ly);
+ bar(mx-lx-15,my-ly,mx+lx+15,my+ly);
+ setfillstyle(1,8);
+ pieslice(mx-lx-31,my-ly,360,180,15);
+ pieslice(mx-lx-31,my+ly,180,360,15);
+ setfillstyle(1,4);
+ bar(mx-lx-30,my-ly-6,mx+lx,my-ly-6);
+ bar(mx-lx-30,my+ly+6,mx+lx,my+ly+6);
+ bar(mx-lx-15,my-ly,mx-lx-15,my+ly);
+ bar(mx+lx+15,my-ly,mx+lx+15,my+ly);
+ ex=mx-lx; ey=my-ly;
+ mx -= lx; my -= ly+2;
+ setcolor(0); centre=false;
+
+ switch (use_icon) {
+ case 0: icon_indent=0; break; /* No icon. */
+ case 1 ... 33: { /* Standard icon */
+ geticon(mx,my+ly / 2,use_icon);
+ icon_indent=53;
+ }
+ break;
+ case 34: { block_drop("about",28,76,15); icon_indent=0; } break;
+ case 35: { block_drop("gameover",52,59,71); icon_indent=0; } break;
+ }
+
+ for( b=1; b <= scrolln; b ++)
+ {
+ switch (scroll[b][length(scroll[b])]) {
+ case '\3' : { centre=true; scroll[b][0] -= 1; } break;
+ case '\14' : { centre=false; scroll[b][0] -= 1; } break;
+ case '\21' : { settextjustify(1,1);
+ dix=mx+lx; diy=my+ly; scroll[b][1]='\40'; groi=getpixel(0,0);
+/* inc(diy,14);*/
+ shbox(dix-65,diy-24,dix- 5,diy-10,"Yes.");
+ shbox(dix+ 5,diy-24,dix+65,diy-10,"No.");
+ }
+ break;
+ }
+
+ if (centre)
+ say(320-length(scroll[b])*4+icon_indent,my,scroll[b]);
+ else
+ say(mx+icon_indent,my,scroll[b]);
+ log_scrollendline(centre);
+ my += 12;
+ }
+
+ underscroll=my+3;
+ setvisualpage(1-cp); dingdongbell();
+ my=getpixel(0,0); dropsok=false; dodgem();
+
+ gotoit();
+
+ undodgem(); dropsok=true;
+ log_divider();
+ setvisualpage(cp); mousepage(cp); off();
+/* mblit(ex-46,ey-6,ex+lx*2+15,ey+ly*2+6,3,0);*/
+ mblit((ex-46) / 8,ey-6,1+(ex+lx*2+15) / 8,ey+ly*2+6,cp,1-cp);
+ blitfix();
+ oncandopageswap=true; /* Normality again */
+ on(); settextjustify(0,0); /*sink*/
+ resetscrolldriver();
+ if (mpress>0) after_the_scroll=true;
+}
+
+void bubble(proc gotoit)
+{
+ integer xl,yl,my,xw,yw; byte fv; array<1,3,pointtype> p;
+ pointer rp1,rp2; /* replace: 1=bubble, 2=pointer */
+ integer xc; /* x correction */
+
+ setvisualpage(cp); setactivepage(1-cp);
+ oncandopageswap=false; /* On can now no longer swap pages. So we can
+ do what we want without its interference! */
+ mousepage(1-cp); /* Mousepage */
+
+ setfillstyle(1,talkb); setcolor(talkb); off();
+
+ xl=0; yl=scrolln*5;
+ for( fv=1; fv <= scrolln; fv ++)
+ if (textwidth(scroll[fv])>xl) xl=textwidth(scroll[fv]);
+ xl=xl / 2;
+
+ xw=xl+18; yw=yl+7;
+ my=yw*2-2; xc=0;
+
+ if ((talkx-xw)<0) xc=-(talkx-xw);
+ if ((talkx+xw)>639) xc=639-(talkx+xw);
+
+ p[1].x=talkx-10; p[1].y=yw;
+ p[2].x=talkx+10; p[2].y=yw;
+ p[3].x=talkx; p[3].y=talky;
+
+/* mblit(talkx-xw+xc,7,talkx+xw+xc,my,0,3);
+ mblit(talkx-10,my,talkx+10,talky,0,3);*/
+ bar(xc+talkx-xw+10,7,talkx+xw-10+xc,my);
+ bar(xc+talkx-xw,12,talkx+xw+xc,my-5);
+ pieslice(xc+talkx+xw-10,12,360,90,9); /* TR */
+ pieslice(xc+talkx+xw-10,my-5,270,360,9); /* BR */
+ pieslice(xc+talkx-xw+10,12,90,180,9); /* TL */
+ pieslice(xc+talkx-xw+10,my-5,180,270,9); /* BL */
+ fillpoly(3,p.body());
+
+ setcolor(talkf); yl -= 3; settextjustify(1,2);
+ for( fv=0; fv <= scrolln-1; fv ++)
+ outtextxy(talkx+xc,(fv*10)+12,scroll[fv+1]);
+ for( fv=1; fv <= scrolln; fv ++) /* These should be separate loops. */
+ log_bubbleline(fv,param,scroll[fv]);
+ log_divider();
+
+ setvisualpage(1-cp);
+ dingdongbell();
+ oncandopageswap=false;
+ on(); dropsok=false; gotoit(); off(); dropsok=true;
+ mblit((talkx-xw+xc) / 8,7,1+(talkx+xw+xc) / 8,my,3,1-cp);
+ mblit((talkx-10) / 8,my,1+(talkx+10) / 8,talky,3,1-cp);
+ blitfix();
+
+ setvisualpage(cp);
+ settextjustify(0,0); on(); /*sink;*/
+ oncandopageswap=true;
+ resetscrolldriver();
+ if (mpress>0) after_the_scroll=true;
+}
+
+boolean ask(string question)
+{
+ boolean ask_result;
+ display(question+'\15'+'\21');
+ if (screturn && (Random(2)==0)) /* half-and-half chance */
+ {
+ display("...Positive about that?\23I\26\r\21"); /* be annoying! */
+ if (screturn && (Random(4)==3)) /* another 25% chance */
+ display("\n100% certain\??!\n\26\r\21"); /* be very annoying! */
+ }
+ ask_result=screturn;
+ return ask_result;
+}
+
+void resetscroll()
+{
+ scrolln=1; fillchar(scroll,sizeof(scroll),'\0');
+}
+
+void natural() /* Natural state of bubbles */
+{
+ talkx=320; talky=200; talkb=8; talkf=15;
+}
+
+string lsd()
+{
+ string x;
+
+ string lsd_result;
+ if (dna.pence<12)
+ { /* just pence */
+ x=strf(dna.pence)+'d';
+ } else
+ if (dna.pence<240)
+ { /* shillings & pence */
+ x=strf(dna.pence / longint(12))+'/';
+ if ((dna.pence % longint(12))==0) x=x+'-'; else x=x+strf(dna.pence % longint(12));
+ } else /* L, s & d */
+ x=string('œ')+strf(dna.pence / longint(240))+'.'+strf((dna.pence / longint(12)) % longint(20))+'.'+
+ strf(dna.pence % longint(12));
+ if (dna.pence>12) x=x+" (that's "+strf(dna.pence)+"d)";
+ lsd_result=x;
+ return lsd_result;
+}
+
+void calldrivers();
+ /* Was the mouse cursor virtual on entry to this proc? */
+
+static void strip(string& q)
+{
+ while (pos("\40",q[length(q)])>0) q[0] -= 1; /* strip trailing spaces */
+}
+
+
+
+static void solidify(byte n)
+{
+ if (pos("\40",scroll[n])==0) return; /* no spaces */
+ /* so there MUST be a space there, somewhere... */
+ do {
+ scroll[n+1]=string(scroll[n][length(scroll[n])])+scroll[n+1];
+ scroll[n][0] -= 1;
+ } while (!(scroll[n][length(scroll[n])]=='\40'));
+ strip(scroll[n]);
+}
+
+void calldrivers()
+{
+ word fv; byte nn; char nnn; boolean mouthnext;
+ boolean call_spriterun; /* Only call sprite_run the FIRST time. */
+
+ boolean was_virtual;
+
+
+ nosound; state(0); screturn=false; mouthnext=false;
+ call_spriterun=true;
+
+ switch (buffer[bufsize]) {
+ case '\4': bufsize -= 1; break; /* ^D = (D)on't include pagebreak */
+ case '\2':case '\21':; break; /* ^B = speech (B)ubble, ^Q = (Q)uestion in dialogue box */
+ default: {
+ bufsize += 1; buffer[bufsize]='\20';
+ }
+ }
+ for( fv=1; fv <= bufsize; fv ++)
+ if (mouthnext)
+ {
+ if (buffer[fv]=='\23') param=0; else
+ switch (buffer[fv]) {
+ case RANGE_10('0','9'): param=ord(buffer[fv])-48;
+ break;
+ case RANGE_26('A','Z'): param=ord(buffer[fv])-55;
+ break;
+ }
+ mouthnext=false;
+ } else
+ switch (buffer[fv]) {
+ case '\20': {
+ if ((scrolln==1) && (scroll[1]=="")) flush();
+
+ if (call_spriterun) sprite_run();
+ call_spriterun=false;
+
+ was_virtual=visible==m_virtual;
+ if (was_virtual) off_virtual();
+ drawscroll(normscroll);
+ if (was_virtual) on_virtual();
+ resetscroll();
+ if (screturn) return;
+ }
+ break;
+ case '\7': scrollbells += 1; break; /* #7 = "Bel" */
+ case '\2': {
+ if ((scrolln==1) && (scroll[1]=="")) flush();
+
+ if (call_spriterun) sprite_run();
+ call_spriterun=false;
+ switch (param) {
+ case 0: natural(); break; /* Not attached: generic bubble with no speaker. */
+ case RANGE_9(1,9): if ((param>numtr) || (! tr[param].quick))
+ { /* not valid */
+ errorled();
+ natural();
+ }
+ else tr[param].chatter();
+ break; /* Normal sprite talking routine. */
+ case 10 ... 36: {
+ quasiped_type& with = quasipeds[param];
+ /* Quasi-peds. (This routine performs the same
+ thing with QPs as triptype.chatter does with the
+ sprites.) */
+ {
+ pedtype& with1 = peds[with.whichped];
+
+ talkx=with1.x; talky=with1.y; /* Position. */
+ }
+ talkf=with.fgc; talkb=with.bgc; /* Colours. */
+ }
+ break;
+ default: { errorled(); natural(); } /* not valid */
+ }
+
+ was_virtual=visible==m_virtual;
+ if (was_virtual) off_virtual();
+ bubble(normscroll);
+ if (was_virtual) on_virtual();
+ resetscroll();
+ if (screturn) return;
+ }
+ break;
+ case '\25': {
+ { dnatype& with = dna;
+ switch (param) {
+ case 1: display(lsd()+'\4'); break; /* insert cash balance (recursion) */
+ case 2: display(words[first_password+with.pass_num].w+'\4'); break;
+ case 3: display(with.like2drink+'\4'); break;
+ case 4: display(with.favourite_song+'\4'); break;
+ case 5: display(with.worst_place_on_earth+'\4'); break;
+ case 6: display(with.spare_evening+'\4'); break;
+ /* ... */
+ case 9: display(strf(with.cat_x)+','+strf(with.cat_y)+'\4'); break;
+ case 10: switch (with.box_contents) {
+ case '\0': { /* Sixpence. */
+ dixi('q',37); /* You find the sixpence. */
+ with.pence += 6;
+ with.box_contents=nowt;
+ points(2); return;
+ }
+ break;
+ case nowt: display("nothing at all. It's completely empty."); break;
+ default: display(get_better(with.box_contents)+'.');
+ }
+ break;
+ case 11: {
+ nn=1;
+ for( nnn='\1'; nnn <= numobjs; nnn ++)
+ if (with.obj[nnn])
+ {
+ nn += 1;
+ display(get_better(nnn)+", "+'\4');
+ }
+ }
+ break;
+ }}
+ }
+ break;
+ case '\26': use_icon=param; break;
+ case '\15': scrolln += 1; break;
+ case '\21': {
+ if (call_spriterun) sprite_run();
+ call_spriterun=false;
+
+ scrolln += 1; scroll[scrolln]='\21';
+ was_virtual=visible==m_virtual;
+ if (was_virtual) off_virtual();
+ drawscroll(dialogue);
+ if (was_virtual) on_virtual();
+ resetscroll();
+ }
+ break;
+ case '\23' : mouthnext=true; break;
+ case '\11' : for( nn=1; nn <= 9; nn ++) scroll[scrolln]=scroll[scrolln]+' ';
+ break;
+ default:
+ { /* add new char */
+ if (length(scroll[scrolln])==50)
+ {
+ solidify(scrolln);
+ scrolln += 1;
+ }
+ scroll[scrolln]=scroll[scrolln]+buffer[fv];
+ }
+ }
+}
+
+void display(string z)
+{
+ bufsize=length(z);
+ move(z[1],buffer,bufsize);
+ calldrivers();
+}
+
+void loadfont()
+{
+ file<raw> f;
+
+ assign(f,"avalot.fnt"); reset(f); f >> ch[0]; close(f);
+ assign(f,"avitalic.fnt"); reset(f); f >> ch[1]; close(f);
+ assign(f,"ttsmall.fnt"); reset(f); f >> little; close(f);
+}
+
+void okay()
+{
+ display("Okay!");
+}
+
+void musical_scroll()
+{
+ boolean was_virtual;
+
+ display(string("To play the harp...\r\rUse these keys:\r\n")+
+ "Q W E R T Y U I O P [ ]\r\rOr press Enter to stop playing.\4");
+
+ sprite_run();
+
+ was_virtual=visible==m_virtual;
+ if (was_virtual) off_virtual();
+ drawscroll(music_scroll);
+ if (was_virtual) on_virtual();
+ resetscroll();
+}
+
+class unit_scrolls_initialize {
+ public: unit_scrolls_initialize();
+};
+static unit_scrolls_initialize scrolls_constructor;
+
+unit_scrolls_initialize::unit_scrolls_initialize() {
+ loadfont();
+ resetscrolldriver();
+}
diff --git a/engines/avalanche/scrolls.h b/engines/avalanche/scrolls.h
new file mode 100644
index 0000000000..d71ec5d5e2
--- /dev/null
+++ b/engines/avalanche/scrolls.h
@@ -0,0 +1,33 @@
+#ifndef __scrolls_h__
+#define __scrolls_h__
+
+
+#include "gyro.h"
+#include "joystick.h"
+
+
+const boolean aboutscroll = false; /* Is this the about box? */
+
+void state(byte x); /* Sets "Ready" light to whatever */
+
+void drawscroll(proc gotoit); /* This is one of the oldest procs in the game. */
+
+void bubble(proc gotoit);
+
+void resetscroll();
+
+void calldrivers();
+
+void display(string z);
+
+boolean ask(string question);
+
+void natural();
+
+string lsd();
+
+void okay(); /* Says "Okay!" */
+
+void musical_scroll();
+
+#endif
diff --git a/engines/avalanche/sequence.cpp b/engines/avalanche/sequence.cpp
new file mode 100644
index 0000000000..00c838a95a
--- /dev/null
+++ b/engines/avalanche/sequence.cpp
@@ -0,0 +1,92 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ SEQUENCE The sequencer. */
+
+#define __sequence_implementation__
+
+
+#include "sequence.h"
+
+
+/*#include "Gyro.h"*/
+/*#include "Timeout.h"*/
+/*#include "Celer.h"*/
+/*#include "Trip5.h"*/
+
+
+void then_show(byte what)
+{
+ byte fv;
+;
+ for( fv=1; fv <= seq_length; fv ++)
+ if (seq[fv]==0)
+ {;
+ seq[fv]=what;
+ return;
+ }
+}
+
+void first_show(byte what)
+{;
+ /* First, we need to blank out the entire array. */
+ fillchar(seq,sizeof(seq),'\0');
+
+ /* Then it's just the same as then_show. */
+ then_show(what);
+
+}
+
+void then_flip(byte where,byte ped)
+{;
+ then_show(now_flip);
+
+ dna.flip_to_where=where;
+ dna.flip_to_ped=ped;
+}
+
+void start_to_close()
+{;
+ lose_timer(reason_sequencer);
+ set_up_timer(7,procsequence,reason_sequencer);
+}
+
+void start_to_open()
+{;
+ dna.user_moves_avvy=false; /* They can't move. */
+ stopwalking; /* And they're not moving now. */
+ start_to_close(); /* Apart from that, it's the same thing. */
+}
+
+void call_sequencer();
+
+ /* This proc is called by Timeout when it's time to do another frame. */
+static void shove_left()
+{;
+ move(seq[2],seq[1],seq_length-1); /* Shift everything to the left. */
+}
+
+void call_sequencer()
+{;
+ switch (seq[1]) {
+ case 0: return; break; /* No more routines. */
+ case 1 ... 176: {; /* Show a frame. */
+ show_one(seq[1]);
+ shove_left();
+ }
+ break;
+ case 177: {;
+ user_moves_avvy=true;
+ fliproom(flip_to_where,flip_to_ped); /* 177 = Flip room. */
+ if (seq[1]==177) shove_left();
+ }
+ break;
+ }
+
+ start_to_close(); /* Make sure this proc gets called again. */
+}
+
diff --git a/engines/avalanche/sequence.h b/engines/avalanche/sequence.h
new file mode 100644
index 0000000000..a6c59a6126
--- /dev/null
+++ b/engines/avalanche/sequence.h
@@ -0,0 +1,32 @@
+#ifndef __sequence_h__
+#define __sequence_h__
+
+
+const integer now_flip = 177;
+
+const integer seq_length = 10;
+
+
+#ifdef __sequence_implementation__
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN array<1,seq_length,byte> seq;
+#undef EXTERN
+#define EXTERN extern
+
+
+void first_show(byte what);
+
+void then_show(byte what);
+
+void then_flip(byte where,byte ped);
+
+void start_to_close();
+
+void start_to_open();
+
+void call_sequencer();
+
+#endif
diff --git a/engines/avalanche/setup.cpp b/engines/avalanche/setup.cpp
new file mode 100644
index 0000000000..60f91e38f1
--- /dev/null
+++ b/engines/avalanche/setup.cpp
@@ -0,0 +1,1268 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+/*#include "Tommys.h"*/
+#include "joystick.h"
+
+
+const integer selected = 0x60; /* Background for selected lines of text. */
+
+typedef array<1,400,varying_string<80> > mobytype;
+
+typedef set byteset; /* Define its typemark. */
+
+enum option {_overrideegacheck, _zoomystart, _loadfirst, _numlockhold, _usemouse,
+ _controller, _logging, _logfile,
+
+ _joystickinstalled, _joytop, _joybottom, _joyleft, _joyright, _joymidx,
+ _joymidy, _joycentringfactor, _whichjoy, _quiet, _soundcard,
+ _baseaddress, _irq, _dma,
+ _samplerate, _keyboardclick,
+
+ _printer,
+
+ option_error, last_option};
+
+
+mobytype* moby;
+word mobylength;
+byte background; /* The current background colour, times 16. */
+byte line; /* Which line you're on in the menus. */
+
+string registrant,reginum;
+
+byte num_printers;
+array<1,10,string> printers;
+string this_printer;
+
+/* THE STATUS VARIABLES: */
+
+ /* general */
+
+boolean override_ega;
+boolean skip_loading_screens;
+string load_particular;
+boolean force_numlock;
+boolean ignore_mouse;
+boolean use_keyboard;
+boolean log_to_printer;
+boolean log_to_file;
+string log_filename;
+string autotype;
+
+ /* joystick */
+
+boolean has_a_joystick;
+word jtop,jbottom,jleft,jright,jmidx,jmidy;
+byte jcentre;
+word whichjoy;
+
+ /* sound */
+
+boolean suppress_sfx;
+byte your_card;
+longint samplerate;
+longint sound_addr,sound_irq,sound_dma;
+boolean wants_keyclick;
+
+ /* registration */
+
+string regname,regnum,chkname,chknum;
+
+
+string trim_and_caps(string this_)
+{
+ byte fv;
+
+ string trim_and_caps_result;
+ while ((this_[1]==' ') && (this_!=""))
+ Delete(this_,1,1); /* Strip leading blanks. */
+ while ((this_[length(this_)]==' ') && (this_!=""))
+ this_[0] -= 1; /* Strip trailing blanks. */
+ for( fv=1; fv <= length(this_); fv ++) this_[fv]=upcase(this_[fv]);/* And capitalise. */
+ trim_and_caps_result=this_;
+ return trim_and_caps_result;
+}
+
+option string_2_option(string field)
+{
+
+ option string_2_option_result;
+ field=trim_and_caps(field);
+
+ if (field=="OVERRIDEEGACHECK") string_2_option_result=_overrideegacheck; else
+ if (field=="ZOOMYSTART") string_2_option_result=_zoomystart; else
+ if (field=="LOADFIRST") string_2_option_result=_loadfirst; else
+ if (field=="NUMLOCKHOLD") string_2_option_result=_numlockhold; else
+ if (field=="USEMOUSE") string_2_option_result=_usemouse; else
+ if (field=="CONTROLLER") string_2_option_result=_controller; else
+ if (field=="LOGGING") string_2_option_result=_logging; else
+ if (field=="LOGFILE") string_2_option_result=_logfile; else
+
+ /* joystick */
+
+ if (field=="JOYSTICKINSTALLED") string_2_option_result=_joystickinstalled; else
+ if (field=="JOYTOP") string_2_option_result=_joytop; else
+ if (field=="JOYBOTTOM") string_2_option_result=_joybottom; else
+ if (field=="JOYLEFT") string_2_option_result=_joyleft; else
+ if (field=="JOYRIGHT") string_2_option_result=_joyright; else
+ if (field=="JOYMIDX") string_2_option_result=_joymidx; else
+ if (field=="JOYMIDY") string_2_option_result=_joymidy; else
+ if (field=="JOYCENTRINGFACTOR") string_2_option_result=_joycentringfactor; else
+ if (field=="WHICHJOY") string_2_option_result=_whichjoy; else
+
+ /* sound */
+
+ if (field=="QUIET") string_2_option_result=_quiet; else
+ if (field=="SOUNDCARD") string_2_option_result=_soundcard; else
+ if (field=="SAMPLERATE") string_2_option_result=_samplerate; else
+ if (field=="KEYBOARDCLICK") string_2_option_result=_keyboardclick; else
+ if (field=="BASEADDRESS") string_2_option_result=_baseaddress; else
+ if (field=="IRQ") string_2_option_result=_irq; else
+ if (field=="DMA") string_2_option_result=_dma; else
+
+ /* printer */
+
+ if (field=="PRINTER") string_2_option_result=_printer; else
+
+
+ string_2_option_result=option_error;
+
+ return string_2_option_result;
+}
+
+void clear_to(byte colour)
+{
+ window(1,1,80,24); background=colour*16; textattr=background; clrscr;
+}
+
+void centre(byte where,byte colour, string what)
+{
+ textattr=background+colour;
+ gotoxy(40-length(what) / 2,where);
+ output << what;
+}
+
+void load_file()
+{
+ text t;
+
+ mobylength=0;
+ /*$I-*/
+ assign(t,"avalot.ini");
+ reset(t);
+ /*$I+*/
+
+ if (ioresult!=0) /* No file. */
+ {
+ output << "SETUP: Avalot.ini not found!" << NL;
+ exit(255);
+ }
+
+ while (! eof(t))
+ {
+ mobylength += 1; /* Preincrement mode. */
+ t >> (*moby)[mobylength] >> NL;
+ }
+
+ close(t);
+
+}
+
+string strhf(longint x) /* assume x is +ve */
+{
+ const array<0,16,char> hexdigits = "0123456789ABCDEF";
+ string y; longint v;
+
+ string strhf_result;
+ v=x; y="";
+
+ while (v!=0)
+ {
+ y=string(hexdigits[v % longint(16)-1])+y;
+ v=v / longint(16);
+ }
+
+ strhf_result=string('$')+y;
+ return strhf_result;
+}
+
+void update_moby();
+
+static byte fv;
+
+static string field;
+
+
+static void get_field(string x)
+{
+ if (pos(";",x)!=0) x=copy(x,1,pos(";",x)-1);
+
+ if (pos("=",x)==0)
+ field="";
+ else
+ {
+ field=copy(x,0,pos("=",x)-1);
+ while (field[1]==' ') field=copy(field,2,255);
+ }
+}
+
+
+
+static string yn1(boolean x)
+ { string yn1_result;
+ if (x) yn1_result="Yes"; else yn1_result="No"; return yn1_result;
+ }
+
+
+
+static string kj(boolean x)
+ { string kj_result;
+ if (x) kj_result="Keyboard"; else kj_result="Joystick"; return kj_result;
+ }
+
+
+
+static string put_logcodes()
+{
+ byte q;
+
+ string put_logcodes_result;
+ q=(byte)(log_to_file)+(byte)(log_to_printer)*2;
+
+ switch (q) {
+ case 0: put_logcodes_result="No"; break;
+ case 1: put_logcodes_result="Disk"; break;
+ case 2: put_logcodes_result="Printer"; break;
+ }
+ return put_logcodes_result;
+}
+
+
+
+static string card()
+{
+ string card_result;
+ switch (your_card) {
+ case 0: card_result="None"; break;
+ case 1: card_result="SB"; break;
+ case 2: card_result="SBPro"; break;
+ case 3: card_result="SB16"; break;
+ case 4: card_result="Pas"; break;
+ case 5: card_result="PasPlus"; break;
+ case 6: card_result="Pas16"; break;
+ case 7: card_result="Aria"; break;
+ case 8: card_result="WinSound"; break;
+ case 9: card_result="Gravis"; break;
+ case 10: card_result="DacLPT"; break;
+ case 11: card_result="StereoDacs"; break;
+ case 12: card_result="StereoOn1"; break;
+ case 13: card_result="Speaker"; break;
+ }
+ return card_result;
+}
+
+
+
+
+static void entail(string x)
+{
+ string before,after;
+
+ before=copy((*moby)[fv],1,pos("=",(*moby)[fv])-1);
+
+ if (pos(";",(*moby)[fv])==0)
+ {
+ (*moby)[fv]=before+'='+x;
+ } else
+ {
+ after=copy((*moby)[fv],pos(";",(*moby)[fv]),255);
+
+ (*moby)[fv]=before+'='+x+' ';
+ while (length((*moby)[fv])<25) (*moby)[fv]=(*moby)[fv]+' ';
+
+ (*moby)[fv]=(*moby)[fv]+after;
+ }
+}
+
+void update_moby()
+{
+ option o;
+
+
+
+
+
+ for( fv=1; fv <= mobylength; fv ++)
+ {
+ get_field((*moby)[fv]);
+
+ if (field!="")
+ {
+ o=string_2_option(field);
+
+ if (o==_overrideegacheck) entail(yn1(override_ega)); else
+ if (o==_zoomystart) entail(yn1(skip_loading_screens)); else
+ if (o==_loadfirst) entail(load_particular); else
+ if (o==_numlockhold) entail(yn1(force_numlock)); else
+ if (o==_usemouse) entail(yn1(ignore_mouse)); else
+ if (o==_controller) entail(kj(use_keyboard)); else
+ if (o==_logging) entail(put_logcodes()); else
+ if (o==_logfile) entail(log_filename); else
+
+ /* joystick */
+
+ if (o==_joystickinstalled) entail(yn1(has_a_joystick)); else
+ if (o==_joytop) entail(strf(jtop)); else
+ if (o==_joybottom) entail(strf(jbottom)); else
+ if (o==_joyleft) entail(strf(jleft)); else
+ if (o==_joyright) entail(strf(jright)); else
+ if (o==_joymidx) entail(strf(jmidx)); else
+ if (o==_joymidy) entail(strf(jmidy)); else
+ if (o==_joycentringfactor) entail(strf(jcentre)); else
+ if (o==_whichjoy) entail(strf(whichjoy)); else
+
+ /* sound */
+
+ if (o==_quiet) entail(yn1(suppress_sfx)); else
+ if (o==_soundcard) entail(card()); else
+ if (o==_samplerate) entail(strf(samplerate)); else
+ if (o==_baseaddress) entail(strhf(sound_addr)); else
+ if (o==_irq) entail(strf(sound_irq)); else
+ if (o==_dma) entail(strf(sound_dma)); else
+ if (o==_keyboardclick) entail(yn1(wants_keyclick)); else
+
+ /* printer */
+
+ if (o==_printer) entail(this_printer);
+
+ }
+ }
+}
+
+void save_file()
+{
+ text t;
+ word fv;
+
+ textattr=10;
+ update_moby();
+
+ clear_to(black);
+ centre(14,14,"Saving...");
+
+ assign(t,"avalot.ini");
+ rewrite(t);
+
+ for( fv=1; fv <= mobylength; fv ++)
+ {
+ t << (*moby)[fv] << NL;
+ }
+
+ close(t);
+}
+
+boolean detect()
+{
+ word x,y,xo,yo;
+ byte count;
+
+ boolean detect_result;
+ count=0;
+ if (joystickpresent())
+ {
+ detect_result=true;
+ return detect_result;
+ }
+ readjoya(xo,yo);
+ do {
+ if (count<7) count += 1; /* Take advantage of "flutter" */
+ if (count==6)
+ {
+ centre(7,1,"The Bios says you don't have a joystick. However, it's often wrong");
+ centre(8,1,"about such matters. So, do you? If you do, move joystick A to");
+ centre(9,1,"continue. If you don't, press any key to cancel.");
+ }
+ readjoya(x,y);
+ } while (!((keypressed()) | (x!=xo) || (y!=yo)));
+ detect_result=~ keypressed();
+ return detect_result;
+}
+
+void display()
+{
+ gotoxy(28,10); output << jleft << " ";
+ gotoxy(28,11); output << jright;
+ gotoxy(28,12); output << jtop << " ";
+ gotoxy(28,13); output << jbottom;
+}
+
+void readjoy(word& x,word& y)
+{
+ if (whichjoy==1) readjoya(x,y); else readjoyb(x,y);
+}
+
+void getmaxmin()
+{
+ word x,y; char r;
+
+ clear_to(green);
+ centre(5,1,"Rotate the joystick around in a circle, as far from the centre as it");
+ centre(6,1,"can get. Then press any key.");
+ centre(7,1,"Press Esc to cancel this part.");
+ centre(16,1,"(To reset these figures, set \"Do you have a joystick?\" to No, then Yes.)");
+
+ gotoxy(20,10); output << "Left :";
+ gotoxy(20,11); output << "Right :";
+ gotoxy(20,12); output << "Top :";
+ gotoxy(20,13); output << "Bottom:";
+
+
+ if (jleft==0) jleft=maxint;
+ if (jtop==0) jtop=maxint;
+ do {
+ readjoy(x,y);
+ if (x<jleft) jleft=x;
+ if (y<jtop) jtop=y;
+ if (x>jright) jright=x;
+ if (y>jbottom) jbottom=y;
+ display();
+ } while (!keypressed());
+
+ do { r=readkey(); } while (!(~ keypressed()));
+ if (r=='\33') return;
+
+ centre(19,1,"Thank you. Now please centre your joystick and hit a button.");
+ do {; } while (!(buttona1() || buttona2()));
+
+ readjoya(jmidx,jmidy);
+
+ has_a_joystick=true;
+}
+
+void joysetup()
+{
+ clear_to(green);
+ if (! detect()) return;
+ getmaxmin();
+}
+
+byte choose_one_of(byteset which);
+
+static shortint direction;
+
+
+static void move(shortint d)
+{
+ direction=d; line=line+d;
+}
+
+
+
+static void highlight(word where,word how)
+{
+ byte fv;
+
+ where=where*160-159;
+ for( fv=0; fv <= 79; fv ++)
+ mem[0xb800*where+fv*2]=(mem[0xb800*where+fv*2] & 0xf)+how;
+}
+
+byte choose_one_of(byteset which)
+
+{
+ const integer upwards = -1;
+ const integer downwards = 1;
+
+ boolean done;
+ char r;
+
+
+ byte choose_one_of_result;
+ done=false; direction=1;
+ do {
+ while (! (which.has(line)))
+ {
+ line=line+direction;
+ if (line>26) line=1;
+ if (line==0) line=26;
+ }
+
+ highlight(line,selected);
+ r=readkey();
+ highlight(line,background);
+ switch (r) {
+ case '\0': switch (readkey()) {
+ case cup: move(upwards); break;
+ case cdown: move(downwards); break;
+ }
+ break;
+ case creturn: done=true; break;
+ case cescape: {
+ choose_one_of_result=15; /* bottom line is always 15. */
+ return choose_one_of_result;
+ }
+ break;
+ }
+
+ } while (!done);
+
+ choose_one_of_result=line;
+ return choose_one_of_result;
+}
+
+void bottom_bar();
+static void load_regi_info();
+
+
+static char decode1(char c)
+{
+ byte b;
+
+ char decode1_result;
+ b=ord(c)-32;
+ decode1_result=chr(( (b & 0xf) << 3) + ((cardinal)(b & 0x70) >> 4));
+ return decode1_result;
+}
+
+
+
+static char decode2(char c)
+{
+ char decode2_result;
+ decode2_result=chr( ((ord(c) & 0xf) << 2) + 0x43);
+ return decode2_result;
+}
+
+
+
+static boolean checker(string proper,string check)
+{
+ byte fv; boolean ok;
+
+ boolean checker_result;
+ ok=true;
+ for( fv=1; fv <= length(proper); fv ++)
+ if ((ord(proper[fv]) & 0xf)!=((cardinal)(ord(check[fv])-0x43) >> 2))
+ ok=false;
+
+ checker_result=ok;
+ return checker_result;
+}
+
+
+static void load_regi_info()
+{
+ text t;
+ byte fv;
+ string x;
+ byte namelen,numlen;
+ string namechk,numchk;
+
+
+ /*$I-*/
+ assign(t,"register.dat"); reset(t);
+ /*$I+*/
+
+ if (ioresult!=0)
+ {
+ registrant="";
+ return;
+ }
+
+ for( fv=1; fv <= 53; fv ++) t >> NL;
+ t >> x >> NL;
+ close(t);
+
+ namelen=107-ord(x[1]); numlen=107-ord(x[2]);
+
+ registrant=copy(x,3,namelen);
+ reginum=copy(x,4+namelen,numlen);
+ namechk=copy(x,4+namelen+numlen,namelen);
+ numchk=copy(x,4+namelen+numlen+namelen,numlen);
+
+ for( fv=1; fv <= namelen; fv ++) registrant[fv]=decode1(registrant[fv]);
+ for( fv=1; fv <= numlen; fv ++) reginum[fv]=decode1(reginum[fv]);
+
+ if ((! checker(registrant,namechk)) || (! checker(reginum,numchk)))
+ { registrant="\?\"!?"; reginum="(."; }
+}
+
+void bottom_bar()
+{
+ load_regi_info();
+ textattr=96; background=96;
+ window(1,1,80,25);
+ gotoxy(1,25); clreol;
+ if (registrant=="")
+ centre(25,15,"Unregistered copy.");
+ else
+ centre(25,15,string("Registered to ")+registrant+" ("+reginum+").");
+}
+
+void new_menu()
+{
+ line=1; /* now that we've got a new menu. */
+}
+
+string two_answers(string ans_true,string ans_false, boolean which)
+{
+ string two_answers_result;
+ if (which)
+ two_answers_result=string(" (")+ans_true+')';
+ else
+ two_answers_result=string(" (")+ans_false+')';
+ return two_answers_result;
+}
+
+string yes_or_no(boolean which)
+{
+ string yes_or_no_result;
+ yes_or_no_result=two_answers("yes","no",which);
+ return yes_or_no_result;
+}
+
+string give_name(string what)
+{
+ string give_name_result;
+ if (what=="")
+ give_name_result=" (none)";
+ else
+ give_name_result=string(" (\"")+what+"\")";
+ return give_name_result;
+}
+
+string sound_card(byte which)
+{
+ string sound_card_result;
+ switch (which) {
+ case 0: sound_card_result="none"; break;
+ case 1: sound_card_result="SoundBlaster"; break;
+ case 2: sound_card_result="SoundBlaster Pro"; break;
+ case 3: sound_card_result="SoundBlaster 16"; break;
+ case 4: sound_card_result="Pro Audio Spectrum"; break;
+ case 5: sound_card_result="Pro Audio Spectrum+"; break;
+ case 6: sound_card_result="Pro Audio Spectrum 16"; break;
+ case 7: sound_card_result="Aria"; break;
+ case 8: sound_card_result="Windows Sound System or compatible"; break;
+ case 9: sound_card_result="Gravis Ultrasound"; break;
+ case 10: sound_card_result="DAC on LPT1"; break;
+ case 11: sound_card_result="Stereo DACs on LPT1 and LPT2"; break;
+ case 12: sound_card_result="Stereo-on-1 DAC on LPT"; break;
+ case 13: sound_card_result="PC speaker"; break;
+ }
+ return sound_card_result;
+}
+
+void get_str(string& n)
+{
+ string x;
+ char r;
+
+ clear_to(black);
+ centre(3,3,"Enter the new value. Press Enter to accept, or Esc to cancel.");
+ x="";
+
+ do {
+
+ r=readkey();
+
+ switch (r) {
+ case cbackspace: if (x[0]>'\0') x[0] -= 1; break;
+ case creturn: {
+ n=x;
+ return;
+ }
+ break;
+ case cescape: return; break;
+
+ default:
+ if (x[0]<'\106') x=x+r;
+ }
+
+
+ centre(7,2,string(' ')+x+' ');
+
+ } while (!false);
+
+}
+
+void get_num(longint& n)
+{
+ string x;
+ char r;
+ integer e;
+
+ clear_to(black);
+ centre(3,3,"Enter the new value. Press Enter to accept, or Esc to cancel.");
+ centre(4,3,"Precede with $ for a hex value.");
+ x="";
+
+ do {
+
+ r=upcase(readkey());
+
+ switch (r) {
+ case cbackspace: if (x[0]>'\0') x[0] -= 1; break;
+ case creturn: {
+ val(x,n,e);
+ return;
+ }
+ break;
+ case cescape: return; break;
+
+ default:
+ if ((x[0]<'\106') &&
+ ((set::of(range('0','9'), eos).has(r)) || ((x[1]=='$') && (set::of(range('A','F'), eos).has(r))) ||
+ ((x=="") && (r=='$'))))
+ x=x+r;
+ }
+
+
+ centre(7,2,string(' ')+x+' ');
+
+ } while (!false);
+
+}
+
+void general_menu()
+{
+ new_menu();
+ do {
+ clear_to(blue);
+
+ centre( 3,15,"General Menu");
+
+ centre( 5, 7,string("Override EGA check?")+yes_or_no(override_ega));
+ centre( 6, 7,string("Skip loading screens?")+yes_or_no(skip_loading_screens));
+ centre( 7, 7,string("Load a particular file by default?")+give_name(load_particular));
+ centre( 8, 7,string("Force NumLock off?")+yes_or_no(force_numlock));
+/* centre( 9, 7,'Ignore the mouse?'+yes_or_no(ignore_mouse));*/
+ centre(10, 7,string("Default controller?")+two_answers("keyboard","joystick",use_keyboard));
+ centre(12, 7,string("Log to printer?")+yes_or_no(log_to_printer));
+ centre(13, 7,string("Log to file?")+yes_or_no(log_to_file));
+ centre(14, 7,string("Filename to log to?")+give_name(log_filename));
+
+ centre(15,15,"Return to main menu.");
+
+ switch (choose_one_of(set::of(5,6,7,8,/*9,*/10,12,13,14,15, eos))) {
+ case 5: override_ega=! override_ega; break;
+ case 6: skip_loading_screens=! skip_loading_screens; break;
+ case 7: get_str(load_particular); break;
+ case 8: force_numlock=! force_numlock; break;
+/* 9: ignore_mouse:=not ignore_mouse;*/
+ case 10: use_keyboard=! use_keyboard; break;
+ case 12: {
+ log_to_printer=! log_to_printer;
+ if (log_to_file && log_to_printer) log_to_file=false;
+ }
+ break;
+ case 13: {
+ log_to_file=! log_to_file;
+ if (log_to_file && log_to_printer) log_to_printer=false;
+ }
+ break;
+ case 14: get_str(log_filename); break;
+ case 15: { new_menu(); return; } break;
+ }
+
+ } while (!false);
+}
+
+void joystick_menu()
+{
+ new_menu();
+ do {
+ clear_to(green);
+
+ centre(3,15,"Joystick Menu");
+
+ centre(5,14,string("Do you have a joystick?")+yes_or_no(has_a_joystick));
+ centre(6,14,string("Which joystick to use? ")+chr(whichjoy+48));
+ centre(7,14,"Select this one to set it up.");
+
+ centre(15,15,"Return to main menu");
+
+ switch (choose_one_of(set::of(5,6,7,15, eos))) {
+ case 5: {
+ has_a_joystick=! has_a_joystick;
+ if (! has_a_joystick)
+ { jleft=0; jright=0; jtop=0; jbottom=0; }
+ }
+ break;
+ case 6: whichjoy=3-whichjoy; break; /* Flips between 2 and 1. */
+ case 7: joysetup(); break;
+ case 15: { new_menu(); return; } break;
+ }
+
+ } while (!false);
+}
+
+void cycle(byte& what, byte upper_limit)
+{
+ if (what==upper_limit)
+ what=0;
+ else
+ what += 1;
+}
+
+void sound_menu()
+{
+ new_menu();
+ do {
+ clear_to(cyan);
+
+ centre(3, 0,"Sound menu");
+
+ centre(5, 0,string("Do you want to suppress sound effects?")+yes_or_no(suppress_sfx));
+ centre(6, 0,string("Sound output device\? (")+sound_card(your_card)+')');
+ centre(7, 0,string("Sampling rate\? (")+strf(samplerate)+"Hz)");
+ centre(8, 0,string("Base address\? (")+strhf(sound_addr)+" *hex*)");
+ centre(9, 0,string("IRQ\? (")+strf(sound_irq)+')');
+ centre(10,0,string("DMA\? (")+strf(sound_dma)+')');
+ centre(11,0,string("Do you want keyclick?")+yes_or_no(wants_keyclick));
+
+ centre(15,15,"Return to main menu");
+
+ centre(17,1,"WARNING: Incorrect values of IRQ and DMA may damage your computer!");
+ centre(18,1,"Read AVALOT.INI for the correct values.");
+
+ switch (choose_one_of(set::of(5,6,7,8,9,10,11,15, eos))) {
+ case 5: suppress_sfx=! suppress_sfx; break;
+ case 6: cycle(your_card,13); break;
+ case 7: get_num(samplerate); break;
+ case 8: get_num(sound_addr); break;
+ case 9: get_num(sound_irq); break;
+ case 10: get_num(sound_dma); break;
+ case 11: wants_keyclick=! wants_keyclick; break;
+ case 15: { new_menu(); return; } break;
+ }
+
+ } while (!false);
+}
+
+void printer_menu()
+{
+ byte fv;
+ byteset chooseable_lines;
+
+ new_menu();
+
+ chooseable_lines=set::of(15, eos);
+ for( fv=1; fv <= num_printers; fv ++)
+ chooseable_lines=chooseable_lines+set::of(fv+8, eos);
+
+ do {
+ clear_to(red);
+
+ centre(3,15,"Printer menu");
+
+ centre(5,15,"Select one of the following printers:");
+ centre(6,15,string("The current choice is ")+this_printer+'.');
+
+ for( fv=1; fv <= num_printers; fv ++)
+ centre(8+fv,14,printers[fv]);
+
+ centre(15,15,"Return to main menu");
+
+ fv=choose_one_of(chooseable_lines);
+
+ if (fv==15) { new_menu(); return; }
+
+ this_printer=printers[fv-8];
+
+ } while (!false);
+}
+
+void regi_split(string x)
+{
+ byte fv;
+
+ regname[0]=chr(107-ord(x[1])); chkname[0]=regname[0];
+ regnum[0]=chr(107-ord(x[2])); chknum[0]=chknum[0];
+
+ move(x[3],regname[1],ord(regname[0]));
+ for( fv=1; fv <= length(regname); fv ++)
+ regname[fv]=chr(abs(((ord(regname[fv])-33)-177*fv) % 94)+33);
+}
+
+
+void registration_menu()
+{
+ char r;
+ text t,o;
+ string x;
+ byte fv;
+
+ clear_to(black);
+
+ centre(3,15,"REGISTRATION");
+ centre(5,14,"Please insert the disk you were sent when you registered");
+ centre(6,14,"into any drive, and press its letter. For example, if the");
+ centre(7,14,"disk is in drive A:, press A.");
+ centre(9,14,"Press Esc to cancel this menu.");
+
+ do { r=upcase(readkey()); } while (!(set::of('\33',range('A','Z'), eos).has(r))); if (r=='\33') return;
+
+ /*$I-*/
+ assign(t,string(r)+":\\REGISTER.DAT");
+ reset(t);
+ /*$I+*/
+ if (ioresult!=0)
+ {
+ centre(17,15,"But it isn't in that drive...");
+ centre(19,15,"Press any key.");
+ r=readkey();
+ return;
+ }
+ for( fv=1; fv <= 54; fv ++) t >> x >> NL;
+ regi_split(x);
+
+ /* Copy the file... */
+
+ assign(o,"register.dat"); rewrite(o); reset(t);
+
+ while (! eof(t))
+ {
+ t >> x >> NL; o << x << NL;
+ }
+ close(t); close(o);
+
+ centre(17,15,"Done! Press any key...");
+ bottom_bar();
+ r=readkey();
+
+}
+
+void menu()
+{
+ bottom_bar();
+ new_menu();
+ do {
+ clear_to(black);
+
+ centre(3,15,"Avalot Setup - Main Menu");
+
+ centre(5, 9,"General setup");
+ centre(6,10,"Joystick setup");
+ centre(7,11,"Sound setup");
+ centre(8,12,"Printer setup");
+ centre(9,14,"REGISTRATION setup");
+
+ centre(15,15,"--- EXIT SETUP ---");
+
+ switch (choose_one_of(set::of(5,6,7,8,9,15, eos))) {
+ case 5: general_menu(); break;
+ case 6: joystick_menu(); break;
+ case 7: sound_menu(); break;
+ case 8: printer_menu(); break;
+ case 9: registration_menu(); break;
+ case 15: {
+ new_menu();
+ clear_to(lightgray);
+ centre(3,0,"Quit: would you like to save changes?");
+ centre(5,1,"Quit and SAVE changes.");
+ centre(6,1,"Quit and DON'T save changes.");
+ centre(15,0,"Cancel and return to the main menu.");
+ switch (choose_one_of(set::of(5,6,15, eos))) {
+ case 5: {
+ save_file();
+ return;
+ }
+ break;
+ case 6: return; break;
+ }
+ new_menu();
+ }
+ break;
+ }
+
+ } while (!false);
+}
+
+void defaults() /* Sets everything to its default value. */
+{
+ /* general */
+
+ override_ega=false;
+ skip_loading_screens=false;
+ load_particular="";
+ force_numlock=true;
+ ignore_mouse=false;
+ use_keyboard=true;
+ log_to_printer=false;
+ log_to_file=false;
+ log_filename="avalot.log";
+
+ /* joystick */
+
+ has_a_joystick=false;
+ /* jtop,jbottom,jleft,jright,jmidx,jmidy need no initialisation. */
+
+ /* sound */
+
+ suppress_sfx=false;
+ your_card=0; /* none */
+ wants_keyclick=false;
+
+ /* other stuff */
+
+ registrant="";
+
+ num_printers=0; this_printer="??";
+}
+
+void parse_file();
+
+const integer parse_weird_field = 1;
+
+const integer parse_not_yes_or_no = 2;
+
+const integer parse_not_numeric = 3;
+
+const integer parse_not_kbd_or_joy = 4;
+
+const integer parse_weird_logcode = 5;
+
+const integer parse_weird_card = 6;
+
+
+static varying_string<80> this_,thiswas;
+
+static boolean error_found,ignoring;
+
+
+static void error(byte what)
+{
+ textattr=15;
+ if (! error_found)
+ {
+ clrscr; textattr=12;
+ output << "SETUP: *** ERROR FOUND IN AVALOT.INI! ***" << NL; textattr=15;
+ }
+ output << ' ';
+ switch (what) {
+ case parse_weird_field: output << "Unknown identifier on the left"; break;
+ case parse_not_yes_or_no: output << "Value on the right should be Yes or No"; break;
+ case parse_not_numeric: output << "Value on the right is not numeric"; break;
+ case parse_not_kbd_or_joy: output << "Value on the right should be Keyboard or Joystick"; break;
+ case parse_weird_logcode: output << "Value on the right should be No, Printer or Disk"; break;
+ case parse_weird_card: output << "Never heard of the card"; break;
+ }
+ output << " in:" << NL; textattr=10; output << thiswas << NL;
+ error_found=true;
+}
+
+
+
+static boolean yesno(string x)
+{
+ boolean yesno_result;
+ if (x=="YES")
+ yesno_result=true;
+ else if (x=="NO")
+ yesno_result=false;
+ else
+ {
+ error(parse_not_yes_or_no);
+ yesno_result=false;
+ }
+ return yesno_result;
+}
+
+
+
+static boolean kbdjoy(string x)
+{
+ boolean kbdjoy_result;
+ if (x=="KEYBOARD")
+ kbdjoy_result=true;
+ else if (x=="JOYSTICK")
+ kbdjoy_result=false;
+ else
+ {
+ error(parse_not_kbd_or_joy);
+ kbdjoy_result=false;
+ }
+ return kbdjoy_result;
+}
+
+
+
+static word numeric(string x)
+{
+ const varying_string<15> hexdigits = "0123456789ABCDEF";
+ word answer; integer e;
+
+ word numeric_result;
+ if (x[1]=='$')
+ {
+ answer=0;
+ for( e=2; e <= length(x); e ++)
+ {
+ answer=answer << 4;
+ answer += pos(upcase(x[e]),hexdigits)-1;
+ }
+ } else
+ {
+ val(x,answer,e);
+ if (e!=0) error(parse_not_numeric);
+ }
+ numeric_result=answer;
+ return numeric_result;
+}
+
+
+
+static void get_logcodes(string x)
+{
+ if (x=="NO") { log_to_file=false; log_to_printer=false; } else
+ if (x=="DISK") { log_to_file=true; log_to_printer=false; } else
+ if (x=="PRINTER") { log_to_file=false; log_to_printer=true; } else
+ error(parse_weird_logcode);
+}
+
+
+
+static void get_card(string x)
+{
+ if (x=="NONE") your_card=0; else
+ if (x=="SB") your_card=1; else
+ if (x=="SBPRO") your_card=2; else
+ if (x=="SB16") your_card=3; else
+ if (x=="PAS") your_card=4; else
+ if (x=="PASPLUS") your_card=5; else
+ if (x=="PAS16") your_card=6; else
+ if (x=="ARIA") your_card=7; else
+ if (x=="WINSOUND") your_card=8; else
+ if (x=="GRAVIS") your_card=9; else
+ if (x=="DACLPT") your_card=10; else
+ if (x=="STEREODACS") your_card=11; else
+ if (x=="STEREOON1") your_card=12; else
+ if (x=="SPEAKER") your_card=13; else
+ error(parse_weird_card);
+}
+
+void parse_file(){
+
+
+ word where;
+ byte position;
+ varying_string<80> field,data,pure_data;
+ option o;
+
+
+ error_found=false;
+ ignoring=false;
+
+ for( where=1; where <= mobylength; where ++)
+ {
+ this_=(*moby)[where]; thiswas=this_;
+
+ position=pos(";",this_);
+ if (position>0) this_=copy(this_,1,position-1);
+
+ if (this_=="") continue_; /* Don't carry on if by now it's empty. */
+
+ if (this_[1]=='[')
+ {
+ ignoring=! (trim_and_caps(this_)=="[END]");
+
+ if (copy(this_,1,8)=="[printer")
+ {
+ num_printers += 1;
+ printers[num_printers]=copy(this_,10,length(this_)-10);
+ }
+ }
+
+ if (ignoring) continue_;
+
+ position=pos("=",this_);
+ field=trim_and_caps(copy(this_,1,position-1)); if (field=="") continue_;
+ pure_data=copy(this_,position+1,255);
+ data=trim_and_caps(pure_data);
+ o=string_2_option(field);
+
+ /* general */
+
+ if (o==_overrideegacheck) override_ega=yesno(data); else
+ if (o==_zoomystart) skip_loading_screens=yesno(data); else
+ if (o==_loadfirst) load_particular=data; else
+ if (o==_numlockhold) force_numlock=yesno(data); else
+ if (o==_usemouse) ignore_mouse=yesno(data); else
+ if (o==_controller) use_keyboard=kbdjoy(data); else
+ if (o==_logging) get_logcodes(data); else
+ if (o==_logfile) log_filename=data; else
+
+ /* joystick */
+
+ if (o==_joystickinstalled) has_a_joystick=yesno(data); else
+ if (o==_joytop) jtop=numeric(data); else
+ if (o==_joybottom) jbottom=numeric(data); else
+ if (o==_joyleft) jleft=numeric(data); else
+ if (o==_joyright) jright=numeric(data); else
+ if (o==_joymidx) jmidx=numeric(data); else
+ if (o==_joymidy) jmidy=numeric(data); else
+ if (o==_joycentringfactor) jcentre=numeric(data); else
+ if (o==_whichjoy) whichjoy=numeric(data); else
+
+ /* sound */
+
+ if (o==_quiet) suppress_sfx=yesno(data); else
+ if (o==_soundcard) get_card(data); else
+ if (o==_samplerate) samplerate=numeric(data); else
+ if (o==_baseaddress) sound_addr=numeric(data); else
+ if (o==_irq) sound_irq=numeric(data); else
+ if (o==_dma) sound_dma=numeric(data); else
+ if (o==_keyboardclick) wants_keyclick=yesno(data); else
+
+ /* printer */
+
+ if (o==_printer) this_printer=pure_data; else
+
+ /* others */
+
+ error(parse_weird_field);
+ }
+
+ if (error_found)
+ {
+ textattr=15;
+ output << " Try and fix the above errors. As a last resort, try deleting or" << NL;
+ output << " renaming AVALOT.INI, and the default values will be used. Good luck." << NL;
+ exit(177);
+ }
+ }
+
+void clear_up()
+{
+ window(1,1,80,25);
+ textattr=31;
+ clrscr;
+ output << NL;
+ output << "Enjoy the game..." << NL;
+ output << NL;
+ cga_cursor_on;
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ cursor_off;
+
+ moby = new mobytype; /* Allocate memory space */
+
+ defaults();
+
+ load_file();
+
+ parse_file();
+
+ menu();
+
+ delete moby; /* Deallocate memory space again */
+
+ clear_up();
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/seu.cpp b/engines/avalanche/seu.cpp
new file mode 100644
index 0000000000..9b1c1c23cc
--- /dev/null
+++ b/engines/avalanche/seu.cpp
@@ -0,0 +1,977 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Dos.h"*/
+/*#include "Crt.h"*/
+/*#include "Tommys.h"*/
+
+
+const integer msize = 100;
+const integer flag = -20047;
+const integer perm = -1;
+
+const integer avvy_shoot = 87;
+const integer facing_right = 88;
+const integer facing_left = 94;
+
+const integer avvy_y = 150;
+
+const integer left_margin = 10;
+const integer right_margin = 605;
+
+const array<0,6,byte> shooting = {{87,80,81,82,81,80,87}};
+
+const integer stocks = 28;
+
+const integer framedelaymax = 2;
+
+const integer maxrunners = 4;
+
+const integer times_a_second = /*31*/18;
+
+const integer flash_time = 20; /* If flash_time is <= this, the word "time" will flash. */
+ /* Should be about 20. */
+
+/* --- Scores for various things --- */
+
+const integer score_for_hitting_face = 3;
+const integer bonus_for_hitting_escaper = 5;
+
+struct mtype {
+ shortint ix,iy;
+ integer x,y;
+ byte p;
+ integer timeout;
+ boolean cameo;
+ byte cameo_frame;
+ boolean missile;
+ boolean wipe;
+};
+
+struct xtype {
+ word s;
+ pointer p;
+};
+
+class rectype {
+public:
+ integer x1,y1,x2,y2;
+};
+
+class plottype : public rectype {
+public:
+ byte which;
+};
+
+class plotmasktype : public plottype {
+public:
+ byte whichmask;
+};
+
+array<1,100,xtype> x;
+array<1,100,mtype> m;
+matrix<0,1,1,100,rectype> r;
+array<0,1,byte> rsize;
+byte cp;
+word score; byte time1;
+
+byte shiftstate; /*ABSOLUTE $40:$17; */
+
+word avvypos;
+word avvywas;
+byte avvyanim;
+byte avvyfacing;
+
+byte was_facing;
+
+boolean alt_was_pressed_before;
+
+byte throw_next;
+
+boolean firing;
+
+array<0,6,byte> stockstatus;
+
+array<1,maxrunners,struct A1 {
+ integer x,y;
+ byte frame;
+ byte toohigh,lowest;
+ shortint ix,iy;
+ byte framedelay;
+ }> running;
+
+varying_string<5> score_is;
+varying_string<3> time_is;
+
+byte time_this_second;
+
+word escape_count;
+byte escape_stock;
+boolean escaping,got_out;
+
+array<0,6,boolean> has_escaped;
+
+byte count321;
+
+word storage_seg,storage_ofs;
+
+byte how_many_have_escaped;
+
+void flippage()
+{
+ setactivepage(cp);
+ cp=1-cp;
+ setvisualpage(cp);
+}
+
+void flesh_colours() {; /*assembler;
+asm
+ mov ax,$1012;
+ mov bx,21; { 21 = light pink (why?) */
+ /*mov cx,1;
+ mov dx,seg @flesh;
+ mov es,dx;
+ mov dx,offset @flesh;
+ int $10;
+
+ mov dx,seg @darkflesh;
+ mov es,dx;
+ mov dx,offset @darkflesh;
+ mov bx,5; { 5 = dark pink. */
+ /*int $10;
+
+ jmp @TheEnd;
+
+ @flesh:
+ db 56,35,35;
+
+ @darkflesh:
+ db 43,22,22;
+
+ @TheEnd: */
+ }
+
+boolean overlap(word a1x,word a1y,word a2x,word a2y,word b1x,word b1y,word b2x,word b2y)
+{ /* By De Morgan's law: */
+ boolean overlap_result;
+ overlap_result=(a2x>=b1x) && (b2x>=a1x) && (a2y>=b1y) && (b2y>=a1y);
+ return overlap_result;
+}
+
+void getsize(byte w, integer& xx,integer& yy)
+{
+ array<0,1,integer> n;
+
+ move(x[w].p,n,4);
+ xx=n[0]; yy=n[1];
+}
+
+void display(integer xx,integer yy, byte w)
+{
+ putimage(xx,yy,x[w].p,0);
+}
+
+byte get_stock_number(byte x)
+{
+ byte get_stock_number_result;
+ while (has_escaped[x])
+ {
+ x += 1;
+ if (x==7) x=0;
+ }
+ get_stock_number_result=x;
+ return get_stock_number_result;
+}
+
+void cameo_display(integer xx,integer yy, byte w1,byte w2)
+{
+ putimage(xx,yy,x[w2].p,andput);
+ putimage(xx,yy,x[w1].p,xorput);
+}
+
+void blankit()
+{
+ byte fv;
+
+ for( fv=1; fv <= rsize[cp]; fv ++)
+ { rectype& with = r[cp][fv];
+ bar(with.x1,with.y1,with.x2,with.y2);}
+ rsize[cp]=0;
+}
+
+void blank(integer xx1,integer yy1,integer xx2,integer yy2)
+{
+ rsize[cp] += 1;
+ {
+ rectype& with = r[cp][rsize[cp]];
+
+ with.x1=xx1;
+ with.y1=yy1;
+ with.x2=xx2;
+ with.y2=yy2;
+ }
+}
+
+void movethem()
+{
+ byte fv;
+
+ for( fv=1; fv <= msize; fv ++)
+ { mtype& with = m[fv];
+ if (with.x!=flag)
+ {
+ with.x=with.x+with.ix;
+ with.y=with.y+with.iy;
+ }}
+}
+
+void plotthem()
+{
+ byte fv; integer xx,yy;
+
+ for( fv=1; fv <= msize; fv ++)
+ { mtype& with = m[fv];
+ if (with.x!=flag)
+ {
+ if (with.cameo)
+ {
+ cameo_display(with.x,with.y,with.p,with.cameo_frame);
+ if (cp==0) { with.cameo_frame += 2; with.p += 2; }
+ } else display(with.x,with.y,with.p);
+ getsize(with.p,xx,yy);
+ if (with.wipe) blank(with.x,with.y,with.x+xx,with.y+yy);
+ if (with.timeout>0)
+ {
+ with.timeout -= 1;
+ if (with.timeout==0) with.x=flag;
+ }
+ }}
+}
+
+void define(integer xx,integer yy, byte pp, shortint ixx,shortint iyy, integer timetime,
+ boolean is_a_missile,boolean do_we_wipe)
+{
+ byte which;
+
+ for( which=1; which <= msize; which ++)
+ {
+ mtype& with = m[which];
+
+ if (with.x==flag)
+ {
+ with.x=xx;
+ with.y=yy;
+ with.p=pp;
+ with.ix=ixx;
+ with.iy=iyy;
+ with.timeout=timetime;
+ with.cameo=false;
+ with.missile=is_a_missile;
+ with.wipe=do_we_wipe;
+
+ return;
+ }
+ }
+}
+
+void define_cameo(integer xx,integer yy, byte pp, integer timetime)
+{
+ byte which;
+
+ for( which=1; which <= msize; which ++)
+ {
+ mtype& with = m[which];
+
+ if (with.x==flag)
+ {
+ with.x=xx;
+ with.y=yy;
+ with.p=pp;
+ with.ix=0;
+ with.iy=0;
+ with.timeout=timetime;
+ with.cameo=true;
+ with.cameo_frame=pp+1;
+ with.missile=false;
+ with.wipe=false;
+
+ return;
+ }
+ }
+}
+
+void get_score()
+{
+ byte fv;
+
+ str(score,5,score_is);
+ for( fv=1; fv <= 5; fv ++)
+ if (score_is[fv]==' ')
+ score_is[fv]='0';
+}
+
+void get_time1()
+{
+ byte fv;
+
+ str(time1,5,time_is);
+ for( fv=1; fv <= 3; fv ++)
+ if (time_is[fv]==' ')
+ time_is[fv]='0';
+}
+
+void display_const(integer x,integer y, byte what)
+{
+ byte page_;
+
+ for( page_=0; page_ <= 1; page_ ++)
+ {
+ setactivepage(page_);
+ display(x,y,what);
+ }
+ setactivepage(1-cp);
+}
+
+void show_stock(byte x)
+{
+ if (escaping && (x==escape_stock))
+ {
+ display_const(x*90+20,30,stocks+2);
+ return;
+ }
+ if (stockstatus[x]>5) return;
+ display_const(x*90+20,30,stocks+stockstatus[x]);
+ stockstatus[x]=1-stockstatus[x];
+}
+
+void show_score()
+{
+ byte fv;
+ varying_string<5> score_was;
+
+ score_was=score_is; get_score();
+ for( fv=1; fv <= 5; fv ++)
+ if (score_was[fv]!=score_is[fv])
+ display_const(30+fv*10,0,ord(score_is[fv])-47);
+}
+
+void show_time()
+{
+ byte fv;
+ varying_string<3> time_was;
+
+ time_was=time_is; get_time1();
+ for( fv=1; fv <= 3; fv ++)
+ if (time_was[fv]!=time_is[fv])
+ display_const(130+fv*10,0,ord(time_is[fv])-47);
+}
+
+void gain(shortint howmuch)
+{
+ if (-howmuch>score) score=0; else
+ score=score+howmuch;
+ show_score();
+}
+
+void new_escape()
+{
+ escape_count=Random(18)*20;
+ escaping=false;
+}
+
+void instructions();
+
+static void nextpage()
+{
+ char c;
+
+ outtextxy(400,190,"Press a key for next page >");
+ c=readkey();
+ cleardevice();
+}
+
+void instructions()
+{
+ display(25,25,facing_right);
+ outtextxy(60,35,"< Avvy, our hero, needs your help - you must move him around.");
+ outtextxy(80,45,"(He's too terrified to move himself!)");
+
+ outtextxy(0,75,"Your task is to prevent the people in the stocks from escaping");
+ outtextxy(0,85,"by pelting them with rotten fruit, eggs and bread. The keys are:");
+ outtextxy(80,115,"LEFT SHIFT"); outtextxy(200,115,"Move left.");
+ outtextxy(72,135,"RIGHT SHIFT"); outtextxy(200,135,"Move right.");
+ outtextxy(136,155,"ALT"); outtextxy(200,155,"Throw something.");
+ nextpage();
+
+ display(25,35,stocks);
+ outtextxy(80,35,"This man is in the stocks. Your job is to stop him getting out.");
+ outtextxy(88,45,"UNFORTUNATELY... the locks on the stocks are loose, and every");
+ outtextxy(88,55,"so often, someone will discover this and try to get out.");
+ display(25, 85,stocks+2);
+ outtextxy(80, 85,"< Someone who has found a way out!");
+ outtextxy(88, 95,"You MUST IMMEDIATELY hit people smiling like this, or they");
+ outtextxy(88,105,"will disappear and lose you points.");
+ display(25,125,stocks+5);
+ display(25,155,stocks+4);
+ outtextxy(80,125,"< Oh dear!");
+ nextpage();
+
+ outtextxy(0,35,"Your task is made harder by:");
+ display(25,55,48);
+ outtextxy(60,55,"< Yokels. These people will run in front of you. If you hit");
+ outtextxy(68,65,"them, you will lose MORE points than you get hitting people");
+ outtextxy(68,75,"in the stocks. So BEWARE!");
+ outtextxy(80,125,"Good luck with the game!");
+ nextpage();
+}
+
+void setup()
+{
+ integer gd,gm;
+ untyped_file f;
+ char rkv;
+
+ rkv=upcase(readkey());
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ flesh_colours();
+
+ assign(f,"notts.avd");
+ reset(f,1); gd=1;
+ score=0; time1=120; score_is="(c)94";
+ time_this_second=0;
+
+ while (! eof(f))
+ {
+ xtype& with = x[gd];
+
+ blockread(f,with.s,2);
+ getmem(with.p,with.s);
+ blockread(f,with.p,with.s);
+ gd += 1;
+ }
+ close(f);
+
+ if ((rkv=='I') || ((rkv=='\0') && (readkey()==cf1))) instructions();
+
+ for( gd=0; gd <= 6; gd ++)
+ {
+ stockstatus[gd]=Random(2);
+ show_stock(gd);
+ }
+
+ fillchar(m,sizeof(m),'\261');
+ setfillstyle(1,0);
+ cp=0;
+ flippage();
+ fillchar(rsize,sizeof(rsize),'\0');
+ avvywas=320;
+ avvypos=320;
+ avvyanim=1;
+ avvyfacing=facing_left;
+
+ alt_was_pressed_before=false;
+ throw_next=74;
+ firing=false;
+
+ for( gd=1; gd <= maxrunners; gd ++)
+ {
+ A1& with = running[gd];
+
+ with.x=flag;
+ }
+
+ new_escape();
+ fillchar(has_escaped,sizeof(has_escaped),'\0'); /* All false. */
+ count321=255; /* Counting down. */
+
+ /* Set up status line. */
+
+ display_const(0,0,17); /* Score: */
+ show_score(); /* value of score (00000 here) */
+ display_const(110,0,20); /* Time: */
+ show_time(); /* value of time */
+
+ Randomize();
+
+ how_many_have_escaped=0;
+}
+
+void init_runner(integer xx,integer yy, byte f1,byte f2, shortint ixx,shortint iyy)
+{
+ byte fv;
+
+ for( fv=1; fv <= maxrunners; fv ++)
+ { A1& with = running[fv];
+ if (with.x==flag)
+ {
+ with.x=xx; with.y=yy;
+ with.frame=f1;
+ with.toohigh=f2;
+ with.lowest=f1;
+ with.ix=ixx; with.iy=iyy;
+ if ((with.ix==0) && (with.iy==0)) with.ix=2; /* To stop them running on the spot! */
+ with.framedelay=framedelaymax;
+ return;
+ }}
+}
+
+void titles()
+{
+ registers r;
+ byte a; /*absolute $A000:0; */
+ untyped_file f;
+ byte bit;
+
+ r.ax=0xd;
+ intr(0x10,r);
+
+ assign(f,"shoot1.avd");
+ reset(f,1);
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a,8000);
+ }
+ close(f);
+}
+/*
+procedure animate3;
+begin
+ define(100,100,10,1,0,perm,false,true);
+ define( 50,20 ,30,3,3,30,false,true);
+ repeat;
+ blankit;
+ plotthem;
+ movethem;
+ flippage;
+ delay(100);
+ until keypressed;
+end;
+
+procedure animate2;
+var
+ x,n:byte;
+ helpx:integer;
+ helpdir:shortint;
+ helpani:byte;
+begin
+ x:=0; n:=0; helpani:=0;
+ helpx:=10; helpdir:=1;
+ setfillstyle(1,0);
+
+ repeat
+ display(x*52,0,n+28);
+ inc(x); inc(n);
+
+ if x=13 then
+ begin
+ bar(helpx-2,50,helpx+5,80);
+ if helpdir>0 then
+ display(helpx,50,80-helpani)
+ else
+ display(helpx,50,86-helpani);
+ helpx:=helpx+helpdir*5;
+ if (helpx>600) or (helpx<3) then helpdir:=-helpdir;
+ if helpani=0 then helpani:=5 else dec(helpani);
+
+ x:=0;
+(* delay(100);*)
+ end;
+ if n=6 then n:=0;
+ until keypressed;
+end;
+*/
+
+void move_avvy()
+{
+ if (avvywas<avvypos)
+ {
+/* bar(avvyWas,avvy_Y,avvyPos,Avvy_Y+85);*/
+ avvyfacing=facing_right;
+ } else if (avvywas>avvypos)
+ {
+/* bar(avvyWas+32,Avvy_Y,avvyPos+33,Avvy_Y+85);*/
+ avvyfacing=facing_left;
+ }
+
+ if (! firing)
+ {
+ if (avvywas==avvypos)
+ avvyanim=1;
+ else
+ {
+ avvyanim += 1;
+ if (avvyanim==6) avvyanim=0;
+ }
+ }
+
+ if (avvyfacing==avvy_shoot)
+ define(avvypos,avvy_y,shooting[avvyanim],0,0,1,false,true);
+ else
+ define(avvypos,avvy_y,avvyanim+avvyfacing,0,0,1,false,true);
+
+ avvywas=avvypos;
+
+ if (avvyfacing==avvy_shoot)
+ {
+ if (avvyanim==6)
+ {
+ avvyfacing=was_facing;
+ avvyanim=0;
+ firing=false;
+ } else avvyanim += 1;
+ }
+}
+
+void read_kbd()
+{
+
+ if (firing) return;
+
+ if ((shiftstate & 8)>0)
+ { /* Alt - shoot */
+ if ((alt_was_pressed_before) || (count321!=0)) return;
+ alt_was_pressed_before=true;
+ firing=true;
+ define(avvypos+27,avvy_y+5,throw_next,0,-2,53,true,true);
+ throw_next += 1; if (throw_next==80) throw_next=74;
+ avvyanim=0;
+ was_facing=avvyfacing;
+ avvyfacing=avvy_shoot;
+ return;
+ }
+
+ alt_was_pressed_before=false;
+
+ if ((shiftstate & 1)>0)
+ { /* Move right. */
+ avvypos += 5;
+ if (avvypos>right_margin) avvypos=right_margin;
+ return;
+ }
+
+ if ((shiftstate & 2)>0)
+ { /* Move left. */
+ avvypos -= 5;
+ if (avvypos<left_margin) avvypos=left_margin;
+ }
+
+}
+
+void animate()
+{
+ byte fv;
+
+ if (Random(10)==1) show_stock(get_stock_number(Random(6)));
+ for( fv=0; fv <= 6; fv ++)
+ if (stockstatus[fv]>5)
+ {
+ stockstatus[fv] -= 1;
+ if (stockstatus[fv]==8)
+ {
+ stockstatus[fv]=0;
+ show_stock(fv);
+ }
+ }
+}
+
+void collision_check()
+{
+ byte fv;
+ integer dist_from_side;
+ byte this_stock;
+
+ for( fv=1; fv <= 100; fv ++)
+ { mtype& with = m[fv];
+ if (with.x!=flag)
+ {
+ if ((with.missile) && (with.y<60) && (with.timeout==1))
+ {
+/* sound(177); delay(1); nosound;*/
+ dist_from_side=(with.x-20) % 90;
+ this_stock=((with.x-20) / 90);
+ if ((! has_escaped[this_stock]) &&
+ (dist_from_side>17) && (dist_from_side<34))
+ {
+ sound(999); delay(3); nosound;
+ define(with.x+20,with.y,26+Random(2),3,1,12,false,true); /* Well done! */
+ define(this_stock*90+20,30,31,0,0,7,false,false); /* Face of man */
+ define_cameo(this_stock*90+20+10,35,40,7); /* Splat! */
+ define(this_stock*90+20+20,50,34+Random(5),0,2,9,false,true); /* Oof! */
+ stockstatus[this_stock]=17;
+ gain(score_for_hitting_face);
+
+ if ((escaping) && (escape_stock==this_stock))
+ { /* Hit the escaper. */
+ sound(1777); delay(1); nosound;
+ gain(bonus_for_hitting_escaper);
+ escaping=false; new_escape();
+ }
+ } else
+ {
+ define(with.x,with.y,83+Random(3),2,2,17,false,true); /* Missed! */
+ if ((! has_escaped[this_stock]) &&
+ ((dist_from_side>3) && (dist_from_side<43)))
+ {
+ define(this_stock*90+20,30,30,0,0,7,false,false); /* Face of man */
+ if (dist_from_side>35)
+ define_cameo(with.x-27,35,40,7); /* Splat! */
+ else
+ define_cameo(with.x-7,35,40,7);
+ stockstatus[this_stock]=17;
+ }
+ }
+ }
+ }}
+}
+
+shortint sgn(integer a)
+{
+ shortint sgn_result;
+ if (a==0) { sgn_result=0; return sgn_result; }
+ if (a>0) { sgn_result=1; return sgn_result; }
+ sgn_result=-1;
+ return sgn_result;
+}
+
+void turn_around(byte who, boolean randomx)
+{
+ {
+ A1& with = running[who];
+
+ if (randomx)
+ {
+ if (with.ix>0) with.ix=-(Random(5)+1); else with.ix=(Random(5)+1);
+ } else
+ with.ix=-with.ix;
+ with.iy=-with.iy;
+ }
+}
+
+void bump_folk()
+{
+ byte fv,ff;
+
+ for( fv=1; fv <= maxrunners; fv ++)
+ if (running[fv].x!=flag)
+ for( ff=fv+1; ff <= maxrunners; ff ++)
+ if ((running[ff].x!=flag) &&
+ overlap(running[fv].x,running[fv].y,
+ running[fv].x+17,running[fv].y+24,
+ running[ff].x,running[ff].y,
+ running[ff].x+17,running[ff].y+24))
+ {
+ turn_around(fv,false); /* Opp. directions. */
+ turn_around(ff,false);
+ }
+}
+
+void people_running()
+{
+ byte fv;
+
+ if (count321!=0) return;
+ for( fv=1; fv <= maxrunners; fv ++)
+ { A1& with = running[fv];
+ if (with.x!=flag)
+ {
+ if (((with.y+with.iy)<=53) || ((with.y+with.iy)>=120))
+ {
+ with.iy=-with.iy;
+ }
+
+ if (with.ix<0)
+ define(with.x,with.y,with.frame,0,0,1,false,true);
+ else
+ define(with.x,with.y,with.frame+7,0,0,1,false,true);
+ if (with.framedelay==0)
+ {
+ with.frame += 1; if (with.frame==with.toohigh) with.frame=with.lowest;
+ with.framedelay=framedelaymax;
+ with.y=with.y+with.iy;
+ } else with.framedelay -= 1;
+
+ if (((with.x+with.ix)<=0) || ((with.x+with.ix)>=620)) turn_around(fv,true);
+
+ with.x=with.x+with.ix;
+ }}
+}
+
+void update_time()
+{
+ if (count321!=0) return;
+ time_this_second += 1;
+ if (time_this_second < times_a_second) return;
+ time1 -= 1;
+ show_time();
+ time_this_second=0;
+ if (time1<=flash_time)
+ if (odd(time1)) display_const(110,0,20); /* Normal time */
+ else display_const(110,0,86); /* Flash time */
+}
+
+void hit_people()
+{
+ byte fv,ff;
+
+ if (count321!=0) return;
+ for( fv=1; fv <= 100; fv ++)
+ { mtype& with = m[fv];
+ if (with.missile && (with.x!=flag))
+ for( ff=1; ff <= maxrunners; ff ++)
+ if ((running[ff].x!=flag) &&
+ overlap(with.x,with.y,with.x+7,with.y+10,
+ running[ff].x,running[ff].y,
+ running[ff].x+17,
+ running[ff].y+24))
+ {
+ sound(7177);
+/* setcolor(4);
+ rectangle(x,y,x+7,y+10);
+ rectangle(running[ff].x,running[ff].y,
+ running[ff].x+17,
+ running[ff].y+24);*/
+ nosound;
+ with.x=flag;
+ gain(-5);
+ define(running[ff].x+20,running[ff].y+3,
+ 34+Random(6),1,3,9,false,true); /* Oof! */
+ define(with.x,with.y,83,1,0,17,false,true); /* Oops! */
+ }}
+}
+
+void escape_check()
+{
+ if (count321!=0) return;
+ if (escape_count>0) { escape_count -= 1; return; }
+
+ /* Escape_count = 0; now what? */
+
+ if (escaping)
+ {
+ if (got_out)
+ {
+ new_escape(); escaping=false;
+ display_const(escape_stock*90+20,30,stocks+4);
+ } else
+ {
+ display_const(escape_stock*90+20,30,stocks+5);
+ escape_count=20; got_out=true;
+ define(escape_stock*90+20,50,25,0,2,17,false,true); /* Escaped! */
+ gain(-10);
+ has_escaped[escape_stock]=true;
+
+ how_many_have_escaped += 1;
+
+ if (how_many_have_escaped == 7)
+ {
+ for( time1=0; time1 <= 1; time1 ++)
+ {
+ setactivepage(time1);
+ cleardevice();
+ }
+ setactivepage(1-cp);
+
+ memw[storage_seg*storage_ofs+1]=0;
+ do {; } while (!(memw[storage_seg*storage_ofs+1]>9));
+
+ setvisualpage(1-cp);
+ display(266,90,23);
+
+ memw[storage_seg*storage_ofs+1]=0;
+ do {; } while (!(memw[storage_seg*storage_ofs+1]>72));
+
+ setvisualpage(cp);
+
+ memw[storage_seg*storage_ofs+1]=0;
+ do {; } while (!(memw[storage_seg*storage_ofs+1]>9));
+
+ time1=0;
+ }
+ }
+ } else
+ {
+ escape_stock=get_stock_number(Random(7)); escaping=true; got_out=false;
+ display_const(escape_stock*90+20,30,stocks+2); /* Smiling! */
+ escape_count=200;
+ }
+}
+
+void check321()
+{
+ if (count321==0) return;
+ count321 -= 1;
+ switch (count321) {
+ case 84: define(320, 60,16, 2, 1,94,false,true); break;
+ case 169: define(320, 60,15, 0, 1,94,false,true); break;
+ case 254: {
+ define(320, 60,14,-2, 1,94,false,true);
+ define( 0,100,18, 2, 0,254,false,true);
+ }
+ break;
+ }
+}
+
+void check_params();
+
+static void not_bootstrap()
+{
+ output << "This is not a standalone program!" << NL;
+ exit(255);
+}
+
+void check_params()
+{
+ integer e;
+
+ if (paramstr(1)!="jsb") not_bootstrap();
+
+ val(paramstr(2),storage_seg,e); if (e!=0) not_bootstrap();
+ val(paramstr(3),storage_ofs,e); if (e!=0) not_bootstrap();
+
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ check_params();
+
+ titles();
+ setup();
+ init_runner( 20, 70,48,54, Random(5)+1,Random(4)-2);
+ init_runner(600, 70,48,54, Random(5)+1,Random(4)-2);
+ init_runner(600,100,61,67,-Random(5)+1,Random(4)-2);
+ init_runner( 20,100,61,67,-Random(5)+1,Random(4)-2);
+ do {
+ memw[storage_seg*storage_ofs+1]=0;
+
+ blankit();
+ hit_people();
+ plotthem();
+ movethem();
+ move_avvy();
+ bump_folk();
+ people_running();
+ animate();
+ escape_check();
+
+ collision_check();
+
+ update_time();
+
+ check321();
+
+ read_kbd();
+ flippage();
+ do {; } while (!(memw[storage_seg*storage_ofs+1]>0));
+
+ } while (!(time1==0));
+
+/* textmode(259);
+ textattr:=1;
+ writeln('Your final score was: ',score,'.');
+ readln;*/
+ mem[storage_seg*storage_ofs]=score;
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/seu_avvy.cpp b/engines/avalanche/seu_avvy.cpp
new file mode 100644
index 0000000000..fb236b95bb
--- /dev/null
+++ b/engines/avalanche/seu_avvy.cpp
@@ -0,0 +1,90 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+
+struct adxtype {
+ varying_string<12> name; /* name of character */
+ varying_string<16> comment; /* comment */
+ byte num; /* number of pictures */
+ byte xl,yl; /* x & y lengths of pictures */
+ byte seq; /* how many in one stride */
+ word size; /* the size of one picture */
+ byte fgc,bgc; /* foreground & background bubble colours */
+ byte accinum; /* the number according to Acci (1=Avvy, etc.) */
+};
+
+integer gd,gm;
+untyped_file sf;
+longint id;
+word soa;
+adxtype a;
+byte xw;
+array<5,2053,byte> mani;
+matrix<0,35,0,4,byte> sil;
+array<1,16000,byte> aa;
+untyped_file outfile;
+
+void plotat(integer xx,integer yy) /* Does NOT cameo the picture!*/
+{
+ word soaa;
+;
+ move(mani,aa[5],sizeof(mani));
+ {;
+ aa[1]=a.xl; aa[2]=0; aa[3]=a.yl; aa[4]=0; /* set up x&y codes */
+ }
+ putimage(xx,yy,aa,0);
+ soaa=sizeof(mani);
+ blockwrite(outfile,soaa,2);
+ blockwrite(outfile,aa,sizeof(mani));
+}
+
+const integer shouldid = -1317732048;
+
+void explode(byte which) /* 0 is the first one! */
+ /* Each character takes five-quarters of (a.size-6) on disk. */
+{
+ byte fv,ff; word so1; /* size of one */
+;
+ {;
+ so1=a.size-6; so1 += so1 / 4;
+ seek(sf,183+soa+so1*which); /* First is at 221 */
+/* where:=filepos(sf);*/
+ xw=a.xl / 8; if ((a.xl % 8)>0) xw += 1;
+
+ for( fv=0; fv <= a.yl; fv ++)
+ blockread(sf,sil[fv],xw);
+ blockread(sf,mani,a.size-6);
+ aa[a.size-1]=0; aa[a.size]=0; /* footer */
+ }
+ plotat(100,100);
+ delay(100);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+
+ assign(outfile,"notts.avd");
+ reset(outfile,1);
+ seek(outfile,filesize(outfile));
+
+ assign(sf,"sprite0.avd");
+ reset(sf,1);
+
+ seek(sf,177);
+ blockread(sf,id,4);
+ blockread(sf,soa,2);
+ blockread(sf,a,soa);
+
+ explode(1);
+ for( gd=6; gd <= 11; gd ++) explode(gd);
+ for( gd=18; gd <= 23; gd ++) explode(gd);
+
+ close(sf);
+ close(outfile);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/sez.cpp b/engines/avalanche/sez.cpp
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/engines/avalanche/sez.cpp
diff --git a/engines/avalanche/sezedit.cpp b/engines/avalanche/sezedit.cpp
new file mode 100644
index 0000000000..946e318ebb
--- /dev/null
+++ b/engines/avalanche/sezedit.cpp
@@ -0,0 +1,406 @@
+#include "ptoc.h"
+
+
+/*$M 65520,0,655360*/
+/*#include "Crt.h"*/
+#include "graph.h"
+
+
+const char marker = '\33';
+const char game[] = "Avalot";
+
+typedef matrix<'\0','\377',0,15,byte> fonttype;
+
+struct markertype {
+ word length;
+ longint offset;
+ byte checksum;
+};
+
+struct sezheader {
+ array<1,2,char> initials; /* should be "TT" */
+ word gamecode;
+ word revision; /* as 3- or 4-digit code (eg v1.00 = 100) */
+ longint chains; /* number of scroll chains */
+ longint size; /* total size of all chains */
+};
+
+array<0,1999,char> buffer,was;
+word bufpos,bufsize;
+longint chainnum;
+varying_string<40> nickname;
+array<1,255,char> junk;
+string temp;
+char r;
+fonttype font;
+integer cpos;
+sezheader sezhead;
+untyped_file f,tempf;
+text nicknames;
+
+byte sumup()
+{
+ word fv; byte total;
+byte sumup_result;
+;
+ total=0;
+ for( fv=0; fv <= bufsize-1; fv ++)
+ {;
+ total += ord(was[fv]);
+ }
+ sumup_result=total;
+return sumup_result;
+}
+
+string findname(longint which)
+{
+ string x; varying_string<10> q;
+string findname_result;
+;
+ str(which,q);
+ reset(nicknames);
+ do { nicknames >> x >> NL; } while (!(x=="{go}"));
+ do {
+ nicknames >> x >> NL;
+ } while (!(pos(q,x)>0));
+ if (eof(nicknames))
+ {;
+ findname_result="noname";
+ } else
+ {;
+ Delete(x,1,3); /* lose "{__" */
+ Delete(x,pos(" ",x),255); /* lose all chars after first space */
+ findname_result=x;
+ }
+ close(nicknames);
+return findname_result;
+}
+
+void cursor()
+{
+ byte fv;
+;
+ for( fv=12; fv <= 15; fv ++)
+ mem[0xa000*cpos+fv*80]=~(mem[0xa000*cpos+fv*80]);
+}
+
+void xy()
+{;
+ cpos=(bufpos / 80)*1280+(bufpos % 80);
+}
+
+void show()
+{
+ word fv,orig,y;
+;
+ for( fv=0; fv <= 1999; fv ++)
+ if (buffer[fv]!=was[fv])
+ {;
+ orig=(fv / 80)*1280+(fv % 80);
+ for( y=0; y <= 15; y ++)
+ mem[0xa000*orig+y*80]=(byte)(font[buffer[fv]][y]);
+ }
+ xy();
+ move(buffer,was,sizeof(buffer));
+}
+
+void sizeup()
+{;
+ do {
+ switch (buffer[bufsize]) {
+ case marker: return; break; /* we've found it OK! */
+ case '\0': bufsize -= 1; break;
+ default: bufsize += 1;
+ }
+ } while (!false);
+}
+
+void graphics()
+{
+ integer gd,gm;
+ file<fonttype> fontfile;
+;
+ gd=3; gm=1; initgraph(gd,gm,"");
+ assign(fontfile,"c:\\thomas\\lanche.fnt");
+ reset(fontfile); fontfile >> font; close(fontfile);
+}
+
+void edit_it();
+
+static void legit(char r)
+{; /* it's a legit keystroke */
+ move(buffer[bufpos],buffer[bufpos+1],1999-bufpos);
+ buffer[bufpos]=r;
+ bufpos += 1; show();
+}
+
+void edit_it()
+{
+ byte fv;
+;
+ for( fv=1; fv <= bufsize; fv ++) buffer[fv] -= (byte)(177*bufsize);
+ fillchar(was,sizeof(was),'\0'); show();
+ do {
+ cursor(); r=readkey(); cursor();
+ switch (r) {
+ case '\0': switch (readkey()) { /* extd keystrokes */
+ case 'K': if (bufpos>0) {; bufpos -= 1; xy(); } break; /* Left */
+ case 'M': if (bufpos<bufsize) {; bufpos += 1; xy(); } break; /* Right */
+ case 'H': if (bufpos>80) {; bufpos -= 80; xy(); } break; /* Up */
+ case 'P': if (bufpos<(cardinal)bufsize-79) {; bufpos += 80; xy(); } break; /* Down */
+ case 'G': {; bufpos=0; xy(); } break; /* Home */
+ case 'O': {; bufpos=bufsize; xy(); } break; /* End */
+ case 'S': {; /* Del */
+ move(buffer[bufpos+1],buffer[bufpos],1999-bufpos); show();
+ }
+ break;
+ case 'A': legit('\357'); break; /* copyright symbol */
+ }
+ break;
+ case '\10': if (bufpos>0) {; /* backspace */
+ bufpos -= 1;
+ move(buffer[bufpos+1],buffer[bufpos],1999-bufpos);
+ show();
+ }
+ break;
+ case '\33': {;
+ for( fv=1; fv <= bufsize; fv ++) buffer[fv] += (byte)(177*bufsize);
+ restorecrtmode();
+ return;
+ }
+ break; /* end of editing */
+ default: legit(r);
+ }
+ sizeup();
+ } while (!false);
+}
+
+void saveit(longint ourchain, word oldsize,word newsize)
+{
+ array<1,17777,byte> buffer;
+ word numread,numwritten,total;
+ char check;
+ word fv;
+ markertype m;
+ integer sizechange; /* so's it can be +ve or -ve */
+ longint wheresit; /* "offset" value for "ourchain" */
+;
+ assign(tempf,"sez.tmp");
+ /* OK, here goes... */
+ sezhead.size=sezhead.size-longint(oldsize)+longint(newsize); /* adjust our size */
+ sizechange=newsize-oldsize; /* +ve if bigger, -ve if smaller, 0 if same */
+ textattr=27;
+
+ rewrite(tempf,1); reset(f,1);
+ seek(f,255+sizeof(sezhead)); /* bypass the junk & sezhead (they're in RAM) */
+
+ blockwrite(tempf,junk,255); /* move the junk... */
+ blockwrite(tempf,sezhead,sizeof(sezhead)); /* and the header to new files */
+
+ /* Now to move the markers */
+ output << "Moving markers..." << NL;
+ for( fv=1; fv <= sezhead.chains; fv ++)
+ {;
+ output << fv << '\15';
+ blockread(f,m,sizeof(m));
+ if (fv==ourchain) /* Right, this one's ours! */
+ {;
+ wheresit=m.offset; /* recorded for later */
+ m.length=newsize-1;
+ m.checksum=sumup();
+ } else
+ if (fv>ourchain)
+ {; /* After ours- its offset will have to be changed... */
+ m.offset=m.offset+longint(sizechange);
+ } /* Otherwise, before ours- leave it well alone */
+ blockwrite(tempf,m,sizeof(m));
+ }
+ output << "Done OK." << NL;
+
+ /* Right, that's the markers done... thank goodness... now it's just the
+ chains themselves! */
+
+ total=0;
+
+ output << "Updating the chains..." << NL;
+ while (total<=wheresit)
+ {;
+ blockread(f,buffer,1,numread);
+ blockwrite(tempf,buffer,numread,numwritten);
+ output << '.';
+ total += numwritten;
+ }
+ output << NL; output << "Updating our chain..." << NL;
+ /* We're now in the right place (at last...) */
+ for( fv=0; fv <= (bufsize-1); fv ++) was[fv] += 3+177*fv*(bufsize-1); /* scramble "was" */
+ blockwrite(tempf,was,newsize); /* "was" contains what the values *were* */
+ seek(f,filepos(f)+oldsize);
+ output << NL; output << "Copying everything else..." << NL;
+ while (! eof(f)) /* high-speed copy */
+ {;
+ blockread(f,buffer,17777,numread);
+ blockwrite(tempf,buffer,numread);
+ output << '.';
+ }
+ output << NL;
+
+ /* Closedown */
+ close(f); close(tempf);
+ erase(f); rename(tempf,string(game)+".SEZ");
+}
+
+void particular()
+{
+ word origsize;
+;
+ bufsize=0;
+ output << "Which one\? (? for a list)"; input >> chainnum >> NL;
+ if ((chainnum<0) || (chainnum>sezhead.chains))
+ {;
+ output << "Don't be silly!" << NL; return;
+ }
+
+ origsize=0 /*bufsize*/; bufpos=0; cpos=0; nickname=findname(chainnum);
+ fillchar(buffer,sizeof(buffer),'\0');
+ buffer[0]=marker;
+ do {
+ textattr=30; output << NL;
+ output << "SEZ EDITOR (c) 1992, Thomas Thurman." << NL;
+ output << NL;
+ output << "Editing scrollchain no." << chainnum << NL;
+ output << "Your text is " << bufsize << " bytes long." << NL;
+ output << NL;
+ output << "Its nickname is \"" << nickname << "\"." << NL;
+ output << NL;
+ output << "Enter a command:" << NL;
+ output << " S) Save the text to disk," << NL;
+ output << " E) Edit this particular chain," << NL;
+ output << " N) change the Nickname," << NL;
+ output << " R) Revert text to the original," << NL;
+ output << "Esc) Exit and do something else!" << NL;
+ output << NL;
+ output << "Your choice? ";
+ r=upcase(readkey()); output << r << NL;
+ switch (r) {
+ case 'N': {;
+ output << NL; output << "New nickname (max 40 chars, Enter to cancel)?";
+ input >> temp >> NL;
+ if (temp!="") nickname=temp;
+ }
+ break;
+ case 'E': {; setgraphmode(1); edit_it(); } break;
+ case 'S': saveit(chainnum,origsize,bufsize); break;
+ case '\33': return; break;
+ }
+ } while (!false);
+}
+
+void titles()
+{
+ const varying_string<7> title = "SEZedit";
+ byte fv; char r;
+;
+ settextstyle(1,0,0);
+ for( fv=7; fv >= 1; fv --)
+ {;
+ setcolor(fv*2);
+ setusercharsize(8-fv,1,8-fv,1);
+ outtextxy(fv*65,fv*40-30,title[fv-1]);
+ }
+ setusercharsize(17,7,1,1); setcolor(green);
+ outtextxy(300,10,"Thorsoft");
+ outtextxy(10,310,"Press any key...");
+ do { r=readkey(); } while (!(! keypressed()));
+ restorecrtmode(); textattr=30; clrscr;
+}
+
+void addone() /* Adds a new, empty chain to the end of the list. */
+{
+ longint fv;
+ markertype m;
+ array<1,17777,byte> buffer;
+ word numread;
+;
+ assign(tempf,"sez.tmp");
+ textattr=27;
+ rewrite(tempf,1); reset(f,1); /* f = AVALOT.SEZ (original file) */
+ seek(f,255+sizeof(sezhead));
+ sezhead.chains += 1; /* we're adding a new chain */
+
+ blockwrite(tempf,junk,255); /* move the junk */
+ blockwrite(tempf,sezhead,sizeof(sezhead)); /* move the header */
+
+ /* Now to move the markers */
+ output << "Moving markers..." << NL;
+ for( fv=1; fv <= sezhead.chains-longint(1); fv ++) /* -1 because we've added 1 to it */
+ {;
+ output << fv << '\12';
+ blockread(f,m,sizeof(m));
+ blockwrite(tempf,m,sizeof(m));
+ }
+ output << "Done OK." << NL;
+ /* Now we add a new marker onto the end! */
+ {;
+ m.offset=sezhead.size; /* right onto the end */
+ m.length=0; /* it's empty */
+ }
+ blockwrite(tempf,m,sizeof(m)); /* write it out to disk */
+
+ /* Copy everything else... including the #177 check char */
+ output << "Copying everything else over..." << NL;
+ while (! eof(f))
+ {;
+ blockread(f,buffer,17777,numread);
+ blockwrite(tempf,buffer,numread);
+ output << '.';
+ }
+ output << NL;
+ close(f); close(tempf);
+ erase(f); rename(tempf,string(game)+".SEZ");
+}
+
+void general()
+{
+ char r;
+;
+ do {
+ textattr=31;
+ output << NL; output << string(game)+".SEZ" << NL;
+ output << NL;
+ output << "No. of chains: " << sezhead.chains << NL;
+ output << NL;
+ output << "Choose one of these:" << NL;
+ output << " A) Add a new scrollchain" << NL;
+ output << " E) Edit one" << NL;
+ output << "Esc) Exit" << NL;
+ output << NL;
+ output << "Your choice? ";
+ r=upcase(readkey()); output << r << NL;
+ switch (r) {
+ case 'A': addone(); break;
+ case 'E': particular(); break;
+ case '\33': exit(0); break;
+ }
+ } while (!false);
+}
+
+void loadit()
+{;
+ reset(f,1);
+ blockread(f,junk,255);
+ blockread(f,sezhead,sizeof(sezhead));
+ close(f);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ assign(f,string(game)+".SEZ");
+ assign(tempf,"sez.tmp");
+ assign(nicknames,string(game)+".NIK");
+ loadit();
+ graphics();
+ titles();
+ general();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/sezunit.cpp b/engines/avalanche/sezunit.cpp
new file mode 100644
index 0000000000..755f247f8d
--- /dev/null
+++ b/engines/avalanche/sezunit.cpp
@@ -0,0 +1,76 @@
+#include "ptoc.h"
+
+#define __sezunit_implementation__
+
+
+#include "sezunit.h"
+
+
+struct markertype {
+ word length;
+ longint offset;
+ byte checksum;
+};
+
+untyped_file f;
+longint number;
+markertype marker;
+word fv;
+byte sum;
+
+void sez_setup() /* This procedure sets up the Sez system (obviously!) */
+{;
+
+ /* Set up variables */
+
+ fillchar(chain,sizeof(chain),'\261'); /* blank out gunk in "chain" */
+ chainsize=0; /* it's empty (for now...) */
+ sezerror=sezok; /* everything's fine! */
+
+ /* Set up AVALOT.SEZ */
+
+ assign(f,"avalot.sez"); reset(f,1);
+ seek(f,255); blockread(f,sezhead,sizeof(sezhead));
+ if (ioresult!=0) {; sezerror=sezgunkyfile; return; } /* too short */
+ {;
+ if ((sezhead.initials!="TT") || (sezhead.gamecode!=thisgamecode)
+ || (sezhead.revision!=thisvercode))
+ {;
+ sezerror=sezgunkyfile; /* not a valid file */
+ return;
+ }
+ }
+}
+
+byte sumup()
+{
+ word fv; byte total;
+byte sumup_result;
+;
+ total=0;
+ for( fv=0; fv <= chainsize; fv ++)
+ {;
+ total += ord(chain[fv]);
+ }
+ sumup_result=total;
+return sumup_result;
+}
+
+void getchain(longint number)
+{;
+ seek(f,longint(262)+number*longint(7)); blockread(f,marker,7);
+ {;
+ seek(f,longint(270)+sezhead.chains*longint(7)+marker.offset);
+ blockread(f,chain,marker.length+1);
+ for( fv=0; fv <= marker.length; fv ++) chain[fv] -= 3+177*fv*marker.length; /* unscramble */
+ chainsize=marker.length;
+ if (sumup()!=marker.checksum)
+ {;
+ sezerror=sezhacked;
+ return;
+ }
+ }
+ close(f);
+ sezerror=sezok; /* nowt went wrong */
+}
+
diff --git a/engines/avalanche/sezunit.h b/engines/avalanche/sezunit.h
new file mode 100644
index 0000000000..6b0a99ee54
--- /dev/null
+++ b/engines/avalanche/sezunit.h
@@ -0,0 +1,42 @@
+#ifndef __sezunit_h__
+#define __sezunit_h__
+
+
+/*#include "Gyro.h"*/
+
+
+struct sezheader {
+ array<1,2,char> initials; /* should be "TT" */
+ word gamecode;
+ word revision; /* as 3- or 4-digit code (eg v1.00 = 100) */
+ longint chains; /* number of scroll chains */
+ longint size; /* total size of all chains */
+};
+
+
+
+#ifdef __sezunit_implementation__
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN array<0,1999,char> chain; /* This chain */
+EXTERN word chainsize; /* Length of "chain" */
+EXTERN byte sezerror; /* Error code */
+EXTERN sezheader sezhead;
+#undef EXTERN
+#define EXTERN extern
+
+
+ /* Error codes for "sezerror" */
+const integer sezok = 0;
+const integer sezgunkyfile = 1;
+const integer sezhacked = 2;
+
+
+void sez_setup();
+
+void getchain(longint number);
+
+
+#endif
diff --git a/engines/avalanche/sezxfr.cpp b/engines/avalanche/sezxfr.cpp
new file mode 100644
index 0000000000..bcc460346d
--- /dev/null
+++ b/engines/avalanche/sezxfr.cpp
@@ -0,0 +1,95 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+ /*$V-*/
+text t;
+string x;
+matrix<1,100,1,2,string> data;
+word dp,ip,fv;
+array<1,20,word> index1;
+array<1,20,varying_string<10> > names;
+array<1,1777,longint> thumb; longint total;
+untyped_file f;
+
+void strip() {; x=copy(x,2,255); }
+
+void squish(string& q)
+{
+ string n; boolean ctrl; byte fv;
+;
+ ctrl=false; n="";
+ for( fv=1; fv <= length(q); fv ++)
+ if (q[fv]=='^') ctrl=true; else
+ {; /* not a caret */
+ if (ctrl) q[fv]=chr(ord(upcase(q[fv]))-64);
+ n=n+q[fv]; ctrl=false;
+ }
+ while (n[length(n)]=='\40') n[0] -= 1; /* strip trailing spaces */
+ for( fv=1; fv <= length(n); fv ++) n[fv] += 177; /* scramble */
+ q=n;
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ dp=0; ip=0; fillchar(data,sizeof(data),'\0');
+ fillchar(thumb,sizeof(thumb),'\261');
+ fillchar(index1,sizeof(index1),'\3');
+ assign(t,"v:sez.dat"); reset(t);
+ while (! eof(t))
+ {;
+ t >> x >> NL;
+ switch (x[1]) {
+ case ';': {; textattr=lightred; strip(); } break;
+ case ':': {;
+ textattr=lightblue; strip();
+ if (dp>0) squish(data[dp][2]);
+ dp += 1; data[dp][1]=x;
+ if (pos("*",x)>0)
+ {; /* index */
+ ip += 1; index1[ip]=dp; names[ip]=copy(x,1,pos("*",x)-1);
+ }
+ }
+ break;
+ default:
+ {;
+ textattr=white;
+ data[dp][2]=data[dp][2]+x+'\40';
+ }
+ }
+ output << x << NL;
+ }
+ squish(data[dp][2]);
+
+ total=1;
+ for( fv=1; fv <= dp; fv ++)
+ {;
+ thumb[fv]=total;
+ total += length(data[fv][2])+1;
+ }
+
+ thumb[dp+1]=total;
+
+ /* save it all! Firstly, the Sez file... */
+
+ assign(f,"v:avalot.sez"); rewrite(f,1);
+ x=string("This is a Sez file for an Avvy game, and it's copyright!")+'\32';
+ blockwrite(f,x[1],57);
+ blockwrite(f,dp,2); blockwrite(f,ip,2);
+ blockwrite(f,index1,40);
+ blockwrite(f,thumb,dp*4+4);
+ for( fv=1; fv <= dp; fv ++)
+ blockwrite(f,data[fv][2],length(data[fv][2])+1);
+ close(f);
+
+ /* ...then the Sed file. */
+
+ assign(t,"v:avalot.sed"); rewrite(t);
+ for( fv=1; fv <= ip; fv ++) t << names[fv] << NL;
+ for( fv=1; fv <= dp; fv ++) t << data[fv][1] << NL;
+ close(t);
+
+ /* Done! */
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/shell1.cpp b/engines/avalanche/shell1.cpp
new file mode 100644
index 0000000000..e8dfb592a3
--- /dev/null
+++ b/engines/avalanche/shell1.cpp
@@ -0,0 +1,36 @@
+#include "ptoc.h"
+
+
+/*$M $800,0,0*/
+/*#include "Dos.h"*/
+
+struct infotype {
+ matrix<128,255,1,8,byte> chars;
+ string data;
+};
+infotype table;
+pointer where;
+string comspec;
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ getintvec(0x1f,where); move(where,table,1280);
+ comspec=getenv("comspec");
+ table.data=table.data+"Avalot;";
+ setintvec(0x1f,&table);
+ output << NL;
+ output << "The Astounding Avvy DOS Shell... don't forget to register!" << NL;
+ output << NL;
+ output << "Use the command EXIT to return to your game." << NL;
+ output << NL;
+ output << "Remember: You *mustn't* load any TSRs while in this DOS shell." << NL;
+ output << NL;
+ output << "This includes: GRAPHICS, PRINT, DOSKEY, and pop-up programs (like Sidekick.)" << NL;
+ output << NL;
+ output << "About to execute \"" << comspec << "\"..." << NL;
+ swapvectors;
+ exec("c:\\command.com","");
+ swapvectors;
+ setintvec(0x1f,where);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/shell2.cpp b/engines/avalanche/shell2.cpp
new file mode 100644
index 0000000000..053bca9eed
--- /dev/null
+++ b/engines/avalanche/shell2.cpp
@@ -0,0 +1,26 @@
+#include "ptoc.h"
+
+
+/*#include "Dos.h"*/
+#include "graph.h"
+
+struct infotype {
+ matrix<128,255,1,8,byte> chars;
+ string data;
+};
+infotype table;
+pointer where;
+integer gd,gm;
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ getintvec(0x1f,where); move(where,table,1280);
+ gd=1; gm=0; initgraph(gd,gm,"c:\\turbo");
+ output << "Now in CGA low-res 320x200." << NL;
+ output << "High ASCII codes work- œœœ °±² ðððññóòôõ" << NL;
+ output << "And the code is..." << NL;
+ output << table.data << NL;
+ output << "Press Enter..." << NL;
+ input >> NL; closegraph();
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/slope.cpp b/engines/avalanche/slope.cpp
new file mode 100644
index 0000000000..a4b2f8a2de
--- /dev/null
+++ b/engines/avalanche/slope.cpp
@@ -0,0 +1,349 @@
+#include "ptoc.h"
+
+
+
+struct joysetup {
+ word xmid,ymid,xmin,ymin,xmax,ymax;
+ byte centre; /* Size of centre in tenths */
+};
+
+const integer bug_twonames = 255;
+const integer bug_pandl = 254;
+const integer bug_weirdswitch = 253;
+const integer bug_invalidini = 252;
+const integer bug_notyesorno = 251;
+const integer bug_weirdcard = 250;
+
+byte fv;
+char t;
+string bugline;
+boolean usingp,usingl;
+boolean zoomy,numlockhold;
+boolean doing_syntax;
+joysetup js; boolean use_joy_a;
+
+boolean filename_specified;
+boolean soundfx;
+
+string inihead,initail; /* For reading the .INI file. */
+
+string filetoload;
+
+boolean cl_override,keyboardclick,demo;
+
+string slopeline;
+
+word storage_seg,storage_ofs;
+
+string argon;
+
+longint soundcard,baseaddr,speed,irq,dma;
+
+string strf(longint x)
+{
+ string q;
+
+ string strf_result;
+ str(x,q); strf_result=q;
+ return strf_result;
+}
+
+void linebug(byte which)
+{
+ output << "AVALOT : ";
+ switch (which) {
+ case bug_twonames : output << "You may only specify ONE filename." << NL; break;
+ case bug_pandl : output << "/p and /l cannot be used together." << NL; break;
+ case bug_weirdswitch : output << "Unknown switch (\"" << bugline <<
+ "\"). Type AVALOT /? for a list of switches." << NL;
+ break;
+ case bug_invalidini: output << "Invalid line in AVALOT.INI (\"" << bugline << "\")" << NL; break;
+ case bug_notyesorno: output << "Error in AVALOT.INI: \"" << inihead << "\" must be \"yes\" or \"no.\"" << NL; break;
+ case bug_weirdcard: output << "Unknown card: " << bugline << '.' << NL; break;
+ }
+
+ exit(which);
+}
+
+longint card(string x)
+{
+ longint card_result;
+ if (x=="NONE") card_result=0; else
+ if (x=="SB") card_result=1; else
+ if (x=="SBPRO") card_result=2; else
+ if (x=="SB16") card_result=3; else
+ if (x=="PAS") card_result=4; else
+ if (x=="PASPLUS") card_result=5; else
+ if (x=="PAS16") card_result=6; else
+ if (x=="ARIA") card_result=7; else
+ if (x=="WINSOUND") card_result=8; else
+ if (x=="GRAVIS") card_result=9; else
+ if (x=="DACLPT") card_result=10; else
+ if (x=="STEREODACS") card_result=11; else
+ if (x=="STEREOON1") card_result=12; else
+ if (x=="SPEAKER") card_result=13; else
+ linebug(bug_weirdcard);
+ return card_result;
+}
+
+void upstr(string& x)
+{
+ byte fv;
+
+ for( fv=1; fv <= length(x); fv ++) x[fv]=upcase(x[fv]);
+}
+
+boolean yesno()
+{
+ boolean yesno_result;
+ if (initail=="YES") yesno_result=true; else
+ if (initail=="NO") yesno_result=false; else
+ linebug(bug_notyesorno);
+ return yesno_result;
+}
+
+word value(string x)
+{
+ const varying_string<15> hexdigits = "0123456789ABCDEF";
+ word w; integer e;
+
+ word value_result;
+ if (x[1]=='$')
+ {
+ w=0;
+ for( e=2; e <= length(x); e ++)
+ {
+ w=w << 4;
+ w += pos(upcase(x[e]),hexdigits)-1;
+ }
+ value_result=w;
+ } else
+ {
+ val(x,w,e);
+ if (e==0) value_result=w; else value_result=0;
+ }
+ return value_result;
+}
+
+void ini_parse()
+{
+ upstr(inihead);
+ upstr(initail);
+
+ if (inihead=="QUIET") soundfx=! yesno(); else
+ if (inihead=="ZOOMYSTART") zoomy=yesno(); else
+ if (inihead=="NUMLOCKHOLD") numlockhold=yesno(); else
+ if (inihead=="LOADFIRST") filetoload=initail; else
+ if (inihead=="OVERRIDEEGACHECK") cl_override=yesno(); else
+ if (inihead=="KEYBOARDCLICK") keyboardclick=yesno(); else
+ if (inihead=="JOYTOP") js.ymin=value(initail); else
+ if (inihead=="JOYBOTTOM") js.ymax=value(initail); else
+ if (inihead=="JOYLEFT") js.xmin=value(initail); else
+ if (inihead=="JOYRIGHT") js.xmax=value(initail); else
+ if (inihead=="JOYMIDX") js.xmid=value(initail); else
+ if (inihead=="JOYMIDY") js.ymid=value(initail); else
+ if (inihead=="JOYCENTRINGFACTOR") js.centre=value(initail); else
+ if (inihead=="WHICHJOY") use_joy_a=value(initail)==1; else
+ if (inihead=="SOUNDCARD") soundcard=card(initail); else
+ if (inihead=="BASEADDRESS") baseaddr=value(initail); else
+ if (inihead=="IRQ") irq=value(initail); else
+ if (inihead=="DMA") dma=value(initail); else
+ if (inihead=="SAMPLERATE") speed=value(initail);
+}
+
+void strip_ini()
+{
+ byte fv;
+
+ if (inihead=="") return;
+
+ /* Firstly, delete any comments. */
+ fv=pos(";",inihead);
+ if (fv>0) Delete(inihead,fv,255);
+
+ /* Lose the whitespace... */
+
+ while (inihead[length(inihead)]==' ') inihead[0] -= 1;
+ while ((inihead!="") && (inihead[1]==' ')) Delete(inihead,1,1);
+
+ /* It's possible that now we'll end up with a blank line. */
+
+ if ((inihead=="") || (inihead[1]=='[')) return;
+
+ fv=pos("=",inihead);
+
+ if (fv==0)
+ { /* No "="! Weird! */
+ bugline=inihead;
+ linebug(bug_invalidini);
+ }
+
+ initail=copy(inihead,fv+1,255);
+ inihead[0]=chr(fv-1);
+}
+
+void load_ini()
+{
+ text ini;
+
+ assign(ini,"AVALOT.INI");
+ reset(ini);
+
+ while (! eof(ini))
+ {
+ ini >> inihead >> NL;
+ strip_ini();
+ if (inihead!="") ini_parse();
+ }
+
+ close(ini);
+}
+
+void parse(string x);
+static string arg;
+
+static string getarg(string otherwis)
+{
+ string getarg_result;
+ if (arg=="") getarg_result=otherwis; else getarg_result=arg;
+ return getarg_result;
+}
+
+void parse(string x)
+
+{
+ switch (x[1]) {
+ case '/':case '-': {
+ arg=copy(x,3,255);
+ switch (upcase(x[2])) {
+ case '?': doing_syntax=true; break;
+ case 'O': cl_override=true; break;
+ case 'L': if (! usingp)
+ {
+ usingl=true;
+ argon=getarg("avvy.log");
+ } else linebug(bug_pandl);
+ break;
+ case 'P': if (! usingl)
+ {
+ usingp=true;
+ argon=getarg("prn");
+ } else linebug(bug_pandl);
+ break;
+ case 'Q': soundfx=false; break;
+ case 'Z': zoomy=true; break;
+ case 'K': keyboardclick=true; break;
+ case 'D': demo=true; break;
+ default: {
+ bugline=x;
+ linebug(bug_weirdswitch);
+ }
+ }
+ }
+ break;
+ case '*': {
+ inihead=copy(x,2,255);
+ strip_ini();
+ if (inihead!="") ini_parse();
+ }
+ break;
+ default: { /* filename */
+ if (filename_specified)
+ linebug(bug_twonames);
+ else
+ filetoload=x;
+ filename_specified=true;
+ }
+ }
+}
+
+void make_slopeline();
+
+static char yn1(boolean b)
+{
+ char yn1_result;
+ if (b) yn1_result='y'; else yn1_result='n';
+ return yn1_result;
+}
+
+
+
+static char pln()
+{
+ char pln_result;
+ if ((! usingp) && (! usingl)) pln_result='n'; else
+ if (usingp) pln_result='p'; else
+ if (usingl) pln_result='l';
+ return pln_result;
+}
+
+void make_slopeline()
+
+{
+ if (argon=="") argon="nul";
+
+ slopeline=string('1')+yn1(doing_syntax)+yn1(soundfx)+yn1(cl_override)+
+ yn1(keyboardclick)+pln()+yn1(demo)+yn1(zoomy)+yn1(numlockhold)+
+ yn1(use_joy_a)+
+ ' '+strf(js.xmid)+
+ ' '+strf(js.ymid)+
+ ' '+strf(js.xmin)+
+ ' '+strf(js.ymin)+
+ ' '+strf(js.xmax)+
+ ' '+strf(js.ymax)+
+ ' '+strf(js.centre)+
+ ' '+argon+' '+filetoload;
+}
+
+void store_slopeline()
+{
+ move(slopeline,mem[storage_seg*storage_ofs+3],sizeof(slopeline));
+ move(js,mem[storage_seg*storage_ofs+300],sizeof(js));
+ move(soundcard,mem[storage_seg*storage_ofs+5000],4);
+ move(baseaddr,mem[storage_seg*storage_ofs+5004],4);
+ move(irq,mem[storage_seg*storage_ofs+5008],4);
+ move(dma,mem[storage_seg*storage_ofs+5012],4);
+ move(speed,mem[storage_seg*storage_ofs+5016],4);
+}
+
+void get_storage_addr();
+
+static void not_through_bootstrap()
+{ output << "Not standalone!" << NL; exit(255); }
+
+void get_storage_addr()
+{
+ integer e;
+
+ if (paramstr(1)!="jsb") not_through_bootstrap();
+ val(paramstr(2),storage_seg,e); if (e!=0) not_through_bootstrap();
+ val(paramstr(3),storage_ofs,e); if (e!=0) not_through_bootstrap();
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ get_storage_addr();
+
+ filetoload=""; argon="";
+ usingl=false;
+ usingp=false;
+ cl_override=false;
+ soundfx=true;
+ zoomy=false;
+ numlockhold=false;
+ filename_specified=false;
+ keyboardclick=false;
+ doing_syntax=false;
+ soundcard=0; baseaddr=0; irq=0; dma=0;
+
+ load_ini();
+
+ for( fv=4; fv <= paramcount; fv ++)
+ parse(paramstr(fv));
+
+ make_slopeline();
+
+ store_slopeline();
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/spread.cpp b/engines/avalanche/spread.cpp
new file mode 100644
index 0000000000..57361e8b46
--- /dev/null
+++ b/engines/avalanche/spread.cpp
@@ -0,0 +1,306 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+
+struct adxtype {
+ varying_string<12> name; /* name of character */
+ byte num; /* number of pictures */
+ byte xl,yl; /* x & y lengths of pictures */
+ byte seq; /* how many in one stride */
+ word size; /* the size of one picture */
+ byte fgc,bgc; /* foreground & background bubble colours */
+};
+
+varying_string<3> sn;
+adxtype a;
+matrix<1,24,0,1,pointer> pic; /* the pictures themselves */
+word bigsize;
+
+const array<0,15,varying_string<6> > col =
+ {{"Black","Blue","Green","Cyan","Red","Pink","Brown","Grey+",
+ "Grey-","Blue+","Green+","Cyan+","Red+","Pink+","Yellow","White"}};
+const string prompt = string('\32')+'\257';
+
+void load()
+{
+ untyped_file f; byte gd,gm,sort,n; pointer p,q;
+;
+ assign(f,string("v:sprite")+sn+".avd"); reset(f,1); seek(f,59);
+ blockread(f,a,sizeof(a)); blockread(f,bigsize,2);
+ setactivepage(3);
+ for( sort=0; sort <= 1; sort ++)
+ {;
+ mark(q); getmem(p,bigsize);
+ blockread(f,p,bigsize);
+ putimage(0,0,p,0); release(q); n=1;
+ for( gm=0; gm <= (a.num / a.seq)-1; gm ++) /* directions */
+ for( gd=0; gd <= a.seq-1; gd ++) /* steps */
+ {;
+ getmem(pic[n][sort],a.size); /* grab the memory */
+ getimage((gm / 2)*(a.xl*6)+gd*a.xl,(gm % 2)*a.yl,
+ (gm / 2)*(a.xl*6)+gd*a.xl+a.xl-1,(gm % 2)*a.yl+a.yl-1,
+ pic[n][sort]); /* grab the pic */
+ n += 1;
+ }
+ }
+ close(f); setactivepage(0);
+}
+
+void save()
+{
+ untyped_file f; byte gd,gm,sort,n; pointer p,q;
+ string x; integer txl,tyl;
+;
+ {;
+ txl=a.seq*a.xl*2; tyl=a.yl*2;
+ }
+
+ assign(f,string("v:sprite")+sn+".avd");
+ x=string("Sprite file for Avvy - Trippancy IV. Subject to copyright.")+'\32';
+ rewrite(f,1); blockwrite(f,x[1],59);
+
+ blockwrite(f,a,sizeof(a)); blockwrite(f,bigsize,2);
+ setactivepage(3);
+ for( sort=0; sort <= 1; sort ++)
+ {;
+ mark(q); getmem(p,bigsize); n=1;
+ for( gm=0; gm <= (a.num / a.seq)-1; gm ++) /* directions */
+ for( gd=0; gd <= a.seq-1; gd ++) /* steps */
+ {;
+ putimage((gm / 2)*(a.xl*6)+gd*a.xl,(gm % 2)*a.yl,
+ pic[n][sort],0); /* drop the pic */
+ n += 1;
+ }
+ getimage(0,0,txl,tyl,p);
+ blockwrite(f,p,bigsize); release(q);
+ }
+ close(f); setactivepage(0);
+}
+
+void setup()
+{
+ integer gd,gm;
+;
+ output << "SPREAD (c) 1992, Thomas Thurman." << NL; output << NL;
+ output << "Enter number of SPRITE*.AVD file to edit:"; input >> sn >> NL;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+}
+
+string strf(longint x)
+{
+ string q;
+string strf_result;
+;
+ str(x,q); strf_result=q;
+return strf_result;
+}
+
+void likethis()
+{;
+ {;
+ setfillstyle(1,a.bgc); setcolor(a.fgc); settextstyle(0,0,1);
+ bar(0,190,100,200); outtextxy(12,191,"Like this!");
+ }
+}
+
+void values()
+{
+ byte fv;
+;
+ settextstyle(2,0,9); setcolor(14);
+ outtextxy(277,0,string("Spread: editing ")+sn); setcolor(15);
+ for( fv=0; fv <= 3; fv ++) putimage(77+(a.xl+10)*fv,17,pic[a.seq*fv+1][1],0);
+ settextstyle(2,0,7);
+ outtextxy(0, 30,"Views:");
+ {;
+ outtextxy(0, 50,string("N: Name: ")+a.name);
+ outtextxy(0, 70,string("No. of pictures: ")+strf(a.num)+" ("+strf(a.num / a.seq)+" ways)");
+ outtextxy(0, 90,string("XY: Size: ")+strf(a.xl)+'x'+strf(a.yl));
+ outtextxy(0,110,string("S: Stride size: ")+strf(a.seq));
+ outtextxy(0,130,string("Imagesize (bytes): ")+strf(a.size));
+ outtextxy(0,150,string("B: Bubble background: ")+col[a.bgc]);
+ outtextxy(0,170,string("F: Bubble foreground: ")+col[a.fgc]);
+ likethis();
+ }
+ setcolor(lightgreen); settextstyle(0,0,1);
+ outtextxy(400,50,"A) Animate");
+ outtextxy(400,60,"E) Edit pictures");
+ outtextxy(400,70,"alt-f2) Save");
+ outtextxy(400,80,"ctrl-f3) Load");
+ outtextxy(400,90,"or any key to the left...");
+}
+
+byte ccol()
+{
+ byte fv;
+byte ccol_result;
+;
+ restorecrtmode();
+ output << "Choose a colour- one of these..." << NL;
+ for( fv=0; fv <= 15; fv ++)
+ {;
+ textattr=14; output << fv << ") "; textattr=fv; output << string('\376')+'\40';
+ textattr=14; output << col[fv] << NL;
+ }
+ textattr=14;
+ do {
+ output << prompt; input >> fv >> NL;
+ } while (!(fv<16));
+ ccol_result=fv; setgraphmode(0);
+return ccol_result;
+}
+
+string cstr(string oc)
+{
+ string x;
+string cstr_result;
+;
+ restorecrtmode();
+ output << string("Old choice is: <")+oc+'>' << NL;
+ output << NL;
+ output << "(Anything after a semi-colon will not be displayed by the game, e.g. Avvy;Monk" << NL;
+ output << " will be displayed as Avvy.)" << NL;
+ output << NL;
+ output << string("New choice, Enter for no change, Space+Enter for a blank?")+prompt; input >> x >> NL;
+ if (x=="") cstr_result=oc; else if (x==' ') cstr_result=""; else cstr_result=x;
+ setgraphmode(0);
+return cstr_result;
+}
+
+longint cnum(longint on)
+{
+ string x; longint q; integer e;
+longint cnum_result;
+;
+ restorecrtmode();
+ do {
+ output << "Old value is: " << on << '.' << NL;
+ output << string("New choice, or Enter for no change?")+prompt; input >> x >> NL;
+ if (x=="")
+ {;
+ e=0; /* must be OK here */ q=on;
+ } else val(x,q,e);
+ if (e!=0) output << x << " isn't a number, silly!" << NL;
+ } while (!(e==0));
+ setgraphmode(0); cnum_result=q;
+return cnum_result;
+}
+
+void animate()
+{
+ byte facing,step,slow,fv;
+;
+ cleardevice();
+ settextstyle(0,0,2); setcolor(12); outtextxy(0,0,"Animate");
+ settextstyle(0,0,1); setcolor(15);
+ outtextxy(0,20,"Enter = Turn, + = Faster, - = Slower, Esc = stop this.");
+ facing=0; step=1; slow=100;
+ do {
+ for( fv=0; fv <= 1; fv ++)
+ putimage(200*fv+177,77,pic[facing*a.seq+step][fv],4-fv*4);
+ if (keypressed())
+ switch (upcase(readkey())) {
+ case '\15': {;
+ facing += 1; if (facing*a.seq>=a.num) facing=0;
+ }
+ break;
+ case '\33': {; cleardevice(); return; } break;
+ case '+': if (slow>0) slow -= 5; break;
+ case '-': if (slow<255) slow += 5; break; default: output << '\7';
+ }
+ step += 1; if (step>a.seq) step=1;
+ delay(slow);
+ } while (!false);
+}
+
+byte tabpel(integer x,integer y)
+{byte tabpel_result;
+;
+ if (getpixel(400+x,17+y)==15) tabpel_result=17;
+ else tabpel_result=getpixel(500+x,17+y);
+return tabpel_result;
+}
+
+void bigpixel(integer x,integer y, byte size,byte col)
+{;
+ if (col==17) setfillstyle(9,8); else setfillstyle(1,col);
+ bar(x*size,y*size,x*size+size-2,y*size+size-2);
+}
+
+void blowup(byte n)
+{
+ byte fv,x,y,xyl;
+;
+ {;
+ for( fv=0; fv <= 1; fv ++) putimage(400+fv*100,17,pic[n][fv],0);
+ xyl=200 / a.yl;
+ for( x=0; x <= a.xl; x ++)
+ for( y=0; y <= a.yl; y ++)
+ bigpixel(x,y,xyl,tabpel(x,y));
+ }
+}
+
+void edit();
+
+static void putnum(byte x,byte p)
+{
+ varying_string<2> z;
+;
+ str(x,z); outtextxy(x*53+17,87,z); putimage(x*53,100,pic[p][1],0);
+}
+
+
+static void title()
+{;
+ cleardevice(); setcolor(11); settextstyle(0,0,2);
+ outtextxy(0,0,"Edit- which one?"); settextstyle(0,0,1); setcolor(15);
+}
+
+void edit()
+{
+ byte fv,ra,rb;
+;
+ {;
+ title(); for( fv=1; fv <= (a.num / a.seq); fv ++) putnum(fv,fv*a.seq);
+ do { ra=ord(readkey())-48; } while (!(ra<(a.num / a.seq))); ra -= 1;
+ title(); for( fv=1; fv <= a.seq; fv ++) putnum(fv,ra*a.seq+fv);
+ do { rb=ord(readkey())-48; } while (!(rb<a.seq));
+ cleardevice();
+ blowup(ra*a.seq+rb); input >> NL;
+ cleardevice();
+ }
+}
+
+void pickone()
+{
+ char r;
+;
+ r=upcase(readkey());
+ switch (r) {
+ case 'N': a.name=cstr(a.name); break;
+ case 'S': a.seq=cnum(a.seq); break;
+ case 'F': a.fgc=ccol(); break;
+ case 'B': a.bgc=ccol(); break;
+ case 'A': animate(); break;
+ case 'E': edit(); break;
+ case '\0': switch (readkey()) {
+ case 'i': save(); break; /* alt-f2 */
+ }
+ break;
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ setup();
+ do {
+ values();
+ pickone();
+ } while (!false);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/spread2.cpp b/engines/avalanche/spread2.cpp
new file mode 100644
index 0000000000..96545c2bc8
--- /dev/null
+++ b/engines/avalanche/spread2.cpp
@@ -0,0 +1,855 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+/*#include "Squeak.h"*/
+
+/*$V-,R+*/
+
+const integer pattern = 12; /* Pattern for transparencies. */
+const fillpatterntype grey50 = {{0xaa, 0x55, 0xaa,
+ 0x55, 0xaa, 0x55, 0xaa, 0x55}};
+
+struct adxtype {
+ varying_string<12> name; /* name of character */
+ varying_string<16> comment; /* comment */
+ byte num; /* number of pictures */
+ byte xl,yl; /* x & y lengths of pictures */
+ byte seq; /* how many in one stride */
+ word size; /* the size of one picture */
+ byte fgc,bgc; /* foreground & background bubble colours */
+ byte accinum; /* the number according to Acci (1=Avvy, etc.) */
+};
+
+untyped_file sf;
+adxtype a;
+char r;
+boolean adxmodi,picmodi;
+array<5,2053,byte> mani;
+matrix<0,99,0,10,byte> sil;
+array<1,16000,byte> aa;
+word soa;
+byte xw;
+byte leftc,rightc;
+boolean lmo;
+array<1,2,pointer> clip;
+integer clipx,clipy;
+boolean boardfull;
+integer xofs,yofs; /* Distance of TL corner of cut from TL corner of pic. */
+
+byte bigpix_size,bigpix_gap; /* Size & gap betwixt big pixels. */
+
+void setup()
+{
+ const integer shouldid = -1317732048;
+ boolean ok;
+ longint id;
+ varying_string<2> sn;
+;
+ output << "Sprite Editor 2 (c) 1993, Thomas Thurman." << NL;
+ bigpix_size=3; bigpix_gap=5;
+ do {
+ ok=true;
+ output << "Number of sprite?"; input >> sn >> NL;
+ assign(sf,string("v:\\sprite")+sn+".avd");
+ reset(sf,1);
+ seek(sf,177);
+ blockread(sf,id,4);
+ if (id!=shouldid)
+ {;
+ output << "That isn't a valid Trip5 spritefile." << NL;
+ output << "Please choose another." << NL;
+ output << NL;
+ ok=false; close(sf);
+ } else
+ {;
+ blockread(sf,soa,2);
+ if (soa!=(cardinal)sizeof(a)) /* to change this, just change the "type adx=" bit.*/
+ {;
+ output << "That spritefile contains an unknown ADX field type." << NL;
+ output << "Please choose another." << NL;
+ output << NL;
+ ok=false; close(sf);
+ }
+ }
+ } while (!ok);
+ blockread(sf,a,soa);
+ output << filepos(sf) << NL;
+ adxmodi=false; picmodi=false;
+ getmem(clip[1],a.size); getmem(clip[2],a.size); boardfull=false;
+}
+
+string strf(longint x)
+{
+ string q;
+string strf_result;
+;
+ str(x,q); strf_result=q;
+return strf_result;
+}
+
+void centre(byte y, string z)
+{;
+ gotoxy(40-length(z) / 2,y); output << z;
+}
+
+void info(byte x,byte y, string p,string q)
+{;
+ gotoxy(x,y);
+ textattr=6; output << p+":ú";
+ textattr=11; output << q;
+ textattr=8; output << 'ú';
+}
+
+void colours(byte f,byte b)
+{;
+ gotoxy(35,11);
+ textattr=6;
+ output << "Bubbles";
+ textattr=b*16+f;
+ output << " like this! ";
+}
+
+void adxinfo()
+{;
+ {;
+ info( 5, 8,"Name",a.name);
+ info(35, 8,"Comment",a.comment);
+ info( 5, 9,"Width",strf(a.xl));
+ info(15, 9,"Height",strf(a.yl));
+ info(35, 9,"Size of one pic",strf(a.size));
+ info( 5,10,"Number in a stride",strf(a.seq));
+ info(35,10,"Number of strides",strf(a.num / a.seq));
+ info( 5,11,"Total number",strf(a.num));
+ info( 5,12,"Acci number",strf(a.accinum));
+ colours(a.fgc,a.bgc);
+ }
+}
+
+void status()
+{;
+ textattr=7;
+ clrscr;
+ textattr=10; centre(3,"Sprite Editor 2 (c) 1993, Thomas Thurman.");
+ textattr=6; gotoxy(3,7); output << "ADX information:";
+ adxinfo();
+ textattr=6;
+ gotoxy(3,14); output << "Options:";
+ gotoxy(5,15); output << "A) edit ADX information";
+ gotoxy(5,16); output << "P) edit pictures";
+ gotoxy(5,17); output << "S) save the ADX info (pics are saved automatically)";
+}
+
+void enterstring(string w, byte l, string& q)
+{
+ string t;
+;
+ textattr=13; clrscr;
+ output << NL;
+ output << "Press Return for no change, Space+Return for a blank." << NL;
+ do {
+ output << "New value for " << w << " (max length " << l << ")?";
+ input >> t >> NL;
+ } while (!(length(t)<=l));
+ if (t==' ') q=""; else if (t!="") q=t;
+ adxmodi=true;
+}
+
+void entercolour(string w, byte& c);
+static byte fv;
+
+static void loseold() {; output << string('\10')+'\377'; }
+
+
+static void drawnew() {; gotoxy(3+fv*5,11); output << '\30'; }
+
+void entercolour(string w, byte& c)
+{;
+ textattr=13; clrscr;
+ output << NL; output << "New value for " << w << '?' << NL;
+ output << " Use \32\33 to move about, Enter=OK, Esc=Cancel." << NL;
+ for( fv=1; fv <= 15; fv ++)
+ {;
+ gotoxy(3+fv*5,10); textattr=fv; output << 'þ';
+ }
+ fv=c;
+ do {
+ drawnew();
+ r=readkey();
+ switch (r) {
+ case '\33': return; break; /* no change to c */
+ case '\15': {;
+ c=fv; adxmodi=true;
+ return;
+ }
+ break;
+ case '\0': switch (readkey()) {
+ case 'G': {; loseold(); fv= 0; drawnew(); } break; /* home */
+ case 'O': {; loseold(); fv=15; drawnew(); } break; /* end */
+ case 'K': if (fv> 0) {; loseold(); fv -= 1; drawnew(); } break; /* left */
+ case 'M': if (fv<15) {; loseold(); fv += 1; drawnew(); } break; /* right */
+ }
+ break;
+ }
+ } while (!false);
+}
+
+void enternum(string w, byte& q)
+{
+ string t; integer e; byte r;
+;
+ textattr=13; clrscr;
+ output << NL;
+ output << "Press Return for no change." << NL;
+ do {
+ output << "New value for " << w << '?';
+ input >> t >> NL;
+ if (t=="") return; /* No change... */
+ val(t,r,e);
+ } while (!(e==0));
+ q=r; /* Update variable. */
+ adxmodi=true;
+}
+
+void editadx()
+{
+ char r;
+;
+ do {
+ clrscr;
+ textattr=10; centre(3,"ADX Editor:");
+ textattr= 9; centre(5,"N: Name, C: Comment, F: Foreground, B: Background, A: Accinum, X: eXit.");
+ adxinfo();
+ r=upcase(readkey());
+ switch (r) {
+ case 'N': enterstring("Name",12,a.name); break;
+ case 'C': enterstring("Comment",16,a.comment); break;
+ case 'F': entercolour("Foreground",a.fgc); break;
+ case 'B': entercolour("Background",a.bgc); break;
+ case 'A': enternum("Accinum",a.accinum); break;
+ case 'X':case '\33': return; break;
+ default: output << '\7';
+ }
+ } while (!false);
+}
+
+void saveit()
+{
+ char pak;
+ integer oldsoa;
+;
+ textattr=10; clrscr;
+ centre(7,"Saving!");
+ if (adxmodi)
+ {;
+ centre(10,"ADX information being saved...");
+ seek(sf,181); /* start of ADX info */
+ soa=sizeof(a);
+ blockread(sf,oldsoa,2);
+/* if soa=oldsoa then
+ begin;*/
+ seek(sf,181);
+ blockwrite(sf,soa,2);
+ blockwrite(sf,a,soa);
+ adxmodi=false;
+/* end else write(#7);*/
+ } else centre(10,"No changes were made to ADX...");
+ centre(25,"Press any key..."); pak=readkey();
+}
+
+void quit()
+{;
+ close(sf);
+ exit(0);
+}
+
+void getsilmani() /* Reclaims original sil & mani arrays */
+{
+ byte x,y,z; word offs;
+;
+
+ /* Sil... */
+
+ getimage(500,150,500+a.xl,150+a.yl,aa);
+
+ for( x=0; x <= 3; x ++)
+ for( y=0; y <= a.yl; y ++)
+ for( z=0; z <= (a.xl / 8); z ++)
+ {;
+ offs=5+y*xw*4+xw*x+z;
+ sil[y][z]=aa[offs];
+ }
+
+ /* ...Mani. */
+
+ getimage(500,50,500+a.xl,50+a.yl,aa);
+
+ move(aa[5],mani,sizeof(mani));
+
+}
+
+void explode(byte which) /* 0 is the first one! */
+ /* Each character takes five-quarters of (a.size-6) on disk. */
+{
+ byte fv,ff; word so1; /* size of one */
+;
+ {;
+ so1=a.size-6; so1 += so1 / 4;
+ seek(sf,183+soa+so1*which); /* First is at 221 */
+/* where:=filepos(sf);*/
+ xw=a.xl / 8; if ((a.xl % 8)>0) xw += 1;
+
+ for( fv=0; fv <= a.yl; fv ++)
+ blockread(sf,sil[fv],xw);
+ blockread(sf,mani,a.size-6);
+ aa[a.size-1]=0; aa[a.size]=0; /* footer */
+ }
+}
+
+void implode(byte which) /* Writes a pic back onto the disk */
+{
+ byte fv,ff; word so1; /* size of one */
+;
+ {;
+
+ getsilmani(); /* Restore original arrays */
+
+ so1=a.size-6; so1 += so1 / 4;
+ seek(sf,183+soa+so1*which); /* First is at 221 */
+
+ xw=a.xl / 8; if ((a.xl % 8)>0) xw += 1;
+
+ for( fv=0; fv <= a.yl; fv ++)
+ blockwrite(sf,sil[fv],xw);
+ blockwrite(sf,mani,a.size-6);
+ aa[a.size-1]=0; aa[a.size]=0; /* footer */
+ }
+}
+
+void plotat(integer xx,integer yy) /* Does NOT cameo the picture!*/
+{;
+ move(mani,aa[5],sizeof(mani));
+ {;
+ aa[1]=a.xl; aa[2]=0; aa[3]=a.yl; aa[4]=0; /* set up x&y codes */
+ }
+ putimage(xx,yy,aa,0);
+}
+
+void plotsil(integer xx,integer yy) /* Plots silhouette- rarely used */
+{
+ byte x,y,z; word offs;
+;
+ for( x=0; x <= 3; x ++)
+ for( y=0; y <= a.yl; y ++)
+ for( z=0; z <= (a.xl / 8); z ++)
+ {;
+ offs=5+y*xw*4+xw*x+z;
+ aa[offs]=sil[y][z];
+ }
+
+ {;
+ aa[1]=a.xl; aa[2]=0; aa[3]=a.yl; aa[4]=0; /* set up x&y codes */
+ }
+
+ putimage(xx,yy,aa,0);
+
+}
+
+void style(byte x)
+{;
+ if (x==16)
+ /*setfillstyle(pattern,8)*/setfillpattern(grey50,8);
+ else
+ setfillstyle(1,x);
+}
+
+void bigpixel(integer x,integer y)
+{;
+ if (getpixel(500+x,150+y)==15)
+ /*setfillstyle(pattern,8)*/setfillpattern(grey50,8);
+ else
+ setfillstyle(1,getpixel(500+x,50+y));
+
+ bar(x*bigpix_gap,y*bigpix_gap,
+ x*bigpix_gap+bigpix_size,y*bigpix_gap+bigpix_size);
+}
+
+void subplot(byte y, integer x, char c)
+{;
+ setfillstyle(1,0); bar(x,0,x+9,170); outtextxy(x+5,y*10+5,c);
+}
+
+void plotleft() {; subplot( leftc,239,'\32'); } /* palette arrows */
+void plotright() {; subplot(rightc,351,'\33'); }
+
+void plotbig(byte x,byte y,byte c)
+{;
+ style(c);
+ bar(x*bigpix_gap,y*bigpix_gap,
+ x*bigpix_gap+bigpix_size,y*bigpix_gap+bigpix_size);
+ if (c==16)
+ {;
+ putpixel(500+x,150+y,15);
+ putpixel(500+x, 50+y,0);
+ } else
+ {;
+ putpixel(500+x,150+y,0);
+ putpixel(500+x, 50+y,c);
+ }
+}
+
+void changepic()
+{;
+ mx=mx / bigpix_gap; my=my / bigpix_gap;
+ if ((mx>a.xl) || (my>a.yl)) return;
+ if (mkey==left)
+ plotbig(mx,my,leftc); else
+ plotbig(mx,my,rightc);
+}
+
+void changecol()
+{;
+ my=my / 10; if (my>16) return;
+ if (mkey==left)
+ {;
+ leftc=my; plotleft();
+ } else
+ {;
+ rightc=my; plotright();
+ }
+}
+
+void showcutpic()
+{;
+ setfillstyle(5,1); bar(20,160,40+clipx,180+clipy);
+ putimage(30,170,clip[2],andput);
+ putimage(30,170,clip[1],xorput);
+}
+
+void movesquare(integer& xc,integer& yc, integer xl,integer yl)
+{
+ integer x2,y2;
+;
+ do {
+ x2=xl+xc; y2=yl+yc;
+ setcolor(15);
+ do {
+ rectangle(xc*bigpix_gap-1,yc*bigpix_gap-1,
+ x2*(bigpix_gap+1)-1,y2*(bigpix_gap+1)-1);
+ } while (!keypressed());
+ setcolor(0); rectangle(xc*bigpix_gap-1,yc*bigpix_gap-1,
+ x2*(bigpix_gap+1)-1,y2*(bigpix_gap+1)-1);
+ switch (readkey()) {
+ case '\0': switch (readkey()) {
+ case '\110': yc -= 1; break;
+ case '\113': xc -= 1; break;
+ case '\115': xc += 1; break;
+ case '\120': yc += 1; break;
+ }
+ break;
+ case '\15': return; break;
+ }
+ while ((xl+xc)>a.xl) xc -= 1;
+ while ((yl+yc)>a.yl) yc -= 1;
+ if (xc<0) xc=0;
+ if (yc<0) yc=0;
+ } while (!false);
+}
+
+void switch_(integer& v1,integer& v2)
+ /* Swaps over the values of v1 and v2. */
+{
+ integer temp;
+;
+ temp=v1; v1=v2; v2=temp;
+}
+
+void choosesquare(integer& x1,integer& y1,integer& x2,integer& y2)
+{
+ boolean tl;
+;
+ do {
+ setcolor(15);
+ do {
+ rectangle(x1*bigpix_gap-1,y1*bigpix_gap-1,
+ (x2+1)*bigpix_gap-1,(y2+1)*bigpix_gap-1);
+ } while (!keypressed());
+ setcolor(0);
+ rectangle(x1*bigpix_gap-1,y1*bigpix_gap-1,
+ (x2+1)*bigpix_gap-1,(y2+1)*bigpix_gap-1);
+ switch (readkey()) {
+ case '\0': switch (readkey()) {
+ case '\110': if (tl) y1 -= 1; else y2 -= 1; break;
+ case '\113': if (tl) x1 -= 1; else x2 -= 1; break;
+ case '\115': if (tl) x1 += 1; else x2 += 1; break;
+ case '\120': if (tl) y1 += 1; else y2 += 1; break;
+ }
+ break;
+ case '\11': tl=! tl; break;
+ case '\15': {;
+ if (x1>x2) switch_(x1,x2); /* Get the square the right way up. */
+ if (y1>y2) switch_(y1,y2);
+ y2 -= y1; x2 -= x1; /* y1 & y2 have to be the OFFSETS! */
+ return;
+ }
+ break;
+ }
+ if (x1<0) x1=0; if (y1<0) y1=0;
+ {;
+ if (y2>a.yl) y2=a.yl; if (x2>a.xl) x2=a.xl;
+ }
+ } while (!false);
+}
+
+void paste()
+{
+ byte x,y;
+;
+ if (! boardfull)
+ {;
+ output << '\7';
+ return;
+ }
+ if (! ((clipx==a.xl) && (clipy==a.yl)))
+ movesquare(xofs,yofs,clipx,clipy);
+ putimage(500+xofs, 50+yofs,clip[1],0);
+ putimage(500+xofs,150+yofs,clip[2],0);
+ for( x=0; x <= a.xl; x ++)
+ for( y=0; y <= a.yl; y ++)
+ {;
+ bigpixel(x,y);
+ }
+}
+
+void cut()
+{;
+ xofs=0; yofs=0; /* From the TL. */
+ {;
+ getimage(500, 50,500+a.xl, 50+a.yl,clip[1]);
+ getimage(500,150,500+a.xl,150+a.yl,clip[2]);
+ clipx=a.xl; clipy=a.yl;
+ }
+ showcutpic();
+ boardfull=true;
+}
+
+void cutsome()
+{;
+ {;
+ choosesquare(xofs,yofs,clipx,clipy);
+ getimage(500+xofs, 50+yofs,500+xofs+clipx, 50+yofs+clipy,clip[1]);
+ getimage(500+xofs,150+yofs,500+xofs+clipx,150+yofs+clipy,clip[2]);
+ }
+ showcutpic();
+ boardfull=true;
+}
+
+boolean confirm(char c, string x)
+{
+ byte col; char groi;
+boolean confirm_result;
+;
+ while (keypressed()) groi=readkey();
+ x=x+"? "+c+" to confirm.";
+ col=1;
+ do {
+ setcolor(col); outtextxy(555,5,x);
+ col += 1; if (col==16) col=1;
+ } while (!keypressed());
+ confirm_result=upcase(readkey())==c;
+ setfillstyle(1,0); bar(470,0,640,10);
+return confirm_result;
+}
+
+void checkbutton(byte which)
+{;
+ my=(my-12) / 25;
+ switch (my) {
+ case 0: if (confirm('S',"Save")) {; implode(which); lmo=true; } break;
+ case 1: if (confirm('C',"Cancel")) lmo=true; break;
+ case 4: cut(); break;
+ case 5: if (confirm('P',"Paste")) paste(); break;
+ case 6: cutsome(); break;
+ }
+}
+
+void animate()
+{;
+}
+
+void undo()
+{;
+}
+
+void fliplr();
+
+static void flipline(integer x1,integer x2,integer y)
+{
+ integer fv,ff;
+;
+ for( fv=x1; fv <= x2; fv ++) putpixel(fv,0,getpixel(fv,y));
+ ff=x2;
+ for( fv=x1; fv <= x2; fv ++)
+ {;
+ putpixel(fv,y,getpixel(ff,0));
+ ff -= 1;
+ }
+}
+
+void fliplr() /* Flips left-to-right. */
+{
+ integer fv,ff;
+;
+ for( fv=0; fv <= a.yl; fv ++)
+ {;
+ flipline(500,500+a.xl, 50+fv);
+ flipline(500,500+a.xl,150+fv);
+ }
+ for( fv=0; fv <= a.xl; fv ++)
+ for( ff=0; ff <= a.yl; ff ++)
+ bigpixel(fv,ff);
+}
+
+void change_colours() /* Swaps one colour with another. */
+{
+ byte fv,ff;
+;
+
+ if ((leftc==16) || (rightc==16)) /* See-through can't be one of the colours. */
+ {;
+ output << '\7'; /* Bleep! */
+ return;
+ }
+
+ for( fv=0; fv <= a.yl; fv ++)
+ for( ff=0; ff <= a.xl; ff ++)
+ if (getpixel(500+ff,50+fv)==leftc)
+ putpixel(500+ff,50+fv,rightc);
+
+ for( fv=0; fv <= a.xl; fv ++)
+ for( ff=0; ff <= a.yl; ff ++)
+ bigpixel(fv,ff);
+}
+
+void redraw()
+{
+ byte x,y;
+;
+ setfillstyle(1,0);
+ bar(0,0,250,200);
+
+ for( x=0; x <= a.xl; x ++)
+ for( y=0; y <= a.yl; y ++)
+ {;
+ bigpixel(x,y);
+ }
+}
+
+void parse(char c) /* Parses keystrokes */
+{;
+ switch (upcase(c)) {
+ case '\26':case 'P': paste(); break;
+ case '\3':case 'C': cut(); break;
+ case '\30':case 'X': cutsome(); break;
+ case 'A': animate(); break;
+ case 'U': undo(); break;
+ case '@': fliplr(); break;
+ case '!': change_colours(); break;
+ case '<': if (bigpix_size>1)
+ {;
+ bigpix_size -= 1; bigpix_gap -= 1;
+ redraw();
+ }
+ break;
+ case '>': if (bigpix_size<8)
+ {;
+ bigpix_size += 1; bigpix_gap += 1;
+ redraw();
+ }
+ break;
+ case '\33': if (confirm('X',"Exit")) lmo=true; break;
+ }
+}
+
+void editone(byte which)
+{
+ byte x,y;
+;
+ cleardevice();
+ explode(which);
+ plotat(500,50);
+ plotsil(500,150);
+ for( x=0; x <= a.xl; x ++)
+ for( y=0; y <= a.yl; y ++)
+ {;
+ bigpixel(x,y);
+ }
+ for( y=0; y <= 16; y ++)
+ {;
+ style(y);
+ bar(251,y*10+1,349,y*10+9);
+ rectangle(250,y*10,350,y*10+10);
+ }
+
+ settextstyle(0,0,1); leftc=15; rightc=16; plotleft(); plotright(); lmo=false;
+
+ outtextxy(410, 25,"Save");
+ outtextxy(410, 50,"Cancel");
+ outtextxy(410, 75,"Animate");
+ outtextxy(410,100,"Undo");
+ outtextxy(410,125,"Cut");
+ outtextxy(410,150,"Paste");
+ outtextxy(410,175,"X: Cut Some");
+ if (boardfull) showcutpic();
+ setfillstyle(6,15);
+ for( y=0; y <= 7; y ++)
+ bar(370,y*25+12,450,y*25+12);
+
+ do {
+ on;
+ do {
+ if (keypressed()) parse(readkey());
+ } while (!(anyo | lmo));
+ off;
+
+ if (! lmo)
+ {;
+ getbuttonstatus;
+
+ switch (mx) {
+ case 1 ... 249: changepic(); break;
+ case 250 ... 350: changecol(); break;
+ case 370 ... 450: checkbutton(which); break;
+ }
+ }
+ } while (!lmo);
+ settextstyle(2,0,7); setcolor(15);
+}
+
+void editstride(byte which);
+
+static char whichc;
+
+static shortint first;
+
+static void drawup(byte& which)
+{
+ byte fv;
+;
+ whichc=chr(which+48);
+ cleardevice();
+ outtextxy(320,10,string("Edit stride ")+whichc);
+ first=(which-1)*a.seq-1;
+ for( fv=1; fv <= a.seq; fv ++)
+ {;
+ explode(fv+first);
+ plotat(fv*73,77);
+ outtextxy(17+fv*73,64,chr(fv+48));
+ }
+ outtextxy(320,177,"Which?");
+}
+
+void editstride(byte which)
+{
+ char r;
+;
+ drawup(which);
+ do {
+ r=readkey();
+ if ((r>'0') && (r<=chr(a.seq+48)))
+ {;
+ editone(ord(r)-48+first);
+ drawup(which);
+ }
+ } while (!(r=='\33'));
+}
+
+void editpics();
+
+static byte nds; /* num div seq */
+
+static void drawup1()
+{
+ byte fv;
+;
+ setgraphmode(0); directvideo=false; settextjustify(1,1);
+ nds=a.num / a.seq;
+ settextstyle(2,0,7);
+ outtextxy(320,10,"Edit pictures...");
+ outtextxy(320,40,"(Usually, 1=away, 2=right, 3=towards, 4=left.)");
+ for( fv=1; fv <= nds; fv ++)
+ {;
+ explode((fv-1)*a.seq);
+ plotat(fv*73,100);
+ outtextxy(17+fv*73,87,chr(fv+48));
+ }
+ outtextxy(320,60,string("There are ")+strf(nds)+" strides available.");
+ outtextxy(320,177,"Which do you want?");
+}
+
+void editpics()
+{
+ char r; byte which; integer e;
+;
+ drawup1();
+ do {
+ r=readkey();
+ if ((r>'0') && (r<=chr(nds+48)))
+ {;
+ editstride(ord(r)-48);
+ drawup1();
+ }
+ } while (!(r=='\33'));
+ restorecrtmode();
+}
+
+void titles()
+{
+ integer gd,gm;
+ char pak; word wait;
+;
+ gd=3; gm=1; initgraph(gd,gm,"c:\\bp\\bgi");
+ settextstyle(5,0,10); settextjustify(1,1);
+ gm=getmaxy() / 2; wait=0;
+ do {
+ for( gm=0; gm <= 15; gm ++)
+ {;
+ setcolor(15-gm);
+ for( gd=0; gd <= (150-gm*10); gd ++)
+ {;
+ outtextxy(320,124-gd,"Spread 2");
+ outtextxy(320,125+gd,"Spread 2");
+ if ((gd==5) && (gm==0)) wait=2345;
+ if ((gd==6) && (gm==0)) wait=0;
+ do {
+ if (keypressed())
+ {;
+ while (keypressed()) pak=readkey();
+ restorecrtmode();
+ return;
+ }
+ if (wait>0) {; wait -= 1; delay(1); }
+ } while (!(wait==0));
+ }
+ }
+ } while (!false);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ titles();
+ setup();
+ do {
+ status();
+ r=upcase(readkey());
+ switch (r) {
+ case 'A': editadx(); break;
+ case 'P': editpics(); break;
+ case 'S': saveit(); break;
+ case 'X':case '\33': quit(); break;
+ }
+ } while (!false);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/squish.cpp b/engines/avalanche/squish.cpp
new file mode 100644
index 0000000000..4f8cad4f55
--- /dev/null
+++ b/engines/avalanche/squish.cpp
@@ -0,0 +1,455 @@
+#include "ptoc.h"
+
+
+
+/* This is the first version. Thanks to Pib. */
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Global declarations for PIBLZW */
+/* */
+/*--------------------------------------------------------------------------*/
+
+const integer maxbuff = 8192 /* Buffer size for input and output files */;
+const integer maxtab = 4095 /* Table size - 1 ==> 2**10-1 ==> 12 bits */;
+const integer no_prev = 0x7fff /* Special code for no previous character */;
+const integer eof_char = -2 /* Marks end of file */;
+const integer end_list = -1 /* Marks end of a list */;
+const integer empty = -3 /* Indicates empty */;
+
+typedef varying_string<255> anystr/* General string type */;
+
+ /* One node in parsing table. */
+struct string_table_entry {
+ boolean used /* Is this node used yet? */;
+ integer prevchar /* Code for preceding string */;
+ integer follchar /* Code for current character */;
+ integer next /* Next dupl in collision list */;
+};
+
+untyped_file input_file /* Input file */;
+untyped_file output_file /* Output file */;
+
+integer inbufsize /* Count of chars in input buffer */;
+
+array<1,maxbuff,byte> input_buffer /* Input buffer area */;
+array<1,maxbuff,byte> output_buffer /* Output buffer area */;
+
+integer input_pos /* Cur. pos. in input buffer */;
+integer output_pos /* Cur. pos. in output buffer */;
+
+ /* String table */
+
+array<0,maxtab,string_table_entry> string_table;
+
+integer table_used /* # string table entries used */;
+integer output_code /* Output compressed code */;
+integer input_code /* Input compressed code */;
+boolean if_compressing /* TRUE if compressing file */;
+integer ierr /* Input/output error */;
+
+string header; varying_string<30> describe; byte method;
+
+void terminate()
+
+{ /* Terminate */
+ /* Write any remaining characters */
+ /* to output file. */
+ if ( output_pos > 0 )
+ blockwrite( output_file, output_buffer, output_pos );
+
+ ierr = ioresult;
+ /* Close input and output files */
+ close( input_file );
+ ierr = ioresult;
+
+ close( output_file );
+ ierr = ioresult;
+
+ output << "done." << NL;
+
+} /* Terminate */
+
+/*--------------------------------------------------------------------------*/
+/* Get_Hash_Code --- Gets hash code for given <w>C string */
+/*--------------------------------------------------------------------------*/
+
+integer get_hash_code( integer prevc, integer follc )
+
+{
+ integer index;
+ integer index2;
+
+ /* Get_Hash_Code */
+ /* Get initial index using hashing */
+
+ integer get_hash_code_result;
+ index = ( ( prevc << 5 ) ^ follc ) & maxtab;
+
+ /* If entry not already used, return */
+ /* its index as hash code for <w>C. */
+
+ if ( ! string_table[index].used )
+ get_hash_code_result = index;
+ else
+ /* If entry already used, search to */
+ /* end of list of hash collision */
+ /* entries for this hash code. */
+ /* Do linear probe to find an */
+ /* available slot. */
+ {
+
+ /* Skip to end of collision list ... */
+
+ while ( string_table[index].next != end_list )
+ index = string_table[index].next;
+
+ /* Begin linear probe down a bit from */
+ /* last entry in collision list ... */
+
+ index2 = ( index + 101 ) & maxtab;
+
+ /* Look for unused entry using linear */
+ /* probing ... */
+
+ while ( string_table[index2].used )
+ index2 = succ(integer, index2 ) & maxtab;
+
+ /* Point prior end of collision list */
+ /* to this new node. */
+
+ string_table[index].next = index2;
+
+ /* Return hash code for <w>C */
+
+ get_hash_code_result = index2;
+
+ }
+
+ return get_hash_code_result;
+} /* Get_Hash_Code */
+
+/*--------------------------------------------------------------------------*/
+/* Make_Table_Entry --- Enter <w>C string in string table */
+/*--------------------------------------------------------------------------*/
+
+void make_table_entry( integer prevc, integer follc )
+
+{ /* Make_Table_Entry */
+ /* Only enter string if there is room left */
+
+ if ( table_used <= maxtab )
+ {
+ {
+ string_table_entry& with = string_table[ get_hash_code( prevc , follc ) ];
+
+ with.used = true;
+ with.next = end_list;
+ with.prevchar = prevc;
+ with.follchar = follc;
+ }
+ /* Increment count of items used */
+
+ table_used += 1;
+/*
+ IF ( Table_Used > ( MaxTab + 1 ) ) THEN
+ BEGIN
+ WRITELN('Hash table full.');
+ END;
+*/
+ }
+
+} /* Make_Table_Entry */
+
+/*--------------------------------------------------------------------------*/
+/* Initialize_String_Table --- Initialize string table */
+/*--------------------------------------------------------------------------*/
+
+void initialize_string_table()
+
+{
+ integer i;
+
+ /* Initialize_String_Table */
+
+ /* No entries used in table yet */
+ table_used = 0;
+ /* Clear all table entries */
+ for( i = 0; i <= maxtab; i ++)
+ {
+ string_table_entry& with = string_table[i];
+
+ with.prevchar = no_prev;
+ with.follchar = no_prev;
+ with.next = -1;
+ with.used = false;
+ }
+ /* Enter all single characters into */
+ /* table */
+ for( i = 0; i <= 255; i ++)
+ make_table_entry( no_prev , i );
+
+} /* Initialize_String_Table */
+
+/*--------------------------------------------------------------------------*/
+/* Initialize --- Initialize compression/decompression */
+/*--------------------------------------------------------------------------*/
+
+void initialize()
+
+{
+ anystr input_name /* Input file name */;
+ anystr output_name /* Output file name */;
+
+ /* Initialize */
+
+ output << "Number of file to compress:"; input >> input_name >> NL;
+ output << "For the moment, I'm writing the compressed version to v:compr" <<
+ input_name << ".avd." << NL;
+ output_name=string("d:compr")+input_name+".avd";
+ input_name=string("d:place")+input_name+".avd";
+
+ output << "Wait... ";
+
+ /* Open input file */
+
+ assign ( input_file , input_name );
+ reset ( input_file , 1 );
+ ierr = ioresult;
+
+ blockread(input_file,header,146);
+ blockread(input_file,describe,30);
+ blockread(input_file,method,1);
+
+ if (method==177)
+ {;
+ output << "It's already compressed!" << NL;
+ exit(177);
+ }
+
+ /* Open output file */
+
+ assign ( output_file , output_name );
+ rewrite( output_file , 1 );
+ ierr = ioresult;
+
+ method=177;
+
+ blockwrite(output_file,header,146);
+ blockwrite(output_file,describe,30);
+ blockwrite(output_file,method,1);
+
+ /* Point input point past end of */
+ /* buffer to force initial read */
+ input_pos = maxbuff + 1;
+ /* Nothing written out yet */
+ output_pos = 0;
+ /* Nothing read in yet */
+ inbufsize = 0;
+ /* No input or output codes yet */
+ /* constructed */
+ output_code = empty;
+ input_code = empty;
+ /* Initialize string hash table */
+ initialize_string_table();
+
+} /* Initialize */
+
+/*--------------------------------------------------------------------------*/
+/* Lookup_String --- Look for string <w>C in string table */
+/*--------------------------------------------------------------------------*/
+
+integer lookup_string( integer prevc, integer follc )
+
+{
+ integer index;
+ integer index2;
+ boolean found;
+
+ /* Lookup_String */
+ /* Initialize index to check from hash */
+
+ integer lookup_string_result;
+ index = ( ( prevc << 5 ) ^ follc ) & maxtab;
+
+ /* Assume we won't find string */
+ lookup_string_result = end_list;
+ /* Search through list of hash collision */
+ /* entries for one that matches <w>C */
+ do {
+
+ found = ( string_table[index].prevchar == prevc ) &&
+ ( string_table[index].follchar == follc );
+
+ if ( ! found )
+ index = string_table[index].next;
+
+ } while (!(found || ( index == end_list )));
+
+ /* Return index if <w>C found in table. */
+ if (found)
+ lookup_string_result = index;
+
+ return lookup_string_result;
+} /* Lookup_String */
+
+/*--------------------------------------------------------------------------*/
+/* Get_Char --- Read character from input file */
+/*--------------------------------------------------------------------------*/
+
+void get_char( integer& c )
+
+{ /* Get_Char */
+ /* Point to next character in buffer */
+ input_pos += 1;
+ /* If past end of block read in, then */
+ /* reset input pointer and read in */
+ /* next block. */
+
+ if ( input_pos > inbufsize )
+ {
+ blockread( input_file, input_buffer, maxbuff, inbufsize );
+ input_pos = 1;
+ ierr = ioresult;
+ }
+ /* If end of file hit, return EOF_Char */
+ /* otherwise return next character in */
+ /* input buffer. */
+ if ( inbufsize == 0 )
+ c = eof_char;
+ else
+ c = input_buffer[input_pos];
+
+} /* Get_Char */
+
+/*--------------------------------------------------------------------------*/
+/* Write_Char --- Write character to output file */
+/*--------------------------------------------------------------------------*/
+
+void put_char( integer c )
+
+{ /* Put_Char */
+ /* If buffer full, write it out and */
+ /* reset output buffer pointer. */
+
+ if ( output_pos >= maxbuff )
+ {
+ blockwrite( output_file, output_buffer, maxbuff );
+ output_pos = 0;
+ ierr = ioresult;
+ }
+ /* Place character in next slot in */
+ /* output buffer. */
+
+ output_pos += 1;
+ output_buffer[output_pos] = c;
+
+} /* Put_Char */
+
+/*--------------------------------------------------------------------------*/
+/* Put_Code --- Write hash code to output file. */
+/*--------------------------------------------------------------------------*/
+
+void put_code( integer hash_code )
+
+{ /* Put_Code */
+ /* Output code word is empty. */
+ /* Put out 1st 8 bits of compression */
+ /* code and save last 4 bit for next */
+ /* time through. */
+
+ if ( output_code == empty )
+ {
+ put_char( ( (cardinal)hash_code >> 4 ) & 0xff );
+ output_code = hash_code & 0xf;
+ }
+ else
+ /* Output code word not empty. */
+ /* Put out last 4 bits of previous */
+ /* code appended to 1st 4 bits of this */
+ /* code. Then put out last 8 bits of */
+ /* this code. */
+ {
+ put_char( ( ( output_code << 4 ) & 0xff0 ) +
+ ( ( (cardinal)hash_code >> 8 ) & 0xf ) );
+ put_char( hash_code & 0xff );
+ output_code = empty;
+ }
+
+} /* Put_Code */
+
+/*--------------------------------------------------------------------------*/
+/* Do_Compression --- Perform Lempel-Ziv-Welch compression */
+/*--------------------------------------------------------------------------*/
+
+void do_compression()
+
+{
+ integer c /* Current input character = C */;
+ integer wc /* Hash code value for <w>C */;
+ integer w /* Hash code value for <w> */;
+
+ /* Do_Compression */
+ /* Read first character ==> Step 2 */
+ get_char( c );
+ /* Initial hash code -- first character */
+ /* has no previous string (<w> is null) */
+
+ w = lookup_string( no_prev , c );
+
+ /* Get next character ==> Step 3 */
+ get_char( c );
+ /* Loop over input characters until */
+ /* end of file reached ==> Step 4. */
+ while( c != eof_char )
+ {
+ /* See if <w>C is in table. */
+
+ wc = lookup_string( w , c );
+
+ /* If <w>C is not in the table, */
+ /* enter it into the table and */
+ /* output <w>. Reset <w> to */
+ /* be the code for C ==> Step 6 */
+
+ if ( wc == end_list )
+ {
+
+ make_table_entry( w , c );
+ put_code( w );
+ w = lookup_string( no_prev , c );
+
+ }
+ else /* If <w>C is in table, keep looking */
+ /* for longer strings == Step 5 */
+
+ w = wc;
+
+ /* Get next input character ==> Step 3 */
+ get_char( c );
+
+ }
+ /* Make sure last code is */
+ /* written out ==> Step 4. */
+ put_code( w );
+
+} /* Do_Compression */
+
+/*--------------------------------------------------------------------------*/
+/* PibCompr --- Main program */
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, const char* argv[])
+{ /* PibCompr */
+ /* We are doing compression */
+ pio_initialize(argc, argv);
+ if_compressing = true;
+ /* Initialize compression */
+ initialize();
+ /* Perform compression */
+ do_compression();
+ /* Clean up and exit */
+ terminate();
+
+ return EXIT_SUCCESS;
+} /* PibCompr */
diff --git a/engines/avalanche/ss_blank.cpp b/engines/avalanche/ss_blank.cpp
new file mode 100644
index 0000000000..670d12cf1d
--- /dev/null
+++ b/engines/avalanche/ss_blank.cpp
@@ -0,0 +1,38 @@
+#include "ptoc.h"
+
+
+/*#include "Dos.h"*/
+/*#include "Crt.h"*/
+
+byte fv;
+boolean test;
+
+boolean the_cows_come_home()
+{
+ registers rmove,rclick;
+boolean the_cows_come_home_result;
+;
+ rmove.ax=11; intr(0x33,rmove);
+ rclick.ax=3; intr(0x33,rclick);
+ the_cows_come_home_result=
+ (keypressed()) | /* key pressed */
+ (rmove.cx>0) || /* mouse moved */
+ (rmove.dx>0) ||
+ (rclick.bx>0); /* button clicked */
+return the_cows_come_home_result;
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ test=the_cows_come_home();
+ textattr=0; clrscr;
+ do {; } while (!the_cows_come_home());
+ textattr=30; clrscr;
+ output << "*** Blank Screen *** (c) 1992, Thomas Thurman. (An Avvy Screen Saver.)" << NL;
+ for( fv=1; fv <= 46; fv ++) output << '~'; output << NL;
+ output << "This program may be freely copied." << NL;
+ output << NL;
+ output << "Have fun!" << NL;
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/ss_clock.cpp b/engines/avalanche/ss_clock.cpp
new file mode 100644
index 0000000000..1880ee5c06
--- /dev/null
+++ b/engines/avalanche/ss_clock.cpp
@@ -0,0 +1,84 @@
+#include "ptoc.h"
+
+
+/*#include "Dos.h"*/
+/*#include "Crt.h"*/
+#include "graph.h"
+/*#include "Drivers.h"*/
+
+
+const integer width = 88;
+const integer height = 8; /* width & height of string returned by "time" */
+
+integer gd,gm;
+integer xx,yy;
+shortint ix,iy;
+byte cp;
+byte count;
+array<0,1,pointtype> pages;
+boolean test;
+
+boolean the_cows_come_home()
+{
+ registers rmove,rclick;
+boolean the_cows_come_home_result;
+;
+ rmove.ax=11; intr(0x33,rmove);
+ rclick.ax=3; intr(0x33,rclick);
+ the_cows_come_home_result=
+ (keypressed()) || /* key pressed */
+ (rmove.cx>0) || /* mouse moved */
+ (rmove.dx>0) ||
+ (rclick.bx>0); /* button clicked */
+return the_cows_come_home_result;
+}
+
+string time1()
+{
+ word h,m,s,s1; varying_string<2> hh,mm,ss; char ampm;
+string time1_result;
+;
+ gettime(h,m,s,s1);
+ if (h<12)
+ ampm='a';
+ else {;
+ ampm='p';
+ if (h==0) h=12; else h -= 12; /* 24-hr adjustment */
+ }
+ str(h,2,hh); str(m,2,mm); str(s,2,ss); /* stringify them */
+ time1_result=hh+'.'+mm+'.'+ss+' '+ampm+'m';
+return time1_result;
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ test=the_cows_come_home();
+ gm=registerbgidriver(&egavgadriverproc);
+ gd=3; gm=1; initgraph(gd,gm,"");
+ ix=3; iy=1; xx=177; yy=177; setcolor(11); cp=0;
+ setfillstyle(1,0); count=2;
+ do {
+ setactivepage(cp); setvisualpage(1-cp); cp=1-cp;
+ delay(20); if (count>0) count -= 1;
+ {
+ pointtype& with = pages[cp];
+ ;
+ if (count==0)
+ bar(with.x,with.y,with.x+width,with.y+height);
+ with.x=xx; with.y=yy; /* update record for next time */
+ }
+ outtextxy(xx,yy,time1());
+ xx=xx+ix; yy=yy+iy;
+ if (xx<= 10) ix=Random(9)+1; if (xx>=629-width) ix=-Random(9)+1;
+ if (yy<= 10) iy=Random(9)+1; if (yy>=339-height) iy=-Random(9)+1;
+ } while (!the_cows_come_home());
+ closegraph();
+ textattr=30; clrscr;
+ output << "*** Bouncing Clock *** (c) 1992, Thomas Thurman. (An Avvy Screen Saver.)" << NL;
+ for( gd=1; gd <= 48; gd ++) output << '~'; output << NL;
+ output << "This program may be freely copied." << NL;
+ output << NL;
+ output << "Have fun!" << NL;
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/stars.cpp b/engines/avalanche/stars.cpp
new file mode 100644
index 0000000000..309d9a4743
--- /dev/null
+++ b/engines/avalanche/stars.cpp
@@ -0,0 +1,562 @@
+#include "ptoc.h"
+
+ /* Demonstration of the Bigo II system. */
+/* $I c:\sleep5\DSMI.INC*/
+#include "graph.h"
+/*#include "Crt.h"*/
+/*#include "Rodent.h"*/
+/*#include "Tommys.h"*/
+
+integer gd,gm;
+
+typedef matrix<'\0','\377',0,15,byte> fonttype;
+
+boolean reverse;
+word spinnum;
+array<0,1,fonttype> f;
+file<fonttype> ff;
+array<0,7,0,15,0,79,byte> strip;
+byte across;
+word w; byte y;
+byte charnum;
+byte cfont; /* current font. 0=roman, 1=italic. */
+
+char* c;
+
+boolean nomusic;
+
+const integer colours = 12; /* Run Workout to see possible values of these two. */
+const integer steps = 6; /* 60,30,20,15,12,10,6,5,4,3,2,1 */
+const integer gmtop = 360 / steps;
+
+ const integer scardcount = 13;
+
+ const array<0,scardcount-1,integer> soundcards =
+ {{1,2,6,3,4,5,8,9,10,7,7,7,7}};
+
+/*$L credits.obj*/ extern void credits();
+
+void bigo2(string date)
+{
+ integer gd,gm;
+ byte c;
+ palettetype p;
+ untyped_file f; pointer pp; word s;
+
+
+ getpalette(p);
+ setvisualpage(1); setactivepage(0);
+ assign(f,"logo.avd"); reset(f,1);
+ for( gd=7; gd <= 194; gd ++)
+ blockread(f,mem[0xa000*(gd*80)],53);
+ close(f);
+ s=imagesize(0,7,415,194); getmem(pp,s); getimage(0,7,415,194,pp);
+
+ cleardevice();
+ for( gd=1; gd <= 64; gd ++)
+ {
+ for( gm=0; gm <= gmtop; gm ++)
+ {
+ c=(c % colours)+1;
+/* putpixel(trunc(sin(gm*steps*n)*gd*6)+320,
+ trunc(cos(gm*steps*n)*gd*3)+175,c); */
+ if (c>5) continue_;
+ setcolor(c); arc(320,175,gm*steps,gm*steps+1,gd*6);
+ }
+ if (keypressed()) { closegraph(); exit(0); }
+ }
+ settextstyle(0,0,1); setcolor(13);
+ outtextxy(550,343,"(press any key)");
+
+ putimage(112,0,pp,orput); freemem(pp,s);
+ resetmouse; setvisualpage(0);
+}
+
+void nextchar() /* Sets up charnum & cline for the next character. */
+{
+
+ c += 1;
+}
+
+void getchar()
+{
+ do {
+ nextchar();
+
+ switch (*c) {
+ case '@': { cfont=1; nextchar(); } break;
+ case '^': { cfont=0; nextchar(); } break;
+ case '%': if (nomusic)
+ {
+ closegraph(); exit(0); /* End of text and no music => stop. */
+ }
+ else c=addr(credits());
+ break; /* End of test, but still playing => again. */
+ }
+
+ } while (!((*c!='\15') && (*c!='\12')));
+
+ for( w=0; w <= 7; w ++)
+ for( y=0; y <= 15; y ++)
+ move(strip[w][y][1],strip[w][y][0],79);
+
+ for( w=0; w <= 7; w ++)
+ for( y=0; y <= 15; y ++)
+ strip[w][y][79]=(byte)((strip[7][y][78] << (w+1)))+
+ ((cardinal)f[cfont][*c][y] >> (7-w));
+
+ across=0;
+}
+
+void scrolltext()
+{
+ byte c,w,y;
+
+ across += 1;
+ if (across==8) getchar();
+
+ for( y=0; y <= 15; y ++)
+ for( w=0; w <= 1; w ++)
+ move(strip[across][y][0],mem[0xa000*24000+(y*2+w)*80],80);
+}
+
+void do_stuff()
+{
+ switch (spinnum) {
+ case 50 ... 110: {
+ setfillstyle(1,14);
+ bar(0,315+(spinnum-50) / 3,640,315+(spinnum-50) / 3);
+ bar(0,316-(spinnum-50) / 3,640,316-(spinnum-50) / 3);
+ if (spinnum>56)
+ {
+ setfillstyle(1,13);
+ bar(0,315+(spinnum-56) / 3,640,315+(spinnum-56) / 3);
+ bar(0,316-(spinnum-56) / 3,640,316-(spinnum-56) / 3);
+ }
+ }
+ break;
+ case 150 ... 198: {
+ setfillstyle(1,0);
+ bar(0,315+(spinnum-150) / 3,640,315+(spinnum-150) / 3);
+ bar(0,316-(spinnum-150) / 3,640,316-(spinnum-150) / 3);
+ }
+ break;
+ case 200: scrolltext(); break;
+ }
+}
+
+void setcol(byte which,byte what)
+/*var dummy:byte;*/
+{;
+/* setpalette(which,what);
+ asm
+(* mov dx,$3DA;
+ in ax,dx;
+
+ or ah,ah;
+
+ mov dx,$3C0;
+ mov al,which;
+ out dx,al;
+
+ mov dx,$3C0;
+ mov al,what;
+ out dx,al;
+ end;
+(* dummy:=port[$3DA];
+ port[$3C0]:=which; port[$3C0]:=what;*/
+}
+
+void bigo2go()
+{
+ palettetype p; byte c; boolean lmo;
+ boolean altnow,altbefore;
+
+ for( gd=0; gd <= 13; gd ++) p.colors[gd]=0;
+
+ setcol(13,24); /* murk */ setcol(14,38); /* gold */
+ setcol(15,egawhite); /* white- of course */
+ p.colors[13]=24; p.colors[14]=38; p.colors[15]=egawhite;
+
+ /***/
+
+ p.colors[5]=egawhite;
+ p.colors[4]=egalightcyan;
+ p.colors[3]=egacyan;
+ p.colors[2]=egalightblue;
+ p.colors[1]=egablue;
+
+ /***/
+
+ c=1; p.size=16; lmo=false;
+ setallpalette(p);
+
+ do {
+/* if reverse then
+ begin
+ dec(c); if c=0 then c:=colours;
+ end else
+ begin
+ inc(c); if c>colours then c:=1;
+ end;
+ for gm:=1 to colours do
+ case p.colors[gm] of
+ egaWhite: begin p.colors[gm]:=egaLightcyan; setcol(gm,egaLightCyan); end;
+ egaLightcyan: begin p.colors[gm]:=egaCyan; setcol(gm,egaCyan); end;
+ egaCyan: begin p.colors[gm]:=egaLightblue; setcol(gm,egaLightblue); end;
+ egaLightblue: begin p.colors[gm]:=egaBlue; setcol(gm,egaBlue); end;
+ egaBlue: begin p.colors[gm]:=0; setcol(gm,0); end;
+ end;
+ p.colors[c]:=egaWhite; setcol(c,egaWhite);
+
+ AltBefore:=AltNow; AltNow:=testkey(sAlt);*/
+
+ if (anymousekeypressed) lmo=true;
+ if (keypressed()) lmo=true;
+ if ((! nomusic) && (ampgetmodulestatus != md_playing)) lmo=true;
+
+ /* if (AltNow=True) and (AltBefore=False) then reverse:=not reverse;*/
+
+ do_stuff();
+ if (spinnum<200) spinnum += 1;
+ } while (!lmo);
+}
+
+void parse_cline()
+{
+ integer e;
+
+ if (paramstr(1)!="jsb")
+ {
+ output << "Not a standalone program." << NL; exit(255);
+ }
+}
+
+integer getsoundhardware(psoundcard scard)
+{
+ integer sc,i,autosel,select;
+ char ch;
+ integer e;
+
+
+
+integer getsoundhardware_result;
+Lagain:
+ sc=detectgus(scard);
+ if (sc!=0) sc=detectpas(scard);
+ if (sc!=0) sc=detectaria(scard);
+ if (sc!=0) sc=detectsb(scard);
+
+ /* if no sound card found, zero scard */
+ if (sc!=0) fillchar(scard,sizeof(tsoundcard),0);
+
+ autosel=-1;
+/* if sc=0 then
+ for i:=0 to scardcount-1 do
+ if scard^.ID=soundcards[i].ID then begin
+ { Set auto selection mark }
+ autosel:=i+1;
+ break;
+ end;*/
+
+ /* Print the list of sound cards */
+
+ val(paramstr(13),select,e);
+
+ /* Default entry? */
+ if (select==0) select=autosel;
+ if (select!=autosel) {
+ /* clear all assumptions */
+ sc=-1;
+ fillchar(scard,sizeof(tsoundcard),0);
+ scard->id=soundcards[select-1]; /* set correct ID */
+ }
+
+ /* Query I/O address */
+ if (scard->id==id_dac) scard->ioport=0x378;
+
+ /* Read user input */
+ val(paramstr(15),i,e);
+
+ if (i!=0) scard->ioport=i;
+ if (sc!=1) /* Not autodetected */
+ switch (scard->id) {
+ case id_sb16:
+ case id_pas16:
+ case id_wss:
+ case id_aria:
+ case id_gus : scard->samplesize=2;
+ break; /* 16-bit card */
+ case id_sbpro:
+ case id_pas:
+ case id_pasplus: scard->stereo=true;
+ break; /* enable stereo */
+ default: {
+ scard->samplesize=1;
+ scard->stereo=false;
+ }
+ }
+
+ if (scard->id!=id_dac) {
+ val(paramstr(17),i,e);
+
+ if (i!=0) scard->dmairq=i;
+
+ val(paramstr(16),i,e);
+
+ if (i!=0) scard->dmachannel=i;
+ } else {
+ /* Select correct DAC */
+ scard->maxrate=44100;
+ if (select==11) {
+ scard->stereo=true;
+ scard->dmachannel=1; /* Special 'mark' */
+ scard->maxrate=60000;
+ } else
+ if (select==12) {
+ scard->stereo=true;
+ scard->dmachannel=2;
+ scard->maxrate=60000;
+ if (scard->ioport==0) scard->ioport=0x378;
+ } else
+ if (select==13) {
+ scard->dmachannel=0;
+ scard->ioport=0x42; /* Special 'mark' */
+ scard->maxrate=44100;
+ }
+ }
+
+/* writeln('Your selection: ',select,' at ',scard^.ioPort,
+ ' using IRQ ',scard^.dmaIRQ,' and DMA channel ',scard^.dmaChannel);
+ readln;*/
+
+ getsoundhardware_result=0;
+return getsoundhardware_result;
+}
+
+tsoundcard scard;
+tmcpstruct mcpstrc;
+tdds dds;
+pmodule module;
+tsdi_init sdi;
+integer e,
+bufsize;
+char ch;
+boolean v86,
+vdsok;
+longint a,rate,
+tempseg;
+string answer;
+pointer temp;
+word flags;
+word curch;
+byte modulevolume;
+array<0,4,tsampleinfo> sample;
+array<0,31,word> voltable;
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ parse_cline();
+
+ nomusic=paramstr(13)=='0';
+
+ if (! nomusic)
+ {
+ /* Read sound card information */
+ if (getsoundhardware(&scard)==-1) exit(1);
+
+
+ /* Initialize Timer Service */
+ tsinit;
+ atexit(&tsclose);
+ if (scard.id==id_gus) {
+ /* Initialize GUS player */
+ #ifndef DPMI
+ scard.extrafield[2]=1; /* GUS DMA transfer does not work in V86 */
+ #endif
+ gusinit(&scard);
+ atexit(&gusclose);
+
+ /* Initialize GUS heap manager */
+ gushminit;
+
+ /* Init CDI */
+ cdiinit;
+
+ /* Register GUS into CDI */
+ cdiregister(&cdi_gus,0,31);
+
+ /* Add GUS event player engine into Timer Service */
+ tsaddroutine(&gusinterrupt,gus_timer);
+ } else {
+ /* Initialize Virtual DMA Specification */
+ #ifndef DPMI
+ vdsok=vdsinit==0;
+ #else
+ vdsok=false;
+ #endif
+
+ fillchar(mcpstrc,sizeof(tmcpstruct),0);
+
+ /* Query for sampling rate */
+ val(paramstr(14),a,e);
+ if (a>4000) rate=a; else rate=21000;
+
+ /* Query for quality */
+ mcpstrc.options=mcp_quality;
+
+ switch (scard.id) {
+ case id_sb : {
+ sdi=sdi_sb;
+ scard.maxrate=22000;
+ }
+ break;
+ case id_sbpro : {
+ sdi=sdi_sbpro;
+ scard.maxrate=22000;
+ }
+ break;
+ case id_pas:
+ case id_pasplus:
+ case id_pas16 : {
+ sdi=sdi_pas;
+ scard.maxrate=44100;
+ }
+ break;
+ case id_sb16 : {
+ sdi=sdi_sb16;
+ scard.maxrate=44100;
+ }
+ break;
+ case id_aria : {
+ sdi=sdi_aria;
+ scard.maxrate=44100;
+ }
+ break;
+ case id_wss : {
+ sdi=sdi_wss;
+ scard.maxrate=48000;
+ }
+ break;
+ #ifndef DPMI
+ case id_dac : sdi=sdi_dac; break; /* Only available in real mode */
+ #endif
+ }
+
+ mcpinitsounddevice(sdi,&scard);
+ a=mcp_tablesize;
+ mcpstrc.reqsize=0;
+
+ /* Calculate mixing buffer size */
+ bufsize=(longint)(2800*(integer)(scard.samplesize) << (byte)(scard.stereo))*
+ (longint)(rate) / (longint)(22000);
+ mcpstrc.reqsize=0;
+ if ((mcpstrc.options & mcp_quality)>0)
+ if (scard.samplesize==1) a += mcp_qualitysize; else
+ a=mcp_tablesize16+mcp_qualitysize16;
+ if ((longint)(bufsize)+(longint)(a)>65500) bufsize=longint(65500)-a;
+
+ #ifdef DPMI
+ dpmiversion((byte)(e),(byte)(e),(byte)(e),flags);
+ v86=(flags & 2)==0;
+ #endif
+
+ /* Allocate volume table + mixing buffer */
+ #ifdef DPMI
+
+ /* In the V86 mode, the buffer must be allocated below 1M */
+ if (v86) {
+ tempseg=0;
+ dpmiallocdos((a+longint(bufsize)) / longint(16)+longint(1),flags,(word)(tempseg));
+ } else {
+ #endif
+ getmem(temp,a+longint(bufsize));
+ if (temp==nil) exit(2);
+ #ifdef DPMI
+ tempseg=seg(temp);
+ }
+ #else
+ tempseg=seg(temp)+ofs(temp) / 16+1;
+ #endif
+ mcpstrc.bufferseg=tempseg;
+ mcpstrc.bufferphysical=-1;
+
+ if (vdsok && (scard.id!=id_dac)) {
+ dds.size=bufsize;
+ dds.segment=tempseg;
+ dds.offset=0;
+
+ /* Lock DMA buffer if VDS present */
+ if (vdslockdma(&dds)==0) mcpstrc.bufferphysical=dds.address;
+ }
+ if (mcpstrc.bufferphysical==-1)
+ #ifdef DPMI
+ mcpstrc.bufferphysical=dpmigetlinearaddr(tempseg);
+ #else
+ mcpstrc.bufferphysical=(longint)(tempseg) << 4;
+ #endif
+
+ mcpstrc.buffersize=bufsize;
+ mcpstrc.samplingrate=rate;
+ /* Initialize Multi Channel Player */
+ if (mcpinit(&mcpstrc)!=0) exit(3);
+ atexit(&mcpclose);
+
+ /* Initialize Channel Distributor */
+ cdiinit;
+
+ /* Register MCP into CDI*/
+ cdiregister(&cdi_mcp,0,31);
+ }
+
+ /* Try to initialize AMP */
+ if (ampinit(0)!=0) exit(3);
+ atexit(&ampclose);
+
+ /* Hook AMP player routine into Timer Service */
+ tsaddroutine(&ampinterrupt,amp_timer);
+
+ #ifndef DPMI
+ /* If using DAC, then adjust DAC timer */
+ if (scard.id==id_dac) setdactimer(tsgettimerrate);
+ #endif
+
+ if (scard.id!=id_gus) mcpstartvoice; else gusstartvoice;
+
+ /* Load an example AMF */
+ module=amploadmod("avalot2.mod",0);
+ if (module==nil) exit(4);
+
+ /* Is it MCP, Quality mode and 16-bit card? */
+ if ((scard.id!=id_gus) && ((mcpstrc.options & mcp_quality)>0)
+ && (scard.samplesize==2)) {
+ /* Open module+2 channels with amplified volumetable (4.7 gain) */
+ for( a=1; a <= 32; a ++) voltable[a-longint(1)]=a*longint(150) / longint(32);
+ cdisetupchannels(0,module->channelcount+2,&voltable);
+ } else {
+ /* Open module+2 channels with regular volumetable */
+ cdisetupchannels(0,module->channelcount+2,nil);
+ }
+
+ curch=module->channelcount;
+ modulevolume=64;
+
+ /***/ ampplaymodule(module,0);
+ }
+
+ gd=3; gm=1; initgraph(gd,gm,"");
+ assign(ff,"avalot.fnt"); reset(ff); ff >> f[0]; close(ff);
+ assign(ff,"avitalic.fnt"); reset(ff); ff >> f[1]; close(ff);
+
+ c=addr(credits()); c -= 1;
+
+ fillchar(strip,sizeof(strip),'\0');
+ reverse=false; spinnum=0; across=7; charnum=1; cfont=0;
+ bigo2("1189"); /* 1189? 79? 2345? 1967? */
+ bigo2go();
+
+ if (! nomusic) ampstopmodule;
+ closegraph();
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/status.cpp b/engines/avalanche/status.cpp
new file mode 100644
index 0000000000..1e046fcc0c
--- /dev/null
+++ b/engines/avalanche/status.cpp
@@ -0,0 +1,34 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+integer gd,gm;
+
+void data(integer y, string a,string b)
+{;
+ setcolor(1); settextjustify(2,0); outtextxy(315,y,a+':');
+ setcolor(0); settextjustify(0,0); outtextxy(325,y,b);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\turbo");
+ setcolor(1); setfillstyle(1,7); bar(0,0,640,200);
+ settextstyle(1,0,0); setusercharsize(10,4,8,6); settextjustify(1,1);
+ outtextxy(317,20,"Status Screen");
+ settextstyle(0,0,1);
+ data( 60,"Current game","NoName.ASG");
+ data( 70,"Saved?","Yes");
+ data( 90,"Current town","Thurringham");
+ data(100,"Score","177");
+ data(110,"Cash","1/-");
+ data(130,"Game","Lord Avalot D'Argent");
+ data(140,"Version","1.00 (beta)");
+ data(150,"Registered to","Unregistered!");
+ data(160,"Number","nix");
+ data(177,"Bios/keyboard","AT (enhanced)"); /* or XT (bog standard) */
+ data(187,"Display","VGA");
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/sticks.cpp b/engines/avalanche/sticks.cpp
new file mode 100644
index 0000000000..1fc11cd313
--- /dev/null
+++ b/engines/avalanche/sticks.cpp
@@ -0,0 +1,90 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ STICKS The joystick handler. */
+
+#define __sticks_implementation__
+
+
+#include "sticks.h"
+
+
+enum lmc {l,m,r, last_lmc}; /* Left, middle & right */
+
+file<joysetup> jf;
+
+byte joyway();
+
+
+static lmc getlmc(word n,word max,word min)
+{lmc getlmc_result;
+;
+ if (n<min) getlmc_result=l; else
+ if (n>max) getlmc_result=r; else
+ getlmc_result=m;
+return getlmc_result;
+}
+
+byte joyway()
+{
+ word x,y;
+ lmc xx,yy;
+byte joyway_result;
+;
+ if (~ dna.user_moves_avvy) return joyway_result;
+ if (use_joy_a) readjoya(x,y); else readjoyb(x,y);
+
+ {;
+ xx=getlmc(x,cxmax,cxmin);
+ yy=getlmc(y,cymax,cymin);
+ }
+
+ switch (xx) {
+ case l: switch (yy) {
+ case l: joyway_result=ul; break;
+ case m: joyway_result=left; break;
+ case r: joyway_result=dl; break;
+ }
+ break;
+ case m: switch (yy) {
+ case l: joyway_result=up; break;
+ case m: joyway_result=stopped; break;
+ case r: joyway_result=down; break;
+ }
+ break;
+ case r: switch (yy) {
+ case l: joyway_result=ur; break;
+ case m: joyway_result=right; break;
+ case r: joyway_result=dr; break;
+ }
+ break;
+ }
+return joyway_result;
+}
+
+void joykeys()
+ /* The 2 joystick keys may be reprogrammed. This parses them. */
+{
+ byte v;
+;
+ if (use_joy_a)
+ {
+ v=(byte)(buttona1); v += (byte)(buttona2)*2;
+ } else
+ {
+ v=(byte)(buttonb1); v += (byte)(buttonb2)*2;
+ }
+
+ switch (v) {
+ case 0: return; break; /* No buttons pressed. */
+ case 1: opendoor; break; /* Button 1 pressed: open door. */
+/* 2: blip; { Button 2 pressed: nothing (joylock?). }*/
+ case 2:case 3: lookaround; break; /* Both buttons pressed: look around. */
+ }
+}
+
+ /* No init code. */ \ No newline at end of file
diff --git a/engines/avalanche/sticks.h b/engines/avalanche/sticks.h
new file mode 100644
index 0000000000..5a54cd44bc
--- /dev/null
+++ b/engines/avalanche/sticks.h
@@ -0,0 +1,13 @@
+#ifndef __sticks_h__
+#define __sticks_h__
+
+
+/*#include "Joystick.h"*/
+/*#include "Acci.h"*/
+/*#include "Gyro.h"*/
+ /* for solidarity */
+
+byte joyway();
+void joykeys();
+
+#endif
diff --git a/engines/avalanche/sunrise.cpp b/engines/avalanche/sunrise.cpp
new file mode 100644
index 0000000000..1ed894a46e
--- /dev/null
+++ b/engines/avalanche/sunrise.cpp
@@ -0,0 +1,57 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+integer gd,gm;
+longint tskellern /*absolute $0:244*/; /* Over int $61 */
+
+void hold()
+{;
+ do {; } while (!(tskellern>=1));
+ tskellern=0;
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=1; initgraph(gd,gm,"c:\\bp\\bgi");
+
+ setvisualpage(1);
+ setfillstyle(1,1);
+ for( gd=1; gd <= 640; gd ++)
+ bar(gd,177+trunc(20*sin((real)(gd)/39)),gd,350);
+ setfillstyle(1,3); setcolor(3);
+ fillellipse(320,277,60,50);
+ settextjustify(1,1); settextstyle(0,0,2); setcolor(9);
+ outtextxy(320,50,"The sun rises over Hertfordshire...");
+ settextjustify(2,0); settextstyle(0,0,1); setcolor(0);
+ outtextxy(635,350,"Press any key...");
+
+ setpalette(0,egablue);
+ setpalette(1,egagreen);
+ setpalette(2,egayellow);
+ setpalette(3,egagreen);
+ setpalette(9,egalightblue);
+ setpalette(11,egalightblue);
+ setvisualpage(0);
+
+ port[0x3c4]=2; port[0x3ce]=4;
+ port[0x3c5]=1 << 1; port[0x3cf]=1;
+
+ for( gm=227; gm >= 1; gm --) /* <<< try running this loop the other way round! */
+ {;
+ move(mem[0xa000*gm*80+80],mem[0xa000*gm*80],8042);
+ hold();
+ if (keypressed()) return 0;
+ }
+
+ for( gm=101; gm >= 1; gm --)
+ {;
+ move(mem[0xa000*80],mem[0xa000*0],gm*80);
+ hold();
+ if (keypressed()) return 0;
+ }
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/tempo.cpp b/engines/avalanche/tempo.cpp
new file mode 100644
index 0000000000..634f3214b6
--- /dev/null
+++ b/engines/avalanche/tempo.cpp
@@ -0,0 +1,77 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+
+enum flavourtype {ch_ega,ch_bgi,ch_natural,ch_two,ch_one, last_flavourtype};
+
+struct chunkblocktype {
+ union {
+ struct {flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;} s_true;
+ array<1,14,byte> all;
+ };
+};
+
+
+byte screennum;
+untyped_file f;
+
+string strf(longint x)
+{
+ string q;
+string strf_result;
+;
+ str(x,q); strf_result=q;
+return strf_result;
+}
+
+void load()
+{
+ byte a /*absolute $A000:1200*/; byte bit;
+;
+ reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a,12080);
+ }
+ close(f);
+ bit=getpixel(0,0);
+}
+
+void init()
+{
+ integer gd,gm;
+;
+ output << "*** Tempo file creater ***" << NL;
+ output << "Enter place*.avd number:";
+ input >> screennum >> NL;
+ gd=3; gm=0;
+ initgraph(gd,gm,"c:\\bp\\bgi");
+ assign(f,string("place")+strf(screennum)+".avd");
+ load();
+ setactivepage(1);
+ setcolor(10);
+ outtextxy(0,150,"CHUNK FILE: please don't change these codes! ->");
+ setactivepage(0);
+}
+
+void choose()
+{
+ integer x1,y1,xl,yl;
+;
+
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ init();
+ choose();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/test.cpp b/engines/avalanche/test.cpp
new file mode 100644
index 0000000000..6d480843f2
--- /dev/null
+++ b/engines/avalanche/test.cpp
@@ -0,0 +1,19 @@
+#include "ptoc.h"
+
+
+/*$M 2048,0,0*/
+/*#include "Dos.h"*/
+
+const array<1,22,char> signature = string("*AVALOT* v1.00 ±tt± ")+'\3'+'\0';
+pointer saveint1f;
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ getintvec(0x1f,saveint1f);
+ setintvec(0x1f,&signature);
+ swapvectors;
+ exec("c:\\command.com","");
+ swapvectors;
+ setintvec(0x1f,saveint1f);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/test2.cpp b/engines/avalanche/test2.cpp
new file mode 100644
index 0000000000..a4f678d650
--- /dev/null
+++ b/engines/avalanche/test2.cpp
@@ -0,0 +1,17 @@
+#include "ptoc.h"
+
+
+/*#include "Dos.h"*/
+
+const array<1,22,char> signature = string("*AVALOT* v1.00 ±tt± ")+'\3'+'\0';
+pointer getint1f;
+array<1,22,char> x;
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ getintvec(0x1f,getint1f);
+ move(getint1f,x,22);
+ if (x==signature)
+ output << "Signature found." << NL; else output << "Signature NOT found!" << NL;
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/testblit.cpp b/engines/avalanche/testblit.cpp
new file mode 100644
index 0000000000..bc00393150
--- /dev/null
+++ b/engines/avalanche/testblit.cpp
@@ -0,0 +1,49 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+
+const integer ttp = 81920;
+const integer borland = xorput;
+const integer mb1 = 2; /* 2 */
+const integer mb2 = 4; /* 4 */
+
+integer gd,gm;
+pointer p;
+word s;
+
+void mblit()
+{
+ byte bit; longint st;
+;
+ st=ttp;
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=mb1;
+ portw[0x3ce]=copyput*256+3;
+ portw[0x3ce]=0x205;
+ port[0x3ce]=0x8;
+ port[0x3c5]=1 << bit;
+ port[0x3cf]=bit;
+ move(mem[longint(0xa000)*st],mem[0xa000*0],7200);
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"");
+ settextstyle(1,0,7);
+ for( gd=0; gd <= 1; gd ++)
+ {;
+ setactivepage(gd); setcolor(6*gd+6);
+ outtextxy(0,0,chr(65+gd));
+ }
+ s=imagesize(0,0,90,90); setactivepage(0); getmem(p,s);
+ getimage(0,0,90,90,p); putimage(100,100,p,0);
+ setactivepage(1); getimage(0,0,90,90,p); setactivepage(0);
+ putimage(100,100,p,borland);
+ mblit();
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/testcard.cpp b/engines/avalanche/testcard.cpp
new file mode 100644
index 0000000000..064b0a10b5
--- /dev/null
+++ b/engines/avalanche/testcard.cpp
@@ -0,0 +1,56 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Dos.h"*/
+
+integer gd,gm;
+string filename;
+
+untyped_file f; byte bit;
+byte a /*absolute $A000:800*/;
+searchrec r;
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+
+ for( gd=0; gd <= 14; gd ++)
+ for( gm=0; gm <= 11; gm ++)
+ {;
+ setfillstyle(gm,gd+1);
+ bar(gd*43,gm*12+10,42+gd*43,gm*12+21);
+ }
+
+ output << NL; output << NL; output << NL; output << NL;
+
+ output << "Thorsoft testcard." << NL;
+ output << NL;
+ output << "Room number? "; input >> filename >> NL;
+
+ findfirst(string("place")+filename+".avd",anyfile,r);
+ if (doserror==0)
+ {;
+ output << "*** ALREADY EXISTS! CANCELLED! ***" << NL;
+ input >> NL;
+ exit(0);
+ }
+
+ output << NL;
+ output << "*** Until this room is drawn, this screen is standing in for it. ***" << NL;
+ output << NL;
+ output << "Any other comments? ";
+ input >> NL;
+
+ assign(f,string("place")+filename+".avd");
+ rewrite(f,1);
+ blockwrite(f,gd,177); /* just anything */
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockwrite(f,a,12080);
+ }
+ close(f);
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/testenh.cpp b/engines/avalanche/testenh.cpp
new file mode 100644
index 0000000000..8077ca33d8
--- /dev/null
+++ b/engines/avalanche/testenh.cpp
@@ -0,0 +1,18 @@
+#include "ptoc.h"
+
+
+/*#include "Enhanced.h"*/
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ do {
+ readkeye;
+ switch (inchar) {
+ case '\0': output << string('[')+extd+']'; break;
+ case '\340': output << string('<')+extd+'>'; break;
+ default: output << inchar;
+ }
+ } while (!(inchar=='\33'));
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/timeout.cpp b/engines/avalanche/timeout.cpp
new file mode 100644
index 0000000000..26ab44989b
--- /dev/null
+++ b/engines/avalanche/timeout.cpp
@@ -0,0 +1,594 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ TIMEOUT The scheduling unit. */
+
+#define __timeout_implementation__
+
+
+#include "timeout.h"
+
+
+#include "visa.h"
+#include "lucerna.h"
+#include "trip5.h"
+#include "scrolls.h"
+#include "sequence.h"
+#include "pingo.h"
+#include "Acci.h"
+#include "enid.h"
+
+
+byte fv;
+
+void set_up_timer(longint howlong, byte whither,byte why)
+{
+ fv=1;
+ while ((fv<8) && (times[fv].time_left!=0)) fv += 1;
+ if (fv==8) return; /* Oh dear... */
+
+ {
+ timetype& with = times[fv]; /* Everything's OK here! */
+
+ with.time_left=howlong;
+ with.then_where=whither;
+ with.what_for=why;
+ }
+}
+
+void one_tick()
+{
+
+ if (ddmnow) return;
+
+ for( fv=1; fv <= 7; fv ++)
+ { timetype& with = times[fv];
+ if (with.time_left>0)
+ {
+ with.time_left -= 1;
+
+ if (with.time_left==0)
+ switch (with.then_where) {
+ case procopen_drawbridge : open_drawbridge(); break;
+ case procavaricius_talks : avaricius_talks(); break;
+ case procurinate : urinate(); break;
+ case proctoilet2 : toilet2(); break;
+ case procbang: bang(); break;
+ case procbang2: bang2(); break;
+ case procstairs: stairs(); break;
+ case proccardiffsurvey: cardiff_survey(); break;
+ case proccardiff_return: cardiff_return(); break;
+ case proc_cwytalot_in_herts: cwytalot_in_herts(); break;
+ case procget_tied_up: get_tied_up(); break;
+ case procget_tied_up2: get_tied_up2(); break;
+ case prochang_around: hang_around(); break;
+ case prochang_around2: hang_around2(); break;
+ case procafter_the_shootemup: after_the_shootemup(); break;
+ case procjacques_wakes_up: jacques_wakes_up(); break;
+ case procnaughty_duke: naughty_duke(); break;
+ case procnaughty_duke2: naughty_duke2(); break;
+ case procnaughty_duke3: naughty_duke3(); break;
+ case procjump: jump(); break;
+ case procsequence: call_sequencer(); break;
+ case proccrapulus_splud_out: crapulus_says_splud_out(); break;
+ case procdawn_delay: dawn(); break;
+ case procbuydrinks: buydrinks(); break;
+ case procbuywine: buywine(); break;
+ case proccallsguards: callsguards(); break;
+ case procgreetsmonk: greetsmonk(); break;
+ case procfall_down_oubliette: fall_down_oubliette(); break;
+ case procmeet_avaroid: meet_avaroid(); break;
+ case procrise_up_oubliette: rise_up_oubliette(); break;
+ case procrobin_hood_and_geida: robin_hood_and_geida(); break;
+ case procrobin_hood_and_geida_talk: robin_hood_and_geida_talk(); break;
+ case procavalot_returns: avalot_returns(); break;
+ case procavvy_sit_down: avvy_sit_down(); break;
+ case procghost_room_phew: ghost_room_phew(); break;
+ case procarkata_shouts: arkata_shouts(); break;
+ case procwinning: winning(); break;
+ case procavalot_falls: avalot_falls(); break;
+ case procspludwick_goes_to_cauldron: spludwick_goes_to_cauldron(); break;
+ case procspludwick_leaves_cauldron: spludwick_leaves_cauldron(); break;
+ case procgive_lute_to_geida: give_lute_to_geida(); break;
+ }
+ }}
+ roomtime += 1; /* Cycles since you've been in this room. */
+ dna.total_time += 1; /* Total amount of time for this game. */
+}
+
+void lose_timer(byte which)
+{
+ byte fv;
+
+ for( fv=1; fv <= 7; fv ++)
+ { timetype& with = times[fv];
+ if (with.what_for==which)
+ with.time_left=0;} /* Cancel this one! */
+}
+
+/*function timer_is_on(which:byte):boolean;
+var fv:byte;
+begin
+ for fv:=1 to 7 do
+ with times[fv] do
+ if (what_for=which) and (time_left>0) then
+ begin
+ timer_is_on:=true;
+ exit;
+ end;
+ timer_is_on:=false;
+end;*/
+
+/* Timeout procedures: */
+
+void open_drawbridge()
+{
+ {
+ dnatype& with = dna;
+
+ with.drawbridge_open += 1;
+ show_one(with.drawbridge_open-1);
+
+ if (with.drawbridge_open==4)
+ magics[2].op=nix; /* You may enter the drawbridge. */
+ else set_up_timer(7,procopen_drawbridge,reason_drawbridgefalls);
+ }
+}
+
+/* --- */
+
+void avaricius_talks()
+{
+ {
+ dnatype& with = dna;
+
+ dixi('q',with.avaricius_talk);
+ with.avaricius_talk += 1;
+
+ if (with.avaricius_talk<17)
+ set_up_timer(177,procavaricius_talks,reason_avariciustalks);
+ else points(3);
+
+ }
+}
+
+void urinate()
+{
+ tr[1].turn(up);
+ stopwalking();
+ showrw();
+ set_up_timer(14,proctoilet2,reason_gototoilet);
+}
+
+void toilet2()
+{
+ display("That's better!");
+}
+
+void bang()
+{
+ display("\6< BANG! >");
+ set_up_timer(30,procbang2,reason_explosion);
+}
+
+void bang2()
+{
+ display("Hmm... sounds like Spludwick's up to something...");
+}
+
+void stairs()
+{
+ blip();
+ tr[1].walkto(4);
+ show_one(2);
+ dna.brummie_stairs=2;
+ magics[11].op=special;
+ magics[11].data=2; /* Reached the bottom of the stairs. */
+ magics[4].op=nix; /* Stop them hitting the sides (or the game will hang.) */
+}
+
+void cardiff_survey()
+{
+ {
+ dnatype& with = dna;
+
+ switch (with.cardiff_things) {
+ case 0: {
+ with.cardiff_things += 1;
+ dixi('q',27);
+ }
+ break;
+ }
+ dixi('z',with.cardiff_things);
+ }
+ interrogation=dna.cardiff_things;
+ set_up_timer(182,proccardiffsurvey,reason_cardiffsurvey);
+}
+
+void cardiff_return()
+{
+ dixi('q',28);
+ cardiff_survey(); /* add end of question. */
+}
+
+void cwytalot_in_herts()
+{
+ dixi('q',29);
+}
+
+void get_tied_up()
+{
+ dixi('q',34); /* ...Trouble! */
+ dna.user_moves_avvy=false;
+ dna.been_tied_up=true;
+ stopwalking();
+ tr[2].stopwalk(); tr[2].stophoming();
+ tr[2].call_eachstep=true;
+ tr[2].eachstep=procgrab_avvy;
+ set_up_timer(70,procget_tied_up2,reason_getting_tied_up);
+}
+
+void get_tied_up2()
+{
+ tr[1].walkto(4);
+ tr[2].walkto(5);
+ magics[4].op=nix; /* No effect when you touch the boundaries. */
+ dna.friar_will_tie_you_up=true;
+}
+
+void hang_around()
+{
+ tr[2].check_me=false;
+ tr[1].init(7,true); /* Robin Hood */
+ whereis[probinhood]=r__robins;
+ apped(1,2);
+ dixi('q',39);
+ tr[1].walkto(7);
+ set_up_timer(55,prochang_around2,reason_hanging_around);
+}
+
+void hang_around2()
+{
+ dixi('q',40);
+ tr[2].vanishifstill=false;
+ tr[2].walkto(4);
+ whereis[pfriartuck]=r__robins;
+ dixi('q',41);
+ tr[1].done(); tr[2].done(); /* Get rid of Robin Hood and Friar Tuck. */
+
+ set_up_timer(1,procafter_the_shootemup,reason_hanging_around); /* Immediately
+ call the following proc (when you have a chance). */
+
+ dna.tied_up=false;
+
+ back_to_bootstrap(1); /* Call the shoot-'em-up. */
+}
+
+void after_the_shootemup()
+{
+ byte shootscore,gain;
+
+ tr[1].init(0,true); /* Avalot. */
+ apped(1,2); dna.user_moves_avvy=true;
+ dna.obj[crossbow]=true; objectlist();
+
+ shootscore=mem[storage_seg*storage_ofs];
+ gain=(shootscore+5) / 10; /* Rounding up. */
+
+ display(string("\6Your score was ")+strf(shootscore)+'.'+"\r\rYou gain ("+
+ strf(shootscore)+" ö 10) = "+strf(gain)+" points.");
+
+ if (gain>20)
+ {
+ display("But we won't let you have more than 20 points!");
+ points(20);
+ } else
+ points(gain);
+
+ dixi('q',70);
+}
+
+void jacques_wakes_up()
+{
+ dna.jacques_awake += 1;
+
+ switch (dna.jacques_awake) { /* Additional pictures. */
+ case 1 : {
+ show_one(1); /* Eyes open. */
+ dixi('Q',45);
+ }
+ break;
+ case 2 : { /* Going through the door. */
+ show_one(2); /* Not on the floor. */
+ show_one(3); /* But going through the door. */
+ magics[6].op=nix; /* You can't wake him up now. */
+ }
+ break;
+ case 3 : { /* Gone through the door. */
+ show_one(2); /* Not on the floor, either. */
+ show_one(4); /* He's gone... so the door's open. */
+ whereis[pjacques]=0; /* Gone! */
+ }
+ break;
+ }
+
+
+ if (dna.jacques_awake==5)
+ {
+ dna.ringing_bells=true;
+ dna.ayles_is_awake=true;
+ points(2);
+ }
+
+ switch (dna.jacques_awake) {
+ case RANGE_3(1,3): set_up_timer(12,procjacques_wakes_up,reason_jacques_waking_up);
+ break;
+ case 4: set_up_timer(24,procjacques_wakes_up,reason_jacques_waking_up); break;
+ }
+
+}
+
+void naughty_duke()
+ /* This is when the Duke comes in and takes your money. */
+{
+ tr[2].init(9,false); /* Here comes the Duke. */
+ apped(2,1); /* He starts at the door... */
+ tr[2].walkto(3); /* He walks over to you. */
+
+ /* Let's get the door opening. */
+
+ show_one(1); first_show(2); start_to_close();
+
+ set_up_timer(50,procnaughty_duke2,reason_naughty_duke);
+}
+
+void naughty_duke2()
+{
+ dixi('q',48); /* Ha ha, it worked again! */
+ tr[2].walkto(1); /* Walk to the door. */
+ tr[2].vanishifstill=true; /* Then go away! */
+ set_up_timer(32,procnaughty_duke3,reason_naughty_duke);
+}
+
+void naughty_duke3()
+{
+ show_one(1); first_show(2); start_to_close();
+}
+
+void jump()
+{
+ {
+ dnatype& with = dna;
+
+ with.jumpstatus += 1;
+
+ { triptype& with1 = tr[1];
+ switch (with.jumpstatus) {
+ case 1:case 2:case 3:case 5:case 7:case 9: with1.y -= 1; break;
+ case 12:case 13:case 14:case 16:case 18:case 19: with1.y += 1; break;
+ }}
+
+ if (with.jumpstatus==20)
+ { /* End of jump. */
+ dna.user_moves_avvy=true;
+ dna.jumpstatus=0;
+ } else
+ { /* Still jumping. */
+ set_up_timer(1,procjump,reason_jumping);
+ }
+
+ if ((with.jumpstatus==10) /* You're at the highest point of your jump. */
+ && (dna.room==r__insidecardiffcastle)
+ && (dna.arrow_in_the_door==true)
+ && (infield(3))) /* beside the wall*/
+ { /* Grab the arrow! */
+ if (dna.carrying>=maxobjs)
+ display("You fail to grab it, because your hands are full.");
+ else
+ {
+ show_one(2);
+ dna.arrow_in_the_door=false; /* You've got it. */
+ dna.obj[bolt]=true;
+ objectlist();
+ dixi('q',50);
+ points(3);
+ }
+ }
+ }
+}
+
+void crapulus_says_splud_out()
+{
+ dixi('q',56);
+ dna.crapulus_will_tell=false;
+}
+
+void buydrinks()
+{
+ show_one(11); /* Malagauche gets up again. */
+ dna.malagauche=0;
+
+ dixi('D',ord(dna.drinking)); /* Display message about it. */
+ wobble(); /* Do the special effects. */
+ dixi('D',1); /* That'll be thruppence. */
+ if (pennycheck(3)) /* Pay 3d. */
+ dixi('D',3); /* Tell 'em you paid up. */
+ have_a_drink();
+}
+
+void buywine()
+{
+ show_one(11); /* Malagauche gets up again. */
+ dna.malagauche=0;
+
+ dixi('D',50); /* You buy the wine. */
+ dixi('D',1); /* It'll be thruppence. */
+ if (pennycheck(3))
+ {
+ dixi('D',4); /* You paid up. */
+ dna.obj[wine]=true;
+ objectlist();
+ dna.winestate=1; /* OK Wine */
+ }
+}
+
+void callsguards()
+{
+ dixi('Q',58); /* GUARDS!!! */
+ gameover();
+}
+
+void greetsmonk()
+{
+ dixi('Q',59); dna.entered_lusties_room_as_monk=true;
+}
+
+void fall_down_oubliette()
+{
+ magics[9].op=nix;
+ tr[1].iy += 1; /* increments dx/dy! */
+ tr[1].y += tr[1].iy; /* Dowwwn we go... */
+ set_up_timer(3,procfall_down_oubliette,reason_falling_down_oubliette);
+}
+
+void meet_avaroid()
+{
+ if (dna.met_avaroid)
+ {
+ display("You can't expect to be \6that\22 lucky twice in a row!");
+ gameover();
+ } else
+ {
+ dixi('Q',60); dna.met_avaroid=true;
+ set_up_timer(1,procrise_up_oubliette,reason_rising_up_oubliette);
+ {
+ triptype& with = tr[1]; with.face=left; with.x=151; with.ix=-3; with.iy=-5; }
+ background(2);
+ }
+}
+
+void rise_up_oubliette()
+{
+ {
+ triptype& with = tr[1];
+
+ with.visible=true;
+ with.iy += 1; /* decrements dx/dy! */
+ with.y -= with.iy; /* Uuuupppp we go... */
+ if (with.iy>0)
+ set_up_timer(3,procrise_up_oubliette,reason_rising_up_oubliette);
+ else
+ dna.user_moves_avvy=true;
+ }
+}
+
+void robin_hood_and_geida()
+{
+ tr[1].init(7,true);
+ apped(1,7);
+ tr[1].walkto(6);
+ tr[2].stopwalk();
+ tr[2].face=left;
+ set_up_timer(20,procrobin_hood_and_geida_talk,reason_robin_hood_and_geida);
+ dna.geida_follows=false;
+}
+
+void robin_hood_and_geida_talk()
+{
+ dixi('q',66); tr[1].walkto(2); tr[2].walkto(2);
+ tr[1].vanishifstill=true; tr[2].vanishifstill=true;
+ set_up_timer(162,procavalot_returns,reason_robin_hood_and_geida);
+}
+
+void avalot_returns()
+{
+ tr[1].done(); tr[2].done();
+ tr[1].init(0,true);
+ apped(1,1);
+ dixi('q',67);
+ dna.user_moves_avvy=true;
+}
+
+void avvy_sit_down()
+ /* This is used when you sit down in the pub in Notts. It loops around so
+ that it will happen when Avvy stops walking. */
+{
+ if (tr[1].homing) /* Still walking */
+ set_up_timer(1,procavvy_sit_down,reason_sitting_down);
+ else
+ {
+ show_one(3);
+ dna.sitting_in_pub=true;
+ dna.user_moves_avvy=false;
+ tr[1].visible=false;
+ }
+}
+
+void ghost_room_phew()
+{
+ display("\6PHEW!\22 You're glad to get out of \6there!");
+}
+
+void arkata_shouts()
+{
+ if (dna.teetotal) return;
+ dixi('q',76);
+ set_up_timer(160,procarkata_shouts,reason_arkata_shouts);
+}
+
+void winning()
+{
+ dixi('q',79);
+ winning_pic();
+ do { checkclick(); } while (!(mrelease==0));
+ callverb(vb_score);
+ display(" T H E E N D ");
+ lmo=true;
+}
+
+void avalot_falls()
+{
+ if (tr[1].step<5)
+ {
+ tr[1].step += 1;
+ set_up_timer(3,procavalot_falls,reason_falling_over);
+ } else
+ display("\r\r\r\r\r\r\n\n\n\n\n\n\23Z\26");
+}
+
+void spludwick_goes_to_cauldron()
+{
+ if (tr[2].homing)
+ set_up_timer(1,procspludwick_goes_to_cauldron,reason_spludwalk);
+ else
+ set_up_timer(17,procspludwick_leaves_cauldron,reason_spludwalk);
+}
+
+void spludwick_leaves_cauldron()
+{
+ tr[2].call_eachstep=true; /* So that normal procs will continue. */
+}
+
+void give_lute_to_geida() /* Moved here from Acci. */
+{
+ dixi('Q',86);
+ points(4);
+ dna.lustie_is_asleep=true;
+ first_show(5); then_show(6); /* He falls asleep... */
+ start_to_close(); /* Not really closing, but we're using the same procedure. */
+}
+
+/* "This is all!" */
+
+class unit_timeout_initialize {
+ public: unit_timeout_initialize();
+};
+static unit_timeout_initialize timeout_constructor;
+
+unit_timeout_initialize::unit_timeout_initialize() {
+ fillchar(times,sizeof(times),'\0');
+}
diff --git a/engines/avalanche/timeout.h b/engines/avalanche/timeout.h
new file mode 100644
index 0000000000..5fa9800388
--- /dev/null
+++ b/engines/avalanche/timeout.h
@@ -0,0 +1,229 @@
+#ifndef __timeout_h__
+#define __timeout_h__
+
+
+#include "gyro.h"
+#include "celer.h"
+
+
+/* reason_ now runs between 1 and 28. */
+
+const integer reason_drawbridgefalls = 2;
+const integer reason_avariciustalks = 3;
+const integer reason_gototoilet = 4;
+const integer reason_explosion = 5;
+const integer reason_brummiestairs = 6;
+const integer reason_cardiffsurvey = 7;
+const integer reason_cwytalot_in_herts = 8;
+const integer reason_getting_tied_up = 9;
+const integer reason_hanging_around = 10; /* Tied to the tree in Nottingham. */
+const integer reason_jacques_waking_up = 11;
+const integer reason_naughty_duke = 12;
+const integer reason_jumping = 13;
+const integer reason_sequencer = 14;
+const integer reason_crapulus_says_spludwick_out = 15;
+const integer reason_dawndelay = 16;
+const integer reason_drinks = 17;
+const integer reason_du_lustie_talks = 18;
+const integer reason_falling_down_oubliette = 19;
+const integer reason_meeting_avaroid = 20;
+const integer reason_rising_up_oubliette = 21;
+const integer reason_robin_hood_and_geida = 22;
+const integer reason_sitting_down = 23;
+const integer reason_ghost_room_phew = 1;
+const integer reason_arkata_shouts = 24;
+const integer reason_winning = 25;
+const integer reason_falling_over = 26;
+const integer reason_spludwalk = 27;
+const integer reason_geida_sings = 28;
+
+/* PROCx now runs between 1 and 41. */
+
+const integer procopen_drawbridge = 3;
+
+const integer procavaricius_talks = 4;
+
+const integer procurinate = 5;
+
+const integer proctoilet2 = 6;
+
+const integer procbang = 7;
+
+const integer procbang2 = 8;
+
+const integer procstairs = 9;
+
+const integer proccardiffsurvey = 10;
+
+const integer proccardiff_return = 11;
+
+const integer proc_cwytalot_in_herts = 12;
+
+const integer procget_tied_up = 13;
+
+const integer procget_tied_up2 = 1;
+
+const integer prochang_around = 14;
+
+const integer prochang_around2 = 15;
+
+const integer procafter_the_shootemup = 32;
+
+const integer procjacques_wakes_up = 16;
+
+const integer procnaughty_duke = 17;
+
+const integer procnaughty_duke2 = 18;
+
+const integer procnaughty_duke3 = 38;
+
+const integer procjump = 19;
+
+const integer procsequence = 20;
+
+const integer proccrapulus_splud_out = 21;
+
+const integer procdawn_delay = 22;
+
+const integer procbuydrinks = 23;
+
+const integer procbuywine = 24;
+
+const integer proccallsguards = 25;
+
+const integer procgreetsmonk = 26;
+
+const integer procfall_down_oubliette = 27;
+
+const integer procmeet_avaroid = 28;
+
+const integer procrise_up_oubliette = 29;
+
+const integer procrobin_hood_and_geida = 2;
+
+const integer procrobin_hood_and_geida_talk = 30;
+
+const integer procavalot_returns = 31;
+
+const integer procavvy_sit_down = 33; /* In Nottingham. */
+
+const integer procghost_room_phew = 34;
+
+const integer procarkata_shouts = 35;
+
+const integer procwinning = 36;
+
+const integer procavalot_falls = 37;
+
+const integer procspludwick_goes_to_cauldron = 39;
+
+const integer procspludwick_leaves_cauldron = 40;
+
+const integer procgive_lute_to_geida = 41;
+
+struct timetype {
+ longint time_left;
+ byte then_where;
+ byte what_for;
+};
+
+
+#ifdef __timeout_implementation__
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN array<1,7,timetype> times;
+#undef EXTERN
+#define EXTERN extern
+
+
+void set_up_timer(longint howlong, byte whither,byte why);
+
+void one_tick();
+
+void lose_timer(byte which);
+
+/*function timer_is_on(which:byte):boolean;*/
+
+ /* Procedures to do things at the end of amounts of time: */
+
+ void open_drawbridge();
+
+ void avaricius_talks();
+
+ void urinate();
+
+ void toilet2();
+
+ void bang();
+
+ void bang2();
+
+ void stairs();
+
+ void cardiff_survey();
+
+ void cardiff_return();
+
+ void cwytalot_in_herts();
+
+ void get_tied_up();
+
+ void get_tied_up2();
+
+ void hang_around();
+
+ void hang_around2();
+
+ void after_the_shootemup();
+
+ void jacques_wakes_up();
+
+ void naughty_duke();
+
+ void naughty_duke2();
+
+ void naughty_duke3();
+
+ void jump();
+
+ void crapulus_says_splud_out();
+
+ void buydrinks();
+
+ void buywine();
+
+ void callsguards();
+
+ void greetsmonk();
+
+ void fall_down_oubliette();
+
+ void meet_avaroid();
+
+ void rise_up_oubliette();
+
+ void robin_hood_and_geida();
+
+ void robin_hood_and_geida_talk();
+
+ void avalot_returns();
+
+ void avvy_sit_down();
+
+ void ghost_room_phew();
+
+ void arkata_shouts();
+
+ void winning();
+
+ void avalot_falls();
+
+ void spludwick_goes_to_cauldron();
+
+ void spludwick_leaves_cauldron();
+
+ void give_lute_to_geida();
+
+#endif
diff --git a/engines/avalanche/travel.cpp b/engines/avalanche/travel.cpp
new file mode 100644
index 0000000000..b7597670d6
--- /dev/null
+++ b/engines/avalanche/travel.cpp
@@ -0,0 +1,64 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+integer gd,gm;
+
+void zoomout(integer x,integer y)
+{
+ integer x1,y1,x2,y2;
+ byte fv;
+;
+ setcolor(white); setwritemode(xorput);
+ setlinestyle(dottedln,0,1);
+
+ for( fv=1; fv <= 20; fv ++)
+ {;
+ x1=x-(x / 20)*fv;
+ y1=y-((y-10) / 20)*fv;
+ x2=x+(((639-x) / 20)*fv);
+ y2=y+(((161-y) / 20)*fv);
+
+ rectangle(x1,y1,x2,y2);
+ delay(17);
+ rectangle(x1,y1,x2,y2);
+ }
+}
+
+void zoomin(integer x,integer y)
+{
+ integer x1,y1,x2,y2;
+ byte fv;
+;
+ setcolor(white); setwritemode(xorput);
+ setlinestyle(dottedln,0,1);
+
+ for( fv=20; fv >= 1; fv --)
+ {;
+ x1=x-(x / 20)*fv;
+ y1=y-((y-10) / 20)*fv;
+ x2=x+(((639-x) / 20)*fv);
+ y2=y+(((161-y) / 20)*fv);
+
+ rectangle(x1,y1,x2,y2);
+ delay(17);
+ rectangle(x1,y1,x2,y2);
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ zoomout(177,77);
+ zoomout(7,31);
+ zoomout(577,124);
+ zoomout(320,85);
+ zoomin(177,77);
+ zoomin(7,31);
+ zoomin(577,124);
+ zoomin(320,85);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/trip.cpp b/engines/avalanche/trip.cpp
new file mode 100644
index 0000000000..3dc89ac9ec
--- /dev/null
+++ b/engines/avalanche/trip.cpp
@@ -0,0 +1,139 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ TRIP The trippancy handler. (Trippancy 2) */
+
+#define __trip_implementation__
+
+
+#include "trip.h"
+
+
+#include "graph.h"
+#include "gyro.h"
+/*#include "Dos.h"*/
+
+
+/* */
+/* EGA Graphic Primitive for Turbo Pascal 3.01A, Version 01FEB86. */
+/* (C) 1986 by Kent Cedola, 2015 Meadow Lake Ct., Norfolk, VA, 23518 */
+/* */
+/* Description: Write a array of colors in a vertical line. The current */
+/* merge setting is used to control the combining of bits. */
+/* */
+ void gpwtcol(void* buf, integer n) /* Cedola */
+ {; /*
+ inline
+ ($1E/$A1/GDCUR_Y/$D1/$E0/$D1/$E0/$03/$06/GDCUR_Y/$05/$A000/$8E/$C0/$8B/$3E/
+ GDCUR_X/$8B/$CF/$D1/$EF/$D1/$EF/$D1/$EF/$BA/$03CE/$8A/$26/GDMERGE/$B0/$03/
+ $EF/$B8/$0205/$EF/$B0/$08/$EE/$42/$B0/$80/$80/$E1/$07/$D2/$C8/$EE/$8B/$4E/
+ $04/$C5/$76/$06/$8A/$24/$46/$26/$8A/$1D/$26/$88/$25/$83/$C7/$50/$E2/$F2/
+ $B0/$FF/$EE/$4A/$B8/>$05/$EF/$B8/>$03/$EF/$1F); */
+ }
+
+
+void loadtrip()
+{
+ untyped_file inf;
+;
+ assign(inf,"t:avvy.trp"); reset(inf,1);
+ seek(inf,0x27);
+ blockread(inf,pozzes,sizeof(pozzes));
+ blockread(inf,blue3,sizeof(blue3)); close(inf);
+}
+
+void plot(word count, integer ox,integer oy) /* orig x & y. Page is always 1. */
+{
+ byte x,y,len;
+;
+ do {
+ len=blue3[count]; if (len==177) return;
+ x=blue3[count+1]; y=blue3[count+2]; count += 3;
+ {;
+ gdcur_x=x+ox; gdcur_y=y+oy;
+ /* fiddle xy coords to match page 1 */
+ gdcur_y += 205; /* 203 */ gdcur_x -= 128; /* 114 */
+ if (gdcur_x<0)
+ {; gdcur_x += 640; gdcur_y -= 1; }
+ gpwtcol(&blue3[count],len); count += len;
+ }
+ } while (!false);
+}
+
+void boundscheck()
+{;
+ if (dna.uy>123) dna.uy=123;
+ if (dna.uy<10) dna.uy=10;
+ if (dna.ux<5) dna.ux=5;
+ if (dna.ux>600) dna.ux=600;
+}
+
+void budge()
+{;
+ if (set::of(up,ul,ur, eos).has(dna.rw)) dna.uy -= 3;
+ if (set::of(down,dl,dr, eos).has(dna.rw)) dna.uy += 3;
+ if (set::of(left,ul,dl, eos).has(dna.rw)) dna.ux -= 5;
+ if (set::of(right,ur,dr, eos).has(dna.rw)) dna.ux += 5;
+
+ boundscheck();
+
+ if (dna.rw>0)
+ {;
+ anim += 1; if (anim==7) anim=1;
+ }
+}
+
+void tripkey(char dir)
+{;
+ if (cw!=177) return;
+ {
+ dnatype& with = dna;
+ ;
+ switch (dir) {
+ case 'H': if (with.rw!=up) {; with.rw=up; ww=up; } else with.rw=0; break;
+ case 'P': if (with.rw!=down) {; with.rw=down; ww=down; } else with.rw=0; break;
+ case 'K': if (with.rw!=left) {; with.rw=left; ww=left; } else with.rw=0; break;
+ case 'M': if (with.rw!=right) {; with.rw=right; ww=right; } else with.rw=0; break;
+ case 'I': if (with.rw!=ur) {; with.rw=ur; ww=right; } else with.rw=0; break;
+ case 'Q': if (with.rw!=dr) {; with.rw=dr; ww=right; } else with.rw=0; break;
+ case 'O': if (with.rw!=dl) {; with.rw=dl; ww=left; } else with.rw=0; break;
+ case 'G': if (with.rw!=ul) {; with.rw=ul; ww=left; } else with.rw=0; break;
+ }
+ if (with.rw==0)
+ {;
+ ux=ppos[0][0]; uy=ppos[0][1]; anim -= 1;
+ if (anim==0) anim=6;
+ }
+ }
+}
+
+void trippancy()
+{;
+ if ((dna.rw==0) || (cw!=177) || (! dropsok)) return;
+ r.ax=11; intr(0x33,r);
+ setactivepage(1); off();
+ if (ppos[0][1]!=-177)
+ {;
+ putimage(ppos[0][0],ppos[0][1],replace[0],0);
+ }
+
+ getimage(dna.ux,dna.uy,dna.ux+xw,dna.uy+yw,replace[0]);
+ ppos[0][0]=dna.ux; ppos[0][1]=dna.uy;
+
+ plot(pozzes[anim*4+dna.ww-4],dna.ux,dna.uy);
+
+ { void& with = r; if ((cx==0) && (dx==0)) on();}
+ getimage(dna.ux-margin,dna.uy-margin,dna.ux+xw+margin,dna.uy+yw+margin,copier);
+ setactivepage(0); off(); putimage(dna.ux-margin,dna.uy-margin,copier,0); on();
+
+ {
+ void& with = mouths[0]; ; x=dna.ux+20; y=dna.uy; }
+
+ budge();
+}
+
+
diff --git a/engines/avalanche/trip.h b/engines/avalanche/trip.h
new file mode 100644
index 0000000000..520e323fe8
--- /dev/null
+++ b/engines/avalanche/trip.h
@@ -0,0 +1,17 @@
+#ifndef __trip_h__
+#define __trip_h__
+
+
+ void loadtrip();
+
+ void plot(word count, integer ox,integer oy);
+
+ void boundscheck();
+
+ void budge();
+
+ void tripkey(char dir);
+
+ void trippancy();
+
+#endif
diff --git a/engines/avalanche/trip3.cpp b/engines/avalanche/trip3.cpp
new file mode 100644
index 0000000000..c67f6e1f51
--- /dev/null
+++ b/engines/avalanche/trip3.cpp
@@ -0,0 +1,231 @@
+#include "ptoc.h"
+
+#define __trip3_implementation__
+ /* Project Minstrel- Trippancy routines */
+
+#include "trip3.h"
+
+
+#include "Graph.h"
+/*#include "Crt.h"*/
+
+/*$S+*/
+
+const integer avvy = 1;
+const integer test = 177;
+
+struct triprec {
+ byte handle; /* who is it? */
+ integer x,y; /* current x&y */
+ byte xm,ym; /* x&y margins */
+ shortint ix,iy; /* inc x&y */
+ byte stage; /* animation */
+ integer xl,yl; /* x&y length */
+ boolean prime; /* true on first move */
+ boolean alive; /* true if it moves */
+};
+
+array<1,10,triprec> tr;
+byte tramt;
+array<1,20000,byte> blue3;
+array<1,24,word> pozzes;
+
+const integer up = 1; const integer right = 2; const integer down = 3; const integer left = 4; const integer ur = 5; const integer dr = 6; const integer dl = 7; const integer ul = 8;
+
+/* */
+/* EGA Graphic Primitive for Turbo Pascal 3.01A, Version 01FEB86. */
+/* (C) 1986 by Kent Cedola, 2015 Meadow Lake Ct., Norfolk, VA, 23518 */
+/* */
+/* Description: Write a array of colors in a vertical line. The current */
+/* merge setting is used to control the combining of bits. */
+/* */
+ void gpwtcol(void* buf, integer n) /* Cedola */
+ {;
+ /* inline
+ ($1E/$A1/GDCUR_Y/$D1/$E0/$D1/$E0/$03/$06/GDCUR_Y/$05/$A000/$8E/$C0/$8B/$3E/
+ GDCUR_X/$8B/$CF/$D1/$EF/$D1/$EF/$D1/$EF/$BA/$03CE/$8A/$26/GDMERGE/$B0/$03/
+ $EF/$B8/$0205/$EF/$B0/$08/$EE/$42/$B0/$80/$80/$E1/$07/$D2/$C8/$EE/$8B/$4E/
+ $04/$C5/$76/$06/$8A/$24/$46/$26/$8A/$1D/$26/$88/$25/$83/$C7/$50/$E2/$F2/
+ $B0/$FF/$EE/$4A/$B8/>$05/$EF/$B8/>$03/$EF/$1F); */
+ }
+
+
+void loadtrip()
+{
+ untyped_file inf;
+;
+ assign(inf,"t:avvy.trp"); reset(inf,1);
+ seek(inf,0x27);
+ blockread(inf,pozzes,sizeof(pozzes));
+ blockread(inf,blue3,sizeof(blue3)); close(inf);
+}
+
+void enter(byte what_handle, integer xx,integer yy,integer lx,integer ly, byte mmx,byte mmy,byte st)
+{;
+ tramt += 1;
+ {
+ triprec& with = tr[tramt];
+ ;
+ with.handle=what_handle;
+ with.ix=0; with.iy=0;
+ with.x=xx; with.y=yy;
+ with.xl=lx; with.yl=ly;
+ with.xm=mmx; with.ym=mmy; with.stage=st;
+ with.prime=true; with.alive=true;
+ }
+}
+
+void plot(byte stage, integer ox,integer oy) /* orig x & y. Page is always 1/UNSEEN. */
+{
+ byte x,y,len; word count;
+;
+ count=pozzes[stage];
+ do {
+ len=blue3[count]; if (len==177) return;
+ x=blue3[count+1]; y=blue3[count+2]; count += 3;
+ {;
+ gdcur_x=x+ox; gdcur_y=y+oy;
+ /* fiddle xy coords to match page 1 */
+ gdcur_y += 205; /* 203 */ gdcur_x -= 128; /* 114 */
+ if (gdcur_x<0)
+ {; gdcur_x += 640; gdcur_y -= 1; }
+ gpwtcol(&blue3[count],len); count += len;
+ }
+ } while (!false);
+}
+
+void trippancy()
+{
+ byte fv; pointer p,saved1,saved2; word s; array<1,10,pointer> q;
+ boolean allstill;
+;
+ if ((cw!=177) || (! dropsok) || keypressed()) return;
+
+ /* Do the Avvy Walk */
+
+ switch (dna.rw) {
+ case up: budge(avvy, 0,-3,anim*4-3); break;
+ case down: budge(avvy, 0, 3,anim*4-1); break;
+ case right: budge(avvy, 5, 0,anim*4-2); break;
+ case left: budge(avvy,-5, 0,anim*4 ); break;
+ case ul: budge(avvy,-5,-3,anim*4 ); break;
+ case dl: budge(avvy,-5, 3,anim*4 ); break;
+ case ur: budge(avvy, 5,-3,anim*4-2); break;
+ case dr: budge(avvy, 5, 3,anim*4-2); break;
+ }
+
+ for( fv=1; fv <= tramt; fv ++) { triprec& with = tr[fv]; boundscheck(with.x,with.y,with.xm,with.ym);}
+
+ allstill=true;
+ for( fv=1; fv <= tramt; fv ++)
+ { triprec& with = tr[fv];
+ if (((with.alive) && (! ((with.ix==0) && (with.iy==0)))) || with.prime) allstill=false;}
+ if (allstill) return;
+
+ if (dna.rw>0)
+ {;
+ anim += 1; if (anim==7) anim=1;
+ }
+
+ /* Trippancy Step 1 - Grab moon array of unmargined sprites (phew) */
+ mark(saved1);
+ setactivepage(1); off();
+ for( fv=1; fv <= tramt; fv ++)
+ {
+ triprec& with = tr[fv];
+ ;
+ s=imagesize(with.x-with.xm,with.y-with.ym,with.x+with.xl+with.xm,with.y+with.yl+with.ym);
+ getmem(q[fv],s); getimage(with.x-with.xm,with.y-with.ym,with.x+with.xl+with.xm,with.y+with.yl+with.ym,q[fv]);
+ }
+ /* Step 2 - Plot sprites on 1/UNSEEN */
+ for( fv=1; fv <= tramt; fv ++)
+ {
+ triprec& with = tr[fv];
+ ;
+ plot(with.stage,with.x,with.y);
+ }
+ /* Step 3 - Copy all eligible from 1/UNSEEN to 0/SEEN */
+ mark(saved2);
+ for( fv=1; fv <= tramt; fv ++)
+ { triprec& with = tr[fv];
+ if (((with.alive) && (! ((with.ix==0) && (with.iy==0)))) || with.prime)
+ {;
+ s=imagesize(with.x-with.xm,with.y-with.ym,with.x+with.xl+with.xm,with.y+with.yl+with.ym);
+ getmem(p,s);
+ setactivepage(1); getimage(with.x-with.xm,with.y-with.ym,with.x+with.xl+with.xm,with.y+with.yl+with.ym,p);
+ setactivepage(0); putimage(with.x-with.xm,with.y-with.ym,p,0);
+ release(saved2); with.prime=false;
+ }}
+ /* Step 4 - Unplot sprites from 1/UNSEEN */
+ setactivepage(1);
+ for( fv=1; fv <= tramt; fv ++)
+ {
+ triprec& with = tr[fv];
+ ;
+ putimage(with.x-with.xm,with.y-with.ym,q[fv],0);
+ if (with.ix!=0) with.x=with.x+with.ix;
+ if (with.iy!=0) with.y=with.y+with.iy;
+ with.ix=0; with.iy=0;
+ if (with.handle==avvy) {
+ dnatype& with1 = dna; ; ux=with.x; uy=with.y; }
+ }
+ on(); release(saved1);
+ for( fv=1; fv <= tramt; fv ++) /* synch xy coords of mouths */
+ {
+ triprec& with = tr[fv];
+ ; mouths[fv].x=with.x+20; mouths[fv].y=with.y; }
+
+ setactivepage(0);
+}
+
+void budge(byte who, shortint xx,shortint yy, byte frame) /* Moving & animation controller */
+{
+ byte fv;
+;
+ for( fv=1; fv <= tramt; fv ++)
+ { triprec& with = tr[fv];
+ if (with.handle==who)
+ {;
+ with.ix=xx; with.iy=yy;
+ with.stage=frame;
+ }}
+}
+
+void tripkey(char dir)
+{;
+ if (cw!=177) return;
+ {
+ dnatype& with = dna;
+ ;
+ switch (dir) {
+ case 'H': if (with.rw!=up) {; with.rw=up; ww=up; } else with.rw=0; break;
+ case 'P': if (with.rw!=down) {; with.rw=down; ww=down; } else with.rw=0; break;
+ case 'K': if (with.rw!=left) {; with.rw=left; ww=left; } else with.rw=0; break;
+ case 'M': if (with.rw!=right) {; with.rw=right; ww=right; } else with.rw=0; break;
+ case 'I': if (with.rw!=ur) {; with.rw=ur; ww=right; } else with.rw=0; break;
+ case 'Q': if (with.rw!=dr) {; with.rw=dr; ww=right; } else with.rw=0; break;
+ case 'O': if (with.rw!=dl) {; with.rw=dl; ww=left; } else with.rw=0; break;
+ case 'G': if (with.rw!=ul) {; with.rw=ul; ww=left; } else with.rw=0; break;
+ }
+ if (with.rw==0)
+ {;
+ ux=ppos[0][0]; uy=ppos[0][1]; anim -= 1;
+ if (anim==0) anim=6;
+ }
+ }
+}
+
+void boundscheck(integer& x,integer& y, byte xm,byte ym)
+{;
+ if (y>127-ym) y=127-ym; if (y<ym+10) y=ym+10;
+ if (x<xm) x=xm; if (x>640-xm) x=640-xm;
+}
+
+class unit_trip3_initialize {
+ public: unit_trip3_initialize();
+};
+static unit_trip3_initialize trip3_constructor;
+
+unit_trip3_initialize::unit_trip3_initialize() {; /* init portion of Trip3 */
+ tramt=0;
+}
diff --git a/engines/avalanche/trip3.h b/engines/avalanche/trip3.h
new file mode 100644
index 0000000000..ccad15346b
--- /dev/null
+++ b/engines/avalanche/trip3.h
@@ -0,0 +1,20 @@
+#ifndef __trip3_h__
+#define __trip3_h__
+
+
+#include "gyro.h"
+
+
+ void loadtrip();
+
+ void boundscheck(integer& x,integer& y, byte xm,byte ym);
+
+ void budge(byte who, shortint xx,shortint yy, byte frame); /* Moving & animation controller */
+
+ void tripkey(char dir);
+
+ void trippancy();
+
+ void enter(byte what_handle, integer xx,integer yy,integer lx,integer ly, byte mmx,byte mmy,byte st);
+
+#endif
diff --git a/engines/avalanche/trip42.cpp b/engines/avalanche/trip42.cpp
new file mode 100644
index 0000000000..b55b209d13
--- /dev/null
+++ b/engines/avalanche/trip42.cpp
@@ -0,0 +1,450 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ TRIP42 Trippancy IV point 2 - "Trip Oop 2" */
+
+#define __trip42_implementation__
+ /* Trippancy IV.2 (Trip Oop) */
+#include "trip42.h"
+
+
+/*#include "Scrolls.h"*/
+/*#include "Lucerna.h"*/
+/*#include "Dropdown.h"*/
+/*#include "Access.h"*/
+
+
+/*procedure copier(x1,y1,x2,y2,x3,y3,x4,y4:integer);
+
+ function dropin(xc,yc,x1,y1,x2,y2:integer):boolean;
+ { Dropin returns True if the point xc,yc falls within the 1-2 rectangle. }
+ begin;
+ dropin:=((xc>=x1) and (xc<=x2) and (yc>=y1) and (yc<=y2));
+ end;
+
+ function lesser(a,b:integer):integer;
+ begin;
+ if a<b then lesser:=a else lesser:=b;
+ end;
+
+ function greater(a,b:integer):integer;
+ begin;
+ if a>b then greater:=a else greater:=b;
+ end;
+
+begin;
+ if dropin(x3,y3,x1,y1,x2,y2)
+ or dropin(x3,y4,x1,y1,x2,y2)
+ or dropin(x4,y3,x1,y1,x2,y2)
+ or dropin(x4,y4,x1,y1,x2,y2) then
+ begin; { Overlaps }
+ mblit(lesser(x1,x3),lesser(y1,y3),greater(x2,x4),greater(y2,y4),1,0);
+ end else
+ begin; { Doesn't overlap- copy both of them seperately }
+ mblit(x3,y3,x4,y4,1,0); { backwards- why not...? }
+ mblit(x1,y1,x2,y2,1,0);
+ end;
+end; */
+
+void loadtrip()
+{
+ byte gm;
+;
+ for( gm=1; gm <= numtr; gm ++) tr[gm].original();
+ tr[1].init(0);
+}
+
+byte checkfeet(integer x1,integer x2,integer oy,integer y, byte yl)
+{
+ byte a,c; integer fv,ff;
+byte checkfeet_result;
+;
+ a=0; setactivepage(2); if (x1<0) x1=0; if (x2>639) x2=639;
+ if (oy<y)
+ for( fv=x1; fv <= x2; fv ++)
+ for( ff=oy+yl; ff <= y+yl; ff ++)
+ {;
+ c=getpixel(fv,ff);
+ if (c>a) a=c;
+ } else
+ for( fv=x1; fv <= x2; fv ++)
+ for( ff=y+yl; ff <= oy+yl; ff ++)
+ {;
+ c=getpixel(fv,ff);
+ if (c>a) a=c;
+ }
+ checkfeet_result=a; setactivepage(1-cp);
+return checkfeet_result;
+}
+
+void touchcol(byte tc);
+static boolean bug;
+
+static void fr(byte a,byte b) {; fliproom(a,b); bug=false; }
+
+void touchcol(byte tc)
+{;
+ bug=true; /* j.i.c. */
+ switch (dna.room) {
+ case 1: fr(2,3); break;
+ case 2: {; /* main corridor */
+ switch (tc) {
+ case 1: fr(3,1); break; /* to the other corridor */
+ case 2: fr(2,1); break; /* to this corridor! Fix this later... */
+ }
+ }
+ break;
+ case 3: {; /* turn corridor */
+ switch (tc) {
+ case 1: fr(2,1); break; /* to the other corridor */
+ case 2: fr(12,1); break; /* through Spludwick's door */
+ }
+ }
+ break;
+ case 12: fr(3,2); break;
+ }
+ if (bug)
+ {;
+ display(string('\7')+"Unknown touchcolour ("+strf(tc)+')'+" in "+strf(dna.room)
+ +'.'); tr[1].bounce();
+ }
+}
+
+triptype* triptype::init(byte spritenum)
+{
+ integer gd,gm; word s; untyped_file f; varying_string<2> xx; byte sort,n;
+ word bigsize; pointer p,q;
+;
+ str(spritenum,xx); assign(f,string("c:\\avalot\\sprite")+xx+".avd");
+ reset(f,1); seek(f,59);
+ blockread(f,a,sizeof(a)); blockread(f,bigsize,2);
+ setactivepage(3);
+ for( sort=0; sort <= 1; sort ++)
+ {;
+ mark(q); getmem(p,bigsize);
+ blockread(f,p,bigsize);
+ off; putimage(0,0,p,0); release(q); n=1;
+ { adxtype& with = a;
+ for( gm=0; gm <= (with.num / with.seq)-1; gm ++) /* directions */
+ for( gd=0; gd <= with.seq-1; gd ++) /* steps */
+ {;
+ getmem(pic[n][sort],a.size); /* grab the memory */
+ getimage((gm / 2)*(with.xl*6)+gd*with.xl,(gm % 2)*with.yl,
+ (gm / 2)*(with.xl*6)+gd*with.xl+with.xl-1,(gm % 2)*with.yl+with.yl-1,
+ pic[n][sort]); /* grab the pic */
+ n += 1;
+ }} /*on;*/
+ }
+ close(f); setactivepage(1-cp);
+
+ x=0; y=0; quick=true; visible=false;
+/* for x:=0 to 1 do getmem(behind[x],a.size);*/
+ homing=false; ix=0; iy=0; step=0; check_me=a.name=="Avalot";
+ count=0;
+return this;
+}
+
+void triptype::original()
+{;
+ quick=false;
+}
+
+void triptype::andexor()
+{
+ byte picnum; /* Picnum, Picnic, what ye heck */
+;
+ picnum=face*a.seq+step+1; off;
+ putimage(x,y,pic[picnum][0],andput);
+ putimage(x,y,pic[picnum][1],xorput); /*on;*/
+}
+
+void triptype::turn(byte whichway)
+{;
+ if (whichway==8) face=0; else face=whichway;
+}
+
+void triptype::appear(integer wx,integer wy, byte wf)
+{;
+ x=(wx / 8)*8; y=wy; ox[cp]=wx; oy[cp]=wy; turn(wf);
+ visible=true; ix=0; iy=0;
+}
+
+void triptype::walk()
+{
+ byte tc; fieldtype r;
+;
+ {;
+ x1=x-1; y1=y-2; x2=x+a.xl+1; y2=y+a.yl+2;
+ }
+ getset[1-cp].remember(r);
+ ox[cp]=x; oy[cp]=y;
+ if (homing) homestep();
+ x=x+ix; y=y+iy;
+ if (check_me) {;
+ tc=checkfeet(x,x+a.xl,oy[cp],y,a.yl);
+ if (tc!=0)
+ { void& with = magics[tc];
+ switch (op) {
+ case exclaim: {; bounce(); dixi('x',data); } break;
+ case bounces: bounce(); break;
+ case transport: fliproom(hi(data),lo(data)); break;
+ case unfinished: {;
+ bounce();
+ display("\7Sorry.\3\rThis place is not avaliable yet!");
+ }
+ break;
+ }}
+ }
+ count += 1;
+ if (((ix!=0) || (iy!=0)) && (count>1))
+ {;
+ step += 1; if (step==a.seq) step=0; count=0;
+ }
+}
+
+void triptype::bounce()
+{; x=ox[cp]; y=oy[cp]; stopwalk(); return; }
+
+void triptype::walkto(integer xx,integer yy)
+{;
+ speed(xx-x,yy-y); hx=xx; hy=yy; homing=true;
+}
+
+void triptype::stophoming()
+{;
+ homing=false;
+}
+
+void triptype::homestep()
+{
+ integer temp;
+;
+ if ((hx==x) && (hy==y))
+ {; /* touching the target */
+ homing=false; return;
+ }
+ ix=0; iy=0;
+ if (hy!=y)
+ {;
+ temp=hy-y; if (temp>4) iy=4; else if (temp<-4) iy=-4; else iy=temp;
+ }
+ if (hx!=x)
+ {;
+ temp=hx-x; if (temp>4) ix=4; else if (temp<-4) ix=-4; else ix=temp;
+ }
+}
+
+void triptype::speed(shortint xx,shortint yy)
+{;
+ ix=xx; iy=yy;
+ if ((ix==0) && (iy==0)) return; /* no movement */
+ if (ix==0)
+ {; /* No horz movement */
+ if (iy<0) turn(up); else turn(down);
+ } else
+ {;
+ if (ix<0) turn(left); else turn(right);
+ }
+}
+
+void triptype::stopwalk()
+{;
+ ix=0; iy=0; homing=false;
+}
+
+void triptype::chatter()
+{;
+ talkx=x+a.xl / 2; talky=y; talkf=a.fgc; talkb=a.bgc;
+}
+
+getsettype* getsettype::init()
+{;
+ numleft=0; /* initialise array pointer */
+ return this;
+}
+
+void getsettype::remember(fieldtype r)
+{;
+ numleft += 1;
+ gs[numleft]=r;
+}
+
+void getsettype::recall(fieldtype& r)
+{;
+ r=gs[numleft];
+ numleft -= 1;
+}
+
+void rwsp(byte t,byte r)
+{
+ const integer xs = 3; const integer ys = 1;
+;
+ { triptype& with = tr[t]; switch (r) {
+ case up: speed( 0,-ys); break; case down: speed( 0, ys); break; case left: speed(-xs, 0); break;
+ case right: speed( xs, 0); break; case ul: speed(-xs,-ys); break; case ur: speed( xs,-ys); break;
+ case dl: speed(-xs, ys); break; case dr: speed( xs, ys); break;
+ }}
+}
+
+void apped(byte trn,byte np)
+{;
+ {
+ triptype& with = tr[trn];
+ ; { void& with1 = peds[np]; appear(with.x-with.a.xl / 2,with.y-with.a.yl,dir);}
+ rwsp(trn,tr[trn].face); }
+}
+
+void getback()
+{
+ byte fv;
+ fieldtype r;
+;
+ { getsettype& with = getset[1-cp];
+ while (with.numleft>0)
+ {;
+ recall(r);
+ mblit(x1,y1,x2,y2,3,1-cp);
+ }}
+}
+
+void trippancy_link()
+{
+ byte fv;
+;
+ if ((ddm_o.menunow) | ontoolbar | seescroll | (~ alive)) return;
+ for( fv=1; fv <= numtr; fv ++) { triptype& with = tr[fv]; if (with.quick) getback();}
+ for( fv=1; fv <= numtr; fv ++) { triptype& with = tr[fv]; if (with.quick) walk();}
+ for( fv=1; fv <= numtr; fv ++) { triptype& with = tr[fv]; if (with.quick && with.visible) andexor();}
+}
+
+void stopwalking()
+{;
+ tr[1].stopwalk(); dna.rw=stopped;
+}
+
+void tripkey(char dir)
+{;
+ if (ctrl==cjoy) return;
+
+ { triptype& with = tr[1];
+ {;
+ switch (dir) {
+ case 'H': if (rw!=up)
+ {; rw=up; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'P': if (rw!=down)
+ {; rw=down; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'K': if (rw!=left)
+ {; rw=left; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'M': if (rw!=right)
+ {; rw=right; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'I': if (rw!=ur)
+ {; rw=ur; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'Q': if (rw!=dr)
+ {; rw=dr; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'O': if (rw!=dl)
+ {; rw=dl; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'G': if (rw!=ul)
+ {; rw=ul; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'L': stopwalking(); break;
+ }
+ }}
+}
+
+void getsetclear()
+{
+ byte fv;
+;
+ for( fv=0; fv <= 1; fv ++) getset[fv].init();
+}
+
+void fliproom(byte room,byte ped)
+{;
+ dusk; getsetclear(); enterroom(room); apped(1,ped);
+ oldrw=dna.rw; dna.rw=tr[1].face; showrw; dawn;
+}
+
+boolean infield(byte x) /* returns True if you're within field "x" */
+{
+ integer yy;
+boolean infield_result;
+;
+ { void& with = fields[x]; {
+ triptype& with = tr[1];
+ ;
+ yy=with.y+with.a.yl;
+ infield_result=(with.x>=x1) && (with.x<=x2) && (yy>=y1) && (yy<=y2);
+ }}
+return infield_result;
+}
+
+boolean neardoor() /* returns True if you're near a door! */
+{
+ integer ux,uy; byte fv; boolean nd;
+boolean neardoor_result;
+;
+ if (numfields<9)
+ {; /* there ARE no doors here! */
+ neardoor_result=false;
+ return neardoor_result;
+ }
+ {
+ triptype& with = tr[1];
+ ;
+ ux=with.x;
+ uy=with.y+with.a.yl;
+ } nd=false;
+ for( fv=9; fv <= numfields; fv ++)
+ {
+ void& with = fields[fv];
+ ;
+ if ((ux>=x1) && (ux<=x2) && (uy>=y1) && (uy<=y2)) nd=true;
+ }
+ neardoor_result=nd;
+return neardoor_result;
+}
+
+void readstick()
+{
+ byte jw;
+;
+ if (ctrl==ckey) return;
+
+ jw=joyway;
+
+ {
+ triptype& with = tr[1];
+ ;
+ if (jw==stopped) stopwalking(); else
+ {;
+ dna.rw=jw; rwsp(1,dna.rw);
+ }
+ }
+
+ if (jw!=oldjw)
+ {;
+ showrw;
+ oldjw=jw;
+ }
+
+}
+
+class unit_trip42_initialize {
+ public: unit_trip42_initialize();
+};
+static unit_trip42_initialize trip42_constructor;
+
+unit_trip42_initialize::unit_trip42_initialize() {;
+ getsetclear();
+}
diff --git a/engines/avalanche/trip42.h b/engines/avalanche/trip42.h
new file mode 100644
index 0000000000..b5e4f13614
--- /dev/null
+++ b/engines/avalanche/trip42.h
@@ -0,0 +1,90 @@
+#ifndef __trip42_h__
+#define __trip42_h__
+
+/* {$R+ but switch it off soon...} */
+
+#include "graph.h"
+/*#include "Crt.h"*/
+/*#include "Gyro.h"*/
+/*#include "Sticks.h"*/
+
+
+const integer maxgetset = 10;
+
+struct adxtype {
+ varying_string<12> name; /* name of character */
+ byte num; /* number of pictures */
+ byte xl,yl; /* x & y lengths of pictures */
+ byte seq; /* how many in one stride */
+ word size; /* the size of one picture */
+ byte fgc,bgc; /* foreground & background bubble colours */
+};
+
+class triptype {
+public:
+ adxtype a; /* vital statistics */
+ byte face,step;
+ integer x,y; /* current xy coords */
+ array<0,1,integer> ox,oy; /* last xy coords */
+ shortint ix,iy; /* amount to move sprite by, each step */
+ matrix<1,24,0,1,pointer> pic; /* the pictures themselves */
+ boolean quick,visible,homing,check_me;
+ integer hx,hy; /* homing x & y coords */
+ byte count; /* counts before changing step */
+
+ triptype* init(byte spritenum); /* loads & sets up the sprite */
+ void original(); /* just sets Quick to false */
+ void andexor(); /* drops sprite onto screen */
+ void turn(byte whichway); /* turns him round */
+ void appear(integer wx,integer wy, byte wf); /* switches him on */
+ void bounce(); /* bounces off walls. */
+ void walk(); /* prepares for andexor, etc. */
+ void walkto(integer xx,integer yy); /* home in on a point */
+ void stophoming(); /* self-explanatory */
+ void homestep(); /* calculates ix & iy for one homing step */
+ void speed(shortint xx,shortint yy); /* sets ix & iy, non-homing, etc */
+ void stopwalk(); /* Stops the sprite from moving */
+ void chatter(); /* Sets up talk vars */
+};
+
+class getsettype {
+public:
+ array<1,maxgetset,fieldtype> gs;
+ byte numleft;
+
+ getsettype* init();
+ void remember(fieldtype r);
+ void recall(fieldtype& r);
+};
+
+const integer numtr = 5; /* current max no. of sprites */
+
+void trippancy_link();
+
+void loadtrip();
+
+void tripkey(char dir);
+
+void apped(byte trn,byte np);
+
+void fliproom(byte room,byte ped);
+
+boolean infield(byte x); /* returns True if you're within field "x" */
+
+boolean neardoor(); /* returns True if you're near a door! */
+
+void readstick();
+
+
+#ifdef __trip42_implementation__
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN array<1,numtr,triptype> tr;
+EXTERN array<0,1,getsettype> getset;
+#undef EXTERN
+#define EXTERN extern
+
+
+#endif
diff --git a/engines/avalanche/trip5.cpp b/engines/avalanche/trip5.cpp
new file mode 100644
index 0000000000..3674b1ffd7
--- /dev/null
+++ b/engines/avalanche/trip5.cpp
@@ -0,0 +1,1888 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ TRIP5 Trippancy V */
+
+#define __trip5_implementation__
+ /* Trippancy V */ /* Define NOASM to use Pascal instead of asm. */
+/*$S- Fast!*/
+#include "trip5.h"
+
+
+/*#include "Scrolls.h"*/
+/*#include "Lucerna.h"*/
+/*#include "Dropdown.h"*/
+/*#include "Visa.h"*/
+/*#include "Celer.h"*/
+/*#include "Timeout.h"*/
+/*#include "Sequence.h"*/
+/*#include "Enid.h"*/
+
+
+void loadtrip()
+{
+ byte gm;
+
+ for( gm=1; gm <= numtr; gm ++) tr[gm].original();
+ fillchar(aa,sizeof(aa),'\0');
+}
+
+byte checkfeet(integer x1,integer x2,integer oy,integer y, byte yl)
+{
+ byte a,c; integer fv,ff;
+
+/* if not alive then begin checkfeet:=0; exit; end;*/
+ byte checkfeet_result;
+ a=0; setactivepage(2); if (x1<0) x1=0; if (x2>639) x2=639;
+ if (oy<y)
+ for( fv=x1; fv <= x2; fv ++)
+ for( ff=oy+yl; ff <= y+yl; ff ++)
+ {
+ c=getpixel(fv,ff);
+ if (c>a) a=c;
+ } else
+ for( fv=x1; fv <= x2; fv ++)
+ for( ff=y+yl; ff <= oy+yl; ff ++)
+ {
+ c=getpixel(fv,ff);
+ if (c>a) a=c;
+ }
+ checkfeet_result=a; setactivepage(1-cp);
+ return checkfeet_result;
+}
+
+byte geida_ped(byte which)
+{
+ byte geida_ped_result;
+ switch (which) {
+ case 1: geida_ped_result= 7; break;
+ case 2:case 6: geida_ped_result= 8; break;
+ case 3:case 5: geida_ped_result= 9; break;
+ case 4: geida_ped_result=10; break;
+ }
+ return geida_ped_result;
+}
+
+void catamove(byte ped)
+ /* When you enter a new position in the catacombs, this procedure should
+ be called. It changes the Also codes so that they may match the picture
+ on the screen. (Coming soon: It draws up the screen, too.) */
+{
+ longint here;
+ word xy_word;
+ byte fv,ff;
+
+/* XY_word is cat_x+cat_y*256. Thus, every room in the
+ catacombs has a different number for it. */
+
+
+ {
+ xy_word=cat_x+cat_y*256;
+ geida_spin=0;
+ }
+ switch (xy_word) {
+ case 1801: { /* Exit catacombs */
+ fliproom(r__lustiesroom,4);
+ display("Phew! Nice to be out of there!");
+ return;
+ }
+ break;
+ case 1033: { /* Oubliette */
+ fliproom(r__oubliette,1);
+ display("Oh, NO!\231\2");
+ return;
+ }
+ break;
+ case 4: {
+ fliproom(r__geidas,1);
+ return;
+ }
+ break;
+ case 2307: {
+ fliproom(r__lusties,5);
+ display("Oh no... here we go again...");
+ dna.user_moves_avvy=false;
+ tr[1].iy=1; tr[1].ix=0;
+ return;
+ }
+ break;
+ }
+
+ if (~ dna.enter_catacombs_from_lusties_room) load(29);
+ here=catamap[cat_y][cat_x];
+
+ switch (here & 0xf) { /* West. */
+ case 0: { /* no connection (wall) */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=nix; /* Door. */
+ show_one(28);
+ }
+ break;
+ case 0x1: { /* no connection (wall + shield), */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=nix; /* Door. */
+ show_one(28); /* Wall, plus... */
+ show_one(29); /* ...shield. */
+ }
+ break;
+ case 0x2: { /* wall with door */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=special; /* Door. */
+ show_one(28); /* Wall, plus... */
+ show_one(30); /* ...door. */
+ }
+ break;
+ case 0x3: { /* wall with door and shield */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=special; /* Door. */
+ show_one(28); /* Wall, plus... */
+ show_one(30); /* ...door, and... */
+ show_one(29); /* ...shield. */
+ }
+ break;
+ case 0x4: { /* no connection (wall + window), */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=nix; /* Door. */
+ show_one(28); /* Wall, plus... */
+ show_one(5); /* ...window. */
+ }
+ break;
+ case 0x5: { /* wall with door and window */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=special; /* Door. */
+ show_one(28); /* Wall, plus... */
+ show_one(30); /* ...door, and... */
+ show_one(5); /* ...window. */
+ }
+ break;
+ case 0x6: { /* no connection (wall + torches), */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=nix; /* No door. */
+ show_one(28); /* Wall, plus... */
+ show_one(7); /* ...torches. */
+ }
+ break;
+ case 0x7: { /* wall with door and torches */
+ magics[2].op=bounces; /* Sloping wall. */
+ magics[3].op=nix; /* Straight wall. */
+ portals[13].op=special; /* Door. */
+ show_one(28); /* Wall, plus... */
+ show_one(30); /* ...door, and... */
+ show_one(7); /* ...torches. */
+ }
+ break;
+ case 0xf: { /* straight-through corridor. */
+ magics[2].op=nix; /* Sloping wall. */
+ magics[3].op=special; /* Straight wall. */
+ }
+ break;
+ }
+
+ /* ---- */
+
+ switch ((cardinal)(here & 0xf0) >> 4) { /* East */
+ case 0: { /* no connection (wall) */
+ magics[5].op=bounces; /* Sloping wall. */
+ magics[6].op=nix; /* Straight wall. */
+ portals[15].op=nix; /* Door. */
+ show_one(19);
+ }
+ break;
+ case 0x1: { /* no connection (wall + window), */
+ magics[5].op=bounces; /* Sloping wall. */
+ magics[6].op=nix; /* Straight wall. */
+ portals[15].op=nix; /* Door. */
+ show_one(19); /* Wall, plus... */
+ show_one(20); /* ...window. */
+ }
+ break;
+ case 0x2: { /* wall with door */
+ magics[5].op=bounces; /* Sloping wall. */
+ magics[6].op=nix; /* Straight wall. */
+ portals[15].op=special; /* Door. */
+ show_one(19); /* Wall, plus... */
+ show_one(21); /* ...door. */
+ }
+ break;
+ case 0x3: { /* wall with door and window */
+ magics[5].op=bounces; /* Sloping wall. */
+ magics[6].op=nix; /* Straight wall. */
+ portals[15].op=special; /* Door. */
+ show_one(19); /* Wall, plus... */
+ show_one(20); /* ...door, and... */
+ show_one(21); /* ...window. */
+ }
+ break;
+ case 0x6: { /* no connection (wall + torches), */
+ magics[5].op=bounces; /* Sloping wall. */
+ magics[6].op=nix; /* Straight wall. */
+ portals[15].op=nix; /* No door. */
+ show_one(19); /* Wall, plus... */
+ show_one(18); /* ...torches. */
+ }
+ break;
+ case 0x7: { /* wall with door and torches */
+ magics[5].op=bounces; /* Sloping wall. */
+ magics[6].op=nix; /* Straight wall. */
+ portals[15].op=special; /* Door. */
+ show_one(19); /* Wall, plus... */
+ show_one(21); /* ...door, and... */
+ show_one(18); /* ...torches. */
+ }
+ break;
+ case 0xf: { /* straight-through corridor. */
+ magics[5].op=nix; /* Sloping wall. */
+ magics[6].op=special; /* Straight wall. */
+ portals[15].op=nix; /* Door. */
+ }
+ break;
+ }
+
+ /* ---- */
+
+ switch ((cardinal)(here & 0xf00) >> 8) { /* South */
+ case 0: { /* No connection. */
+ magics[7].op=bounces;
+ magics[12].op=bounces;
+ magics[13].op=bounces;
+ }
+ break;
+ case 0x1: {
+ show_one(22);
+ { void& with = magics[13];
+ if ((xy_word==2051) & (dna.geida_follows))
+ op=exclaim;
+ else op=special;} /* Right exit south. */
+ magics[7].op=bounces;
+ magics[12].op=bounces;
+ }
+ break;
+ case 0x2: {
+ show_one(23);
+ magics[7].op=special; /* Middle exit south. */
+ magics[12].op=bounces;
+ magics[13].op=bounces;
+ }
+ break;
+ case 0x3: {
+ show_one(24);
+ magics[12].op=special; /* Left exit south. */
+ magics[7].op=bounces;
+ magics[13].op=bounces;
+ }
+ break;
+ }
+
+ switch ((cardinal)(here & 0xf000) >> 12) { /* North */
+ case 0: { /* No connection */
+ magics[1].op=bounces;
+ portals[12].op=nix; /* Door. */
+ }
+ break;
+ /* LEFT handles: */
+/* $1: begin
+ show_one(4);
+ magics[1].op:=bounces; { Left exit north. } { Change magic number! }
+ portals[12].op:=special; { Door. }
+ end;*/
+ case 0x2: {
+ show_one(4);
+ magics[1].op=bounces; /* Middle exit north. */
+ portals[12].op=special; /* Door. */
+ }
+ break;
+/* $3: begin
+ show_one(4);
+ magics[1].op:=bounces; { Right exit north. } { Change magic number! }
+ portals[12].op:=special; { Door. }
+ end;
+ { RIGHT handles: }
+ $4: begin
+ show_one(3);
+ magics[1].op:=bounces; { Left exit north. } { Change magic number! }
+ portals[12].op:=special; { Door. }
+ end;*/
+ case 0x5: {
+ show_one(3);
+ magics[1].op=bounces; /* Middle exit north. */
+ portals[12].op=special; /* Door. */
+ }
+ break;
+/* $6: begin
+ show_one(3);
+ magics[1].op:=bounces; { Right exit north. }
+ portals[12].op:=special; { Door. }
+ end;*/
+ /* ARCHWAYS: */
+ case 0x7:case 0x8:case 0x9: {
+ show_one(6);
+
+ if (((cardinal)(here & 0xf000) >> 12)>0x7) show_one(31);
+ if (((cardinal)(here & 0xf000) >> 12)==0x9) show_one(32);
+
+ magics[1].op=special; /* Middle arch north. */
+ portals[12].op=nix; /* Door. */
+ }
+ break;
+ /* DECORATIONS: */
+ case 0xd: { /* No connection + WINDOW */
+ magics[1].op=bounces;
+ portals[12].op=nix; /* Door. */
+ show_one(14);
+ }
+ break;
+ case 0xe: { /* No connection + TORCH */
+ magics[1].op=bounces;
+ portals[12].op=nix; /* Door. */
+ show_one(8);
+ }
+ break;
+ /* Recessed door: */
+ case 0xf: {
+ magics[1].op=nix; /* Door to Geida's room. */
+ show_one(1);
+ portals[12].op=special; /* Door. */
+ }
+ break;
+ }
+
+ switch (xy_word) {
+ case 514: show_one(17); break; /* [2,2] : "Art Gallery" sign over door. */
+ case 264: show_one(9); break; /* [8,1] : "The Wrong Way!" sign. */
+ case 1797: show_one(2); break; /* [5,7] : "Ite Mingite" sign. */
+ case 258: for( fv=0; fv <= 2; fv ++) /* [2,1] : Art gallery - pictures */
+ {
+ show_one_at(15,130+fv*120,70);
+ show_one_at(16,184+fv*120,78);
+ }
+ break;
+ case 1287: for( fv=10; fv <= 13; fv ++) show_one(fv); break; /* [7,5] : 4 candles. */
+ case 776: show_one(10); break; /* [8,3] : 1 candle. */
+ case 2049: show_one(11); break; /* [1,8] : another candle. */
+ case 257: { show_one(12); show_one(13); } break; /* [1,1] : the other two. */
+ }
+
+ if ((dna.geida_follows) & (ped>0))
+ {
+ triptype& with = tr[2];
+
+ if (! with.quick) /* If we don't already have her... */
+ tr[2].init(5,true); /* ...Load Geida. */
+ apped(2,geida_ped(ped));
+ tr[2].call_eachstep =true;
+ tr[2].eachstep=procgeida_procs;
+ }
+}
+
+void call_special(word which);
+
+ /* This proc gets called whenever you touch a line defined as Special. */
+static void dawndelay()
+ { set_up_timer(2,procdawn_delay,reason_dawndelay); }
+
+void call_special(word which)
+{
+ switch (which) {
+ case 1: { /* Special 1: Room 22: top of stairs. */
+ show_one(1);
+ dna.brummie_stairs=1;
+ magics[10].op=nix;
+ set_up_timer(10,procstairs,reason_brummiestairs);
+ stopwalking();
+ dna.user_moves_avvy=false;
+ }
+ break;
+ case 2: { /* Special 2: Room 22: bottom of stairs. */
+ dna.brummie_stairs=3;
+ magics[11].op=nix;
+ magics[12].op=exclaim;
+ magics[12].data=5;
+ magics[4].op=bounces; /* Now works as planned! */
+ stopwalking();
+ dixi('q',26);
+ dna.user_moves_avvy=true;
+ }
+ break;
+ case 3: { /* Special 3: Room 71: triggers dart. */
+ tr[1].bounce(); /* Must include that. */
+
+ if (~ dna.arrow_triggered)
+ {
+ dna.arrow_triggered=true;
+ apped(2,4); /* The dart starts at ped 4, and... */
+ tr[2].walkto(5); /* flies to ped 5. */
+ tr[2].face=0; /* Only face. */
+ /* Should call some kind of Eachstep procedure which will deallocate
+ the sprite when it hits the wall, and replace it with the chunk
+ graphic of the arrow buried in the plaster. */
+ /* OK! */
+ tr[2].call_eachstep=true;
+ tr[2].eachstep=procarrow_procs;
+ }
+ }
+ break;
+
+ case 4: { /* This is the ghost room link. */
+ dusk;
+ tr[1].turn(right); /* you'll see this after we get back from bootstrap */
+ set_up_timer(1,procghost_room_phew,reason_ghost_room_phew);
+ back_to_bootstrap(3);
+ }
+ break;
+
+ case 5: if (dna.friar_will_tie_you_up)
+ { /* Special 5: Room 42: touched tree, and get tied up. */
+ magics[4].op=bounces; /* Boundary effect is now working again. */
+ dixi('q',35);
+ tr[1].done();
+ /*tr[1].vanishifstill:=true;*/
+ show_one(2);
+ dixi('q',36);
+ dna.tied_up=true;
+ dna.friar_will_tie_you_up=false;
+ tr[2].walkto(3);
+ tr[2].vanishifstill=true;
+ tr[2].check_me=true; /* One of them must have Check_Me switched on. */
+ whereis[pfriartuck]=177; /* Not here, then. */
+ set_up_timer(364,prochang_around,reason_hanging_around);
+ }
+ break;
+
+ case 6: { /* Special 6: fall down oubliette. */
+ dna.user_moves_avvy=false;
+ tr[1].ix=3;
+ tr[1].iy=0;
+ tr[1].face=right;
+ set_up_timer(1,procfall_down_oubliette,reason_falling_down_oubliette);
+ }
+ break;
+
+ case 7: { /* Special 7: stop falling down oubliette. */
+ tr[1].visible=false;
+ magics[10].op=nix;
+ stopwalking();
+ lose_timer(reason_falling_down_oubliette);
+ mblit(12,80,38,160,3,0);
+ mblit(12,80,38,160,3,1);
+ display("Oh dear, you seem to be down the bottom of an oubliette.");
+ set_up_timer(200,procmeet_avaroid,reason_meeting_avaroid);
+ }
+ break;
+
+ case 8: /* Special 8: leave du Lustie's room. */
+ if ((geida_follows) & (~ lustie_is_asleep))
+ {
+ dixi('q',63);
+ tr[2].turn(down); tr[2].stopwalk(); tr[2].call_eachstep=false; /* Geida */
+ gameover;
+ }
+ break;
+
+ case 9: { /* Special 9: lose Geida to Robin Hood... */
+ if (~ dna.geida_follows) return; /* DOESN'T COUNT: no Geida. */
+ tr[2].call_eachstep=false; /* She no longer follows Avvy around. */
+ tr[2].walkto(4); /* She walks to somewhere... */
+ tr[1].done(); /* Lose Avvy. */
+ dna.user_moves_avvy=false;
+ set_up_timer(40,procrobin_hood_and_geida,reason_robin_hood_and_geida);
+ }
+ break;
+
+ case 10: { /* Special 10: transfer north in catacombs. */
+ if ((dna.cat_x==4) && (dna.cat_y==1))
+ { /* Into Geida's room. */
+ if (dna.obj[key]) dixi('q',62); else
+ {
+ dixi('q',61);
+ return;
+ }
+ }
+ dusk;
+ dna.cat_y -= 1;
+ catamove(4); if (dna.room!=r__catacombs) return;
+ delavvy;
+ switch ((cardinal)(catamap[cat_y][cat_x] & 0xf00) >> 8) {
+ case 0x1: apped(1,12); break;
+ case 0x3: apped(1,11); break;
+ default: apped(1,4);
+ }
+ getback();
+ dawndelay();
+ }
+ break;
+ case 11: { /* Special 11: transfer east in catacombs. */
+ dusk;
+ dna.cat_x += 1;
+ catamove(1); if (dna.room!=r__catacombs) return;
+ delavvy;
+ apped(1,1);
+ getback();
+ dawndelay();
+ }
+ break;
+ case 12: { /* Special 12: transfer south in catacombs. */
+ dusk;
+ dna.cat_y += 1;
+ catamove(2); if (dna.room!=r__catacombs) return;
+ delavvy;
+ apped(1,2);
+ getback();
+ dawndelay();
+ }
+ break;
+ case 13: { /* Special 13: transfer west in catacombs. */
+ dusk;
+ dna.cat_x -= 1;
+ catamove(3); if (dna.room!=r__catacombs) return;
+ delavvy;
+ apped(1,3);
+ getback();
+ dawndelay();
+ }
+ break;
+ }
+}
+
+void hide_in_the_cupboard();
+
+void open_the_door(byte whither,byte ped,byte magicnum)
+ /* This slides the door open. (The data really ought to be saved in
+ the Also file, and will be next time. However, for now, they're
+ here.) */
+{
+ switch (dna.room) {
+ case r__outsideyours:case r__outsidenottspub:case r__outsideducks:
+ {
+ first_show(1);
+ then_show(2);
+ then_show(3);
+ }
+ break;
+ case r__insidecardiffcastle:
+ {
+ first_show(1);
+ then_show(5);
+ }
+ break;
+ case r__avvysgarden:case r__entrancehall:case r__insideabbey:
+ {
+ first_show(1);
+ then_show(2);
+ }
+ break;
+ case r__musicroom:case r__outsideargentpub:
+ {
+ first_show(5);
+ then_show(6);
+ }
+ break;
+ case r__lusties:
+ switch (magicnum) {
+ case 14: if (dna.avvys_in_the_cupboard)
+ {
+ hide_in_the_cupboard();
+ first_show(8); then_show(7);
+ start_to_close;
+ return;
+ } else
+ {
+ apped(1,6);
+ tr[1].face=right; /* added by TT 12/3/1995 */
+ first_show(8); then_show(9);
+ }
+ break;
+ case 12: {
+ first_show(4); then_show(5); then_show(6);
+ }
+ break;
+ }
+ break;
+ }
+
+ then_flip(whither,ped);
+ start_to_open;
+}
+
+void newspeed()
+ /* Given that you've just changed the speed in triptype.xs, this adjusts
+ ix. */
+{
+ const bytefield lightspace = {40, 199, 47, 199};
+ byte page_;
+
+ {
+ triptype& with = tr[1];
+
+ with.ix=(with.ix / 3)*with.xs;
+ setactivepage(3);
+
+ setfillstyle(1,14);
+ if (with.xs==run) bar(371,199,373,199); else bar(336,199,338,199);
+ setfillstyle(1,9);
+ if (with.xs==run) bar(336,199,338,199); else bar(371,199,373,199);
+
+ setactivepage(1-cp);
+ for( page_=0; page_ <= 1; page_ ++) getset[page_].remember(lightspace);
+ }
+}
+
+triptype* triptype::init(byte spritenum, boolean do_check)
+{
+ const integer idshould = -1317732048;
+ integer gd,gm; varying_string<2> xx;
+ byte fv/*,nds*/;
+ byte aa,bb;
+ longint id; word soa;
+ untyped_file inf;
+
+ if (spritenum==177) return; /* Already running! */
+ str(spritenum,xx); assign(inf,string("sprite")+xx+".avd");
+ reset(inf,1);
+ seek(inf,177);
+ blockread(inf,id,4);
+ if (id!=idshould)
+ {
+ output << '\7';
+ close(inf);
+ exit(0);
+ }
+
+ blockread(inf,soa,2);
+ blockread(inf,a,soa);
+
+ {
+ adxtype& with = a;
+
+ /*nds:=num div seq;*/ totalnum=1;
+ xw=with.xl / 8; if ((with.xl % 8)>0) xw += 1;
+ for( aa=1; aa <= /*nds*seq*/with.num; aa ++)
+ {
+ getmem(sil[totalnum],11*(with.yl+1));
+ getmem(mani[totalnum],with.size-6);
+ for( fv=0; fv <= with.yl; fv ++)
+ {
+ blockread(inf,(*sil[totalnum])[fv],xw);
+ }
+ blockread(inf,*mani[totalnum],with.size-6);
+ totalnum += 1;
+ }
+ }
+
+ /* on; */
+ x=0; y=0; quick=true; visible=false; xs=3; ys=1;
+/* if spritenum=1 then newspeed; { Just for the lights. }*/
+
+ homing=false; ix=0; iy=0; step=0; check_me=do_check;
+ count=0; whichsprite=spritenum; vanishifstill=false;
+ call_eachstep=false;
+ close(inf);
+ return this;
+}
+
+void triptype::original()
+{
+ quick=false; whichsprite=177;
+}
+
+void triptype::andexor()
+{
+ byte picnum; /* Picnum, Picnic, what ye heck */
+ byte lay,laz; /* Limits for Qaz and Qay or equivs. (Laz always = 3). */
+#ifdef NOASM
+ word offs,fv;
+ byte qax,qay,qaz;
+#else
+ word segmani,ofsmani;
+ word ofsaa,realofsaa;
+ word segsil,ofssil;
+ word z; byte xwidth;
+
+#endif
+
+ if ((vanishifstill) && (ix==0) && (iy==0)) return;
+ picnum=face*a.seq+step+1;
+
+ {
+ adxtype& with = a;
+
+ getimage(x,y,x+with.xl,y+with.yl,aa); /* Now loaded into our local buffer. */
+
+ /* Now we've got to modify it! */
+
+ /* Qaz ranges over the width of the sprite/8.
+ Qay " " the height.
+ Qax " " 1 to 4 (the planes). */
+
+ {
+ adxtype& with1 = a;
+
+ #ifdef NOASM
+ laz=xw-1; lay=with1.yl; /* -1's only for Pascal. */
+ #else
+ laz=xw; lay=with1.yl+1; /* +1's only for ASM! */
+ #endif
+ }
+
+ /* ASSEMBLERISED: */
+#ifdef NOASM
+ for( qax=0; qax <= 3; qax ++) /* 3 */
+ for( qay=0; qay <= lay; qay ++) /* 35 */
+ for( qaz=0; qaz <= laz; qaz ++) /* 4 */
+ {
+ offs=5+qay*xw*4+xw*qax+qaz;
+ aa[offs]=aa[offs] & (*sil[picnum])[qay][qaz];
+ }
+
+ for( fv=5; fv <= with.size-2; fv ++)
+ aa[fv]=aa[fv] ^ (*mani[picnum])[fv];
+
+#else
+ /* OK, here's the same thing in assembler...
+
+ AL is Qax,
+ BL is Qay,
+ CL is Qaz,
+ DX is Offs */
+
+ /* For the first part: */
+ xwidth=xw;
+ segsil=seg(*sil[picnum]);
+ ofssil=ofs(*sil[picnum]);
+
+ /* For the first and second parts: */
+ segmani=seg(*mani[picnum]); /* It's easier to do this in Pascal, and */
+ ofsmani=ofs(*mani[picnum])+1; /* besides it only goes round once here. */
+ /* Segment of AA is always the current data segment. */
+ ofsaa=ofs(aa)+5;
+ realofsaa=ofs(aa)-1; /* We may not need this. */
+ z=with.size-7;
+/*
+ asm
+
+ xor ax,ax; { Initialise ax, bx, and cx, using a rather }
+ @QAXloop: { AL }
+
+ xor bx,bx; { nifty speed trick. }
+ @QAYloop: { BL }
+
+ xor cx,cx;
+ @QAZloop: { CL }
+
+ { Right, well, here we are. We have to do some rather nifty array
+ manipulation, stuff like that. We're trying to assemblerise:
+ DX:= 5 + BX * xw * 4 + xw * AX + CX;
+ aa[DX]:=aa[DX] and sil[picnum]^[BL,CL]; }
+
+ push ax; {AXcdx} { OK, we're going to do some strange things }
+ { with ax, so we'd better save it. }
+ mov dx,5; { First of all... set dx to 5. }
+ add dx,cx; { DX now = 5+CX }
+ mul xwidth; { Multiply ax by xw (the Pascal variable.) }
+ add dx,ax; { DX now = 5+CX+xw*AX }
+
+ { Right. Mul only works on ax. Don't ask me why. Ask Intel. Anyway,
+ since ax is saved on the stack, we can move bx over it. Note that
+ if xw was a word, using mul would have destroyed the contents of
+ dx. NOT a good idea! }
+
+ push cx; {CXmul} { We must just borrow cx for a second. }
+ mov ax,bx; { Make ax = bx. }
+ mul xwidth; { Do the same to it as we did to ax before. }
+ mov cl,2;
+ shl ax,cl; { And multiply it by 4 (i.e., shl it by 2.) }
+ add dx,ax; { DX now = 5+CX+xw*AX+xw*BX*4. That's OK. }
+
+ pop cx; {CXmul}
+ pop ax; {AXcdx} { Now we have to get ax and cx back again. }
+
+ { Registers are now returned to original status. }
+
+ { Righto. DX is now all worked out OK. We must now find out the
+ contents of: 1) aa[dx], and 2) (harder) sil[picnum]^[BL,CL]. Gulp. }
+
+ { DS already points to the segment of AA. So... let's use CL to
+ put aa[dx] in, and use BX for the offset. Looks like we're going
+ to have to push a few registers! }
+
+ push ax; { AXaa. Saving loop value of AX. }
+ { Let's use ax to do our dirty work with. }
+ push dx; { Saving Offs(DX.) }
+
+ push bx; { BXaa. Saving loop value of BX. }
+
+ mov bx,realofsaa; { aa is now pointed to by [ds:bx]. }
+ add bx,dx; { Offset is dx bytes. }
+ mov dl,[bx]; { cl now holds the contents of aa[dx]. }
+
+ pop bx; { BXaa. Restoring loop value of BX. }
+
+ { Stack now holds: Offs(DX). }
+
+ { ^^^ That works. Now to find sil[picnum]^[BL,CL]. Our first task is
+ to find the address of sil[picnum]^. Since it's dynamic, we must
+ push and pop ds. }
+
+ push ds; { DXaa. Saving value of Trip5's data segment. }
+ { Push ds. Now we can put the segment of sil[picnum]^... }
+ mov ds,segsil; { ...into ds, and... }
+ mov ax,ofssil; { ...its offset into ax. }
+ { Addr of sil[picnum]^ is now in [ds:ax]. BUT we want a particular
+ offset: to wit, [BL,CL]. Now, siltype is defined so that this offset
+ will be at an offset of (BL*11)+CL. }
+
+ push bx; { Saving loop value of BX. }
+ push cx; { Saving loop value of CX. }
+ push ax; { Saving offset of sil[picnum]^. }
+ { Save them for a bit (!) }
+ mov al,bl; { Put bl into al. }
+ mov bl,11; { ... }
+ mul bl; { ...times it by 11. }
+ mov bx,ax; { Put it back into bx (now = bx*11) }
+ pop ax; { Restoring offset of sil[picnum]^. }
+ { Get ax back again. }
+ add ax,bx; { Add (original bl)*11 to al. }
+ add ax,cx; { Add cl to al. }
+ { AX now holds the offset of sil[picnum]^[bx,cl]. }
+
+ { Stack now holds: loop value of AX, Trip5's DS, lv of BX, lv of CX. }
+
+ { Right. Now the address of sil[picnum]^[bl,cl] is in [ds:ax]. Let's
+ get the elusive byte itself, and put it into ax. Firstly, we must
+ swap ax and bx. }
+
+ xchg ax,bx;
+ mov al,[bx]; { AX now contains sil[picnum]^[bl,cl], AT LAST!! }
+
+ { So now AL contains the sil stuff, and DL holds aa[offs]. }
+
+ and al,dl; { aa[offs]:=aa[offs] and sil[picnum]^[Qay,Qaz]. }
+
+ pop cx; { Restoring loop value of CX. }
+ pop bx; { Restoring loop value of BX. }
+ pop ds; { Restore value of Trip5's data segment. }
+
+ { Right. AL contains the byte we need to replace aa[offs] with.
+ All that's left to do is to put it back. Remember that we already
+ have the segment of aa in the current DS, so... }
+
+ pop dx; { Restore Offs(DX). }
+
+ { Stack is now as when we entered the loop. Since this copy of DX
+ is now being used for the last time, we can muck around with it. }
+
+ { Recap: DX now holds the offset from the start of AA. If we add
+ the offset of aa to it, we'll get the offset of the byte we want.
+ DS is already set up. }
+
+ push bx; { I'm just borrowing bx for a sec. I'll put it back in 5 lines.}
+ mov bx,realofsaa;
+ add dx,bx; { Now aa[offs] is at aa[ds:dx]. }
+ mov bx,dx; { But we can't address memory with dx, so use bx. }
+ mov [bx],al; { Shove it into the memory! }
+ pop bx; { See! I said I would. }
+
+ pop ax; { Restore loop value of AX. }
+
+ { Right, the fancy stuff's all done now. Finish off the loop code. }
+
+ inc cl;
+ cmp cl,laz; { CL must not reach 5. Does it? }
+ jnz @QAZloop; { no, keep going around the QAZloop. }
+
+ inc bl;
+ cmp bl,lay; { BL must not reach 36. Does it? }
+ jnz @QAYloop; { no, keep going around the QAYloop. }
+
+ inc al;
+ cmp al,4; { AL must not reach 4. Does it? }
+ jnz @QAXloop; { no, keep going around the QAXloop. }
+
+ { al, bl and cl are now at their maxima, so we can stop the loops. }
+
+ { *** SECOND ASSEMBLER BIT. *** }
+
+ mov cx,z; { Find the size of the array, -7. }
+ mov bx,ofsmani; { Now find the offset and put that into bx. }
+ mov dx,ofsaa; { We'll use dx to be the same as fv, +5. }
+
+ { DS should already hold the segment of aa. }
+
+ @nextbyte: { Main loop... }
+
+ { Firstly, we must get hold of aa[fv] (here called aa[dx].)}
+ push bx; { We need to "borrow" bx for a second... }
+ mov bx,dx; { Wrong register- shove it into bx. }
+ mov al,[bx]; { Get aa[fv] and put it into al. }
+ pop bx; { Right, you can have bx back again. }
+
+ { Secondly, we must get hold of mani[picnum]^[fv]. }
+ push cx; { Let's borrow cx for this one. }
+ push ds; { we must use ds to point to segmani. }
+ mov ds,segmani; { Find the segment of mani[picnum]^, }
+ mov cl,[bx]; { now get the byte at [ds:bx] and put it into cl. }
+ pop ds; { Put ds back to being the current data segment. }
+
+ { Right: now we can do what we came here for in the first place.
+ AL contains aa[fv], CL contains mani[picnum]^[fv]. }
+
+ xor al,cl; { Xor al with bl. That's it! }
+
+ pop cx; { We don't need cx any more for this now. }
+
+ push bx; { Borrow bx... }
+ mov bx,dx; { Put dx into bx. }
+ mov [bx],al; { Put the changed al back into [ds:bx] (ie, [ds:dx].}
+ pop bx; { Get it back. }
+
+ inc bx; { Add one to bx, for the next char. }
+ inc dx; { And dx, for the same reason. }
+
+ loop @nextbyte; { Keep going round until cx=0. }
+*/
+{;
+}
+#endif
+
+ /* Now.. let's try pasting it back again! */
+
+ putimage(x,y,aa,0);
+ }
+}
+
+void triptype::turn(byte whichway)
+{
+ if (whichway==8) face=0; else face=whichway;
+}
+
+void triptype::appear(integer wx,integer wy, byte wf)
+{
+ x=(wx / 8)*8; y=wy; ox[cp]=wx; oy[cp]=wy; turn(wf);
+ visible=true; ix=0; iy=0;
+}
+
+
+
+
+static boolean collision_check()
+{
+ byte fv;
+
+ boolean collision_check_result;
+ for( fv=1; fv <= numtr; fv ++)
+ if (tr[fv].quick && (tr[fv].whichsprite!=whichsprite) &&
+ ((x+a.xl)>tr[fv].x) &&
+ (x<(tr[fv].x+tr[fv].a.xl)) &&
+ (tr[fv].y==y))
+ {
+ collision_check_result=true;
+ return collision_check_result;
+ }
+ collision_check_result=false;
+ return collision_check_result;
+}
+
+void triptype::walk()
+{
+ byte tc; bytefield r;
+
+
+ if (visible)
+ {
+ {
+ x1=(x / 8)-1;
+ if (x1==255) x1=0;
+ y1=y-2;
+ x2=((x+a.xl) / 8)+1;
+ y2=y+a.yl+2;
+ }
+ getset[1-cp].remember(r);
+ }
+
+ if (~ doing_sprite_run)
+ {
+ ox[cp]=x; oy[cp]=y;
+ if (homing) homestep();
+ x=x+ix; y=y+iy;
+ }
+
+ if (check_me)
+ {
+ if (collision_check())
+ {
+ bounce();
+ return;
+ }
+
+ tc=checkfeet(x,x+a.xl,oy[cp],y,a.yl);
+
+ if ((tc!=0) & (~ doing_sprite_run))
+ { void& with = magics[tc];
+ switch (op) {
+ case exclaim: {
+ bounce(); mustexclaim=true; saywhat=data;
+ }
+ break;
+ case bounces: bounce(); break;
+ case transport: fliproom(hi(data),lo(data)); break;
+ case unfinished: {
+ bounce();
+ display("\7Sorry.\3\rThis place is not available yet!");
+ }
+ break;
+ case special: call_special(data); break;
+ case mopendoor: open_the_door(hi(data),lo(data),tc); break;
+ }}
+ }
+
+ if (~ doing_sprite_run)
+ {
+ count += 1;
+ if (((ix!=0) || (iy!=0)) && (count>1))
+ {
+ step += 1; if (step==a.seq) step=0; count=0;
+ }
+ }
+
+}
+
+void triptype::bounce()
+{
+ x=ox[cp]; y=oy[cp];
+ if (check_me) stopwalking(); else stopwalk();
+ oncandopageswap=false;
+ showrw;
+ oncandopageswap=true;
+}
+
+shortint sgn(integer x)
+{
+ shortint sgn_result;
+ if (x>0) sgn_result=1; else
+ if (x<0) sgn_result=-1; else
+ sgn_result=0; /* x=0 */
+ return sgn_result;
+}
+
+void triptype::walkto(byte pednum)
+{
+ speed(sgn(peds[pednum].x-x)*4,sgn(peds[pednum].y-y));
+ hx=peds[pednum].x-a.xl / 2;
+ hy=peds[pednum].y-a.yl; homing=true;
+}
+
+void triptype::stophoming()
+{
+ homing=false;
+}
+
+void triptype::homestep()
+{
+ integer temp;
+
+ if ((hx==x) && (hy==y))
+ { /* touching the target */
+ stopwalk();
+ return;
+ }
+ ix=0; iy=0;
+ if (hy!=y)
+ {
+ temp=hy-y; if (temp>4) iy=4; else if (temp<-4) iy=-4; else iy=temp;
+ }
+ if (hx!=x)
+ {
+ temp=hx-x; if (temp>4) ix=4; else if (temp<-4) ix=-4; else ix=temp;
+ }
+}
+
+void triptype::speed(shortint xx,shortint yy)
+{
+ ix=xx; iy=yy;
+ if ((ix==0) && (iy==0)) return; /* no movement */
+ if (ix==0)
+ { /* No horz movement */
+ if (iy<0) turn(up); else turn(down);
+ } else
+ {
+ if (ix<0) turn(left); else turn(right);
+ }
+}
+
+void triptype::stopwalk()
+{
+ ix=0; iy=0; homing=false;
+}
+
+void triptype::chatter()
+{
+ talkx=x+a.xl / 2; talky=y; talkf=a.fgc; talkb=a.bgc;
+}
+
+void triptype::set_up_saver(trip_saver_type& v)
+{
+ v.whichsprite=whichsprite;
+ v.face=face;
+ v.step=step;
+ v.x=x;
+ v.y=y;
+ v.ix=ix;
+ v.iy=iy;
+ v.visible=visible;
+ v.homing=homing;
+ v.check_me=check_me;
+ v.count=count;
+ v.xw=xw;
+ v.xs=xs;
+ v.ys=ys;
+ v.totalnum=totalnum;
+ v.hx=hx;
+ v.hy=hy;
+ v.call_eachstep=call_eachstep;
+ v.eachstep=eachstep;
+ v.vanishifstill=vanishifstill;
+}
+
+void triptype::unload_saver(trip_saver_type v)
+{
+ whichsprite=v.whichsprite;
+ face=v.face;
+ step=v.step;
+ x=v.x;
+ y=v.y;
+ ix=v.ix;
+ iy=v.iy;
+ visible=v.visible;
+ homing=v.homing;
+ check_me=v.check_me;
+ count=v.count;
+ xw=v.xw;
+ xs=v.xs;
+ ys=v.ys;
+ totalnum=v.totalnum;
+ hx=v.hx;
+ hy=v.hy;
+ call_eachstep=v.call_eachstep;
+ eachstep=v.eachstep;
+ vanishifstill=v.vanishifstill;
+}
+
+void triptype::savedata(untyped_file& f)
+{
+ trip_saver_type tripsaver;
+
+ set_up_saver(tripsaver);
+
+ {
+ blockwrite(f,tripsaver.whichsprite,1);
+ blockwrite(f,tripsaver.face,1); blockwrite(f,tripsaver.step,1);
+ blockwrite(f,tripsaver.x,2); blockwrite(f,tripsaver.y,2);
+ blockwrite(f,tripsaver.ix,1); blockwrite(f,tripsaver.iy,1);
+ blockwrite(f,tripsaver.visible,1);
+ blockwrite(f,tripsaver.homing,1);
+ blockwrite(f,tripsaver.check_me,1);
+ blockwrite(f,tripsaver.count,1);
+ blockwrite(f,tripsaver.xw,1);
+ blockwrite(f,tripsaver.xs,1); blockwrite(f,tripsaver.ys,1);
+ blockwrite(f,tripsaver.totalnum,1);
+ blockwrite(f,tripsaver.hx,2); blockwrite(f,tripsaver.hy,2);
+ blockwrite(f,tripsaver.call_eachstep,1);
+ blockwrite(f,tripsaver.eachstep,1);
+ blockwrite(f,tripsaver.vanishifstill,1);
+ }
+}
+
+void triptype::loaddata(untyped_file& f)
+{
+ word spritewas,spriteis,saveface,savex,savey,savestep;
+ boolean wasquick;
+ trip_saver_type tripsaver;
+
+
+ wasquick=quick;
+ quick=true; spritewas=whichsprite;
+
+ {
+ blockread(f,tripsaver.whichsprite,1);
+ blockread(f,tripsaver.face,1); blockread(f,tripsaver.step,1);
+ blockread(f,tripsaver.x,2); blockread(f,tripsaver.y,2);
+ blockread(f,tripsaver.ix,1); blockread(f,tripsaver.iy,1);
+
+ if ((! wasquick) || ((unsigned char)tripsaver.whichsprite!=spritewas))
+ {
+ spriteis=tripsaver.whichsprite;
+ savex=tripsaver.x; savey=tripsaver.y; saveface=tripsaver.face; savestep=tripsaver.step;
+
+ if (wasquick) done();
+
+ init(spriteis,tripsaver.check_me);
+
+ appear(savex,savey,saveface); tripsaver.step=savestep;
+ }
+
+ blockread(f,tripsaver.visible,1);
+ blockread(f,tripsaver.homing,1);
+ blockread(f,tripsaver.check_me,1);
+ blockread(f,tripsaver.count,1);
+ blockread(f,tripsaver.xw,1);
+ blockread(f,tripsaver.xs,1); blockread(f,tripsaver.ys,1);
+ blockread(f,tripsaver.totalnum,1);
+ blockread(f,tripsaver.hx,2); blockread(f,tripsaver.hy,2);
+ blockread(f,tripsaver.call_eachstep,1);
+ blockread(f,tripsaver.eachstep,1);
+ blockread(f,tripsaver.vanishifstill,1);
+ }
+
+ unload_saver(tripsaver);
+}
+
+triptype* triptype::done()
+{
+ integer gd,gm; varying_string<2> xx;
+ byte fv/*,nds*/;
+ byte aa,bb;
+ longint id; word soa;
+
+ {
+ adxtype& with = a;
+
+/* nds:=num div seq;*/
+ xw=with.xl / 8; if ((with.xl % 8)>0) xw += 1;
+ for( aa=1; aa <= /*nds*seq*/ with.num; aa ++)
+ {
+ totalnum -= 1;
+ freemem(mani[totalnum],with.size-6);
+ freemem(sil[totalnum],11*(with.yl+1)); /* <<- Width of a siltype. */
+ }
+ }
+
+ quick=false; whichsprite=177;
+ return this;
+}
+
+getsettype* getsettype::init()
+{
+ numleft=0; /* initialise array pointer */
+ return this;
+}
+
+void getsettype::remember(bytefield r)
+{
+ numleft += 1;
+ if (numleft>maxgetset) runerror(runerr_getset_overflow);
+ gs[numleft]=r;
+}
+
+void getsettype::recall(bytefield& r)
+{
+ r=gs[numleft];
+ numleft -= 1;
+}
+
+void rwsp(byte t,byte r)
+{
+ { triptype& with = tr[t]; switch (r) {
+ case up: speed( 0,-with.ys); break; case down: speed( 0, with.ys); break; case left: speed(-with.xs, 0); break;
+ case right: speed( with.xs, 0); break; case ul: speed(-with.xs,-with.ys); break; case ur: speed( with.xs,-with.ys); break;
+ case dl: speed(-with.xs, with.ys); break; case dr: speed( with.xs, with.ys); break;
+ }}
+}
+
+void apped(byte trn,byte np)
+{
+ { triptype& with = tr[trn];
+ {
+ void& with1 = peds[np];
+
+ appear(with.x-with.a.xl / 2,with.y-with.a.yl,dir);
+ rwsp(trn,dir);
+ }}
+}
+
+void getback();
+
+static bytefield r;
+
+
+/* function overlap(x1,y1,x2,y2,x3,y3,x4,y4:word):boolean;
+ begin { By De Morgan's law: }
+ overlap:=(x2>=x3) and (x4>=x1) and (y2>=y3) and (y4>=y1);
+ end;*/
+ /* x1,x2 - as bytefield, but *8. y1,y2 - as bytefield.
+ x3,y3 = mx,my. x4,y4 = mx+16,my+16. */
+static boolean overlaps_with_mouse()
+{
+ boolean overlaps_with_mouse_result;
+ overlaps_with_mouse_result=
+ (x2*8>=mx) && (mx+16>=x1*8) && (y2>=my) && (my+16>=y1);
+ return overlaps_with_mouse_result;
+}
+
+void getback()
+{
+ byte fv;
+ boolean endangered;
+
+
+ endangered=false;
+/* Super_Off;*/
+
+ { getsettype& with = getset[1-cp];
+ while (with.numleft>0)
+ {
+ recall(r);
+
+/* if overlaps_with_mouse and not endangered then
+ begin
+ endangered:=true;
+ blitfix;
+ Super_Off;
+ end;*/
+
+ mblit(x1,y1,x2,y2,3,1-cp);
+ }}
+
+ blitfix;
+ /*if endangered then*/ /*Super_On;*/
+}
+
+/* Eachstep procedures: */
+void follow_avvy_y(byte tripnum)
+{
+ {
+ triptype& with = tr[tripnum];
+
+ if (tr[1].face==left) return;
+ if (with.homing) with.hy=tr[1].y; else
+ {
+ if (with.y<tr[1].y)
+ with.y += 1; else
+ if (with.y>tr[1].y)
+ with.y -= 1; else
+ return;
+ if (with.ix==0) { with.step += 1; if (with.step==with.a.seq) with.step=0; with.count=0; }
+ }
+ }
+}
+
+void back_and_forth(byte tripnum)
+{
+ { triptype& with = tr[tripnum];
+ if (! with.homing)
+ {
+ if (with.face==right) walkto(4); else walkto(5);
+ }}
+}
+
+void face_avvy(byte tripnum)
+{
+ { triptype& with = tr[tripnum];
+ if (! with.homing)
+ {
+ if (tr[1].x>=with.x) with.face=right;
+ else with.face=left;
+ }}
+}
+
+void arrow_procs(byte tripnum)
+{
+ byte fv;
+
+ { triptype& with = tr[tripnum];
+ if (with.homing)
+ { /* Arrow is still in flight. */
+ /* We must check whether or not the arrow has collided with Avvy's head.
+ This is so if: a) the bottom of the arrow is below Avvy's head,
+ b) the left of the arrow is left of the right of Avvy's head, and
+ c) the right of the arrow is right of the left of Avvy's head. */
+ if (((with.y+with.a.yl)>=tr[1].y) /* A */
+ && (with.x<=(tr[1].x+tr[1].a.xl)) /* B */
+ && ((with.x+with.a.xl)>=tr[1].x)) /* C */
+ { /* OK, it's hit him... what now? */
+
+ tr[2].call_eachstep=false; /* prevent recursion. */
+ dixi('Q',47); /* Complaint! */
+ done(); /* Deallocate the arrow. */
+/* tr[1].done; { Deallocate normal pic of Avvy. }
+
+ off;
+ for fv:=0 to 1 do
+ begin
+ cp:=1-cp;
+ getback;
+ end;
+ on;*/
+
+ gameover;
+
+ dna.user_moves_avvy=false; /* Stop the user from moving him. */
+ set_up_timer(55,procnaughty_duke,reason_naughty_duke);
+ }
+ } else /* Arrow has hit the wall! */
+ {
+ done(); /* Deallocate the arrow. */
+ show_one(3); /* Show pic of arrow stuck into the door. */
+ dna.arrow_in_the_door=true; /* So that we can pick it up. */
+ }}
+}
+
+/*procedure Spludwick_procs(tripnum:byte);
+var fv:byte;
+begin
+ with tr[tripnum] do
+ if not homing then { We only need to do anything if Spludwick *stops*
+ walking. }
+ with dna do
+ begin
+ inc(DogfoodPos);
+ if DogfoodPos=8 then DogfoodPos:=1;
+ walkto(DogfoodPos);
+ end;
+end;*/
+
+void grab_avvy(byte tripnum) /* For Friar Tuck, in Nottingham. */
+{
+ byte fv; integer tox,toy;
+
+ { triptype& with = tr[tripnum];
+ {
+ tox=tr[1].x + 17;
+ toy=tr[1].y - 1;
+ if ((with.x==tox) && (with.y==toy))
+ {
+ with.call_eachstep=false;
+ with.face=left;
+ stopwalk();
+ /* ... whatever ... */
+ } else
+ { /* Still some way to go. */
+ if (with.x<tox)
+ {
+ with.x += 5;
+ if (with.x>tox) with.x=tox;
+ }
+ if (with.y<toy) with.y += 1;
+ with.step += 1; if (with.step==with.a.seq) with.step=0;
+ }
+ }}
+}
+
+void geida_procs(byte tripnum);
+
+static void take_a_step(byte& tripnum)
+{
+ { triptype& with = tr[tripnum];
+ if (with.ix==0)
+ { with.step += 1; if (with.step==with.a.seq) with.step=0; with.count=0; }}
+}
+
+
+
+static void spin(byte whichway, byte& tripnum)
+{
+ { triptype& with = tr[tripnum];
+ if (with.face!=whichway)
+ {
+ with.face=whichway;
+ if (with.whichsprite==2) return; /* Not for Spludwick */
+
+ dna.geida_spin += 1;
+ dna.geida_time=20;
+ if (dna.geida_spin==5)
+ {
+ display("Steady on, Avvy, you'll make the poor girl dizzy!");
+ dna.geida_spin=0; dna.geida_time=0; /* knock out records */
+ }
+ }}
+}
+
+void geida_procs(byte tripnum)
+{
+ {
+ triptype& with = tr[tripnum];
+
+ if (dna.geida_time>0)
+ {
+ dna.geida_time -= 1;
+ if (dna.geida_time==0) dna.geida_spin=0;
+ }
+
+ if (with.y<(tr[1].y-2))
+ { /* Geida is further from the screen than Avvy. */
+ spin(down, tripnum);
+ with.iy=1; with.ix=0;
+ take_a_step(tripnum);
+ return;
+ } else
+ if (with.y>(tr[1].y+2))
+ { /* Avvy is further from the screen than Geida. */
+ spin(up, tripnum);
+ with.iy=-1; with.ix=0;
+ take_a_step(tripnum);
+ return;
+ }
+
+ with.iy=0;
+ if (with.x<tr[1].x-tr[1].xs*8)
+ {
+ with.ix=tr[1].xs;
+ spin(right, tripnum);
+ take_a_step(tripnum);
+ } else
+ if (with.x>tr[1].x+tr[1].xs*8)
+ {
+ with.ix=-tr[1].xs;
+ spin(left, tripnum);
+ take_a_step(tripnum);
+ } else with.ix=0;
+ }
+}
+
+/* That's all... */
+
+void call_andexors()
+{
+ array<1,5,byte> order;
+ byte fv,temp;
+ boolean ok;
+
+ fillchar(order,5,'\0');
+ for( fv=1; fv <= numtr; fv ++) { triptype& with = tr[fv];
+ if (with.quick && with.visible)
+ order[fv]=fv;}
+
+ do {
+ ok=true;
+ for( fv=1; fv <= 4; fv ++)
+ if (((order[fv]!=0) && (order[fv+1]!=0))
+ && (tr[order[fv]].y>tr[order[fv+1]].y))
+ { /* Swap them! */
+ temp=order[fv];
+ order[fv]=order[fv+1];
+ order[fv+1]=temp;
+ ok=false;
+ }
+ } while (!ok);
+
+ for( fv=1; fv <= 5; fv ++)
+ if (order[fv]>0)
+ tr[order[fv]].andexor();
+}
+
+void trippancy_link()
+{
+ byte fv;
+
+ if (ddmnow | ontoolbar | seescroll) return;
+ for( fv=1; fv <= numtr; fv ++) { triptype& with = tr[fv]; if (with.quick) walk();}
+ call_andexors();
+ for( fv=1; fv <= numtr; fv ++) { triptype& with = tr[fv];
+ if (with.quick && with.call_eachstep)
+ {
+ switch (tr[fv].eachstep) {
+ case procfollow_avvy_y : follow_avvy_y(fv); break;
+ case procback_and_forth : back_and_forth(fv); break;
+ case procface_avvy : face_avvy(fv); break;
+ case procarrow_procs : arrow_procs(fv); break;
+/* PROCSpludwick_procs : spludwick_procs(fv);*/
+ case procgrab_avvy : grab_avvy(fv); break;
+ case procgeida_procs : geida_procs(fv); break;
+ }
+ }}
+ if (mustexclaim)
+ {
+ mustexclaim=false;
+ dixi('x',saywhat);
+ }
+}
+
+void get_back_loretta()
+{
+ byte fv;
+
+/* for fv:=1 to numtr do with tr[fv] do if quick then getback;*/
+ for( fv=1; fv <= numtr; fv ++) if (tr[fv].quick)
+ {
+ getback();
+ return;
+ }
+/* for fv:=0 to 1 do begin cp:=1-cp; getback; end;*/
+}
+
+void stopwalking()
+{
+ tr[1].stopwalk(); dna.rw=stopped; if (alive) tr[1].step=1;
+}
+
+void tripkey(char dir)
+{
+ if ((ctrl==cjoy) | (~ dna.user_moves_avvy)) return;
+
+ { triptype& with = tr[1];
+ {
+ switch (dir) {
+ case 'H': if (rw!=up)
+ { rw=up; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'P': if (rw!=down)
+ { rw=down; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'K': if (rw!=left)
+ { rw=left; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'M': if (rw!=right)
+ { rw=right; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'I': if (rw!=ur)
+ { rw=ur; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'Q': if (rw!=dr)
+ { rw=dr; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'O': if (rw!=dl)
+ { rw=dl; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'G': if (rw!=ul)
+ { rw=ul; rwsp(1,rw); } else stopwalking();
+ break;
+ case 'L': stopwalking(); break;
+ }
+ }}
+}
+
+void readstick()
+{
+ byte jw;
+
+ if (ctrl==ckey) return;
+
+ jw=joyway;
+
+ {
+ triptype& with = tr[1];
+
+ if (jw==stopped) stopwalking(); else
+ {
+ dna.rw=jw; rwsp(1,dna.rw);
+ }
+ }
+
+ if (jw!=oldjw)
+ {
+ showrw;
+ oldjw=jw;
+ }
+
+}
+
+void getsetclear()
+{
+ byte fv;
+
+ for( fv=0; fv <= 1; fv ++) getset[fv].init();
+}
+
+void hide_in_the_cupboard()
+{
+ const char nowt = '\372'; /* As in Acci. */
+
+ {
+ if (avvys_in_the_cupboard)
+ {
+ if (wearing==nowt)
+ display("\6AVVY!\22 Get dressed first!");
+ else
+ {
+ tr[1].visible=true;
+ user_moves_avvy=true;
+ apped(1,3); /* Walk out of the cupboard. */
+ display("You leave the cupboard. Nice to be out of there!");
+ avvys_in_the_cupboard=false;
+ first_show(8); then_show(7); start_to_close;
+ }
+ } else
+ { /* Not hiding in the cupboard */
+ tr[1].visible=false;
+ user_moves_avvy=false;
+ display(string("You walk into the room...\20It seems to be an empty, ")+
+ "but dusty, cupboard. Hmmmm... you leave the door slightly open to "+
+ "avoid suffocation.");
+ avvys_in_the_cupboard=true;
+ show_one(8);
+ }
+ }
+}
+
+void fliproom(byte room,byte ped);
+static integer beforex,beforey;
+static void tidy_after_mouse();
+
+
+static void tidy_up(integer a,integer b,integer c,integer d)
+{
+ bytefield bf;
+
+ {
+ x1=a / 8;
+ y1=b;
+ x2=(c+7) / 8;
+ y2=d;
+ setactivepage(0);
+ rectangle(x1*8,y1,x2*8+7,y2);
+ }
+ getset[0].remember(bf);
+ getset[1].remember(bf);
+}
+
+
+
+static void tidy_after_mouse()
+{
+ tidy_up(beforex,beforey,beforex+15,beforey+15);
+ xycheck;
+ tidy_up(mx,my,mx+15,my+15);
+}
+
+void fliproom(byte room,byte ped)
+{
+ byte fv;
+
+
+ if (~ alive)
+ { /* You can't leave the room if you're dead. */
+ tr[1].ix=0; tr[1].iy=0; /* Stop him from moving. */
+ return;
+ }
+
+ if ((ped==177) && (dna.room==r__lusties))
+ {
+ hide_in_the_cupboard();
+ return;
+ }
+
+ if ((dna.jumpstatus>0) && (dna.room==r__insidecardiffcastle))
+ { /* You can't *jump* out of Cardiff Castle! */
+ tr[1].ix=0;
+ return;
+ }
+
+ xycheck; beforex=mx; beforey=my;
+
+ exitroom(dna.room);
+ dusk; getsetclear();
+
+
+ for( fv=2; fv <= numtr; fv ++)
+ { triptype& with = tr[fv];
+ if (with.quick) done();} /* Deallocate sprite */
+
+ if (dna.room==r__lustiesroom)
+ dna.enter_catacombs_from_lusties_room=true;
+
+ enterroom(room,ped); apped(1,ped);
+ dna.enter_catacombs_from_lusties_room=false;
+ oldrw=dna.rw; dna.rw=tr[1].face; showrw;
+
+ for( fv=0; fv <= 1; fv ++)
+ {
+ cp=1-cp;
+ getback();
+ }
+ dawn;
+
+ /* Tidy up after mouse. I know it's a kludge... */
+/* tidy_after_mouse;*/
+}
+
+boolean infield(byte which)
+ /* returns True if you're within field "which" */
+{
+ integer yy;
+
+ boolean infield_result;
+ { void& with = fields[which]; {
+ triptype& with = tr[1];
+
+ yy=with.y+with.a.yl;
+ infield_result=(with.x>=x1) && (with.x<=x2) && (yy>=y1) && (yy<=y2);
+ }}
+ return infield_result;
+}
+
+boolean neardoor() /* returns True if you're near a door! */
+{
+ integer ux,uy; byte fv; boolean nd;
+
+ boolean neardoor_result;
+ if (numfields<9)
+ { /* there ARE no doors here! */
+ neardoor_result=false;
+ return neardoor_result;
+ }
+ {
+ triptype& with = tr[1];
+
+ ux=with.x;
+ uy=with.y+with.a.yl;
+ } nd=false;
+ for( fv=9; fv <= numfields; fv ++)
+ {
+ void& with = fields[fv];
+
+ if ((ux>=x1) && (ux<=x2) && (uy>=y1) && (uy<=y2)) nd=true;
+ }
+ neardoor_result=nd;
+ return neardoor_result;
+}
+
+void new_game_for_trippancy() /* Called by gyro.newgame */
+{
+ tr[1].visible=false;
+}
+
+void triptype::save_data_to_mem(word& where)
+{
+ trip_saver_type tripsaver;
+
+ set_up_saver(tripsaver);
+ move(tripsaver,mem[storage_seg*where],sizeof(tripsaver));
+ where += sizeof(tripsaver);
+}
+
+void triptype::load_data_from_mem(word& where)
+{
+ word spritewas,spriteis,saveface,savex,savey,savestep;
+ boolean wasquick;
+ trip_saver_type tripsaver;
+
+ move(mem[storage_seg*where],tripsaver,sizeof(tripsaver));
+ where += sizeof(tripsaver);
+ unload_saver(tripsaver);
+
+ spriteis=whichsprite;
+ savex=x; savey=y; saveface=face; savestep=step;
+
+ init(spriteis,check_me);
+
+ appear(savex,savey,saveface); unload_saver(tripsaver);
+ step=savestep;
+}
+
+class unit_trip5_initialize {
+ public: unit_trip5_initialize();
+};
+static unit_trip5_initialize trip5_constructor;
+
+unit_trip5_initialize::unit_trip5_initialize() {
+ getsetclear(); mustexclaim=false;
+}
diff --git a/engines/avalanche/trip5.h b/engines/avalanche/trip5.h
new file mode 100644
index 0000000000..9e7b3a33bc
--- /dev/null
+++ b/engines/avalanche/trip5.h
@@ -0,0 +1,175 @@
+#ifndef __trip5_h__
+#define __trip5_h__
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+/*#include "Gyro.h"*/
+/*#include "Sticks.h"*/
+
+
+const integer maxgetset = 35;
+
+typedef array<5,2053,byte> manitype;
+
+typedef matrix<0,50,0,10,byte> siltype; /* 35, 4 */
+
+struct adxtype { /* Second revision of ADX type */
+ varying_string<12> name; /* name of character */
+ varying_string<16> comment; /* comment */
+ byte num; /* number of pictures */
+ byte xl,yl; /* x & y lengths of pictures */
+ byte seq; /* how many in one stride */
+ word size; /* the size of one picture */
+ byte fgc,bgc; /* foreground & background bubble colours */
+ byte accinum; /* the number according to Acci (1=Avvy, etc.) */
+};
+
+struct trip_saver_type {
+ byte whichsprite;
+ byte face; byte step;
+ integer x; integer y;
+ shortint ix; shortint iy;
+ boolean visible;
+ boolean homing;
+ boolean check_me;
+ byte count;
+ byte xw,xs,ys;
+ byte totalnum;
+ integer hx; integer hy;
+ boolean call_eachstep;
+ byte eachstep;
+ boolean vanishifstill;
+};
+
+class triptype {
+public:
+ adxtype a; /* vital statistics */
+ byte face,step;
+ integer x,y; /* current xy coords */
+ array<0,1,integer> ox,oy; /* last xy coords */
+ shortint ix,iy; /* amount to move sprite by, each step */
+ array<1,24,manitype*> mani;
+ array<1,24,siltype*> sil;
+ byte whichsprite;
+ boolean quick,visible,homing,check_me;
+ integer hx,hy; /* homing x & y coords */
+ byte count; /* counts before changing step */
+ byte xw; /* x-width in bytes */
+ byte xs,ys; /* x & y speed */
+ byte totalnum; /* total number of sprites */
+ boolean vanishifstill; /* Do we show this sprite if it's still? */
+
+ boolean call_eachstep; /* Do we call the eachstep procedure? */
+ byte eachstep;
+
+ triptype* init(byte spritenum, boolean do_check);
+ /* loads & sets up the sprite */
+ void original(); /* just sets Quick to false */
+ void andexor(); /* drops sprite onto screen */
+ void turn(byte whichway); /* turns him round */
+ void appear(integer wx,integer wy, byte wf); /* switches him on */
+ void bounce(); /* bounces off walls. */
+ void walk(); /* prepares for andexor, etc. */
+ void walkto(byte pednum); /* home in on a point */
+ void stophoming(); /* self-explanatory */
+ void homestep(); /* calculates ix & iy for one homing step */
+ void speed(shortint xx,shortint yy); /* sets ix & iy, non-homing, etc */
+ void stopwalk(); /* Stops the sprite from moving */
+ void chatter(); /* Sets up talk vars */
+ void set_up_saver(trip_saver_type& v);
+ void unload_saver(trip_saver_type v);
+ void savedata(untyped_file& f); /* Self-explanatory, */
+ void loaddata(untyped_file& f); /* really. */
+ void save_data_to_mem(word& where);
+ void load_data_from_mem(word& where);
+ triptype* done();
+};
+
+class getsettype {
+public:
+ array<1,maxgetset,bytefield> gs;
+ byte numleft;
+
+ getsettype* init();
+ void remember(bytefield r);
+ void recall(bytefield& r);
+};
+
+
+const integer up = 0;
+const integer right = 1;
+const integer down = 2;
+const integer left = 3;
+const integer ur = 4; const integer dr = 5; const integer dl = 6; const integer ul = 7;
+const integer stopped = 8;
+
+const integer numtr = 5; /* current max no. of sprites */
+
+
+
+const integer procfollow_avvy_y = 1;
+
+const integer procback_and_forth = 2;
+
+const integer procface_avvy = 3;
+
+const integer procarrow_procs = 4;
+
+const integer procspludwick_procs = 5;
+
+const integer procgrab_avvy = 6;
+
+const integer procgeida_procs = 7;
+
+
+void trippancy_link();
+
+void get_back_loretta();
+
+void loadtrip();
+
+void call_special(word which);
+
+void open_the_door(byte whither,byte ped,byte magicnum); /* Handles slidey-open doors. */
+
+void catamove(byte ped);
+
+void stopwalking();
+
+void tripkey(char dir);
+
+void rwsp(byte t,byte r);
+
+void apped(byte trn,byte np);
+
+void getback();
+
+void fliproom(byte room,byte ped);
+
+boolean infield(byte which); /* returns True if you're within field "which" */
+
+boolean neardoor(); /* returns True if you're near a door! */
+
+void readstick();
+
+void newspeed();
+
+void new_game_for_trippancy();
+
+
+#ifdef __trip5_implementation__
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN array<1,numtr,triptype> tr;
+EXTERN array<0,1,getsettype> getset;
+EXTERN array<1,16000,byte> aa;
+
+EXTERN boolean mustexclaim; EXTERN word saywhat;
+#undef EXTERN
+#define EXTERN extern
+
+
+#endif
diff --git a/engines/avalanche/trip5tst.cpp b/engines/avalanche/trip5tst.cpp
new file mode 100644
index 0000000000..4b95ff4437
--- /dev/null
+++ b/engines/avalanche/trip5tst.cpp
@@ -0,0 +1,135 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+/*$R+*/
+
+struct adxtype {
+ varying_string<12> name; /* name of character */
+ varying_string<16> comment; /* comment */
+ byte num; /* number of pictures */
+ byte xl,yl; /* x & y lengths of pictures */
+ byte seq; /* how many in one stride */
+ word size; /* the size of one picture */
+ byte fgc,bgc; /* foreground & background bubble colours */
+};
+
+integer gd,gm;
+untyped_file inf;
+adxtype a;
+array<1,16000,byte> aa;
+array<5,2053,byte> mani;
+matrix<0,35,0,4,byte> sil;
+byte xw;
+
+void filesetup()
+{
+ const integer idshould = -1317732048;
+ longint id;
+ word soa;
+;
+ assign(inf,"v:sprite2.avd");
+ reset(inf,1);
+ seek(inf,177);
+ blockread(inf,id,4);
+ if (id!=idshould)
+ {;
+ output << '\7';
+ close(inf);
+ exit(0);
+ }
+
+ blockread(inf,soa,2);
+ blockread(inf,a,soa);
+}
+
+void loadpic()
+{
+ byte fv,ff;
+;
+ {;
+ xw=a.xl / 8; if ((a.xl % 8)>0) xw += 1;
+
+/* aa[1]:=xl; aa[2]:=0; aa[3]:=yl; aa[4]:=0;*/
+ /* The putimage x&y codes are words but xl & yl are bytes, hence the #0s. */
+/* seek(inf,filepos(inf)+xw*(yl+1));*/
+ for( fv=0; fv <= a.yl; fv ++)
+ blockread(inf,sil[fv],xw);
+ blockread(inf,mani,a.size-6);
+/* blockread(inf,aa[5+fv*xw*4+xw*ff],xw);*/
+ aa[a.size-1]=0; aa[a.size]=0; /* footer */
+ }
+/* putimage(0,0,aa,0);*/
+}
+
+void plotone(integer xx,integer yy)
+{
+ word s;
+ word ofs,fv;
+ byte x,y,z;
+;
+ {;
+ s=imagesize(x,y,xx+a.xl,yy+a.yl);
+ getimage(xx,yy,xx+a.xl,yy+a.yl,aa); /* Now loaded into our local buffer. */
+
+ /* Now we've got to modify it! */
+
+ for( x=0; x <= 3; x ++)
+ for( y=0; y <= 35; y ++)
+ for( z=0; z <= 4; z ++)
+ {;
+ ofs=5+y*xw*4+xw*x+z;
+ aa[ofs]=aa[ofs] & sil[y][z];
+ }
+
+ /* mov ax,5 ; AX = ofs
+ mov bx,xw ; wherever we get xw from
+ mov cx,x ; ditto
+ mov dx,y ; ditto
+ mul cx,bx ; x*xw
+ mul dx,bx ; y*yw
+ add ax,cx ; now add 'em all up
+ add ax,dx ; ...
+ mov bx,z ; get z (we don't need x any more)
+ mov cx,syz ; get silyz (where from??!)
+ add ax,bx ; add on the last part of the addition
+ and ax,cx ; AND ax with cx. That's it! */
+
+/*
+ for x:=1 to 4 do
+ begin;
+ for y:=0 to 35 do
+ for z:=0 to 4 do
+ begin;
+ ofs:=5+y*xw*4+xw*x+z;
+ aa[ofs]:=aa[ofs] xor pic[x,y,z];
+ end;
+ end;
+*/
+
+ for( fv=5; fv <= a.size-2; fv ++)
+ aa[fv]=aa[fv] ^ mani[fv];
+
+ /* Now.. let's try pasting it back again! */
+
+ putimage(xx,yy,aa,0);
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ initgraph(gd,gm,"");
+ setfillstyle(6,1); bar(0,0,640,200);
+ filesetup();
+ for( gd=1; gd <= 9; gd ++) loadpic();
+ do {
+ plotone(Random(500),Random(150));
+ } while (!keypressed());
+ plotone(0,0);
+ close(inf);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/trip5xf.cpp b/engines/avalanche/trip5xf.cpp
new file mode 100644
index 0000000000..0aa5f32ae2
--- /dev/null
+++ b/engines/avalanche/trip5xf.cpp
@@ -0,0 +1,172 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+
+const string crlf = string('\15')+'\12'; const char eof_ = '\32';
+const array<1,177,char> trip5head =
+ string("Sprite*.AVD ... data file for Trippancy Five")+crlf+crlf+
+ "[Thorsoft relocatable fiveplane sprite image format]"+crlf+crlf+
+ "Thomas Thurman was here. ... Have fun!"+crlf+crlf+eof_+
+ "±±±±±±± * G. I. E. D. ! * ";
+
+const array<1,4,char> tripid = string('\x30')+'\x1'+'\x75'+'\261';
+
+const array<1,50,char> trip5foot = crlf+crlf+
+ " and that's it! Enjoy the game. "+'\3'+crlf+crlf+
+ "\n\n\n\n\n\n\n"+"tt";
+
+struct adxotype {
+ varying_string<12> name; /* name of character */
+ byte num; /* number of pictures */
+ byte xl,yl; /* x & y lengths of pictures */
+ byte seq; /* how many in one stride */
+ word size; /* the size of one picture */
+ byte fgc,bgc; /* foreground & background bubble colours */
+};
+
+struct adxtype {
+ varying_string<12> name; /* name of character */
+ varying_string<16> comment; /* comment */
+ byte num; /* number of pictures */
+ byte xl,yl; /* x & y lengths of pictures */
+ byte seq; /* how many in one stride */
+ word size; /* the size of one picture */
+ byte fgc,bgc; /* foreground & background bubble colours */
+};
+
+varying_string<2> sn;
+adxotype oa;
+adxtype a;
+matrix<1,24,0,1,pointer> pic; /* the pictures themselves */
+array<1,16000,byte> aa;
+untyped_file out;
+integer bigsize;
+
+void copyaoa()
+{;
+ {;
+ a.name=oa.name;
+ a.comment="Transferred";
+ a.num=oa.num;
+ a.xl=oa.xl;
+ a.yl=oa.yl;
+ a.seq=oa.seq;
+ a.size=oa.size;
+ a.fgc=oa.fgc;
+ a.bgc=oa.bgc;
+ }
+}
+
+void load()
+{
+ untyped_file f; byte gd,gm,sort,n; pointer p,q;
+ pointer xf;
+;
+ assign(f,string("v:osprte")+sn+".avd"); reset(f,1); seek(f,59);
+ blockread(f,oa,sizeof(oa)); blockread(f,bigsize,2);
+ copyaoa();
+
+ getmem(xf,a.size);
+
+ for( sort=0; sort <= 1; sort ++)
+ {;
+ mark(q); getmem(p,bigsize);
+ blockread(f,p,bigsize);
+ putimage(0,0,p,0); release(q); n=1;
+
+ if (sort==0) setfillstyle(1,15); else setfillstyle(1,0);
+ bar(177,125,300,200);
+
+ for( gm=0; gm <= (a.num / a.seq)-1; gm ++) /* directions */
+ for( gd=0; gd <= a.seq-1; gd ++) /* steps */
+ {;
+ getmem(pic[n][sort],a.size); /* grab the memory */
+ getimage((gm / 2)*(a.xl*6)+gd*a.xl,(gm % 2)*a.yl,
+ (gm / 2)*(a.xl*6)+gd*a.xl+a.xl-1,(gm % 2)*a.yl+a.yl-1,
+ xf);
+ putimage(177,125,xf,0);
+ getimage(177,125,177+a.xl,125+a.yl,pic[n][sort]); /* grab the pic */
+ n += 1;
+ }
+ }
+ close(f);
+ freemem(xf,a.size);
+ cleardevice();
+ for( gm=0; gm <= 1; gm ++)
+ for( gd=1; gd <= a.num; gd ++)
+ putimage(gd*15,gm*40,pic[gd][gm],0);
+}
+
+void setup()
+{
+ integer gd,gm;
+;
+ output << "TRIP5XF (c) 1992, Thomas Thurman." << NL; output << NL;
+ output << "Enter number of SPRITE*.AVD file to convert:"; input >> sn >> NL;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ load();
+}
+
+string strf(longint x)
+{
+ string q;
+string strf_result;
+;
+ str(x,q); strf_result=q;
+return strf_result;
+}
+
+void save()
+{
+ byte sort,n;
+ word fv,ff; char r; byte xw;
+ byte nxl,nyl;
+ word soa;
+;
+ cleardevice();
+ {;
+ a.size=imagesize(0,0,a.xl,a.yl);
+ soa=sizeof(a);
+
+ assign(out,string("v:sprite")+sn+".avd"); rewrite(out,1);
+ blockwrite(out,trip5head,177);
+ blockwrite(out,tripid,4);
+ blockwrite(out,soa,2);
+ blockwrite(out,a,soa);
+
+ nxl=a.xl; nyl=a.yl;
+ xw=nxl / 8;
+ if ((nxl % 8)>0) xw += 1;
+
+ for( n=1; n <= a.num; n ++)
+ {;
+ putimage( 0,0,pic[n][0],0);
+ getimage( 0,0,a.xl,a.yl,aa);
+ for( fv=0; fv <= nyl; fv ++)
+ blockwrite(out,aa[5+fv*xw*4],xw);
+
+ putimage(100,0,pic[n][1],0);
+ getimage(100,0,100+a.xl,a.yl,aa);
+ putimage(100,100,aa,4);
+/* for ff:=1 to 4 do { actually 2 to 5, but it doesn't matter here }
+ for fv:=0 to nyl do*/
+/* for ff:=5 to size-2 do
+ blockwrite(out,aa[ff],1);*/
+ blockwrite(out,aa[5],a.size-6);
+ }
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ setup();
+ save();
+
+ blockwrite(out,trip5foot,50);
+ close(out);
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/tripoop.cpp b/engines/avalanche/tripoop.cpp
new file mode 100644
index 0000000000..15035c864d
--- /dev/null
+++ b/engines/avalanche/tripoop.cpp
@@ -0,0 +1,290 @@
+#include "ptoc.h"
+
+ /* Trip Oop (Trippancy 4 Andexor */
+#include "graph.h"
+/*#include "Crt.h"*/
+
+
+const integer up = 0;
+const integer right = 1;
+const integer down = 2;
+const integer left = 3;
+
+const integer numtr = 1; /* current max no. of sprites */
+
+struct adxtype {
+ varying_string<12> name; /* name of character */
+ byte num; /* number of pictures */
+ byte xl,yl; /* x & y lengths of pictures */
+ byte seq; /* how many in one stride */
+ word size; /* the size of one picture */
+ byte fgc,bgc; /* foreground & background bubble colours */
+};
+
+class triptype {
+public:
+ adxtype a; /* vital statistics */
+ byte face,step;
+ integer x,y; /* current xy coords */
+ integer ox,oy; /* last xy coords */
+ integer tax,tay; /* "behind" taken at... */
+ shortint ix,iy; /* amount to move sprite by, each step */
+ matrix<1,24,0,1,pointer> pic; /* the pictures themselves */
+ boolean quick,visible,homing;
+ pointer behind; /* what's behind you */
+ integer hx,hy; /* homing x & y coords */
+
+ triptype* init(byte spritenum); /* loads & sets up the sprite */
+ void original(); /* just sets Quick to false */
+ void andexor(); /* drops sprite onto screen 1 */
+ void turn(byte whichway); /* turns him round */
+ void appear(integer wx,integer wy, byte wf); /* switches him on */
+ void walk(); /* prepares for do_it, andexor, etc. */
+ void do_it(); /* Actually copies the picture over */
+ void getback(); /* gets background before sprite is drawn */
+ void putback(); /* ...and wipes sprite from screen 1 */
+ void walkto(integer xx,integer yy); /* home in on a point */
+ void stophoming(); /* self-explanatory */
+ void homestep(); /* calculates ix & iy for one homing step */
+ void speed(shortint xx,shortint yy); /* sets ix & iy, non-homing, etc */
+ void halt(); /* Stops the sprite from moving */
+};
+
+integer gd,gm;
+array<1,1,triptype> tr;
+
+void copier(integer x1,integer y1,integer x2,integer y2,integer x3,integer y3,integer x4,integer y4);
+
+
+static boolean dropin(integer xc,integer yc,integer x1,integer y1,integer x2,integer y2)
+/* Dropin returns True if the point xc,yc falls within the 1-2 rectangle. */
+{boolean dropin_result;
+;
+ dropin_result=((xc>=x1) && (xc<=x2) && (yc>=y1) && (yc<=y2));
+return dropin_result;
+}
+
+
+
+static void transfer(integer x1,integer y1,integer x2,integer y2)
+{
+ pointer p,q; word s;
+;
+ s=imagesize(x1,y1,x2,y2); setfillstyle(1,0);
+ mark(q); getmem(p,s);
+ setactivepage(1); getimage(x1,y1,x2,y2,p);
+ setactivepage(0); putimage(x1,y1,p,copyput);
+ setactivepage(1); release(q);
+}
+
+
+
+static integer lesser(integer a,integer b)
+{integer lesser_result;
+;
+ if (a<b) lesser_result=a; else lesser_result=b;
+return lesser_result;
+}
+
+
+
+static integer greater(integer a,integer b)
+{integer greater_result;
+;
+ if (a>b) greater_result=a; else greater_result=b;
+return greater_result;
+}
+
+void copier(integer x1,integer y1,integer x2,integer y2,integer x3,integer y3,integer x4,integer y4)
+
+{;
+ if (dropin(x3,y3,x1,y1,x2,y2)
+ || dropin(x3,y4,x1,y1,x2,y2)
+ || dropin(x4,y3,x1,y1,x2,y2)
+ || dropin(x4,y4,x1,y1,x2,y2))
+ {; /* Overlaps */
+ transfer(lesser(x1,x3),lesser(y1,y3),greater(x2,x4),greater(y2,y4));
+ } else
+ {; /* Doesn't overlap- copy both of them seperately */
+ transfer(x3,y3,x4,y4); /* backwards- why not...? */
+ transfer(x1,y1,x2,y2);
+ }
+}
+
+void setup()
+{
+ integer gd,gm;
+;
+ gd=3; gm=0; initgraph(gd,gm,"");
+ for( gd=0; gd <= 1; gd ++)
+ {;
+ setactivepage(gd);
+ setfillstyle(9,1); bar(0,0,640,200);
+ }
+ for( gm=1; gm <= numtr; gm ++) tr[gm].original();
+}
+
+triptype* triptype::init(byte spritenum)
+{
+ integer gd,gm; word s; untyped_file f; varying_string<2> xx; pointer p,q; word bigsize;
+ byte sort,n;
+;
+ str(spritenum,xx); assign(f,string("v:sprite")+xx+".avd");
+ reset(f,1); seek(f,59);
+ blockread(f,a,sizeof(a)); blockread(f,bigsize,2);
+ setvisualpage(3); setactivepage(3);
+ for( sort=0; sort <= 1; sort ++)
+ {;
+ mark(q); getmem(p,bigsize);
+ blockread(f,p,bigsize);
+ putimage(0,0,p,0); release(q); n=1;
+ { adxtype& with = a;
+ for( gm=0; gm <= (with.num / with.seq)-1; gm ++) /* directions */
+ for( gd=0; gd <= with.seq-1; gd ++) /* steps */
+ {;
+ getmem(pic[n][sort],a.size); /* grab the memory */
+ getimage((gm / 2)*(with.xl*6)+gd*with.xl,(gm % 2)*with.yl,
+ (gm / 2)*(with.xl*6)+gd*with.xl+with.xl-1,(gm % 2)*with.yl+with.yl-1,
+ pic[n][sort]); /* grab the pic */
+ putimage((gm / 2)*(with.xl*6)+gd*with.xl,(gm % 2)*with.yl,
+ pic[n][sort],notput); /* test the pic */
+ n += 1;
+ }}
+ }
+ close(f); setactivepage(0); setvisualpage(0);
+ x=0; y=0; quick=true; visible=false; getmem(behind,a.size);
+ homing=false; ix=0; iy=0;
+return this;
+}
+
+void triptype::original()
+{;
+ quick=false;
+}
+
+void triptype::getback()
+{;
+ tax=x; tay=y;
+ getimage(x,y,x+a.xl,y+a.yl,behind);
+}
+
+void triptype::andexor()
+{
+ byte picnum; /* Picnum, Picnic, what ye heck */
+;
+ picnum=face*a.seq+step+1;
+ putimage(x,y,pic[picnum][0],andput);
+ putimage(x,y,pic[picnum][1],xorput);
+}
+
+void triptype::turn(byte whichway)
+{;
+ face=whichway; step=0;
+}
+
+void triptype::appear(integer wx,integer wy, byte wf)
+{;
+ x=wx; y=wy; ox=wx; oy=wy; turn(wf); visible=true;
+}
+
+void triptype::walk()
+{;
+ ox=x; oy=y;
+ if (homing) homestep();
+ x=x+ix; y=y+iy;
+ step += 1; if (step==a.seq) step=0; getback();
+}
+
+void triptype::do_it()
+{;
+ copier(ox,oy,ox+a.xl,oy+a.yl,x,y,x+a.xl,y+a.yl);
+}
+
+void triptype::putback()
+{;
+ putimage(tax,tay,behind,0);
+}
+
+void triptype::walkto(integer xx,integer yy)
+{;
+ speed(xx-x,yy-y); hx=xx; hy=yy; homing=true;
+}
+
+void triptype::stophoming()
+{;
+ homing=false;
+}
+
+void triptype::homestep()
+{
+ integer temp;
+;
+ if ((hx==x) && (hy==y))
+ {; /* touching the target */
+ homing=false; return;
+ }
+ ix=0; iy=0;
+ if (hy!=y)
+ {;
+ temp=hy-y; if (temp>4) iy=4; else if (temp<-4) iy=-4; else iy=temp;
+ }
+ if (hx!=x)
+ {;
+ temp=hx-x; if (temp>4) ix=4; else if (temp<-4) ix=-4; else ix=temp;
+ }
+}
+
+void triptype::speed(shortint xx,shortint yy)
+{;
+ ix=xx; iy=yy;
+ if ((ix==0) && (iy==0)) return; /* no movement */
+ if (ix==0)
+ {; /* No horz movement */
+ if (iy<0) turn(up); else turn(down);
+ } else
+ {;
+ if (ix<0) turn(left); else turn(right);
+ }
+}
+
+void triptype::halt()
+{;
+ ix=0; iy=0; homing=false;
+}
+
+void trip()
+{
+ byte fv;
+;
+ for( fv=1; fv <= numtr; fv ++)
+ {
+ triptype& with = tr[fv];
+ ;
+ walk();
+ if (with.quick && with.visible) andexor();
+ do_it();
+ putback();
+ }
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ setup();
+ {
+ triptype& with = tr[1];
+ ;
+ init(1);
+ appear(600,100,left);
+ do {
+ /*
+ speed(-5,0); repeat trip until keypressed or (x= 0);
+ speed( 5,0); repeat trip until keypressed or (x=600);
+ */
+ walkto( 10, 10); do { trip(); } while (!(keypressed() || ! with.homing));
+ walkto( 70,150); do { trip(); } while (!(keypressed() || ! with.homing));
+ walkto(600, 77); do { trip(); } while (!(keypressed() || ! with.homing));
+ } while (!keypressed());
+ }
+return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/ttmenuxf.cpp b/engines/avalanche/ttmenuxf.cpp
new file mode 100644
index 0000000000..51903e948b
--- /dev/null
+++ b/engines/avalanche/ttmenuxf.cpp
@@ -0,0 +1,112 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Tommys.h"*/
+/*#include "Crt.h"*/
+
+integer gd,gm;
+word s; pointer p;
+file<byte> f;
+byte bit;
+
+void load() /* Load2, actually */
+{
+ byte a0; /*absolute $A000:800;*/
+ byte a1; /*absolute $A000:17184;*/
+ byte bit;
+ untyped_file f; varying_string<2> xx;
+ boolean was_virtual;
+
+ assign(f,"v:ttmenu.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+ bit=getpixel(0,0);
+}
+
+void finder()
+{
+ char r; integer x,y;
+;
+ setfillstyle(0,0); setcolor(14);
+ x=320; y=100; setwritemode(xorput);
+ do {
+ bar(0,0,200,10);
+ outtextxy(0,0,strf(x)+','+strf(y));
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ do {; } while (!keypressed());
+ line(x-20,y,x+20,y); line(x,y-20,x,y+20);
+ switch (readkey()) {
+ case '\15': return; break;
+ case '8': y -= 10; break;
+ case '4': x -= 10; break;
+ case '6': x += 10; break;
+ case '2': y += 10; break;
+ case '\0': switch (readkey()) {
+ case cup: y -= 1; break;
+ case cdown: y += 1; break;
+ case cleft: x -= 1; break;
+ case cright: x += 1; break;
+ }
+ break;
+ }
+ } while (!false);
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ gd=3; gm=1; initgraph(gd,gm,"");
+ load();
+ finder();
+ s=imagesize(342,21,407,119);
+ getmem(p,s);
+ getimage(342,21,407,119,p);
+ putimage(342,21,p,4);
+ input >> NL;
+ putimage(264,120,p,0);
+ input >> NL;
+ freemem(p,s);
+
+ s=imagesize(264,12,329,217);
+ getmem(p,s);
+ getimage(264,21,329,218,p);
+ putimage(264,21,p,4);
+ putimage(0,0,p,0);
+ freemem(p,s);
+ input >> NL;
+
+ s=imagesize(180,103,188,135);
+ getmem(p,s);
+ getimage(180,103,188,135,p);
+ putimage(0,200,p,0);
+ input >> NL;
+
+ assign(f,"v:menu.avd");
+ rewrite(f);
+
+ for( bit=0; bit <= 3; bit ++)
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( gd=0; gd <= 196; gd ++)
+ for( gm=0; gm <= 8; gm ++)
+ {
+ f << mem[0xa000*gd*80+gm];
+ mem[0xa000*gd*80+gm]=~ mem[0xa000*gd*80+gm];
+ }
+
+ for( gd=200; gd <= 232; gd ++)
+ {
+ f << mem[0xa000*gd*80];
+ mem[0xa000*gd*80]=~ mem[0xa000*gd*80];
+ }
+ }
+
+ close(f);
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/unsquish.cpp b/engines/avalanche/unsquish.cpp
new file mode 100644
index 0000000000..ad8bd58ace
--- /dev/null
+++ b/engines/avalanche/unsquish.cpp
@@ -0,0 +1,524 @@
+#include "ptoc.h"
+
+ /*$S-*/
+#include "graph.h"
+
+
+typedef array<1,50000,byte> buffertype;
+
+integer gd,gm;
+varying_string<29> describe;
+byte method;
+shortint bit;
+word offset;
+byte a0; /*absolute $A000:800;*/
+array<1,12080,byte> a7; /*absolute $A000:800;*/
+buffertype* buffer;
+word bufsize;
+
+void putup(byte what)
+{;
+ if (offset>12080)
+ {;
+ bit += 1;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ offset=1;
+ }
+
+ a7[offset]=what;
+ offset += 1;
+}
+
+void load_uncomp(string xx) /* Load2, actually */
+/* a1:byte absolute $A000:17184;*/
+{
+ byte this_;
+ untyped_file f;
+ word place;
+;
+ assign(f,string("v:place")+xx+".avd"); reset(f,1); seek(f,146);
+ blockread(f,describe,30); blockread(f,method,1);
+ bufsize=filesize(f)-177; blockread(f,*buffer,bufsize);
+ close(f);
+
+ bit=-1; offset=12081; place=1;
+
+ while (place<=bufsize)
+ {;
+ this_=(*buffer)[place];
+ place += 1;
+ putup(this_);
+ }
+
+ output << method << " : \"" << describe << '"' << NL;
+}
+
+void load_comp(string xx);
+
+const integer maxtab = 4095 /* Table size - 1 ==> 2**10-1 ==> 12 bits */;
+
+const integer no_prev = -1 /* Special code for no previous character */;
+
+const integer end_list = -1 /* Marks end of a list */;
+
+const integer maxstack = 4096 /* Decompression stack size */;
+
+
+
+
+ /* One node in parsing table. */
+struct string_table_entry {
+ boolean unused /* Is this node *NOT* used yet?*/;
+ integer prevchar /* Code for preceding string */;
+ integer follchar /* Code for current character */;
+ integer next /* Next dupl in collision list */;
+};
+
+
+
+typedef array<0,maxtab,string_table_entry> sttype;
+
+
+ /* String table */
+
+static sttype* string_table;
+
+
+static integer table_used /* # string table entries used */;
+
+static byte input_code /* Input compressed code */;
+
+static boolean inempty,popempty;
+
+ /* Decompression stack */
+
+static array<1,maxstack,byte> stack;
+
+
+static integer stack_pointer /* Decompression stack depth */;
+
+static word place;
+
+
+static integer get_hash_code( integer& prevc, integer& follc )
+
+{
+ integer index;
+ integer index2;
+
+ /* Get_Hash_Code */
+ /* Get initial index using hashing */
+
+ integer get_hash_code_result;
+ index = ( ( prevc << 5 ) ^ follc ) & maxtab;
+
+ /* If entry not already used, return */
+ /* its index as hash code for <w>C. */
+
+ if ( (*string_table)[index].unused )
+ get_hash_code_result = index;
+ else
+ /* If entry already used, search to */
+ /* end of list of hash collision */
+ /* entries for this hash code. */
+ /* Do linear probe to find an */
+ /* available slot. */
+ {
+
+ /* Skip to end of collision list ... */
+
+ while ( (*string_table)[index].next != end_list )
+ index = (*string_table)[index].next;
+
+ /* Begin linear probe down a bit from */
+ /* last entry in collision list ... */
+
+ index2 = ( index + 101 ) & maxtab;
+
+ /* Look for unused entry using linear */
+ /* probing ... */
+
+ while ( ! (*string_table)[index2].unused )
+ index2 = succ(integer, index2 ) & maxtab;
+
+ /* Point prior end of collision list */
+ /* to this new node. */
+
+ (*string_table)[index].next = index2;
+
+ /* Return hash code for <w>C */
+
+ get_hash_code_result = index2;
+
+ }
+
+ return get_hash_code_result;
+} /* Get_Hash_Code */
+
+
+
+ /*--------------------------------------------------------------------------*/
+ /* Make_Table_Entry --- Enter <w>C string in string table */
+ /*--------------------------------------------------------------------------*/
+
+static void make_table_entry( integer& prevc, integer& follc )
+
+{ /* Make_Table_Entry */
+ /* Only enter string if there is room left */
+
+ if ( table_used <= maxtab )
+ {
+ {
+ string_table_entry& with = (*string_table)[ get_hash_code( prevc , follc ) ];
+
+ with.unused = false;
+ with.next = end_list;
+ with.prevchar = prevc;
+ with.follchar = follc;
+ }
+ /* Increment count of items used */
+
+ table_used += 1;
+/*
+ IF ( Table_Used > ( MaxTab + 1 ) ) THEN
+ BEGIN
+ WRITELN('Hash table full.');
+ END;
+ */
+ }
+
+} /* Make_Table_Entry */
+
+
+
+static void firstentries()
+/* This is just a fast version of the above, when PrevC = No_Prev. TT. */
+
+{
+ integer i,j;
+
+
+ /* There MUST be room- we've only just started! */
+
+ j=no_prev;
+
+ for( i=0; i <= 255; i ++)
+ {
+ string_table_entry& with = (*string_table)[ ((no_prev << 5 ) ^ i) & maxtab];
+
+ with.unused = false;
+ with.next = end_list;
+ with.prevchar = no_prev;
+ with.follchar = i;
+ }
+
+ table_used += 256; /* Increment count of items used */
+
+}
+
+
+
+ /*--------------------------------------------------------------------------*/
+ /* Initialize_String_Table --- Initialize string table */
+ /*--------------------------------------------------------------------------*/
+
+static void initialize_string_table()
+
+{
+ integer i;
+
+ /* Initialize_String_Table */
+
+ /* No entries used in table yet */
+ table_used = 0;
+
+ fillchar(*string_table,(maxtab+1)*sizeof((*string_table)[1]),'\377');
+ /* Enter all single characters into */
+ /* table */
+ firstentries();
+
+} /* Initialize_String_Table */
+
+
+
+ /*--------------------------------------------------------------------------*/
+ /* Lookup_String --- Look for string <w>C in string table */
+ /*--------------------------------------------------------------------------*/
+
+static integer lookup_string( integer prevc, integer follc )
+
+{
+ integer index;
+ integer index2;
+ boolean found;
+
+ /* Lookup_String */
+ /* Initialize index to check from hash */
+
+ integer lookup_string_result;
+ index = ( ( prevc << 5 ) ^ follc ) & maxtab;
+
+ /* Assume we won't find string */
+ lookup_string_result = end_list;
+ /* Search through list of hash collision */
+ /* entries for one that matches <w>C */
+ do {
+
+ found = ( (*string_table)[index].prevchar == prevc ) &&
+ ( (*string_table)[index].follchar == follc );
+
+ if ( ! found )
+ index = (*string_table)[index].next;
+
+ } while (!(found || ( index == end_list )));
+
+ /* Return index if <w>C found in table. */
+ if (found)
+ lookup_string_result = index;
+
+ return lookup_string_result;
+} /* Lookup_String */
+
+
+
+ /*--------------------------------------------------------------------------*/
+ /* Push --- Push character onto stack */
+ /*--------------------------------------------------------------------------*/
+
+static void push( byte c)
+
+{ /* Push */
+
+ stack_pointer += 1;
+ stack[ stack_pointer ] = c;
+
+ if ( stack_pointer >= maxstack )
+ {
+ output << "Stack overflow!" << NL;
+ exit(0);
+ }
+
+} /* Push */
+
+
+
+ /*--------------------------------------------------------------------------*/
+ /* Pop --- Pop character from stack */
+ /*--------------------------------------------------------------------------*/
+
+static void pop( integer& c )
+
+{ /* Pop */
+
+ popempty=stack_pointer==0;
+
+ if (! popempty)
+ {
+ c = stack[stack_pointer];
+ stack_pointer -= 1;
+ }
+
+} /* Pop */
+
+
+
+ /*--------------------------------------------------------------------------*/
+ /* Get_Code --- Get compression code from input file */
+ /*--------------------------------------------------------------------------*/
+
+static void get_code( integer& hash_code )
+
+{
+ byte local_buf;
+
+ /* Get_Code */
+
+ if (inempty)
+ {
+
+ if (place>bufsize) return; else
+ {;
+ local_buf=(*buffer)[place];
+ place += 1;
+ }
+
+ if (place>bufsize) return; else
+ {;
+ input_code=(*buffer)[place];
+ place += 1;
+ }
+
+ hash_code = ( ( local_buf << 4 ) & 0xff0 ) +
+ ( ( (cardinal)input_code >> 4 ) & 0xf );
+
+ input_code = input_code & 0xf;
+ inempty=false;
+
+ }
+ else
+ {
+
+ if (place>bufsize) return; else
+ {;
+ local_buf=(*buffer)[place];
+ place += 1;
+ }
+
+ hash_code = local_buf + ( ( input_code << 8 ) & 0xf00 );
+ inempty=true;
+
+ }
+
+} /* Get_Code */
+
+
+
+ /*--------------------------------------------------------------------------*/
+ /* Do_Decompression --- Perform decompression */
+ /*--------------------------------------------------------------------------*/
+
+static void do_decompression()
+
+{
+ integer c /* Current input character */;
+ integer code /* Current code string */;
+ integer old_code /* Previous code string */;
+ integer fin_char /* Final input character */;
+ integer in_code /* Current input code */;
+ integer last_char /* Previous character */;
+ boolean unknown /* TRUE if code not found */;
+ integer temp_c /* Char popped off stack */;
+
+ /* Do_Decompression */
+
+ stack_pointer = 0; /* Decompression stack is empty */
+ unknown = false; /* First string is always known */
+ get_code( old_code ); /* Get first string == Step 1 */
+ code = old_code;
+
+ c=(*string_table)[code].follchar; /* Output corresponding character */
+ putup( c );
+ fin_char = c; /* Remember this character -- it */
+ /* is final character of next string */
+
+ get_code( in_code ); /* Get next code == Step 2 */
+
+ while (place<=bufsize)
+ {
+ code = in_code; /* Set code to this input code */
+
+ /* If code not in table, do special */
+ /* case ==> Step 3 */
+
+ if ( (*string_table)[code].unused )
+ {
+ last_char = fin_char;
+ code = old_code;
+ unknown = true;
+ }
+ /* Run through code extracting single */
+ /* characters from code string until */
+ /* no more characters can be removed. */
+ /* Push these onto stack. They will */
+ /* be entered in reverse order, and */
+ /* will come out in forwards order */
+ /* when popped off. */
+ /* */
+ /* ==> Step 4 */
+
+ while( (*string_table)[code].prevchar != no_prev )
+ {
+ string_table_entry& with = (*string_table)[code];
+
+ push( with.follchar );
+ code = with.prevchar;
+ }
+ /* We now have the first character in */
+ /* the string. */
+
+ fin_char = (*string_table)[code].follchar;
+
+ /* Output first character ==> Step 5 */
+ putup( fin_char );
+ /* While the stack is not empty, remove */
+ /* and output all characters from stack */
+ /* which are rest of characters in the */
+ /* string. */
+ /* */
+ /* ==> Step 6 */
+ pop( temp_c );
+
+ while (! popempty)
+ {
+ putup( temp_c );
+ pop( temp_c );
+ }
+ /* If code isn't known, output the */
+ /* follower character of last character */
+ /* of string. */
+ if (unknown)
+ {
+ fin_char = last_char;
+ putup( fin_char );
+ unknown = false;
+ }
+ /* Enter code into table ==> Step 7 */
+
+ make_table_entry( old_code , fin_char );
+
+ /* Make current code the previous code */
+ old_code = in_code;
+
+ /* Get next code == Step 2 */
+ get_code( in_code );
+
+ }
+
+} /* Do_Decompression */
+
+void load_comp(string xx){
+
+ /* This loads in the compressed file. */
+
+const integer maxbuff = 8192 /* Buffer size for input and output files */;
+
+integer output_code /* Output compressed code */;
+boolean if_compressing /* TRUE if compressing file */;
+
+byte this_;
+untyped_file f;
+
+;
+string_table = new sttype;
+inempty=true;
+initialize_string_table();
+
+assign(f,string("v:compr")+xx+".avd"); reset(f,1); seek(f,146);
+blockread(f,describe,30); blockread(f,method,1);
+bufsize=filesize(f)-177; blockread(f,*buffer,bufsize);
+close(f);
+
+bit=-1; offset=12081; place=1;
+
+do_decompression();
+
+output << method << " : \"" << describe << '"' << NL;
+
+delete string_table;
+ }
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+buffer = new buffertype;
+#ifdef uncomp
+load_uncomp("21");
+#else
+load_comp("21");
+#endif
+delete buffer;
+return EXIT_SUCCESS;
+}
+
+
diff --git a/engines/avalanche/viewdocs.cpp b/engines/avalanche/viewdocs.cpp
new file mode 100644
index 0000000000..effb1c5474
--- /dev/null
+++ b/engines/avalanche/viewdocs.cpp
@@ -0,0 +1,522 @@
+#include "ptoc.h"
+
+ /*$S-*/
+/*#include "dos.h"*/
+/*#include "crt.h"*/
+/*#include "tommys.h"*/
+
+
+typedef array<0,49999,byte> bigtextarray;
+struct chaptertype {
+ varying_string<60> headername;
+ word headeroffset;
+};
+typedef array<1,1120,byte> sbtype;
+
+const integer contsize = 29; /*number of headers in AVALOT.DOC*/
+const varying_string<80> contentsheader = " -=- The contents of the Lord AVALOT D'Argent (version 1.3) documentation -=-";
+const array<0,15,byte> listpal = {{1,0,3,0,7,0,7,7,0,0,0,0,0,0,0,0}};
+const array<0,15,byte> blankpal = {{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}};
+const integer tabstop = 8; /*length of tab stops*/
+
+/*NOTE: Tabs are not properly implemented. The program just interprets them*/
+/*as a number of spaces.*/
+
+matrix<1,256, 0,15,byte> textvar,textvar8;
+array<0,1500,word> posof13;
+array<1,65535,byte> scvar; /*absolute $A000:$0000;*/
+sbtype stbar,stbar2;
+pointer dpt;
+word sot,nol,bat,bab,tlab,nosl,bfseg,bfofs,useless;
+bigtextarray* textmem;
+boolean atsof,fast,regimode;
+byte hol;
+varying_string<80> stline;
+array<1,contsize,chaptertype> contlist;
+integer lat;
+
+void wipeit(longint pos, word count) /*Like fillchar, but wraps*/
+{
+ longint wpos;
+
+ wpos=(word)(pos);
+ fillchar(mem[longint(0xa000)+wpos / longint(16)*wpos % longint(16)],count,0);
+}
+
+void wrapcopy(sbtype fromarr, longint pos) /*Like fillchar, but wraps*/
+{
+ longint wpos;
+
+ wpos=(word)(pos);
+ move(fromarr,mem[longint(0xa000)+wpos / longint(16)*wpos % longint(16)],1120);
+}
+
+void blankscreen() /*blanks the screen (!)*/
+{
+ registers r;
+
+ r.ax=0x1002;
+ r.es=seg(blankpal);
+ r.dx=ofs(blankpal);
+ intr(0x10,r);
+}
+
+void showscreen() /*shows the screen (!)*/
+{
+ registers r;
+
+ r.ax=0x1002;
+ r.es=seg(listpal);
+ r.dx=ofs(listpal);
+ intr(0x10,r);
+}
+
+void wipesb(word wheretop)
+{
+ byte plane;
+
+ for( plane=2; plane <= 3; plane ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << plane; port[0x3cf]=plane;
+ fillchar(scvar[(wheretop+336)*80+1],1120,0);
+ }
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=2; port[0x3cf]=1;
+}
+
+void displstat(byte wipepos) /*displays the status bar*/
+{
+ byte plane;
+
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=4; port[0x3cf]=2;
+ wrapcopy(stbar,(lat+336)*80);
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=8; port[0x3cf]=3;
+ wrapcopy(stbar2,(lat+336)*80);
+ for( plane=2; plane <= 3; plane ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << plane; port[0x3cf]=plane;
+ switch (wipepos) {
+ case 0: wipeit((lat+335)*80-1,80); break;
+ case 1: wipeit(lat*80-1,80); break;
+ }
+ }
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=2; port[0x3cf]=1;
+}
+
+void udstat() /*updates the status bar*/
+{
+ varying_string<3> pt;
+ byte fv,fv2;
+
+ fillchar(pt,4,'\0');
+ str(round((real)((tlab-21))/(nol-21)*100),pt);
+ for( fv=1; fv <= 3; fv ++)
+ for( fv2=0; fv2 <= 13; fv2 ++)
+ {;
+ stbar[fv2*80+fv+68]=~ textvar[ord(pt[fv])+1][fv2];
+ stbar2[fv2*80+fv+68]=textvar[ord(pt[fv])+1][fv2];
+ }
+}
+
+void finddocinfo() /*finds the line breaks in AVALOT.DOC & finds the
+headers by searching for '"""'*/
+{
+ word wv,oldwv,varpos,varpos2,contlpos;
+ boolean thisaheader;
+ varying_string<60> headerstring;
+
+ thisaheader=false;
+ posof13[0]=65535; /*this +2 will wrap around to 1*/
+ wv=1;
+ oldwv=1;
+ varpos=1;
+ contlist[1].headername="Start of documentation";
+ contlist[1].headeroffset=0;
+ contlpos=2;
+ while (wv<sot)
+ {
+ while (((*textmem)[wv]!=13) && ((*textmem)[wv]!=34) && (wv-oldwv<80)) wv += 1;
+ switch ((*textmem)[wv]) {
+ case 13: {
+ posof13[varpos]=wv;
+ varpos += 1;
+ oldwv=wv+1;
+ thisaheader=false;
+ }
+ break;
+ case 34: if (((*textmem)[wv-1]==34) && ((*textmem)[wv-2]==34) && (varpos>12)
+ && (thisaheader==false))
+ {
+ thisaheader=true;
+ headerstring[0]='\0';
+ varpos2=posof13[varpos-2]+2;
+ while (((*textmem)[varpos2]==32) || ((*textmem)[varpos2]==9)) varpos2 += 1;
+ while (varpos2!=posof13[varpos-1])
+ {;
+ headerstring=headerstring+chr((*textmem)[varpos2]);
+ varpos2 += 1;
+ }
+ contlist[contlpos].headername=headerstring;
+ contlist[contlpos].headeroffset=varpos-2;
+ contlpos += 1;
+ }
+ break;
+ }
+ wv += 1;
+ }
+ nol=varpos-2;
+ nosl=nol*14;
+}
+
+void graphmode(byte gm) /*puts the display adaptor into a specified mode*/
+{
+ registers regs;
+
+ regs.ax=gm;
+ intr(0x10,regs);
+}
+
+void setoffset(word where_on_screen) {; /*assembler; {for scrolling the screen*/
+/*asm
+ mov bx, where_on_screen
+ mov dx, $03D4
+ mov ah, bh
+ mov al, $C
+ out dx, ax
+
+ mov ah, bl
+ inc al
+ out dx, ax*/
+ }
+
+void setupsb(byte sbtype) /*sets up the status bar in several styles*/
+{
+ integer fv;
+
+ switch (sbtype) {
+ case 1: if (regimode==false) stline=string("Doc lister: PgUp, PgDn, Home & End to move. Esc exits. C=")
+ +'\32'+"contents "+'\263'+" % through "; else
+ stline=string("Doc lister: PgUp, PgDn, Home & End to move. Esc exits to main menu.")
+ +'\263'+" % through";
+ break;
+ case 2: stline=string("Esc=to doc lister ")+'\263'+" Press the key listed next to the section you wish to jump to"; break;
+ }
+ for( fv=0; fv <= 1118; fv ++) {;
+ stbar[fv+1]=~ textvar[ord(stline[fv % 80+1])+1][fv / 80];
+ stbar2[fv+1]=textvar[ord(stline[fv % 80+1])+1][fv / 80];
+ }
+}
+
+void setup() /*sets up graphics, variables, etc.*/
+{
+ untyped_file f;
+ integer fv;
+ registers r;
+
+ if ((paramstr(1)!="REGI") && (paramstr(1)!="ELMPOYTEN"))
+
+ {
+ clrscr;
+ output << "This program cannot be run on its own. Run AVALOT.EXE." << NL;
+ exit(123);
+ }
+ val(paramstr(2),bfseg,useless);
+ val(paramstr(3),bfofs,useless);
+ bfofs += 1;
+ atsof=true;
+ fast=false;
+ assign(f,"avalot.fnt");
+ reset(f,1);
+ blockread(f,textvar,4096);
+ close(f);
+ assign(f,"ttsmall.fnt");
+ reset(f,1);
+ blockread(f,textvar8,4096);
+ close(f);
+ assign(f,"avalot.doc");
+ reset(f,1);
+ sot=filesize(f);
+ mark(dpt);
+ textmem = new bigtextarray;
+ blockread(f,*textmem,sot);
+ close(f);
+ finddocinfo();
+ if (paramstr(1)=="REGI")
+ {;
+ regimode=true;
+ tlab=contlist[contsize].headeroffset+24;
+ lat=contlist[contsize].headeroffset*14;
+ }
+ else
+ {;
+ lat=0; tlab=24;
+ regimode=false;
+ }
+ setupsb(1);
+ graphmode(16);
+ directvideo=false;
+ showscreen();
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=2; port[0x3cf]=1;
+}
+
+void drawscreenf(integer tl) /*draws a screen from a line forwards*/
+/*N.B. tl>1*/
+{
+ word fv,fv2,curbyte,plane;
+ byte xpos;
+
+ blankscreen();
+ wipesb(lat);
+ if (tl>nol-24) tl=nol-24;
+ if (tl<0) tl=0;
+ lat=tl*14;
+ for( plane=2; plane <= 3; plane ++) /*wipe sb off*/
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << plane; port[0x3cf]=plane;
+ /*fillchar(mem [$A000:((lat-1)*80) mod 65536],26800,0);*/
+ wipeit(lat*80,26800);
+ }
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=2; port[0x3cf]=1; /*back to normal*/
+ if (tl>0) curbyte=posof13[tl-1]+2; else curbyte=0;
+ bat=curbyte;
+ for( fv=lat; fv <= lat+335; fv ++)
+ {
+ fv2=curbyte;
+ xpos=1;
+ while (xpos<=80)
+ {
+ if (fv2<posof13[tl])
+ {
+ if ((*textmem)[fv2]==9)
+ {
+ wipeit(fv*80+xpos,tabstop);
+ xpos += tabstop;
+ } else
+ {
+ mem[0xa000*(word)(fv*80+xpos-1)]=
+ textvar[(*textmem)[fv2]+1][fv % 14];
+ xpos += 1;
+ }
+ } else
+ {
+ wipeit(fv*80+xpos-1,82-xpos);
+ xpos=81;
+ }
+ fv2 += 1;
+ }
+ if (fv % 14==0)
+ {
+ tl += 1;
+ curbyte=posof13[tl-1]+2;
+ }
+ }
+ bab=curbyte;
+ tlab=tl;
+ udstat();
+ displstat(2);
+ setoffset((word)(lat*80));
+ if (tl-23>1) atsof=false;
+ showscreen();
+}
+
+void displcont() /*displays the contents*/
+{
+ byte fv,fv2,fv3,keyon,jumppos,plane;
+ word olat;
+ varying_string<62> curstr;
+ char rkv;
+
+ blankscreen();
+ olat=lat; lat=0; keyon=1; jumppos=0;
+ setoffset(0);
+ for( plane=1; plane <= 3; plane ++) /*wipe sb off*/
+ {
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << plane; port[0x3cf]=plane;
+ fillchar(scvar,26800,0);
+ }
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=2; port[0x3cf]=1; /*back to normal*/
+ setupsb(2);
+ displstat(2);
+ for( fv=1; fv <= 80; fv ++)
+ for( fv2=0; fv2 <= 27; fv2 ++)
+ {
+ scvar[fv2*80+fv]=textvar[ord(contentsheader[fv-1])+1][fv2 / 2];
+ }
+ for( fv=1; fv <= contsize; fv ++)
+ {
+ if (keyon<10) curstr=strf(keyon)+". "+contlist[fv].headername; else
+ curstr=string(chr(keyon+55))+". "+contlist[fv].headername;
+ for( fv2=1; fv2 <= length(curstr); fv2 ++)
+ for( fv3=0; fv3 <= 7; fv3 ++)
+ scvar[(fv+3)*640+fv3*80+fv2]=textvar8[ord(curstr[fv2])+1][fv3];
+ keyon += 1;
+ }
+ showscreen();
+ do {; } while (!keypressed());
+ rkv=readkey();
+ switch (rkv) {
+ case RANGE_9('\61','\71'): jumppos=ord(rkv)-48;
+ break;
+ case RANGE_26('\101','\132'): jumppos=ord(rkv)-55;
+ break;
+ case RANGE_26('\141','\172'): jumppos=ord(rkv)-87;
+ break;
+ default: lat=olat;
+ }
+ if (jumppos>0) lat=contlist[jumppos].headeroffset;
+ setupsb(1);
+ if (fast==false) wipesb(0);
+ drawscreenf(lat);
+}
+
+void down() /*scrolls the screen down one line*/
+{
+ word fv,xpos,wpos,lab;
+
+ lat += 1;
+ lab=lat+335;
+ setoffset((word)(lat*80));
+ if (lab % 14==0) {
+ bat=posof13[tlab-24]+2; bab=posof13[tlab]+2; tlab += 1; udstat(); }
+ fv=bab;
+ xpos=1;
+ while (xpos<=80)
+ {
+ if (fv<posof13[tlab])
+ {
+ if ((*textmem)[fv]==9)
+ {
+ wipeit(lab*80+xpos-1,tabstop);
+ xpos += tabstop;
+ } else
+ {
+ wpos=(lab*80+xpos) % 65536;
+ /*fillchar(mem[$A000+wpos div 16*wpos mod 16],count,0)*/
+ mem[0xa000*wpos-1]=textvar[(*textmem)[fv]+1][lab % 14];
+ xpos += 1;
+ }
+ } else
+ {
+ wipeit(lab*80+xpos-1,81-xpos);
+ xpos=81;
+ }
+ fv += 1;
+ }
+ atsof=false;
+ if (fast==true) displstat(0);
+}
+
+void up() /*scrolls the screen up one line*/
+{
+ word fv,xpos,wpos;
+
+ if (lat==0) { atsof=true; return; }
+ if (lat % 14==0)
+ if (tlab>24)
+ {
+ tlab -= 1; bat=posof13[tlab-24]+2; bab=posof13[tlab-1]+2; udstat(); } else
+ { atsof=true; udstat(); return; }
+ lat -= 1;
+ setoffset((word)(lat*80));
+ fv=bat;
+ xpos=1;
+ while (xpos<=80)
+ {
+ if (fv<posof13[tlab-23])
+ {
+ if ((*textmem)[fv]==9)
+ {
+ wipeit(lat*80+xpos-1,tabstop);
+ xpos += tabstop;
+ } else
+ {
+ wpos=(word)((lat*80+xpos) % 65536);
+ mem[0xa000*wpos-1]=textvar[(*textmem)[fv]+1][lat % 14];
+ xpos += 1;
+ }
+ } else
+ {
+ wipeit(lat*80+xpos-1,81-xpos);
+ xpos=81;
+ }
+ fv += 1;
+ }
+ if (fast==true) displstat(1);
+ /*ateof:=false;*/
+}
+
+void endit() /*Ends the program*/
+{
+ release(dpt);
+ graphmode(2);
+}
+
+void control() /*User control*/
+{
+ char rkv,rkv2/*the sequel*/,rkv3;
+ integer fv;
+ boolean first;
+
+ if (regimode==false) displcont(); else drawscreenf(tlab-24);
+ first=true;
+ do {;
+ rkv=readkey();
+ switch (rkv) {
+ case '\0': {
+ rkv2=readkey();
+ switch (rkv2) {
+ case chome:drawscreenf(0); break;
+ case cend: drawscreenf(nol-24); break;
+ case cpgdn:
+ {;
+ memw[bfseg*bfofs]=0;
+ if (fast==false) wipesb(lat);
+ fv=1;
+ while (((cardinal)lat+336<nosl) && (fv<337))
+ {
+ fv += 1;
+ down();
+ }
+ if ((first==true) && (memw[bfseg*bfofs]<=2)) fast=true;
+ if ((fast==false) || (first==true)) displstat(0);
+ }
+ break;
+ case cpgup:
+ {;
+ memw[bfseg*bfofs]=0;
+ if (fast==false) wipesb(lat);
+ fv=1;
+ while ((atsof==false) && (fv<337))
+ {
+ fv += 1;
+ up();
+ }
+ if ((first==true) && (memw[bfseg*bfofs]<=2)) fast=true;
+ if ((fast==false) || (first==true)) displstat(0);
+ }
+ break;
+/* cUp:repeat;
+ up;
+ readkey;
+ until (readkey<>cUp) or (atsof=true);
+ cDown: repeat;
+ down;
+ readkey;
+ until (readkey<>cDown) or (ateof=true);*/
+ }
+ first=false;
+ }
+ break;
+ case '\33': return; break;
+ case '\103':case '\143': if (regimode==false) { wipesb(lat); displcont(); } break;
+ }
+ } while (!false);
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ setup();
+ control();
+ endit();
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/visa.cpp b/engines/avalanche/visa.cpp
new file mode 100644
index 0000000000..f5bd51131e
--- /dev/null
+++ b/engines/avalanche/visa.cpp
@@ -0,0 +1,264 @@
+#include "ptoc.h"
+
+/*
+ ÛßÜ ÛßÜ ÜßßÜ ßÛß Ûßß Üß ßÛß ÜßÛßÜ ßÛß ÛÜ Û ÜÛßß ßÛß ÛßÜ Ûßß Û
+ Ûß ÛÛ Û Û Ü Û Ûßß ßÜ Û Û Û Û Û Û ÛÜÛ ßßßÜ Û ÛÛ Ûßß Û
+ ß ß ß ßß ßß ßßß ß ß ß ß ß ßßß ß ßß ßßß ß ß ß ßßß ßßß
+
+ VISA The new Sez handler. (Replaces Access.) */
+
+#define __visa_implementation__
+
+
+#include "visa.h"
+
+
+/*#include "Gyro.h"*/
+/*#include "Scrolls.h"*/
+/*#include "Acci.h"*/
+/*#include "Trip5.h"*/
+/*#include "Lucerna.h"*/
+
+
+const boolean bubbling = false;
+const boolean report_dixi_errors = true;
+
+boolean went_ok;
+
+void unskrimble()
+{
+ word fv;
+
+ for( fv=1; fv <= bufsize; fv ++) buffer[fv]=(char)((~(ord(buffer[fv])-fv)) % 256);
+}
+
+void do_the_bubble()
+{
+ bufsize += 1;
+ buffer[bufsize]='\2';
+}
+
+void dixi(char block, byte point)
+{
+ untyped_file indexfile,sezfile;
+ word idx_offset,sez_offset;
+ boolean error;
+
+ error=false;
+
+ assign(indexfile,"avalot.idx"); assign(sezfile,"avalot.sez");
+
+ reset(indexfile,1);
+ seek(indexfile,(ord(upcase(block))-65)*2);
+ blockread(indexfile,idx_offset,2);
+ if (idx_offset==0) error=true;
+ seek(indexfile,idx_offset+point*2);
+ blockread(indexfile,sez_offset,2);
+ if (sez_offset==0) error=true;
+ close(indexfile);
+
+ went_ok=! error;
+
+ if (error)
+ {
+ if (report_dixi_errors)
+ display(string('\7')+"Error accessing scroll "+block+strf(point));
+ return;
+ }
+
+ reset(sezfile,1);
+ seek(sezfile,sez_offset);
+ blockread(sezfile,bufsize,2);
+ blockread(sezfile,buffer,bufsize);
+ close(sezfile);
+ unskrimble();
+
+ if (bubbling) do_the_bubble();
+
+ calldrivers;
+}
+
+void speech(byte who, byte subject)
+{
+ untyped_file indexfile,sezfile;
+ word idx_offset,sez_offset,next_idx_offset;
+
+ if (subject==0)
+ { /* No subject. */
+ bubbling=true; report_dixi_errors=false;
+ dixi('s',who);
+ bubbling=false; report_dixi_errors=true;
+ } else
+ { /* Subject given. */
+ assign(indexfile,"converse.avd"); assign(sezfile,"avalot.sez");
+
+ went_ok=false; /* Assume that until we know otherwise. */
+ reset(indexfile,1);
+ seek(indexfile,who*2-2);
+ blockread(indexfile,idx_offset,2);
+ blockread(indexfile,next_idx_offset,2);
+
+ if ((idx_offset==0) ||
+ ((((next_idx_offset-idx_offset) / 2)-1) < subject)) return;
+
+ seek(indexfile,idx_offset+subject*2);
+ /*$I-*/
+ blockread(indexfile,sez_offset,2);
+ if ((sez_offset==0) || (ioresult!=0)) return;
+ /*$I+*/
+ close(indexfile);
+
+ reset(sezfile,1);
+ seek(sezfile,sez_offset);
+ blockread(sezfile,bufsize,2);
+ blockread(sezfile,buffer,bufsize);
+ close(sezfile);
+
+ unskrimble();
+ do_the_bubble();
+
+ calldrivers;
+ went_ok=true;
+ }
+}
+
+void talkto(byte whom)
+{
+ byte fv;
+ boolean no_matches;
+
+ if (person==pardon)
+ {
+ person=chr(subjnumber);
+ subjnumber=0;
+ }
+
+ if (subjnumber==0)
+ switch (chr(whom)) {
+ case pspludwick:
+
+ if ((dna.lustie_is_asleep) & (~ dna.obj[potion]))
+ {
+ dixi('q',68);
+ dna.obj[potion]=true;
+ objectlist; points(3); return;
+ } else
+ {
+ if (dna.talked_to_crapulus)
+ switch (dna.given2spludwick) { /* Spludwick - what does he need? */
+ /* 0 - let it through to use normal routine. */
+ case RANGE_2(1,2): {
+ display(string("Can you get me ")+
+ get_better(spludwick_order[dna.given2spludwick])+", please?"+
+ "\232\2");
+ return;
+ }
+ break;
+ case 3: {
+ dixi('q',30); /* need any help with the game? */
+ return;
+ }
+ break;
+ }
+ else {
+ dixi('q',42); /* Haven't talked to Crapulus. Go and talk to him. */
+ return;
+ }
+ }
+ break;
+
+ case pibythneth: if (dna.givenbadgetoiby)
+ {
+ dixi('q',33); /* Thanks a lot! */
+ return; /* And leave the proc. */
+ }
+ break; /* Or... just continue, 'cos he hasn't got it. */
+ case pdogfood: if (dna.wonnim)
+ { /* We've won the game. */
+ dixi('q',6); /* "I'm Not Playing!" */
+ return; /* Zap back. */
+ } else dna.asked_dogfood_about_nim=true;
+ break;
+ case payles: if (~ dna.ayles_is_awake)
+ {
+ dixi('q',43); /* He's fast asleep! */
+ return;
+ } else
+ if (~ dna.given_pen_to_ayles)
+ {
+ dixi('q',44); /* Can you get me a pen, Avvy? */
+ return;
+ }
+ break;
+
+ case pjacques: { dixi('q',43); return; } break;
+ case pgeida: if (dna.geida_given_potion)
+ dna.geida_follows=true; else
+ {
+ dixi('u',17);
+ return;
+ }
+ break;
+ case pspurge: if (~ dna.sitting_in_pub)
+ {
+ dixi('q',71); /* Try going over and sitting down. */
+ return;
+ } else
+ {
+ if (spurge_talk<5) spurge_talk += 1;
+ if (spurge_talk>1)
+ { /* no. 1 falls through */
+ dixi('q',70+spurge_talk);
+ return;
+ }
+ }
+ break;
+ } else /* On a subject. Is there any reason to block it? */
+ switch (chr(whom)) {
+ case payles: if (~ dna.ayles_is_awake)
+ {
+ dixi('q',43); /* He's fast asleep! */
+ return;
+ }
+ break;
+ }
+
+ if (whom>149) whom -= 149;
+
+ no_matches=true;
+ for( fv=1; fv <= numtr; fv ++)
+ if (tr[fv].a.accinum==whom)
+ {
+ display(string('\23')+chr(fv+48)+'\4');
+ no_matches=false;
+ flush();
+ }
+
+ if (no_matches) display("\23\23\4");
+
+ speech(whom,subjnumber);
+ if (! went_ok) /* File not found! */
+ dixi('n',whom);
+
+ if (subjnumber==0)
+ switch (chr(whom+149)) {
+ case pcrapulus:
+ { /* Crapulus: get the badge - first time only */
+ dna.obj[badge]=true;
+ objectlist;
+ dixi('q',1); /* Circular from Cardiff. */
+ dna.talked_to_crapulus=true;
+
+ whereis[pcrapulus]=177; /* Crapulus walks off. */
+
+ tr[2].vanishifstill=true;
+ tr[2].walkto(4); /* Walks away. */
+
+ points(2);
+ }
+ break;
+
+ }
+}
+
+
diff --git a/engines/avalanche/visa.h b/engines/avalanche/visa.h
new file mode 100644
index 0000000000..8b79d6be18
--- /dev/null
+++ b/engines/avalanche/visa.h
@@ -0,0 +1,9 @@
+#ifndef __visa_h__
+#define __visa_h__
+
+
+void dixi(char block, byte point);
+
+void talkto(byte whom);
+
+#endif
diff --git a/engines/avalanche/visatest.cpp b/engines/avalanche/visatest.cpp
new file mode 100644
index 0000000000..52970adacb
--- /dev/null
+++ b/engines/avalanche/visatest.cpp
@@ -0,0 +1,84 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+
+
+char block;
+word point;
+
+array<1,2000,char> result;
+word result_len;
+
+void unskrimble()
+{
+ word fv;
+
+ for( fv=1; fv <= 2000; fv ++) result[fv]=(char)((~(ord(result[fv])-fv)) % 256);
+}
+
+void visa_get_scroll(char block, word point)
+{
+ untyped_file indexfile,sezfile;
+ word idx_offset,sez_offset;
+
+ assign(indexfile,"avalot.idx"); assign(sezfile,"avalot.sez");
+
+ reset(indexfile,1);
+ seek(indexfile,(ord(upcase(block))-65)*2);
+ blockread(indexfile,idx_offset,2);
+ seek(indexfile,idx_offset+point*2);
+ blockread(indexfile,sez_offset,2);
+ close(indexfile);
+
+ reset(sezfile,1);
+ seek(sezfile,sez_offset);
+ blockread(sezfile,result_len,2);
+ blockread(sezfile,result,result_len);
+ close(sezfile);
+ unskrimble();
+}
+
+void access_get_scroll(char block, word point)
+{
+ string x;
+ untyped_file f;
+
+ str(point,x);
+ x=string('S')+block+x+".RAW";
+ assign(f,x);
+ reset(f,1);
+ result_len=filesize(f);
+ blockread(f,result,result_len);
+ close(f);
+}
+
+void display_it()
+{
+ word fv;
+
+ for( fv=1; fv <= result_len; fv ++) output << result[fv];
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ do {
+ output << NL;
+ output << NL;
+ output << "Block?"; input >> block >> NL;
+ output << "Point?"; input >> point >> NL;
+
+ output << "ACCESS reports (this one is always correct):" << NL;
+ output << NL;
+ access_get_scroll(block,point);
+ display_it();
+
+ output << NL; output << NL;
+ output << "VISA reports:" << NL;
+ output << NL;
+ visa_get_scroll(block,point);
+ display_it();
+ } while (!false);
+ return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/waver.cpp b/engines/avalanche/waver.cpp
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/engines/avalanche/waver.cpp
diff --git a/engines/avalanche/xf_gover.cpp b/engines/avalanche/xf_gover.cpp
new file mode 100644
index 0000000000..67bb5ff561
--- /dev/null
+++ b/engines/avalanche/xf_gover.cpp
@@ -0,0 +1,95 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+
+void load()
+{
+ byte a; /*absolute $A000:1200;*/ byte bit; untyped_file f;
+;
+ assign(f,"avagame.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a,12080);
+ }
+ close(f);
+ bit=getpixel(0,0);
+}
+
+void gfx()
+{
+ integer gd,gm;
+
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+}
+
+void blit(integer x1,integer y1,integer x2,integer y2,integer x3,integer y3)
+{
+ pointer p,q; word s;
+
+ mark(q);
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+ putimage(x3,y3,p,0);
+
+ release(q);
+}
+
+void copy_hammer()
+{
+ blit(274,47,311,67,92,10);
+}
+
+void do_text()
+{
+ settextjustify(1,1); setcolor(0);
+ settextstyle(2,0,4);
+ setusercharsize(120,100,100,100);
+ outtextxy(112,32,"Thorsoft of Letchworth presents");
+ blit(3,30,218,31,4,30);
+ blit(4,35,219,38,3,35);
+}
+
+void dump_to_file(byte x1,byte y1,byte x2,byte y2, string fn)
+{
+ byte y,bit;
+ untyped_file f;
+
+ assign(f,fn);
+ rewrite(f,1);
+
+ for( y=y1; y <= y2; y ++)
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockwrite(f,mem[0xa000*y*80+x1],x2-x1);
+ }
+
+ close(f);
+
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ gfx();
+ load();
+
+ setfillstyle(1,7);
+ bar(2,10,219,37);
+ bar(0,0,1,200);
+ bar(220,0,250, 88);
+ bar(0,88,213,147);
+ bar(622,88,640,147);
+ copy_hammer();
+ do_text();
+
+ dump_to_file( 0,10,28,86,"about.avd");
+ dump_to_file(26,88,78,147,"gameover.avd");
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/xf_help.cpp b/engines/avalanche/xf_help.cpp
new file mode 100644
index 0000000000..1f8063952e
--- /dev/null
+++ b/engines/avalanche/xf_help.cpp
@@ -0,0 +1,86 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+/*#include "Tommys.h"*/
+
+
+const integer max_pages = 34;
+
+byte fv;
+text i;
+untyped_file o;
+string x;
+char t;
+byte p,w;
+
+array<0,max_pages,word> where;
+
+void out(string x)
+{
+ byte fz;
+
+ for( fz=1; fz <= length(x); fz ++)
+ x[fz]=chr(ord(x[fz]) ^ 177);
+ blockwrite(o,x[0],1);
+ blockwrite(o,x[1],length(x));
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ assign(o,"help.avd");
+ rewrite(o,1);
+
+ blockwrite(o,where,sizeof(where));
+
+ for( fv=0; fv <= max_pages; fv ++)
+ {
+ where[fv]=filepos(o);
+
+ assign(i,string('h')+strf(fv)+".raw");
+ reset(i);
+
+ i >> x >> NL; /* Title. */
+ out(x);
+
+ i >> p >> NL; /* Picture. */
+ blockwrite(o,p,1);
+
+ do {
+ i >> x >> NL;
+ out(x);
+ } while (!(x=='!'));
+
+ while (! eof(i))
+ {
+ i >> x >> NL;
+ if (x=='-')
+ { /* Null point */
+ t='\0'; p=0; w=177;
+ } else
+ { /* Has a point. */
+ i >> t >> NL;
+ i >> p >> NL;
+ i >> w >> NL;
+ }
+
+ blockwrite(o,t,1);
+ blockwrite(o,p,1);
+ blockwrite(o,w,1);
+ }
+
+ t='\261';
+ blockwrite(o,t,1);
+ blockwrite(o,p,1);
+ blockwrite(o,w,1);
+
+ close(i);
+
+ }
+
+ seek(o,0); blockwrite(o,where,sizeof(where));
+
+ close(o);
+ return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/xf_visa.cpp b/engines/avalanche/xf_visa.cpp
new file mode 100644
index 0000000000..888df55d4e
--- /dev/null
+++ b/engines/avalanche/xf_visa.cpp
@@ -0,0 +1,178 @@
+#include "ptoc.h"
+
+
+/*#include "Crt.h"*/
+/*#include "Dos.h"*/
+
+/*$R+*/
+
+const varying_string<9> used = "DNPQSTUXZ";
+
+const varying_string<12> header = string("Avalot Sez:")+'\32';
+
+untyped_file sez,infile;
+searchrec s;
+
+matrix<'A','Z',0,99,word> positions;
+array<'A','Z',word> maxlen;
+
+matrix<1,50,0,255,word> speak_positions;
+array<1,50,word> speak_maxlen;
+
+array<1,2000,char> data;
+word data_length;
+
+byte fv;
+
+byte numeric_bit()
+{
+ varying_string<5> x; integer e; byte result;
+
+ byte numeric_bit_result;
+ x=copy(s.name,3,pos(".",s.name)-3);
+ val(x,result,e);
+ if (e!=0)
+ {
+ output << "NUMERIC ERROR: " << s.name << '/' << x << NL;
+ exit(255);
+ }
+ numeric_bit_result=result;
+ return numeric_bit_result;
+}
+
+byte speak_left()
+{
+ string x; integer e; byte result;
+
+ byte speak_left_result;
+ x=copy(s.name,3,pos(".",s.name)-3);
+ x=copy(x,1,pos("-",x)-1);
+ val(x,result,e);
+ if (e!=0)
+ {
+ output << "NUMERIC ERROR (left): " << s.name << '/' << x << NL;
+ exit(255);
+ }
+ speak_left_result=result;
+ return speak_left_result;
+}
+
+byte speak_right()
+{
+ string x; integer e; byte result;
+
+ byte speak_right_result;
+ x=copy(s.name,3,pos(".",s.name)-3);
+ x=copy(x,pos("-",x)+1,255);
+ val(x,result,e);
+ if (e!=0)
+ {
+ output << "NUMERIC ERROR (right): " << s.name << '/' << x << NL;
+ exit(255);
+ }
+ speak_right_result=result;
+ return speak_right_result;
+}
+
+void write_out()
+{
+ array<'A','Z',word> points;
+ array<1,50,word> speak_points;
+ untyped_file outf;
+ byte fv;
+
+ fillchar(points,sizeof(points),'\0');
+ fillchar(speak_points,sizeof(speak_points),'\0');
+
+ assign(outf,"v:avalot.idx");
+ rewrite(outf,1);
+ blockwrite(outf,points,sizeof(points));
+
+ for( fv=1; fv <= length(used); fv ++)
+ {
+ points[used[fv-1]]=filepos(outf);
+ blockwrite(outf,positions[used[fv-1]],maxlen[used[fv-1]]*2+2);
+ }
+
+ seek(outf,0);
+ blockwrite(outf,points,sizeof(points));
+
+ close(outf);
+
+ /* --- now the speech records --- */
+
+ assign(outf,"v:converse.avd");
+ rewrite(outf,1);
+ blockwrite(outf,speak_points,sizeof(speak_points));
+
+ for( fv=1; fv <= 15; fv ++)
+ {
+ speak_points[fv]=filepos(outf);
+
+ blockwrite(outf,speak_positions[fv],speak_maxlen[fv]*2+2);
+ }
+
+ seek(outf,0);
+ blockwrite(outf,speak_points,sizeof(speak_points));
+
+ close(outf);
+}
+
+void skrimble()
+{
+ word fv;
+
+ for( fv=1; fv <= 2000; fv ++) data[fv]=(char)((~(ord(data[fv]))+fv) % 256);
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ fillchar(positions,sizeof(positions),'\0');
+ fillchar(maxlen,sizeof(maxlen),'\0');
+
+ clrscr;
+
+ assign(sez,"v:avalot.sez");
+ rewrite(sez,1);
+ blockwrite(sez,header[1],12);
+
+ findfirst("s*.raw",anyfile,s);
+ while (doserror==0)
+ {
+ assign(infile,s.name);
+ reset(infile,1);
+ blockread(infile,data,2000,data_length);
+ close(infile);
+
+ clrscr;
+ if (pos("-",s.name)==0)
+ { /* Not a speech record. */
+ output << s.name << format(numeric_bit(),10) << NL;
+
+ positions[s.name[2]][numeric_bit()]=filepos(sez);
+ if (maxlen[s.name[2]]<(unsigned char)numeric_bit()) maxlen[s.name[2]]=numeric_bit();
+
+ } else
+ { /* A speech record. */
+ output << s.name << format(speak_left(),10) << format(speak_right(),10) << " SR" << NL;
+
+ speak_positions[speak_left()][speak_right()]=filepos(sez);
+ if (speak_maxlen[speak_left()]<(unsigned char)speak_right())
+ speak_maxlen[speak_left()]=speak_right();
+ }
+
+ skrimble();
+
+ blockwrite(sez,data_length,2);
+ blockwrite(sez,data,data_length);
+
+ findnext(s);
+ clreol;
+ }
+
+ close(sez);
+
+ write_out();
+ return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/engines/avalanche/xfbutton.cpp b/engines/avalanche/xfbutton.cpp
new file mode 100644
index 0000000000..dfbaf5e559
--- /dev/null
+++ b/engines/avalanche/xfbutton.cpp
@@ -0,0 +1,62 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+
+integer x,y;
+untyped_file f,out;
+
+void load() /* Load2, actually */
+{
+ byte a0; /*absolute $A000:800;*/
+ byte bit;
+ untyped_file f;
+ integer gd,gm;
+
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+
+ assign(f,"d:butnraw.avd"); reset(f,1);
+ seek(f,177);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a0,12080);
+ }
+ close(f);
+ bit=getpixel(0,0);
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2) /* s=930 */
+{
+ word s; pointer p;
+
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+ putimage(0,0,p,0);
+ blockwrite(out,p,s);
+ freemem(p,s);
+ rectangle(x1,y1,x2,y2);
+}
+
+int main(int argc, const char* argv[])
+{
+ pio_initialize(argc, argv);
+ assign(f,"d:butnraw.avd");
+ assign(out,"v:buttons.avd"); rewrite(out,1);
+ load();
+ for( x=0; x <= 5; x ++)
+ for( y=0; y <= 3; y ++)
+ {
+ if (!
+ (((x==1) && (y==0))
+ || ((x==4) && (y==2))
+ || ((y==3) && (x>2) && (x<5))))
+ {
+ input >> NL;
+ grab(100+x*83,51+y*22,180+x*83,71+y*22);
+ }
+ }
+ close(out);
+ return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/xfghost.cpp b/engines/avalanche/xfghost.cpp
new file mode 100644
index 0000000000..8809bb58a3
--- /dev/null
+++ b/engines/avalanche/xfghost.cpp
@@ -0,0 +1,246 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+
+
+const array<1,44,char> chunkheader =
+string("Spooky file! Nearly a Chunk... (c) MT.")+'\32'+'\261'+'\x30'+'\x1'+'\x75'+'\261';
+
+const integer n = -1; /* "No change" in new-whatever */
+
+const integer aa = -2; /* This is an aargh. */
+
+const integer aargh_x_ofs = -177; const integer aargh_y_ofs = 52;
+
+enum flavourtype {ch_ega,ch_bgi,ch_natural,ch_two,ch_one, last_flavourtype};
+
+struct chunkblocktype {
+ flavourtype flavour;
+ integer x,y;
+ integer xl,yl;
+ longint size;
+};
+
+integer gd,gm,x,y;
+untyped_file f; byte bit;
+byte a; /*absolute $A000:0;*/
+palettetype cc;
+char r; text t;
+word s; pointer p;
+
+untyped_file chunkfile;
+chunkblocktype cb;
+
+pointer a_p; word a_s;
+
+void open_chunk()
+{;
+ assign(chunkfile,"v:spooky.avd");
+ rewrite(chunkfile,1);
+ blockwrite(chunkfile,chunkheader,sizeof(chunkheader));
+}
+
+void close_chunk()
+{;
+ close(chunkfile);
+}
+
+void grab(integer x1,integer y1,integer x2,integer y2, flavourtype how, integer newx,integer newy)
+{
+ pointer p;
+ word s;
+ integer y;
+ byte bit;
+
+;
+#ifndef DRYRUN
+ {;
+ cb.flavour=how;
+ switch (newx) {
+ case n: cb.x=x1; break;
+ case aa: cb.x=x1+aargh_x_ofs; break;
+ default: cb.x=newx;
+ }
+
+ switch (newy) {
+ case n: cb.y=y1; break;
+ case aa: cb.y=y1+aargh_y_ofs; break;
+ default: cb.y=newy;
+ }
+
+ cb.xl=x2-x1;
+ if (set_of_enum(flavourtype)::of(ch_ega,ch_one,ch_two, eos).has(how)) cb.xl=((cb.xl+7) / 8)*8;
+ cb.yl=y2-y1;
+ }
+
+ if (how!=ch_natural)
+ {;
+ s=imagesize(x1,y1,x2,y2);
+ getmem(p,s);
+ getimage(x1,y1,x2,y2,p);
+ }
+
+ rectangle(x1,y1,x2,y2);
+
+ switch (how) {
+ case ch_bgi: cb.size=s; break;
+ }
+
+ blockwrite(chunkfile,cb,sizeof(cb));
+
+ switch (how) {
+ case ch_bgi: blockwrite(chunkfile,p,s); break;
+ case ch_ega: {;
+ setactivepage(1);
+ cleardevice();
+ putimage(0,0,p,0);
+ setactivepage(0);
+
+ for( bit=0; bit <= 3; bit ++)
+ for( y=0; y <= cb.yl; y ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4;
+ port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockwrite(chunkfile,mem[0xa400*y*80],cb.xl / 8);
+ }
+
+ y=getpixel(0,0);
+ }
+ break;
+ case ch_two: {; /* Same as EGA, but with only 2 planes. */
+ setactivepage(1);
+ cleardevice();
+ putimage(0,0,p,0);
+ setactivepage(0);
+
+ for( bit=2; bit <= 3; bit ++) /* << Bit to grab? */
+ for( y=0; y <= cb.yl; y ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4;
+ port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockwrite(chunkfile,mem[0xa400*y*80],cb.xl / 8);
+ }
+
+ y=getpixel(0,0);
+ }
+ break;
+ case ch_one: {; /* ...but with only one plane! */
+ setactivepage(1);
+ cleardevice();
+ putimage(0,0,p,0);
+ setactivepage(0);
+
+ for( bit=3; bit <= 3; bit ++)
+ for( y=0; y <= cb.yl; y ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4;
+ port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockwrite(chunkfile,mem[0xa400*y*80],cb.xl / 8);
+ }
+
+ y=getpixel(0,0);
+ }
+ break;
+ }
+
+ freemem(p,s); #endif
+ rectangle(x1,y1,x2,y2);
+
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+#ifndef DRYRUN
+ open_chunk();
+#endif
+
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ assign(f,"c:\\sleep4\\colour.ptx"); reset(f,1);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ blockread(f,a,16000); /* 28000 */
+ }
+ close(f);
+
+ setwritemode(xorput);
+
+ /* Grab the big ghost. */
+
+ grab( 0, 0,160, 65,ch_two,n,n); /* First column, */
+ grab( 0, 67,172,127,ch_two,n,n);
+ grab( 0,132,158,190,ch_two,n,n);
+
+ a_s=imagesize(349,36,361,43); getmem(a_p,a_s);
+ getimage(349,36,361,43,a_p);
+ setfillstyle(1,0); bar(349,36,361,43);
+
+ grab(173, 66,347,124,ch_two,n,n); /* Second column. */
+ grab(173, 6,352, 64,ch_two,n,n);
+
+ putimage(349,36,a_p,0);
+
+ /* Grab Avvy's eyes and the exclamation mark. */
+
+ grab(605, 10,620, 12,ch_bgi,n,n); /* Eyes looking left */
+ grab(622, 10,638, 12,ch_bgi,n,n); /* Ditto looking right (eye eye, sir) */
+ grab(611, 0,616, 5,ch_bgi,n,n); /* ! */
+
+ /* Grab the cobweb. */
+
+ grab(535, 25,639, 75,ch_one,n,0);
+ /* ^^^ Interesting point here: the ch_EGA save routine pads with black
+ space to the RIGHT of the object. Since this cobweb needs to be right-
+ justified, we must decrease x1 until xl is a multiple of 8. */
+
+ /* Grab Mark's signature. */
+
+ grab(462, 61,525, 65,ch_ega,576,195);
+
+ /* Grab the open door. */
+
+ grab(180,132,294,180,ch_ega,520,127);
+
+ /* Grab the bat. */
+
+ grab(354, 0,474, 28,ch_bgi,n,n);
+ grab(484, 0,526, 23,ch_bgi,n,n);
+ grab(542, 2,564, 22,ch_bgi,n,n);
+
+ /* Grab the big fade-in face. */
+
+ grab(350, 71,420,105,ch_ega,n,n); /* Top line. */
+ grab(421, 71,491,105,ch_ega,n,n);
+
+ grab(350,107,419,141,ch_ega,n,n); /* Second line. */
+ grab(421,107,490,141,ch_ega,n,n);
+
+ grab(350,143,420,177,ch_ega,n,n); /* Third line. */
+ grab(422,143,489,177,ch_ega,n,n);
+
+ /* Grab the "AARGH!" */
+
+ grab(349, 36,361, 43,ch_bgi,aa,aa); /* A */
+ grab(366, 31,385, 46,ch_bgi,aa,aa); /* Aa */
+ grab(394, 34,415, 52,ch_bgi,aa,aa); /* Aar */
+ grab(428, 33,457, 57,ch_bgi,aa,aa); /* Aarg */
+ grab(471, 30,508, 59,ch_bgi,aa,aa); /* Aargh */
+ grab(524, 30,524, 58,ch_bgi,aa,aa); /* Aargh! */
+
+ for( gd=0; gd <= 4; gd ++)
+ grab(509, 76+gd*22,551, 96+gd*22,ch_bgi,n,n); /* The big green eyes. */
+
+ for( gd=5; gd >= 0; gd --)
+ grab(181+gd*34,186,214+gd*34,199,ch_bgi,n,n); /* The red greldet. */
+
+ for( gd=0; gd <= 5; gd ++)
+ grab(390+gd*34,186,423+gd*34,199,ch_bgi,n,n); /* The blue greldet. */
+
+#ifndef DRYRUN
+ close_chunk();
+#endif
+return EXIT_SUCCESS;
+}
diff --git a/engines/avalanche/zapdraw.cpp b/engines/avalanche/zapdraw.cpp
new file mode 100644
index 0000000000..5645fa9330
--- /dev/null
+++ b/engines/avalanche/zapdraw.cpp
@@ -0,0 +1,38 @@
+#include "ptoc.h"
+
+
+#include "graph.h"
+/*#include "Crt.h"*/
+/*#include "Dos.h"*/
+
+
+untyped_file f;
+byte bit;
+byte a; /*absolute $A000:0; */
+integer gd,gm;
+
+void graphmode(integer mode)
+{
+ registers regs;
+;
+ regs.ax=(mode % 0x100);
+ intr(0x10,regs);
+}
+
+int main(int argc, const char* argv[])
+{pio_initialize(argc, argv);
+;
+ gd=3; gm=0; initgraph(gd,gm,"c:\\bp\\bgi");
+ assign(f,"d:avltzap.raw"); reset(f,1);
+ for( bit=0; bit <= 3; bit ++)
+ {;
+ port[0x3c4]=2; port[0x3ce]=4; port[0x3c5]=1 << bit; port[0x3cf]=bit;
+ for( gd=0; gd <= 199; gd ++)
+ blockread(f,mem[0xa000*gd*80],40); /* 28000 */
+ }
+ close(f);
+ setwritemode(xorput);
+ rectangle( 0, 0, 5, 8);
+ rectangle( 0, 10, 27, 19);
+return EXIT_SUCCESS;
+}