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/>.
27 #include "gameglobals.h"
35 ////////////////////////////////////////////////////////////////////////////////
36 #define MAP_WIDTH (44)
37 #define MAP_HEIGHT (41)
38 #define VIS_WIDTH (15)
39 #define VIS_HEIGHT (17)
44 ////////////////////////////////////////////////////////////////////////////////
45 static const char *itemNames
[] = {
77 int type
; // 0: inactive
79 int frame
; // animation frame
80 int fframe
, lframe
; // first and last anim frame
86 ////////////////////////////////////////////////////////////////////////////////
88 static char levelname
[257];
91 static Uint8 bmap
[MAP_HEIGHT
][MAP_WIDTH
];
92 static Uint8 fmap
[MAP_HEIGHT
][MAP_WIDTH
];
93 static Uint8 xflags
[MAP_WIDTH
];
97 static int doSave
= 0;
99 static int demorecmode
= 0; // 0: none; 1: recording; -1: playing
100 static int demoSize
= 0;
101 static int demoPos
= 0;
102 static Uint8
*demoData
= NULL
;
103 static Uint8 demoPrevKeyState
= 0;
104 static int demoKeyStateRepeats
= 0;
106 static char message
[256];
107 //static Uint32 msgEndTime = 0;
109 static Uint32 demo_m_w
= 0;
110 static Uint32 demo_m_z
= 0;
113 ////////////////////////////////////////////////////////////////////////////////
114 static int gamekeys
[12];
117 static void setGameKeysGVars (void) {
118 vmGVars
[GVAR_KEY_LEFT
] = gamekeys
[0] ? 1 : 0;
119 vmGVars
[GVAR_KEY_RIGHT
] = gamekeys
[1] ? 1 : 0;
120 vmGVars
[GVAR_KEY_UP
] = gamekeys
[2] ? 1 : 0;
121 vmGVars
[GVAR_KEY_DOWN
] = gamekeys
[3] ? 1 : 0;
122 vmGVars
[GVAR_KEY_TAKE
] = gamekeys
[4] ? 1 : 0;
123 vmGVars
[GVAR_KEY_USE
] = gamekeys
[5] ? 1 : 0;
125 vmGVars
[GVAR_KEY_MINIMAP
] = gamekeys
[6] ? 1 : 0;
126 vmGVars
[GVAR_KEY_RESTART
] = gamekeys
[7] ? 1 : 0;
128 vmGVars
[GVAR_KEY_FALL_CHEAT
] = gamekeys
[8] ? 1 : 0;
129 vmGVars
[GVAR_KEY_WALK_CHEAT
] = gamekeys
[9] ? 1 : 0;
130 vmGVars
[GVAR_KEY_PLEV_CHEAT
] = gamekeys
[10] ? 1 : 0;
131 vmGVars
[GVAR_KEY_NLEV_CHEAT
] = gamekeys
[11] ? 1 : 0;
135 ////////////////////////////////////////////////////////////////////////////////
136 #define ROOM_SCRIPTS_MARK " room script labels starts here "
139 static void loadMapScript (ResFile
*resfile
) {
143 vmGVars
[GVAR_ROOM_SCRIPT_TID
] = -1;
144 l
= vmLabelAddMark(ROOM_SCRIPTS_MARK
);
145 l
->value
= vmCodeSize
;
146 if ((csz
= loadCodeFile(resfile
, vmCodeSize
, 94+curLevel
)) > 1) {
147 VMLabelInfo
*l
= vmFindLabel("entry_local_room_script");
149 if (l
!= NULL
&& l
->type
== LB_CODE
) {
151 tid
= vmNewThread(l
->value
);
152 vmGVars
[GVAR_ROOM_SCRIPT_TID
] = tid
;
153 if (goobers
) fprintf(stderr
, "local room script loaded and initialized\n");
159 static void unloadMapScript (void) {
162 while ((l
= vmFindMark(ROOM_SCRIPTS_MARK
)) != NULL
) {
163 VMLabelInfo
*ucl
= vmFindLabel("entry_local_room_script_unload");
165 if (ucl
!= NULL
&& ucl
->type
== LB_CODE
) {
166 vmExecuteBSR(0, ucl
->value
, 0);
169 vmCodeSize
= l
->value
;
170 vmFreeLabelsUntilMark(ROOM_SCRIPTS_MARK
);
175 ////////////////////////////////////////////////////////////////////////////////
180 static int readBuf (FILE *fl
, void *buf
, int len
) {
181 unsigned char *c
= (unsigned char *)buf
;
186 if (fread(&b
, 1, 1, fl
) != 1) return -1;
194 static int writeBuf (FILE *fl
, const void *buf
, int len
) {
195 const unsigned char *c
= (const unsigned char *)buf
;
198 unsigned char b
= *c
++;
201 if (fwrite(&b
, 1, 1, fl
) != 1) return -1;
207 static int readDW (FILE *fl
, int *v
) {
210 for (int f
= 0; f
< 4; ++f
) {
213 if (fread(&b
, 1, 1, fl
) != 1) return -1;
219 for (int f
= 0; f
< 4; ++f
) *v
|= t
[f
]<<(8*f
);
225 static int writeDW (FILE *fl
, int v
) {
226 for (int f
= 0; f
< 4; ++f
) {
231 if (fwrite(&b
, 1, 1, fl
) != 1) return -1;
238 static int readUDW (FILE *fl
, Uint32
*v
) {
241 for (int f
= 0; f
< 4; ++f
) {
244 if (fread(&b
, 1, 1, fl
) != 1) return -1;
250 for (int f
= 0; f
< 4; ++f
) *v
|= t
[f
]<<(8*f
);
256 static int writeUDW (FILE *fl
, Uint32 v
) {
257 for (int f
= 0; f
< 4; ++f
) {
262 if (fwrite(&b
, 1, 1, fl
) != 1) return -1;
269 ////////////////////////////////////////////////////////////////////////////////
270 static int loadGame (void) {
271 FILE *fl
= fopen("awish.sav", "rb");
274 if (vmLoadState(fl
) != 0) goto error
;
275 if (readUDW(fl
, &demo_m_w
) != 0) goto error
;
276 if (readUDW(fl
, &demo_m_z
) != 0) goto error
;
277 if (readDW(fl
, &inMinimap
) != 0) goto error
;
278 if (readDW(fl
, &curLevel
) != 0) goto error
;
279 if (readBuf(fl
, levelname
, sizeof(levelname
)) != 0) goto error
;
280 if (readDW(fl
, &lnamex
) != 0) goto error
;
281 if (readDW(fl
, &levelback
) != 0) goto error
;
282 if (readBuf(fl
, bmap
, sizeof(bmap
)) != 0) goto error
;
283 if (readBuf(fl
, fmap
, sizeof(fmap
)) != 0) goto error
;
284 if (readBuf(fl
, xflags
, sizeof(xflags
)) != 0) goto error
;
292 if (goobers
) fprintf(stderr
, "error loading saved game\n");
297 static int saveGame (void) {
298 FILE *fl
= fopen("awish.sav", "wb");
301 demo_m_w
= getSeedL();
302 demo_m_z
= getSeedH();
303 if (vmSaveState(fl
) != 0) goto error
;
304 if (writeUDW(fl
, demo_m_w
) != 0) goto error
;
305 if (writeUDW(fl
, demo_m_z
) != 0) goto error
;
306 if (writeDW(fl
, inMinimap
) != 0) goto error
;
307 if (writeDW(fl
, curLevel
) != 0) goto error
;
308 if (writeBuf(fl
, levelname
, sizeof(levelname
)) != 0) goto error
;
309 if (writeDW(fl
, lnamex
) != 0) goto error
;
310 if (writeDW(fl
, levelback
) != 0) goto error
;
311 if (writeBuf(fl
, bmap
, sizeof(bmap
)) != 0) goto error
;
312 if (writeBuf(fl
, fmap
, sizeof(fmap
)) != 0) goto error
;
313 if (writeBuf(fl
, xflags
, sizeof(xflags
)) != 0) goto error
;
320 if (goobers
) fprintf(stderr
, "error saving game\n");
325 ////////////////////////////////////////////////////////////////////////////////
326 static void demoClear (void) {
330 demoPrevKeyState
= 0;
331 demoKeyStateRepeats
= 0;
332 if (demoData
!= NULL
) free(demoData
);
337 static void demoAddByte (Uint8 b
) {
338 if (demoPos
+1 > demoSize
&& demoSize
> 1024*1024*16) fatal("out of memory in demo recording!");
339 if (demoPos
+1 > demoSize
) {
340 int newsz
= demoSize
+1024*32;
341 Uint8
*nn
= realloc(demoData
, newsz
);
343 if (!nn
) fatal("out of memory in demo recording!");
347 demoData
[demoPos
++] = b
;
351 static Uint8
demoGetKeyState (void) {
353 ((gamekeys
[0]?1:0)<<0) |
354 ((gamekeys
[1]?1:0)<<1) |
355 ((gamekeys
[2]?1:0)<<2) |
356 ((gamekeys
[3]?1:0)<<3) |
357 ((gamekeys
[4]?1:0)<<4) |
358 ((gamekeys
[5]?1:0)<<5);
362 static void demoSetKeyState (Uint8 kstate
) {
363 gamekeys
[0] = (kstate
&(1<<0)) != 0;
364 gamekeys
[1] = (kstate
&(1<<1)) != 0;
365 gamekeys
[2] = (kstate
&(1<<2)) != 0;
366 gamekeys
[3] = (kstate
&(1<<3)) != 0;
367 gamekeys
[4] = (kstate
&(1<<4)) != 0;
368 gamekeys
[5] = (kstate
&(1<<5)) != 0;
372 static void demoAddFrameData (void) {
373 Uint8 kstate
= demoGetKeyState();
375 if (demoKeyStateRepeats
== 256) {
376 demoAddByte(demoKeyStateRepeats
-1);
377 demoAddByte(demoPrevKeyState
);
378 demoKeyStateRepeats
= 0;
381 if (kstate
!= demoPrevKeyState
) {
382 if (demoKeyStateRepeats
> 0) {
383 demoAddByte(demoKeyStateRepeats
-1);
384 demoAddByte(demoPrevKeyState
);
386 demoPrevKeyState
= kstate
;
387 demoKeyStateRepeats
= 1;
389 ++demoKeyStateRepeats
;
394 static void demoGetFrameData (void) {
395 while (demoKeyStateRepeats
< 1) {
396 if (demoPos
+2 > demoSize
) {
399 if (goobers
) fprintf(stderr
, "demo complete\n");
400 strcpy(message
, "demo stopped");
403 demoKeyStateRepeats
= demoData
[demoPos
++];
404 ++demoKeyStateRepeats
;
405 demoPrevKeyState
= demoData
[demoPos
++];
407 --demoKeyStateRepeats
;
409 demoSetKeyState(demoPrevKeyState
);
413 static int demoSave (void) {
418 if (demoKeyStateRepeats
> 0) {
419 demoAddByte(demoKeyStateRepeats
-1);
420 demoAddByte(demoPrevKeyState
);
423 sprintf(buf
, "awish%02d.dmo", curLevel
+1);
424 fl
= fopen(buf
, "wb");
426 if (goobers
) fprintf(stderr
, "can't create demo file '%s'\n", buf
);
429 strcpy(sign
, "AWD1");
430 if (fwrite(sign
, 4, 1, fl
) != 1) goto error
;
431 if (writeDW(fl
, curLevel
) != 0) goto error
;
432 if (writeUDW(fl
, demo_m_w
) != 0) goto error
;
433 if (writeUDW(fl
, demo_m_z
) != 0) goto error
;
434 if (writeDW(fl
, demoPos
) != 0) goto error
;
435 if (writeBuf(fl
, demoData
, demoPos
) != 0) goto error
;
437 if (goobers
) fprintf(stderr
, "demo saved to file '%s'\n", buf
);
442 if (goobers
) fprintf(stderr
, "can't write demo file '%s'\n", buf
);
447 static int demoLoad (void) {
454 sprintf(buf
, "awish%02d.dmo", curLevel
+1);
455 fl
= fopen(buf
, "rb");
457 if (goobers
) fprintf(stderr
, "can't open demo file '%s'\n", buf
);
461 if (fread(sign
, 4, 1, fl
) != 1) goto error
;
462 if (memcmp(sign
, "AWD1", 4) != 0) goto error
;
463 if (readDW(fl
, &level
) != 0) goto error
;
464 if (readUDW(fl
, &demo_m_w
) != 0) goto error
;
465 if (readUDW(fl
, &demo_m_z
) != 0) goto error
;
466 if (readDW(fl
, &size
) != 0) goto error
;
467 if (size
< 1 || size
> 1024*1024*16) goto error
;
468 demoData
= malloc(size
);
469 if (demoData
== NULL
) goto error
;
470 if (readBuf(fl
, demoData
, size
) != 0) goto error
;
476 if (goobers
) fprintf(stderr
, "loaded demo file '%s'\n", buf
);
481 if (goobers
) fprintf(stderr
, "can't load demo file '%s'\n", buf
);
487 // CODE_GAME_RESTART_LEVEL
489 // CONST_GAME_STATE_DEAD
490 // CONST_GAME_STATE_COMPLETE
491 // CONST_GAME_STATE_STARTED
492 // CONST_GAME_STATE_PLAYING
494 static inline int isGameStopped (void) {
496 vmGVars
[GVAR_GAME_STATE
] == CONST_GAME_STATE_DEAD
||
497 vmGVars
[GVAR_GAME_STATE
] == CONST_GAME_STATE_COMPLETE
;
501 static void demoCB (void) {
502 if (vmGVars
[GVAR_GAME_STATE
] == CONST_GAME_STATE_STARTED
) unloadMapScript();
504 switch (demorecmode
) {
505 case -666: // prepare to load demo
506 if (demoLoad() != 0) {
512 case 666: // prepare to save demo
513 vmSetPC(0, CODE_GAME_RESTART_LEVEL
);
514 vmGVars
[GVAR_CUR_LEVEL
] = curLevel
;
515 vmGVars
[GVAR_GAME_STATE
] = -1; // invalid state
516 if (demorecmode
> 0) {
521 case -1: // demo replaying
522 case 1: // demo saving
523 if (isGameStopped()) {
524 // the level is over or prof is dead
525 if (demorecmode
> 0) demoSave();
529 ((demorecmode
< 0) ? demoGetFrameData
: demoAddFrameData
)();
532 case -2: // waiting for 'game started' trigger
533 case 2: // waiting for 'game started' trigger
534 if (vmGVars
[GVAR_GAME_STATE
] >= 0) {
535 if (goobers
) fprintf(stderr
, "demo %s started...\n", demorecmode
<0?"replaying":"recording");
536 if (demorecmode
< 0) {
542 demo_m_w
= getSeedL();
543 demo_m_z
= getSeedH();
545 demorecmode
= (demorecmode
< 0) ? -1 : 1;
553 ////////////////////////////////////////////////////////////////////////////////
554 static void frmGameKey (SDL_KeyboardEvent
*key
) {
555 if (key
->type
== SDL_KEYDOWN
) {
556 switch (key
->keysym
.sym
) {
560 if (vmPaused
&& inMinimap
) {
568 vmGVars
[GVAR_KEY_QUIT
] = 1;
584 if (demorecmode
!= 0) { demoClear(); demorecmode
= 0; }
585 if ((key
->keysym
.mod
&(KMOD_CTRL
)) != 0) {
591 if (vmPaused
== 0 && !demorecmode
) {
592 if (goobers
&& (key
->keysym
.mod
&(KMOD_CTRL
)) != 0) { doSave
= 1; vmPaused
= 1; }
596 if (vmPaused
== 0 && !demorecmode
) {
597 if (goobers
&& (key
->keysym
.mod
&(KMOD_CTRL
)) != 0) { doSave
= -1; vmPaused
= 1; }
602 if (goobers
&& (key
->keysym
.mod
&(KMOD_CTRL
)) != 0) {
604 demorecmode
= 666; // 'start saving'
615 if (goobers
&& (key
->keysym
.mod
&(KMOD_CTRL
)) != 0) {
617 demorecmode
= -666; // 'start playing'
630 if (demorecmode
== 0 || demorecmode
== 1) {
631 switch (key
->keysym
.sym
) {
632 case SDLK_LEFT
: case SDLK_KP4
: gamekeys
[0] = (key
->type
== SDL_KEYDOWN
); break;
633 case SDLK_RIGHT
: case SDLK_KP6
: gamekeys
[1] = (key
->type
== SDL_KEYDOWN
); break;
634 case SDLK_UP
: case SDLK_KP8
: gamekeys
[2] = (key
->type
== SDL_KEYDOWN
); break;
635 case SDLK_DOWN
: case SDLK_KP2
: gamekeys
[3] = (key
->type
== SDL_KEYDOWN
); break;
636 case SDLK_SPACE
: case SDLK_KP0
: gamekeys
[4] = (key
->type
== SDL_KEYDOWN
); break;
637 case SDLK_RETURN
: case SDLK_KP_PERIOD
: gamekeys
[5] = (key
->type
== SDL_KEYDOWN
); break;
641 if (goobers
&& !demorecmode
) {
642 switch (key
->keysym
.sym
) {
643 case SDLK_f
: gamekeys
[8] = (key
->type
== SDL_KEYDOWN
); break;
644 case SDLK_w
: gamekeys
[9] = (key
->type
== SDL_KEYDOWN
); break;
645 case SDLK_KP_MINUS
: gamekeys
[10] = (key
->type
== SDL_KEYDOWN
); break;
646 case SDLK_KP_PLUS
: gamekeys
[11] = (key
->type
== SDL_KEYDOWN
); break;
648 case SDLK_F1
: fkeys
[1] = (key
->type
== SDL_KEYDOWN
); break;
649 case SDLK_F2
: fkeys
[2] = (key
->type
== SDL_KEYDOWN
); break;
650 case SDLK_F3
: fkeys
[3] = (key
->type
== SDL_KEYDOWN
); break;
651 case SDLK_F4
: fkeys
[4] = (key
->type
== SDL_KEYDOWN
); break;
652 case SDLK_F5
: fkeys
[5] = (key
->type
== SDL_KEYDOWN
); break;
653 case SDLK_F6
: fkeys
[6] = (key
->type
== SDL_KEYDOWN
); break;
654 case SDLK_F7
: fkeys
[7] = (key
->type
== SDL_KEYDOWN
); break;
655 case SDLK_F8
: fkeys
[8] = (key
->type
== SDL_KEYDOWN
); break;
656 case SDLK_F9
: fkeys
[9] = (key
->type
== SDL_KEYDOWN
); break;
664 ////////////////////////////////////////////////////////////////////////////////
665 static int loadLevelInternal (ResFile
*resfile
, int lidx
) {
667 int sz
, res
= -1, pos
;
668 static Item items
[256];
669 static int itemCount
;
670 static int scrX
, scrY
;
671 static int profX
, profY
;
678 vmGVars
[GVAR_MAP_WIDTH
] = MAP_WIDTH
;
679 vmGVars
[GVAR_MAP_HEIGHT
] = MAP_HEIGHT
;
680 vmGVars
[GVAR_VIS_WIDTH
] = VIS_WIDTH
;
681 vmGVars
[GVAR_VIS_HEIGHT
] = VIS_HEIGHT
;
683 if ((lvl
= loadResFile(resfile
, lidx
+9, &sz
)) == NULL
) return -1;
684 if (sz
< 3700) goto quit
;
685 if (lvl
[0] > 25) goto quit
;
686 memset(levelname
, 0, sizeof(levelname
));
687 if (lvl
[0] > 0) memcpy(levelname
, lvl
+1, lvl
[0]);
688 lnamex
= (320-strlen(levelname
)*8)/2;
689 sprintf(buf
, "%d", lidx
+1);
690 while (lnamex
+strlen(levelname
)*8+strlen(buf
)*8+6*8 > 320) lnamex
-= 8;
692 if (levelback
< 1 || levelback
> 7) levelback
= 1;
695 vmSetTVar(0, TVAR_POS_X
, profX
);
696 vmSetTVar(0, TVAR_POS_Y
, profY
);
698 scrY
= lvl
[30]; if (scrY
> 0) --scrY
;
699 vmGVars
[GVAR_SCR_X
] = scrX
;
700 vmGVars
[GVAR_SCR_Y
] = scrY
;
702 memset(bmap
, 0, sizeof(bmap
));
703 memset(fmap
, 0, sizeof(fmap
));
704 memset(xflags
, 0, sizeof(xflags
));
705 for (int x
= 1; x
< MAP_WIDTH
; ++x
) {
706 for (int y
= 0; y
< MAP_HEIGHT
; ++y
) {
707 bmap
[y
][x
] = lvl
[pos
++];
710 for (int x
= 1; x
< MAP_WIDTH
; ++x
) {
711 for (int y
= 0; y
< MAP_HEIGHT
; ++y
) {
712 fmap
[y
][x
] = lvl
[pos
++];
714 pos
+= 3; // skip unknown bytes
717 itemCount
= lvl
[pos
++]+1; // at least one item is always here
718 for (int f
= 0; f
< itemCount
; ++f
) {
721 items
[f
].x
= lvl
[pos
++];
722 items
[f
].y
= lvl
[pos
++];
723 items
[f
].fframe
= lvl
[pos
++];
724 items
[f
].lframe
= lvl
[pos
++];
725 items
[f
].frame
= lvl
[pos
++];
726 items
[f
].animated
= lvl
[pos
++];
727 if (!items
[f
].animated
) items
[f
].frame
= items
[f
].fframe
;
730 items
[f
].type
= lvl
[pos
++];
733 tid
= vmNewThread(CODE_ENTRY_ITEM
);
734 if (tid
< 0) goto quit
;
735 vmSetTVar(tid
, TVAR_ITEM_ID
, items
[f
].type
);
736 vmSetTVar(tid
, TVAR_ANIMATED
, items
[f
].animated
);
737 vmSetTVar(tid
, TVAR_AFIRST_FRAME
, items
[f
].fframe
);
738 vmSetTVar(tid
, TVAR_ALAST_FRAME
, items
[f
].lframe
);
739 vmSetTVar(tid
, TVAR_AFRAME
, items
[f
].frame
);
740 if (items
[f
].type
== 6) vmSetTVar(tid
, TVAR_AFRAME
, lvl
[pos
-6]);
741 vmSetTVar(tid
, TVAR_POS_X
, items
[f
].x
);
742 vmSetTVar(tid
, TVAR_POS_Y
, items
[f
].y
);
743 vmSetTVar(tid
, TVAR_POS_TX
, 0);
744 vmSetTVar(tid
, TVAR_POS_TY
, 0);
745 vmSetTVar(tid
, TVAR_SPR_BANK
, CONST_BANK_ITEMS
);
746 vmSetTVar(tid
, TVAR_SPR_NUM
, items
[f
].frame
);
747 vmSetTVar(tid
, TVAR_SPR_DIR
, 0);
754 loadMapScript(resfile
);
762 ////////////////////////////////////////////////////////////////////////////////
763 static inline Uint8
fgTile (int x
, int y
) {
764 return (x
>= 0 && y
>= 0 && x
< MAP_WIDTH
&& y
< MAP_HEIGHT
) ? fmap
[y
][x
]&0x0f : 0;
768 static inline Uint8
bgTile (int x
, int y
) {
769 if (y
== -666) return (x
>= 0 && x
< MAP_WIDTH
) ? xflags
[x
] : 0;
770 return (x
>= 0 && y
>= 0 && x
< MAP_WIDTH
&& y
< MAP_HEIGHT
) ? bmap
[y
][x
]&0x0f : 0;
774 static int mapGet (int tid
, int fg
, int x
, int y
) {
775 return fg
? fgTile(x
, y
) : bgTile(x
, y
);
779 static inline void setFGTile (int x
, int y
, Uint8 tile
) {
780 if (x
>= 0 && y
>= 0 && x
< MAP_WIDTH
&& y
< MAP_HEIGHT
) fmap
[y
][x
] = (fmap
[y
][x
]&0xf0)|(tile
&0x0f);
784 static inline void setBGTile (int x
, int y
, Uint8 tile
) {
785 if (y
== -666 && x
>= 0 && x
< MAP_WIDTH
) xflags
[x
] = tile
;
786 if (x
>= 0 && y
>= 0 && x
< MAP_WIDTH
&& y
< MAP_HEIGHT
) bmap
[y
][x
] = (bmap
[y
][x
]&0xf0)|(tile
&0x0f);
790 static void mapSet (int tid
, int fg
, int x
, int y
, int tile
) {
791 if (fg
) setFGTile(x
, y
, tile
); else setBGTile(x
, y
, tile
);
795 ////////////////////////////////////////////////////////////////////////////////
796 // cliprect should be set
797 static void levelDrawMap (SDL_Surface
*frame
) {
799 int scrX
= vmGVars
[GVAR_SCR_X
], scrY
= vmGVars
[GVAR_SCR_Y
];
801 for (int dy
= 0; dy
< VIS_HEIGHT
; ++dy
) {
802 for (int dx
= 0; dx
< VIS_WIDTH
; ++dx
) {
803 int x
= scrX
+dx
, y
= scrY
+dy
;
804 Uint8 b
= bgTile(x
, y
), f
= fgTile(x
, y
);
806 if (b
) blitSurface2x(frame
, VIS_X
+dx
*20, VIS_Y
+dy
*10, banks
[CONST_BANK_BG_TILES
].spr
[b
-1][0]);
807 if (f
) blitSurface2x(frame
, VIS_X
+dx
*20, VIS_Y
+dy
*10, banks
[CONST_BANK_FG_TILES
].spr
[f
-1][0]);
811 for (int dy
= 0; dy
< MAP_HEIGHT
; ++dy
) {
812 for (int dx
= 1; dx
< MAP_WIDTH
; ++dx
) {
813 Uint8 b
= bgTile(dx
, dy
), f
= fgTile(dx
, dy
), t
= 8;
816 if (b
>= 1 && b
<= 8) t
= b
-1; else t
= 8;
820 if (banks
[CONST_BANK_MAP_TILES
].spr
[t
][0]) {
821 blitSurface2x(frame
, VIS_X
+dx
*6, VIS_Y
+dy
*4, banks
[CONST_BANK_MAP_TILES
].spr
[t
][0]);
829 static void levelDrawSprites (SDL_Surface
*frame
) {
831 int scrX
= vmGVars
[GVAR_SCR_X
], scrY
= vmGVars
[GVAR_SCR_Y
];
832 int py
= vmGetTVar(0, TVAR_POS_Y
)-scrY
;
834 for (int cc
= 0; cc
<= 2; ++cc
) {
835 for (int f
= cc
==1?1:0; f
<= vmLastThread(); ++f
) {
836 if (vmIsThreadAlive(f
) && !vmIsSuspendedThread(f
)) {
837 int b
= vmGetTVar(f
, TVAR_SPR_BANK
);
838 int s
= vmGetTVar(f
, TVAR_SPR_NUM
);
839 int d
= vmGetTVar(f
, TVAR_SPR_DIR
);
841 if (d
>= 0 && d
<= 1 && s
>= 0 && b
>= 0 && b
<= 255 && s
< banks
[b
].count
&& banks
[b
].spr
[s
][d
]) {
842 SDL_Surface
*sf
= banks
[b
].spr
[s
][d
];
843 int x
= vmGetTVar(f
, TVAR_POS_X
)-scrX
;
844 int y
= vmGetTVar(f
, TVAR_POS_Y
)-scrY
;
845 int tx
= vmGetTVar(f
, TVAR_POS_TX
);
846 int ty
= vmGetTVar(f
, TVAR_POS_TY
);
847 int si
= vmGetTVar(f
, TVAR_SPR_ITEM
);
849 if (cc
== 0 && b
== CONST_BANK_ITEMS
) continue;
850 if (cc
== 1 && b
!= CONST_BANK_ITEMS
) continue;
852 if (b
!= CONST_BANK_PROF
) {
853 if (b
!= CONST_BANK_ITEMS
) continue;
854 if (y
< py
) continue;
857 if (b
== CONST_BANK_IM_PROF
|| b
== CONST_BANK_PROF
) tx
-= 5;
858 blitSurface2x(frame
, VIS_X
+x
*20+tx
, VIS_Y
+y
*10+ty
-sf
->h
/2, sf
);
859 if (si
> 0 && si
< banks
[CONST_BANK_ITEMS
].count
) {
860 sf
= banks
[CONST_BANK_ITEMS
].spr
[si
][0];
861 blitSurface2x(frame
, VIS_X
+x
*20+tx
, VIS_Y
+y
*10+ty
-sf
->h
/2-24, sf
);
868 blitSurface2x(frame
, VIS_X
+(vmGetTVar(0, TVAR_POS_X
)+0)*6, VIS_Y
+(vmGetTVar(0, TVAR_POS_Y
)-4)*4, banks
[CONST_BANK_MAP_ITEMS
].spr
[0][0]);
869 for (int f
= 1; f
< VM_MAX_THREADS
; ++f
) {
870 if (vmIsThreadAlive(f
) && !vmIsSuspendedThread(f
)) {
871 int i
= vmGetTVar(f
, TVAR_ITEM_ID
);
872 if (i
> 0 && i
< ITEM_MAX
) {
873 SDL_Surface
*sf
= banks
[CONST_BANK_MAP_ITEMS
].spr
[i
][0];
874 int x
= vmGetTVar(f
, TVAR_POS_X
);
875 int y
= vmGetTVar(f
, TVAR_POS_Y
);
877 blitSurface2x(frame
, VIS_X
+(x
+0)*6, VIS_Y
+(y
-2)*4, sf
);
885 static void levelDrawCode (SDL_Surface
*frame
) {
886 int pos
= vmGVars
[GVAR_LEVEL_CODE_OFS
], len
= vmGVars
[GVAR_LEVEL_CODE_LEN
], x
;
889 if (pos
< 0 || len
< 1 || pos
+len
> vmCodeSize
) return;
891 sprintf(buf
, "%d", curLevel
);
893 for (; len
> 0; x
+= 8, ++pos
, --len
) drawChar(frame
, vmCode
[pos
], x
, 0, 3);
897 static void levelDrawMisc (SDL_Surface
*frame
) {
898 if (demorecmode
< 0) {
899 if (SDL_GetTicks()%1000 < 500) drawChar(frame
, 'R', 0, 8, 3);
900 } else if (demorecmode
> 0) {
901 if (SDL_GetTicks()%1000 < 500) drawChar(frame
, 'D', 0, 8, 3);
906 static void drawSpriteBank (SDL_Surface
*frame
, SpriteBank
*bank
) {
908 int x
= 0, y
= 0, maxh
= 0;
910 SDL_SetClipRect(frame
, NULL
);
915 SDL_FillRect(frame
, &dst
, palette
[3]);
917 for (int num
= 0; num
< bank
->count
; ++num
) {
918 SDL_Surface
*s
= bank
->spr
[num
][0];
924 sprintf(buf
, "%d", num
);
925 if (w
< strlen(buf
)*8+2) w
= strlen(buf
)*8+2;
931 if (maxh
< s
->h
/2+1) maxh
= s
->h
/2+1;
932 blitSurface2x(frame
, x
, y
, s
);
933 drawString(frame
, buf
, x
, y
, 1);
940 static void frmGameDraw (SDL_Surface
*frame
) {
945 if (vmPaused
&& doSave
) {
952 vmPaused
= inMinimap
;
955 SDL_SetClipRect(frame
, NULL
);
959 blitSurface(frame
, 0, 0, backs
[levelback
]);
961 blitSurface(frame
, 0, 0, backs
[1]);
963 drawString(frame
, levelname
, lnamex
, 0, 0x76);
964 levelDrawCode(frame
);
965 levelDrawMisc(frame
);
967 pi
= vmGVars
[GVAR_PROF_ITEM
];
968 if (vmIsThreadAlive(pi
) && vmIsSuspendedThread(pi
)) {
969 pi
= vmGetTVar(pi
, TVAR_ITEM_ID
);
970 if (pi
> 0 && pi
< 11) {
971 drawString(frame
, itemNames
[pi
], 0, 0, 1);
975 sprintf(buf
, "%d", curLevel
+1);
976 drawString(frame
, buf
, 320-strlen(buf
)*8, 0, 1);
980 rc
.w
= VIS_WIDTH
*20*2;
981 rc
.h
= VIS_HEIGHT
*10*2;
982 SDL_SetClipRect(frame
, &rc
);
985 levelDrawSprites(frame
);
993 SDL_FillRect(frame
, &dst
, palette
[0]);
996 SDL_SetClipRect(frame
, NULL
);
997 levelDrawMisc(frame
);
1000 for (int f
= 84; f
<= 90; ++f
) if (fkeys
[f
-83]) drawSpriteBank(frame
, &banks
[f
]);
1005 ////////////////////////////////////////////////////////////////////////////////
1006 int loadLevel (int lidx
) {
1007 if (lidx
< 0 || lidx
> 73) return -1;
1008 return loadLevelInternal(&resfile
, lidx
);
1012 void activateMinimap (void) {
1019 ////////////////////////////////////////////////////////////////////////////////
1020 void setMainLoopGame (void) {
1021 frameCB
= frmGameDraw
;
1023 beforeVMCB
= demoCB
;
1024 vmMapGetCB
= mapGet
;
1025 vmMapSetCB
= mapSet
;
1027 setSeed(time(NULL
));
1034 memset(fkeys
, 0, sizeof(fkeys
));
1035 memset(gamekeys
, 0, sizeof(gamekeys
));