11 #include "gameglobals.h"
15 ////////////////////////////////////////////////////////////////////////////////
16 #define MAP_WIDTH (44)
17 #define MAP_HEIGHT (41)
18 #define VIS_WIDTH (15)
19 #define VIS_HEIGHT (17)
24 ////////////////////////////////////////////////////////////////////////////////
25 static const char *itemNames
[] = {
57 int type
; // 0: inactive
59 int frame
; // animation frame
60 int fframe
, lframe
; // first and last anim frame
66 ////////////////////////////////////////////////////////////////////////////////
68 static char levelname
[257];
70 static Uint8 levelback
;
71 static Uint8 bmap
[MAP_HEIGHT
][MAP_WIDTH
];
72 static Uint8 fmap
[MAP_HEIGHT
][MAP_WIDTH
];
73 static Item items
[256];
75 static int scrX
, scrY
;
76 static int profX
, profY
;
77 //static Item profItem;
82 ////////////////////////////////////////////////////////////////////////////////
83 static void frmGameKey (SDL_KeyboardEvent
*key
) {
84 if (key
->type
== SDL_KEYDOWN
) {
85 switch (key
->keysym
.sym
) {
90 vmGVars
[GVAR_KEY_MINIMAP
] = 0;
94 vmGVars
[GVAR_KEY_QUIT
] = 1;
97 vmGVars
[GVAR_KEY_MINIMAP
] = 1;
103 switch (key
->keysym
.sym
) {
104 case SDLK_LEFT
: case SDLK_KP4
: vmGVars
[GVAR_KEY_LEFT
] = (key
->type
== SDL_KEYDOWN
); break;
105 case SDLK_RIGHT
: case SDLK_KP6
: vmGVars
[GVAR_KEY_RIGHT
] = (key
->type
== SDL_KEYDOWN
); break;
106 case SDLK_UP
: case SDLK_KP8
: vmGVars
[GVAR_KEY_UP
] = (key
->type
== SDL_KEYDOWN
); break;
107 case SDLK_DOWN
: case SDLK_KP2
: vmGVars
[GVAR_KEY_DOWN
] = (key
->type
== SDL_KEYDOWN
); break;
108 case SDLK_SPACE
: case SDLK_KP0
: vmGVars
[GVAR_KEY_TAKE
] = (key
->type
== SDL_KEYDOWN
); break;
109 case SDLK_RETURN
: case SDLK_KP_PERIOD
: vmGVars
[GVAR_KEY_USE
] = (key
->type
== SDL_KEYDOWN
); break;
111 case SDLK_f
: vmGVars
[GVAR_KEY_FALL_CHEAT
] = (key
->type
== SDL_KEYDOWN
); break;
112 case SDLK_w
: vmGVars
[GVAR_KEY_WALK_CHEAT
] = (key
->type
== SDL_KEYDOWN
); break;
113 case SDLK_KP_MINUS
: vmGVars
[GVAR_KEY_PLEV_CHEAT
] = (key
->type
== SDL_KEYDOWN
); break;
114 case SDLK_KP_PLUS
: vmGVars
[GVAR_KEY_NLEV_CHEAT
] = (key
->type
== SDL_KEYDOWN
); break;
116 case SDLK_F1
: fkeys
[1] = (key
->type
== SDL_KEYDOWN
); break;
117 case SDLK_F2
: fkeys
[2] = (key
->type
== SDL_KEYDOWN
); break;
118 case SDLK_F3
: fkeys
[3] = (key
->type
== SDL_KEYDOWN
); break;
119 case SDLK_F4
: fkeys
[4] = (key
->type
== SDL_KEYDOWN
); break;
120 case SDLK_F5
: fkeys
[5] = (key
->type
== SDL_KEYDOWN
); break;
121 case SDLK_F6
: fkeys
[6] = (key
->type
== SDL_KEYDOWN
); break;
122 case SDLK_F7
: fkeys
[7] = (key
->type
== SDL_KEYDOWN
); break;
123 case SDLK_F8
: fkeys
[8] = (key
->type
== SDL_KEYDOWN
); break;
124 case SDLK_F9
: fkeys
[9] = (key
->type
== SDL_KEYDOWN
); break;
130 ////////////////////////////////////////////////////////////////////////////////
131 static int loadLevelInternal (ResFile
*resfile
, int lidx
) {
133 int sz
, res
= -1, pos
;
135 vmGVars
[GVAR_MAP_WIDTH
] = MAP_WIDTH
;
136 vmGVars
[GVAR_MAP_HEIGHT
] = MAP_HEIGHT
;
137 vmGVars
[GVAR_VIS_WIDTH
] = VIS_WIDTH
;
138 vmGVars
[GVAR_VIS_HEIGHT
] = VIS_HEIGHT
;
140 if ((lvl
= loadResFile(resfile
, lidx
+9, &sz
)) == NULL
) return -1;
141 if (sz
< 3700) goto quit
;
142 if (lvl
[0] > 25) goto quit
;
143 memset(levelname
, 0, sizeof(levelname
));
144 if (lvl
[0] > 0) memcpy(levelname
, lvl
+1, lvl
[0]);
145 lnamex
= (320-strlen(levelname
)*8)/2;
147 if (levelback
< 1 || levelback
> 7) levelback
= 1;
148 profX
= lvl
[27]; //if (profX > 0) --profX;
150 vmSetTVar(0, TVAR_POS_X
, profX
);
151 vmSetTVar(0, TVAR_POS_Y
, profY
);
152 scrX
= lvl
[29]; //if (scrX > 0) --scrX;
153 scrY
= lvl
[30]; if (scrY
> 0) --scrY
;
154 vmGVars
[GVAR_SCR_X
] = scrX
;
155 vmGVars
[GVAR_SCR_Y
] = scrY
;
157 memset(bmap
, 0, sizeof(bmap
));
158 memset(fmap
, 0, sizeof(fmap
));
159 for (int x
= 1; x
< MAP_WIDTH
; ++x
) {
160 for (int y
= 0; y
< MAP_HEIGHT
; ++y
) {
161 bmap
[y
][x
] = lvl
[pos
++];
164 for (int x
= 1; x
< MAP_WIDTH
; ++x
) {
165 for (int y
= 0; y
< MAP_HEIGHT
; ++y
) {
166 fmap
[y
][x
] = lvl
[pos
++];
168 pos
+= 3; // skip unknown bytes
171 //fprintf(stderr, "pos: 0x%08x\n", pos);
172 itemCount
= lvl
[pos
++]+1; // at least one item is always here
173 vmGVars
[GVAR_ITEM_COUNT
] = itemCount
;
174 //fprintf(stderr, "ic=%d\n", itemCount);
175 for (int f
= 0; f
< itemCount
; ++f
) {
178 items
[f
].x
= lvl
[pos
++]; //--items[f].x;
179 items
[f
].y
= lvl
[pos
++]; //--items[f].y;
180 items
[f
].fframe
= lvl
[pos
++];
181 items
[f
].lframe
= lvl
[pos
++];
182 items
[f
].frame
= lvl
[pos
++];
183 items
[f
].animated
= lvl
[pos
++];
184 if (!items
[f
].animated
) items
[f
].frame
= items
[f
].fframe
;
187 items
[f
].type
= lvl
[pos
++];
189 //fprintf(stderr, "%d: x=%d; y=%d; type=%d\n", f, items[f].x, items[f].y, items[f].type);
191 tid
= vmNewThread(CODE_ENTRY_ITEM
);
192 if (tid
< 0) goto quit
;
193 vmSetTVar(tid
, TVAR_ITEM_ID
, items
[f
].type
);
194 vmSetTVar(tid
, TVAR_ANIMATED
, items
[f
].animated
);
195 vmSetTVar(tid
, TVAR_AFIRST_FRAME
, items
[f
].fframe
);
196 vmSetTVar(tid
, TVAR_ALAST_FRAME
, items
[f
].lframe
);
197 vmSetTVar(tid
, TVAR_AFRAME
, items
[f
].frame
);
198 vmSetTVar(tid
, TVAR_POS_X
, items
[f
].x
);
199 vmSetTVar(tid
, TVAR_POS_Y
, items
[f
].y
);
200 vmSetTVar(tid
, TVAR_POS_TX
, 0);
201 vmSetTVar(tid
, TVAR_POS_TY
, 0);
202 vmSetTVar(tid
, TVAR_SPR_BANK
, CONST_BANK_ITEMS
);
203 vmSetTVar(tid
, TVAR_SPR_NUM
, items
[f
].frame
);
204 vmSetTVar(tid
, TVAR_SPR_DIR
, 0);
214 ////////////////////////////////////////////////////////////////////////////////
216 static int itemAt (int x, int y) {
217 for (int f = 0; f < itemCount; ++f) {
218 if (items[f].type > ITEM_NOTHING && items[f].tx == 0 && items[f].ty == 0 && items[f].x == x && items[f].y == y) return f;
225 static inline Uint8
fgTile (int x
, int y
) {
226 return (x
>= 0 && y
>= 0 && x
< MAP_WIDTH
&& y
< MAP_HEIGHT
) ? fmap
[y
][x
]&0x0f : 0;
230 static inline Uint8
bgTile (int x
, int y
) {
231 return (x
>= 0 && y
>= 0 && x
< MAP_WIDTH
&& y
< MAP_HEIGHT
) ? bmap
[y
][x
]&0x0f : 0;
235 static int mapGet (int tid
, int fg
, int x
, int y
) {
236 return fg
? fgTile(x
, y
) : bgTile(x
, y
);
240 static inline void setFGTile (int x
, int y
, Uint8 tile
) {
241 if (x
>= 0 && y
>= 0 && x
< MAP_WIDTH
&& y
< MAP_HEIGHT
) fmap
[y
][x
] = (fmap
[y
][x
]&0xf0)|(tile
&0x0f);
245 static inline void setBGTile (int x
, int y
, Uint8 tile
) {
246 if (x
>= 0 && y
>= 0 && x
< MAP_WIDTH
&& y
< MAP_HEIGHT
) bmap
[y
][x
] = (bmap
[y
][x
]&0xf0)|(tile
&0x0f);
250 static void mapSet (int tid
, int fg
, int x
, int y
, int tile
) {
251 if (fg
) setFGTile(x
, y
, tile
); else setBGTile(x
, y
, tile
);
255 ////////////////////////////////////////////////////////////////////////////////
256 // cliprect should be set
257 static void levelDrawMap (SDL_Surface
*frame
) {
259 int scrX
= vmGVars
[GVAR_SCR_X
], scrY
= vmGVars
[GVAR_SCR_Y
];
261 for (int dy
= 0; dy
< VIS_HEIGHT
; ++dy
) {
262 for (int dx
= 0; dx
< VIS_WIDTH
; ++dx
) {
263 int x
= scrX
+dx
, y
= scrY
+dy
;
264 Uint8 b
= bgTile(x
, y
), f
= fgTile(x
, y
);
266 if (b
) blitSurface2x(frame
, VIS_X
+dx
*20, VIS_Y
+dy
*10, banks
[CONST_BANK_BG_TILES
].spr
[b
-1][0]);
267 if (f
) blitSurface2x(frame
, VIS_X
+dx
*20, VIS_Y
+dy
*10, banks
[CONST_BANK_FG_TILES
].spr
[f
-1][0]);
271 for (int dy
= 0; dy
< MAP_HEIGHT
; ++dy
) {
272 for (int dx
= 1; dx
< MAP_WIDTH
; ++dx
) {
273 Uint8 b
= bgTile(dx
, dy
), f
= fgTile(dx
, dy
), t
= 8;
276 if (b
>= 1 && b
<= 8) t
= b
-1; else t
= 8;
280 if (banks
[CONST_BANK_MAP_TILES
].spr
[t
][0]) {
281 blitSurface2x(frame
, VIS_X
+dx
*6, VIS_Y
+dy
*4, banks
[CONST_BANK_MAP_TILES
].spr
[t
][0]);
289 static void levelDrawSprites (SDL_Surface
*frame
) {
291 int scrX
= vmGVars
[GVAR_SCR_X
], scrY
= vmGVars
[GVAR_SCR_Y
];
293 for (int f
= 0; f
< VM_MAX_THREADS
; ++f
) {
294 if (vmIsThreadAlive(f
) && !vmIsSuspendedThread(f
)) {
295 int b
= vmGetTVar(f
, TVAR_SPR_BANK
);
296 int s
= vmGetTVar(f
, TVAR_SPR_NUM
);
297 int d
= vmGetTVar(f
, TVAR_SPR_DIR
);
299 if (d
>= 0 && d
<= 1 && s
>= 0 && b
>= 0 && b
<= 255 && s
< banks
[b
].count
&& banks
[b
].spr
[s
][d
]) {
300 SDL_Surface
*sf
= banks
[b
].spr
[s
][d
];
301 int x
= vmGetTVar(f
, TVAR_POS_X
)-scrX
;
302 int y
= vmGetTVar(f
, TVAR_POS_Y
)-scrY
;
303 int tx
= vmGetTVar(f
, TVAR_POS_TX
);
304 int ty
= vmGetTVar(f
, TVAR_POS_TY
);
306 if (b
== CONST_BANK_IM_PROF
|| b
== CONST_BANK_PROF
) tx
-= 6;
307 blitSurface2x(frame
, VIS_X
+x
*20+tx
, VIS_Y
+y
*10+ty
-sf
->h
/2, sf
);
312 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]);
313 for (int f
= 1; f
< VM_MAX_THREADS
; ++f
) {
314 if (vmIsThreadAlive(f
) && !vmIsSuspendedThread(f
)) {
315 int i
= vmGetTVar(f
, TVAR_ITEM_ID
);
316 if (i
> 0 && i
< ITEM_MAX
) {
317 SDL_Surface
*sf
= banks
[CONST_BANK_MAP_ITEMS
].spr
[i
][0];
318 int x
= vmGetTVar(f
, TVAR_POS_X
);
319 int y
= vmGetTVar(f
, TVAR_POS_Y
);
321 blitSurface2x(frame
, VIS_X
+(x
+0)*6, VIS_Y
+(y
-2)*4, sf
);
329 static void drawSpriteBank (SDL_Surface
*frame
, SpriteBank
*bank
) {
331 int x
= 0, y
= 0, maxh
= 0;
333 SDL_SetClipRect(frame
, NULL
);
338 SDL_FillRect(frame
, &dst
, palette
[0]);
340 for (int num
= 0; num
< bank
->count
; ++num
) {
341 SDL_Surface
*s
= bank
->spr
[num
][0];
347 sprintf(buf
, "%d", num
);
348 if (w
< strlen(buf
)*8+2) w
= strlen(buf
)*8+2;
354 if (maxh
< s
->h
/2+1) maxh
= s
->h
/2+1;
355 blitSurface2x(frame
, x
, y
, s
);
356 drawString(frame
, buf
, x
, y
, 1);
363 static void frmGameDraw (SDL_Surface
*frame
) {
368 SDL_SetClipRect(frame
, NULL
);
370 blitSurface(frame
, 0, 0, backs
[levelback
]);
372 blitSurface(frame
, 0, 0, backs
[1]);
374 drawString(frame
, levelname
, lnamex
, 0, 0x76);
376 pi
= vmGVars
[GVAR_PROF_ITEM
];
377 if (vmIsThreadAlive(pi
) && vmIsSuspendedThread(pi
)) {
378 pi
= vmGetTVar(pi
, TVAR_ITEM_ID
);
379 if (pi
> 0 && pi
< 11) {
380 //blitSurface2x(frame, 0, 0, itemSpr[profItem.frame]);
381 drawString(frame
, itemNames
[pi
], 0, 0, 1);
385 sprintf(buf
, "%d", curLevel
+1);
386 drawString(frame
, buf
, 320-strlen(buf
)*8, 0, 1);
390 rc
.w
= VIS_WIDTH
*20*2;
391 rc
.h
= VIS_HEIGHT
*10*2;
392 SDL_SetClipRect(frame
, &rc
);
395 levelDrawSprites(frame
);
397 levelDrawProf(frame);
398 levelDrawItems(frame);
399 levelDrawProfDeath(frame);
403 SDL_SetClipRect(frame, NULL);
404 //ebfDrawText(frame, xen, "TESTING:09!", 1, 1);
405 if (keyF1) drawSpriteList(frame, profSpr[0], PROF_CNT);
407 for (int f
= 84; f
<= 90; ++f
) if (fkeys
[f
-83]) drawSpriteBank(frame
, &banks
[f
]);
411 ////////////////////////////////////////////////////////////////////////////////
412 int loadLevel (int lidx
) {
413 if (lidx
< 0 || lidx
> 73) return -1;
414 return loadLevelInternal(&resfile
, lidx
);
418 void activateMinimap (void) {
424 ////////////////////////////////////////////////////////////////////////////////
425 void setMainLoopGame (void) {
426 frameCB
= frmGameDraw
;
434 memset(fkeys
, 0, sizeof(fkeys
));
436 for (int f = 0; f < VM_MAX_THREADS; ++f) {
437 vmSetTVar(f, TVAR_ITEM_ID, -1);
438 vmSetTVar(f, TVAR_SPR_BANK, 0);
439 vmSetTVar(f, TVAR_SPR_NUM, 0);
440 vmSetTVar(f, TVAR_POS_X, 0);
441 vmSetTVar(f, TVAR_POS_Y, 0);
442 vmSetTVar(f, TVAR_POS_TX, 0);
443 vmSetTVar(f, TVAR_POS_TY, 0);