2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation, either version 3 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "SDL_endian.h"
31 #include "gameglobals.h"
40 ////////////////////////////////////////////////////////////////////////////////
41 static SDL_Surface
*loadCFScreen (const char *fname
, SDL_Surface
*old
, int w
, int h
, int chained
) {
43 static Uint8 pal
[256][3];
44 static Uint32 opal
[256];
45 static Uint8 scr
[64000];
47 uint8_t *diskdata
= tryDiskFile(fname
, &rsz
);
49 if (diskdata
== NULL
) return old
;
50 if (rsz
< w
*h
+(chained
>= 0 ? 768 : 0)) { free(diskdata
); return old
; }
52 new = createSurface(320*2, 200*2);
53 if (!new) { free(diskdata
); return old
; }
55 for (int dy
= 0; dy
< 200; ++dy
) {
56 for (int dx
= 0; dx
< 320; ++dx
) {
57 putPixel2x(new, dx
, dy
, 0);
61 memcpy(scr
, diskdata
, w
*h
);
62 if (chained
>= 0) memcpy(pal
, diskdata
+w
*h
, 768);
66 memcpy(opal
, palette
, 256*4);
67 for (int f
= 0; f
< 256; ++f
) {
69 if (pal
[f
][0] != 0) pal
[f
][0] |= 3;
71 if (pal
[f
][1] != 0) pal
[f
][1] |= 3;
73 if (pal
[f
][2] != 0) pal
[f
][2] |= 3;
74 palette
[f
] = SDL_MapRGB(screen
->format
, pal
[f
][0], pal
[f
][1], pal
[f
][2]);
79 for (int dy
= 0; dy
< h
; ++dy
) {
80 for (int dx
= 0; dx
< w
/4; ++dx
) {
81 for (int c
= 0; c
< 4; ++c
) {
82 putPixel2x(new, dx
*4+c
, dy
, scr
[dy
*(w
/4)+(w
*h
)/4*c
+dx
]);
87 for (int dy
= 0; dy
< h
; ++dy
) {
88 for (int dx
= 0; dx
< w
; ++dx
) {
89 putPixel2x(new, dx
, dy
, scr
[dy
*w
+dx
]);
94 memcpy(palette
, opal
, 256*4);
100 ////////////////////////////////////////////////////////////////////////////////
101 static int loadFont (void) {
103 uint8_t *buf
= loadResFile(&resfile
, 92, &sz
);
105 if (buf
== NULL
) return -1;
106 if (sz
!= 256*8) { free(buf
); return -1; }
107 memcpy(font
, buf
, 256*8);
113 static int loadPalette (void) {
115 uint8_t *buf
= loadResFile(&resfile
, 83, &sz
);
117 if (buf
== NULL
) return -1;
118 if (sz
!= 768) { free(buf
); return -1; }
119 for (int f
= 0; f
< 768; ++f
) {
121 if (buf
[f
] != 0) buf
[f
] |= 3;
123 for (int f
= 0; f
< 256; ++f
) palette
[f
] = SDL_MapRGB(screen
->format
, buf
[f
*3+0], buf
[f
*3+1], buf
[f
*3+2]);
129 static SDL_Surface
*loadImage (ResFile
*resfile
, int idx
) {
134 img
= loadResFile(resfile
, idx
, &sz
);
135 if (img
== NULL
) return NULL
;
136 if (sz
< 320*200) { free(img
); return NULL
; }
137 res
= createSurface(320*2, 200*2);
138 if (res
== NULL
) { free(img
); return NULL
; }
139 SDL_SetColorKey(res
, 0, 0); // clear colorkey info (it's the fullscreen image after all!)
140 for (int f
= 0; f
< 320*200; ++f
) putPixel2x(res
, f
%320, f
/320, img
[f
]);
146 // return # of sprites loaded or <0 on error
147 static int loadSpriteBank (SpriteBank
*bank
, ResFile
*resfile
, int idx
) {
151 if ((buf
= loadResFile(resfile
, idx
, &sz
)) == NULL
) return -1;
152 if (sz
< 3) { free(buf
); return -1; }
156 while (pos
+4 <= sz
) {
157 int h
= ((Uint32
)buf
[pos
+0])+256*((Uint32
)buf
[pos
+1]);
158 int w
= ((Uint32
)buf
[pos
+2])+256*((Uint32
)buf
[pos
+3]);
161 if (h
> 0 && w
> 0) {
162 SDL_Surface
*s0
= createSurface(w
*2, h
*2);
163 SDL_Surface
*s1
= createSurface(w
*2, h
*2);
165 if (!s0
|| !s1
) { free(buf
); return -1; }
167 for (int y
= 0; y
< h
; ++y
) {
168 for (int x
= 0; x
< w
; ++x
) {
170 putPixel2x(s0
, x
, y
, buf
[pos
]);
171 putPixel2x(s1
, w
-x
-1, y
, buf
[pos
]);
176 bank
->spr
[bank
->count
][0] = s0
;
177 bank
->spr
[bank
->count
][1] = s1
;
187 static void freeSpriteBank (SpriteBank *bank) {
188 for (int f = bank->count-1; f >= 0; --f) {
189 SDL_FreeSurface(bank->spr[f][1]);
190 SDL_FreeSurface(bank->spr[f][0]);
196 ////////////////////////////////////////////////////////////////////////////////
197 static void quitCleanupRes (void) {
199 deinitResFile(&resfile
);
200 //for (int f = 0; f < sizeof(banks)/sizeof(SpriteBank); ++f) freeSpriteBank(&banks[f]);
204 ////////////////////////////////////////////////////////////////////////////////
205 static int awishRST (int tid
, int opcode
, int argc
, int argv
[], int *argp
[]) {
206 vmGVars
[GVAR_RST_RESULT
] = 0;
208 if (argv
[0] == CONST_FRST_ML_TITLE
) {
210 } else if (argv
[0] == CONST_FRST_ML_GAME
) {
212 } else if (argv
[0] == CONST_FRST_MINIMAP
) {
214 } else if (argv
[0] == CONST_FRST_LOAD_LEVEL
) {
216 if (vmLoadArgs(tid
, 2, argv
, argp
, argc
, argv
, argp
) != 0) fatal("out of args");
217 vmGVars
[GVAR_RST_RESULT
] = loadLevel(argv
[1]);
218 } else if (argv
[0] == CONST_FRST_DEBUG_PRINT_STR
) {
219 int pos
= 0, len
= 0;
227 dolen
: if (pos
>= 0) {
228 while (pos
< vmCodeSize
&& vmCode
[pos
+len
]) ++len
;
237 for (; len
> 0; --len
, ++pos
) if (pos
>= 0 && pos
< vmCodeSize
) fputc(vmCode
[pos
], stderr
);
239 } else if (argv
[0] == CONST_FRST_DEBUG_PRINT_NUM
) {
241 case 1: argv
[1] = vmPop(tid
); // fallthru
242 case 2: if (goobers
) fprintf(stderr
, "%d", argv
[1]); break;
243 case 3: if (goobers
) fprintf(stderr
, "%d,%d", argv
[1], argv
[2]); break;
246 fatal("invalid RST: %d", argv
[0]);
252 ////////////////////////////////////////////////////////////////////////////////
253 static int checkLevelCode (const char *t
) {
256 if (!t
|| !t
[0]) return -1;
257 ctrd
= vmNewThread(0);
258 for (int level
= 0; level
< vmGVars
[GVAR_MAX_LEVEL
]; ++level
) {
259 //fprintf(stderr, "%d/%d\n", level+1, vmGVars[GVAR_MAX_LEVEL]);
261 if (vmExecuteBSR(ctrd
, CODE_ENTRY_GET_LEVEL_CODE
, 0) == 0) {
262 int pos
= vmGVars
[GVAR_LEVEL_CODE_OFS
], len
= vmGVars
[GVAR_LEVEL_CODE_LEN
], ok
= 1;
264 if (strlen(t
) == len
&& pos
>= 0 && len
> 0 && pos
+len
<= vmCodeSize
) {
265 //fwrite(vmCode+pos, len, 1, stderr);
266 //fprintf(stderr, " [%s]\n", t);
267 for (int f
= 0; f
< len
; ++f
) {
268 //fprintf(stderr, "%c %c\n", tolower(t[f]), tolower(vmCode[pos+f]));
269 if (tolower(t
[f
]) != tolower(vmCode
[pos
+f
])) { ok
= 0; break; }
272 if (goobers
) fprintf(stderr
, "found code for level #%02d\n", level
+1);
277 if (goobers
) fprintf(stderr
, "sorry!\n");
286 ////////////////////////////////////////////////////////////////////////////////
288 # include "cmdline.c"
292 ////////////////////////////////////////////////////////////////////////////////
293 int main (int argc
, char *argv
[]) {
300 for (int f
= 1; f
< argc
; ++f
) {
301 if (strcmp(argv
[f
], "-goobers") == 0) goobers
= 1;
302 else if (strcmp(argv
[f
], "-dat") == 0) datfirst
= 1;
304 for (int c
= f
+1; c
< argc
; ++c
) argv
[c
-1] = argv
[c
];
309 initResFile(&resfile
, "RESOURCE.DAT");
310 atexit(quitCleanupRes
);
312 if (loadFont() != 0) {
313 fprintf(stderr
, "FATAL: can't load font!\n");
320 if (loadPalette() != 0) {
321 fprintf(stderr
, "FATAL: can't load palette!\n");
328 lockSurface(&lock
, screen
);
329 drawString(screen
, "loading...", 2, 200-9, 1);
330 unlockSurface(&lock
);
334 for (int f
= 0; f
< 8; ++f
) {
335 if ((backs
[(f
+1)%8] = loadImage(&resfile
, f
)) == NULL
) {
336 fprintf(stderr
, "FATAL: can't load image #%d!\n", f
);
341 backs
[0] = loadCFScreen("CFTITLE.DAT", backs
[0], 320, 200, 1);
342 backs
[0] = loadCFScreen("cftitle.dat", backs
[0], 320, 200, 1);
344 memset(banks
, 0, sizeof(banks
));
345 for (int f
= 84; f
<= 90; ++f
) {
346 if (loadSpriteBank(&banks
[f
], &resfile
, f
)) {
347 fprintf(stderr
, "FATAL: can't load sprint bank #%d!\n", f
);
352 if (loadVMCode(&resfile
)) {
353 fprintf(stderr
, "FATAL: can't load VM code!\n");
358 memset(vmGVars
, 0, sizeof(vmGVars
));
359 //vmGVars[GVAR_KEY_QUIT] = 0;
360 //vmGVars[GVAR_KEY_START] = 0;
361 vmGVars
[GVAR_GOOBERS
] = goobers
;
363 if (vmInitialize() != 0) fatal("can't init VM");
364 vmSetPC(0, CODE_ENTRY_TITLE
);
366 if (vmExecuteBSR(0, CODE_ENTRY_MAIN_INIT
, 0) != 0) fatal("can't initialize game");
367 if (goobers
) fprintf(stderr
, "MAX LEVEL: %d\n", vmGVars
[GVAR_MAX_LEVEL
]);
371 for (int f
= 1; f
< argc
; ++f
) {
372 int lvl
= checkLevelCode(argv
[f
]);
375 vmGVars
[GVAR_START_LEVEL
] = lvl
;
388 int CALLBACK
WinMain (HINSTANCE hInstance
, HINSTANCE unused__
, LPSTR lpszCmdLine
, int nCmdShow
) {
389 char *shit
[] = { (char *)"shit", NULL
};
390 return SDL_main(1, shit
);