1 /**
2  * Common code for FreeDink and FreeDinkedit
3 
4  * Copyright (C) 1997, 1998, 1999, 2002, 2003  Seth A. Robinson
5  * Copyright (C) 2003  Shawn Betts
6  * Copyright (C) 2005, 2006  Dan Walma
7  * Copyright (C) 2005, 2007, 2008, 2009, 2010, 2012  Sylvain Beucler
8 
9  * This file is part of GNU FreeDink
10 
11  * GNU FreeDink is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 3 of the
14  * License, or (at your option) any later version.
15 
16  * GNU FreeDink is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * General Public License for more details.
20 
21  * You should have received a copy of the GNU General Public License
22  * along with this program.  If not, see
23  * <http://www.gnu.org/licenses/>.
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 
30 #define WIN32_LEAN_AND_MEAN
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <strings.h> /* strncasecmp */
35 #include <ctype.h>
36 #include <time.h>
37 
38 #ifdef _WIN32
39 /* GetWindowsDirectory */
40 #include <windows.h>
41 #endif
42 /* #include <windowsx.h> */
43 /* #include <direct.h> */
44 /* #include <io.h> */
45 #include <fcntl.h>
46 /* #include <process.h> */
47 
48 
49 /* #include <mmsystem.h> */
50 /* #define DIRECTINPUT_VERSION 0x0700 */
51 /* #include <dinput.h> */
52 /* #include <ddraw.h> */
53 
54 #include "SDL.h"
55 #include "SDL_image.h"
56 #include "SDL_framerate.h"
57 
58 #include "game_engine.h"
59 #include "screen.h"
60 #include "dinkini.h"
61 #include "input.h"
62 
63 /* #include "ddutil.h" */
64 #include "fastfile.h"
65 #include "io_util.h"
66 
67 
68 #include "freedink.h"
69 #include "dinkvar.h"
70 #include "gfx.h"
71 #include "gfx_tiles.h"
72 #include "gfx_sprites.h"
73 #include "gfx_palette.h"
74 /* for DinkC's initfonts(): */
75 #include "gfx_fonts.h"
76 #include "bgm.h"
77 #include "sfx.h"
78 #include "dinkc.h"
79 #include "dinkc_bindings.h"
80 
81 #include "str_util.h"
82 #include "paths.h"
83 #include "log.h"
84 
85 //if true, will close app as soon as the message pump is empty
86 int g_b_kill_app = 0;
87 
88 int dinkspeed = 3;
89 int show_inventory = 0; // display inventory?
90 
91 void update_status_all(void);
92 int add_sprite(int x1, int y, int brain,int pseq, int pframe );
93 
94 void add_exp(int num, int h);
95 void draw_status_all(void);
96 void check_seq_status(int h);
97 
98 int realhard(int tile);
99 int flub_mode = -500;
100 int draw_map_tiny = -1;
101 
102 int walk_off_screen = /*false*/0;
103 
104 /* Skip flipping the double buffer for this frame only - used when
105    setting up show_bmp and copy_bmp */
106 /*bool*/int abort_this_flip = /*false*/0;
107 
108 
109 #define SEQ_LEVEL_NUMS 442
110 
111 
112 struct show_bmp showb;
113 
114 int keep_mouse = 0;
115 
116 
117 struct attackinfo_struct bow;
118 
119 int screenlock = 0;
120 
121 struct talk_struct talk;
122 
123 unsigned long mold;
124 
125 int mbase_count;
126 
127 
128 int push_active = 1;
129 
130 
131 #define TEXT_MIN 2700
132 #define TEXT_TIMER 77
133 
134 int stop_entire_game;
135 const int max_game = 20;
136 /*bool*/int in_enabled = /*false*/0;
137 char *in_string;
138 
139 
140 
141 
142 /* If true, and if the engine is executing a screen's attached script,
143    and if main() loads new graphics (preload_seq()...), then
144    load_sprites and load_sprite_pak will display a "Please Wait"
145    animation. */
146 /*bool*/int no_running_main = /*false*/0;
147 
148 char dir[80];
149 
150 
151 //defaults
152 
153 
154 
155 
156 int  show_dot = /*FALSE*/0;
157 
158 unsigned long timer = 0;
159 char *command_line;
160 /*bool*/int dinkedit = /*false*/0;
161 int base_timing = 0;
162 int weapon_script = 0;
163 int magic_script = 0;
164 
165 int sp_mode = 0;
166 int fps,fps_final = 0;
167 int move_screen = 0;
168 int move_counter = 0;
169 int playx = 620;
170 /*bool*/int windowed = /*false*/0; /* TODO: move to gfx.c? */
171 int playl = 20;
172 
173 /*bool*/int mouse1 = /*false*/0;
174 int playy = 400;
175 int cur_map;
176 
177 /* Number of ms since an arbitrarily fixed point */
178 Uint32 thisTickCount,lastTickCount;
179 /* SDL_gfx accurate framerate */
180 FPSmanager framerate_manager;
181 
182 unsigned long timecrap;
183 rect math,box_crap,box_real;
184 
185 
186 int mode;
187 
188 struct small_map pam;
189 
190 
191 /*bool*/int trig_man = /*false*/0;
192 /*bool*/int total_trigger = /*false*/0;
193 
194 struct player_info play;
195 
196 
197 
198 
199 /* LPDIRECTDRAWSURFACE     game[max_game];       // Game pieces */
200 /* LPDIRECTDRAWPALETTE     lpDDPal = NULL;        // The primary surface palette */
201 /* PALETTEENTRY    pe[256]; */
202 
203 int bActive = /*false*/0;        // is application active/foreground?
204 //LPDIRECTINPUT lpDI;
205 
206 
207 //direct input stuff for mouse reading
208 
209 /* LPDIRECTINPUT          g_pdi = NULL; */
210 /* LPDIRECTINPUTDEVICE    g_pMouse = NULL; */
211 /* #define DINPUT_BUFFERSIZE           16 */
212 
213 /* HANDLE                 g_hevtMouse = NULL; */
214 
215 
216 //LPCDIDATAFORMAT lpc;
217 
218 unsigned char torusColors[256];  // Marks the colors used in the torus
219 
220 
221 /* HWND                    hWndMain = NULL; */
222 struct hardness hmap;
223 
clear_talk(void)224 void clear_talk(void)
225 {
226         memset(&talk, 0, sizeof(talk));
227         play.mouse = 0;
228 }
229 
230 
lmon(long money,char * dest)231 char * lmon(long money, char *dest)
232 {
233         char ho[30];
234         int k,c;
235         char lmon1[30];
236         char buffer[30];
237         /*BOOL*/int quit1;
238         quit1 = /*FALSE*/0;
239 
240         sprintf(buffer, "%ld", money);
241         strcpy(lmon1, buffer);
242         // prf("ORG IS '%s'",lmon1);
243 
244         if (strlen(lmon1) < 4)
245         {
246                 strcpy(dest, lmon1);
247                 return(dest);
248         }
249 
250         sprintf(buffer, "%ld", money);
251         strcpy(ho, buffer);
252         k = strlen(ho);
253         c = -1;
254         lmon1[0]=0;
255         do {
256                 strchar(lmon1,ho[k]);
257                 k--;
258                 c++;
259                 if (c == 3)
260                 {
261                         if (k > -1)
262                         {
263                                 strchar(lmon1,',');
264                                 c = 0;
265                         }
266                 }
267                 if (k < 0) quit1 = /*TRUE*/1;
268         }while (quit1 == /*FALSE*/0);
269         reverse(lmon1);
270 
271         strcpy(dest, lmon1);
272         return(dest);
273 }
274 
275 
276 
277 /* void dderror(HRESULT hErr) */
278 /* {        */
279 /*     switch (hErr) */
280 /*     { */
281 /*         case DDERR_ALREADYINITIALIZED: */
282 /*                 Msg("DDERR_ALREADYINITIALIZED"); break; */
283 /*         case DDERR_CANNOTATTACHSURFACE: */
284 /*                 Msg("DDERR_CANNOTATTACHSURFACE"); break; */
285 /*         case DDERR_CANNOTDETACHSURFACE: */
286 /*                 Msg("DDERR_CANNOTDETACHSURFACE"); break; */
287 /*         case DDERR_CURRENTLYNOTAVAIL: */
288 /*                 Msg("DDERR_CURRENTLYNOTAVAIL"); break; */
289 /*         case DDERR_EXCEPTION: */
290 /*                 Msg("DDERR_EXCEPTION"); break; */
291 /*         case DDERR_GENERIC: */
292 /*                 Msg("DDERR_GENERIC"); break; */
293 /*         case DDERR_HEIGHTALIGN: */
294 /*                 Msg("DDERR_HEIGHTALIGN"); break; */
295 /*         case DDERR_INCOMPATIBLEPRIMARY: */
296 /*                 Msg("DDERR_INCOMPATIBLEPRIMARY"); break; */
297 /*         case DDERR_INVALIDCAPS: */
298 /*                 Msg("DDERR_INVALIDCAPS"); break; */
299 /*         case DDERR_INVALIDCLIPLIST: */
300 /*                 Msg("DDERR_INVALIDCLIPLIST"); break; */
301 /*         case DDERR_INVALIDMODE: */
302 /*                 Msg("DDERR_INVALIDMODE"); break; */
303 /*         case DDERR_INVALIDOBJECT: */
304 /*                 Msg("DDERR_INVALIDOBJECT"); break; */
305 /*         case DDERR_INVALIDPARAMS: */
306 /*                 Msg("DDERR_INVALIDPARAMS"); break; */
307 /*         case DDERR_INVALIDPIXELFORMAT: */
308 /*                 Msg("DDERR_INVALIDPIXELFORMAT"); break; */
309 /*         case DDERR_INVALIDRECT: */
310 /*                 Msg("DDERR_INVALIDRECT"); break; */
311 /*         case DDERR_LOCKEDSURFACES: */
312 /*                 Msg("DDERR_LOCKEDSURFACES"); break; */
313 /*         case DDERR_NO3D: */
314 /*                 Msg("DDERR_NO3D"); break; */
315 /*         case DDERR_NOALPHAHW: */
316 /*                 Msg("DDERR_NOALPHAHW"); break; */
317 /*         case DDERR_NOCLIPLIST: */
318 /*                 Msg("DDERR_NOCLIPLIST"); break; */
319 /*         case DDERR_NOCOLORCONVHW: */
320 /*                 Msg("DDERR_NOCOLORCONVHW"); break; */
321 /*         case DDERR_NOCOOPERATIVELEVELSET: */
322 /*                 Msg("DDERR_NOCOOPERATIVELEVELSET"); break; */
323 /*         case DDERR_NOCOLORKEY: */
324 /*                 Msg("DDERR_NOCOLORKEY"); break; */
325 /*         case DDERR_NOCOLORKEYHW: */
326 /*                 Msg("DDERR_NOCOLORKEYHW"); break; */
327 /*         case DDERR_NODIRECTDRAWSUPPORT: */
328 /*                 Msg("DDERR_NODIRECTDRAWSUPPORT"); break; */
329 /*         case DDERR_NOEXCLUSIVEMODE: */
330 /*                 Msg("DDERR_NOEXCLUSIVEMODE"); break; */
331 /*         case DDERR_NOFLIPHW: */
332 /*                 Msg("DDERR_NOFLIPHW"); break; */
333 /*         case DDERR_NOGDI: */
334 /*                 Msg("DDERR_NOGDI"); break; */
335 /*         case DDERR_NOMIRRORHW: */
336 /*                 Msg("DDERR_NOMIRRORHW"); break; */
337 /*         case DDERR_NOTFOUND: */
338 /*                 Msg("DDERR_NOTFOUND"); break; */
339 /*         case DDERR_NOOVERLAYHW: */
340 /*                 Msg("DDERR_NOOVERLAYHW"); break; */
341 /*         case DDERR_NORASTEROPHW: */
342 /*                 Msg("DDERR_NORASTEROPHW"); break; */
343 /*         case DDERR_NOROTATIONHW: */
344 /*                 Msg("DDERR_NOROTATIONHW"); break; */
345 /*         case DDERR_NOSTRETCHHW: */
346 /*                 Msg("DDERR_NOSTRETCHHW"); break; */
347 /*         case DDERR_NOT4BITCOLOR: */
348 /*                 Msg("DDERR_NOT4BITCOLOR"); break; */
349 /*         case DDERR_NOT4BITCOLORINDEX: */
350 /*                 Msg("DDERR_NOT4BITCOLORINDEX"); break; */
351 /*         case DDERR_NOT8BITCOLOR: */
352 /*                 Msg("DDERR_NOT8BITCOLOR"); break; */
353 /*         case DDERR_NOTEXTUREHW: */
354 /*                 Msg("DDERR_NOTEXTUREHW"); break; */
355 /*         case DDERR_NOVSYNCHW: */
356 /*                 Msg("DDERR_NOVSYNCHW"); break; */
357 /*         case DDERR_NOZBUFFERHW: */
358 /*                 Msg("DDERR_NOZBUFFERHW"); break; */
359 /*         case DDERR_NOZOVERLAYHW: */
360 /*                 Msg("DDERR_NOZOVERLAYHW"); break; */
361 /*         case DDERR_OUTOFCAPS: */
362 /*                 Msg("DDERR_OUTOFCAPS"); break; */
363 /*         case DDERR_OUTOFMEMORY: */
364 /*                 Msg("DDERR_OUTOFMEMORY"); break; */
365 /*         case DDERR_OUTOFVIDEOMEMORY: */
366 /*                 Msg("DDERR_OUTOFVIDEOMEMORY"); break; */
367 /*         case DDERR_OVERLAYCANTCLIP: */
368 /*                 Msg("DDERR_OVERLAYCANTCLIP"); break; */
369 /*         case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: */
370 /*                 Msg("DDERR_OVERLAYCOLORKEYONLYONEACTIVE"); break; */
371 /*         case DDERR_PALETTEBUSY: */
372 /*                 Msg("DDERR_PALETTEBUSY"); break; */
373 /*         case DDERR_COLORKEYNOTSET: */
374 /*                 Msg("DDERR_COLORKEYNOTSET"); break; */
375 /*         case DDERR_SURFACEALREADYATTACHED: */
376 /*                 Msg("DDERR_SURFACEALREADYATTACHED"); break; */
377 /*         case DDERR_SURFACEALREADYDEPENDENT: */
378 /*                 Msg("DDERR_SURFACEALREADYDEPENDENT"); break; */
379 /*         case DDERR_SURFACEBUSY: */
380 /*                 Msg("DDERR_SURFACEBUSY"); break; */
381 /*         case DDERR_CANTLOCKSURFACE: */
382 /*                 Msg("DDERR_CANTLOCKSURFACE"); break; */
383 /*         case DDERR_SURFACEISOBSCURED: */
384 /*                 Msg("DDERR_SURFACEISOBSCURED"); break; */
385 /*         case DDERR_SURFACELOST: */
386 /*                 Msg("DDERR_SURFACELOST"); break; */
387 /*         case DDERR_SURFACENOTATTACHED: */
388 /*                 Msg("DDERR_SURFACENOTATTACHED"); break; */
389 /*         case DDERR_TOOBIGHEIGHT: */
390 /*                 Msg("DDERR_TOOBIGHEIGHT"); break; */
391 /*         case DDERR_TOOBIGSIZE: */
392 /*                 Msg("DDERR_TOOBIGSIZE"); break; */
393 /*         case DDERR_TOOBIGWIDTH: */
394 /*                 Msg("DDERR_TOOBIGWIDTH"); break; */
395 /*         case DDERR_UNSUPPORTED: */
396 /*                 Msg("DDERR_UNSUPPORTED"); break; */
397 /*         case DDERR_UNSUPPORTEDFORMAT: */
398 /*                 Msg("DDERR_UNSUPPORTEDFORMAT"); break; */
399 /*         case DDERR_UNSUPPORTEDMASK: */
400 /*                 Msg("DDERR_UNSUPPORTEDMASK"); break; */
401 /*         case DDERR_VERTICALBLANKINPROGRESS: */
402 /*                 Msg("DDERR_VERTICALBLANKINPROGRESS"); break; */
403 /*         case DDERR_WASSTILLDRAWING: */
404 /*                 Msg("DDERR_WASSTILLDRAWING"); break; */
405 /*         case DDERR_XALIGN: */
406 /*                 Msg("DDERR_XALIGN"); break; */
407 /*         case DDERR_INVALIDDIRECTDRAWGUID: */
408 /*                 Msg("DDERR_INVALIDDIRECTDRAWGUID"); break; */
409 /*         case DDERR_DIRECTDRAWALREADYCREATED: */
410 /*                 Msg("DDERR_DIRECTDRAWALREADYCREATED"); break; */
411 /*         case DDERR_NODIRECTDRAWHW: */
412 /*                 Msg("DDERR_NODIRECTDRAWHW"); break; */
413 /*         case DDERR_PRIMARYSURFACEALREADYEXISTS: */
414 /*                 Msg("DDERR_PRIMARYSURFACEALREADYEXISTS"); break; */
415 /*         case DDERR_NOEMULATION: */
416 /*                 Msg("DDERR_NOEMULATION"); break; */
417 /*         case DDERR_REGIONTOOSMALL: */
418 /*                 Msg("DDERR_REGIONTOOSMALL"); break; */
419 /*         case DDERR_CLIPPERISUSINGHWND: */
420 /*                 Msg("DDERR_CLIPPERISUSINGHWND"); break; */
421 /*         case DDERR_NOCLIPPERATTACHED: */
422 /*                 Msg("DDERR_NOCLIPPERATTACHED"); break; */
423 /*         case DDERR_NOHWND: */
424 /*                 Msg("DDERR_NOHWND"); break; */
425 /*         case DDERR_HWNDSUBCLASSED: */
426 /*                 Msg("DDERR_HWNDSUBCLASSED"); break; */
427 /*         case DDERR_HWNDALREADYSET: */
428 /*                 Msg("DDERR_HWNDALREADYSET"); break; */
429 /*         case DDERR_NOPALETTEATTACHED: */
430 /*                 Msg("DDERR_NOPALETTEATTACHED"); break; */
431 /*         case DDERR_NOPALETTEHW: */
432 /*                 Msg("DDERR_NOPALETTEHW"); break; */
433 /*         case DDERR_BLTFASTCANTCLIP: */
434 /*                 Msg("DDERR_BLTFASTCANTCLIP"); break; */
435 /*         case DDERR_NOBLTHW: */
436 /*                 Msg("DDERR_NOBLTHW"); break; */
437 /*         case DDERR_NODDROPSHW: */
438 /*                 Msg("DDERR_NODDROPSHW"); break; */
439 /*         case DDERR_OVERLAYNOTVISIBLE: */
440 /*                 Msg("DDERR_OVERLAYNOTVISIBLE"); break; */
441 /*         case DDERR_NOOVERLAYDEST: */
442 /*                 Msg("DDERR_NOOVERLAYDEST"); break; */
443 /*         case DDERR_INVALIDPOSITION: */
444 /*                 Msg("DDERR_INVALIDPOSITION"); break; */
445 /*         case DDERR_NOTAOVERLAYSURFACE: */
446 /*                 Msg("DDERR_NOTAOVERLAYSURFACE"); break; */
447 /*         case DDERR_EXCLUSIVEMODEALREADYSET: */
448 /*                 Msg("DDERR_EXCLUSIVEMODEALREADYSET"); break; */
449 /*         case DDERR_NOTFLIPPABLE: */
450 /*                 Msg("DDERR_NOTFLIPPABLE"); break; */
451 /*         case DDERR_CANTDUPLICATE: */
452 /*                 Msg("DDERR_CANTDUPLICATE"); break; */
453 /*         case DDERR_NOTLOCKED: */
454 /*                 Msg("DDERR_NOTLOCKED"); break; */
455 /*         case DDERR_CANTCREATEDC: */
456 /*                 Msg("DDERR_CANTCREATEDC"); break; */
457 /*         case DDERR_NODC: */
458 /*                 Msg("DDERR_NODC"); break; */
459 /*         case DDERR_WRONGMODE: */
460 /*                 Msg("DDERR_WRONGMODE"); break; */
461 /*         case DDERR_IMPLICITLYCREATED: */
462 /*                 Msg("DDERR_IMPLICITLYCREATED"); break; */
463 /*         case DDERR_NOTPALETTIZED: */
464 /*                 Msg("DDERR_NOTPALETTIZED"); break; */
465 /*         case DDERR_UNSUPPORTEDMODE: */
466 /*                 Msg("DDERR_UNSUPPORTEDMODE"); break; */
467 /*         case DDERR_NOMIPMAPHW: */
468 /*                 Msg("DDERR_NOMIPMAPHW"); break; */
469 /*         case DDERR_INVALIDSURFACETYPE: */
470 /*                 Msg("DDERR_INVALIDSURFACETYPE"); break; */
471 /*         case DDERR_DCALREADYCREATED: */
472 /*                 Msg("DDERR_DCALREADYCREATED"); break; */
473 /*         case DDERR_CANTPAGELOCK: */
474 /*                 Msg("DDERR_CANTPAGELOCK"); break; */
475 /*         case DDERR_CANTPAGEUNLOCK: */
476 /*                 Msg("DDERR_CANTPAGEUNLOCK"); break; */
477 /*         case DDERR_NOTPAGELOCKED: */
478 /*                 Msg("DDERR_NOTPAGELOCKED"); break; */
479 /*         case DDERR_NOTINITIALIZED: */
480 /*                 Msg("DDERR_NOTINITIALIZED"); break; */
481 /*         default: */
482 /*                 Msg("Unknown Error"); break; */
483 /*         } */
484 /*         Msg("\n"); */
485 /* } */
486 
487 
488 //add hardness from a sprite
489 
490 /**
491  * Get the current graphic (current sequence/current frame) for sprite
492  * 'sprite_no'
493  */
getpic(int sprite_no)494 int getpic(int sprite_no)
495 {
496   if (spr[sprite_no].pseq == 0)
497     return 0;
498 
499   if (spr[sprite_no].pseq >= MAX_SEQUENCES)
500     {
501       log_error("Sequence %d?  But max is %d!", spr[sprite_no].pseq, MAX_SEQUENCES);
502       return 0;
503     }
504 
505   return seq[spr[sprite_no].pseq].frame[spr[sprite_no].pframe];
506 }
507 
508 
add_hardness(int sprite,int num)509 void add_hardness (int sprite, int num)
510 {
511   int xx;
512   for (xx = spr[sprite].x + k[getpic(sprite)].hardbox.left; xx < spr[sprite].x + k[getpic(sprite)].hardbox.right; xx++)
513     {
514       int yy;
515       for (yy = spr[sprite].y + k[getpic(sprite)].hardbox.top; yy < spr[sprite].y + k[getpic(sprite)].hardbox.bottom; yy++)
516 	{
517 	  if ( (xx-20 > 600) | (xx-20 < 0)| (yy > 400) | (yy < 0))
518 	    ; /* Nothing */
519 	  else
520 	    hm.x[xx-20].y[yy] = num;
521 	}
522     }
523 }
524 
525 
526 
527 
528 /**
529  * Check whether planned new position (x1,y1) is solid
530  *
531  * Only used in 'check_if_move_is_legal'
532  */
get_hard(int x1,int y1)533 unsigned char get_hard(int x1, int y1)
534 {
535   if (screenlock)
536     {
537       if (x1 < 0)        x1 = 0;
538       else if (x1 > 599) x1 = 599;
539 
540       if (y1 < 0)        y1 = 0;
541       else if (y1 > 399) y1 = 399;
542     }
543   if ((x1 < 0) || (y1 < 0) || (x1 > 599) || (y1 > 399))
544     return 0;
545 
546   int value = hm.x[x1].y[y1];
547   return(value);
548 }
549 
550 /**
551  * Check whether planned new position (x1,y1) is solid
552  *
553  * Does something weird when hard value is > 100??
554  *
555  * Only used in 'human_brain'
556  */
get_hard_play(int h,int x1,int y1)557 unsigned char get_hard_play(int h, int x1, int y1)
558 {
559   x1 -= 20;
560 
561   if (screenlock)
562     {
563       if (x1 < 0)        x1 = 0;
564       else if (x1 > 599) x1 = 599;
565 
566       if (y1 < 0)        y1 = 0;
567       else if (y1 > 399) y1 = 399;
568     }
569   if ((x1 < 0) || (y1 < 0) || (x1 > 599) || (y1 > 399))
570     return 0;
571 
572   int value =  hm.x[x1].y[y1];
573   if (value > 100 && pam.sprite[value-100].is_warp != 0)
574     {
575       flub_mode = value;
576       value = 0;
577     }
578   return(value);
579 }
580 
581 
get_hard_map(int h,int x1,int y1)582 unsigned char get_hard_map(int h,int x1, int y1)
583 {
584 
585 
586         if ((x1 < 0) || (y1 < 0)) return(0);
587         if ((x1 > 599) ) return(0);
588         if (y1 > 399) return(0);
589 
590 
591         int til = (x1 / 50) + ( ((y1 / 50)) * 12);
592         //til++;
593 
594         int offx = x1 - ((x1 / 50) * 50);
595 
596 
597         int offy = y1 - ((y1 / 50) * 50);
598 
599         //Msg("tile %d ",til);
600 
601         return( hmap.htile[ realhard(til )  ].x[offx].y[offy]);
602 
603 }
604 
605 
606 
fill_hardxy(rect box)607 void fill_hardxy(rect box)
608 {
609   int x1, y1;
610   //Msg("filling hard of %d %d %d %d", box.top, box.left, box.right, box.bottom);
611 
612   if (box.right > 600)  box.right  = 600;
613   if (box.top < 0)      box.top    = 0;
614   if (box.bottom > 400) box.bottom = 400;
615   if (box.left < 0)     box.left   = 0;
616 
617   for (x1 = box.left; x1 < box.right; x1++)
618     for (y1 = box.top; y1 < box.bottom; y1++)
619       hm.x[x1].y[y1] = get_hard_map(0,x1,y1);
620 }
621 
622 
623 /**
624  * Add experience - no "did the player really kill this enemy?"
625  * checks
626  */
add_exp_force(int num,int source_sprite)627 void add_exp_force(int num, int source_sprite)
628 {
629   if (num > 0)
630     {
631       //add experience
632       *pexper += num;
633 
634       int crap2 = add_sprite(spr[source_sprite].x, spr[source_sprite].y, 8, 0, 0);
635       spr[crap2].y -= k[seq[spr[source_sprite].pseq].frame[spr[source_sprite].pframe]].yoffset;
636       spr[crap2].x -= k[seq[spr[source_sprite].pseq].frame[spr[source_sprite].pframe]].xoffset;
637       spr[crap2].y -= k[seq[spr[source_sprite].pseq].frame[spr[source_sprite].pframe]].box.bottom / 3;
638       spr[crap2].x += k[seq[spr[source_sprite].pseq].frame[spr[source_sprite].pframe]].box.right / 5;
639       spr[crap2].y -= 30;
640       spr[crap2].speed = 1;
641       spr[crap2].hard = 1;
642       spr[crap2].brain_parm = 5000;
643       spr[crap2].my = -1;
644       spr[crap2].kill = 1000;
645       spr[crap2].dir = 8;
646       spr[crap2].damage = num;
647 
648       if (*pexper > 99999)
649 	*pexper = 99999;
650     }
651 }
652 
add_exp(int num,int killed_sprite)653 void add_exp(int num, int killed_sprite)
654 {
655   if (spr[killed_sprite].last_hit != 1)
656     return;
657 
658   add_exp_force(num, killed_sprite);
659 }
660 
661 /**
662  * Return hardness index for this screen tile, either its default
663  * hardness, or the replaced/alternative hardness. Tile is in [0,95].
664  */
realhard(int tile)665 int realhard(int tile)
666 {
667   if (pam.t[tile].althard > 0)
668     return(pam.t[tile].althard);
669   else
670     return(hmap.btile_default[pam.t[tile].square_full_idx0]);
671 }
672 
673 
fill_whole_hard(void)674 void fill_whole_hard(void)
675 {
676   int til;
677   for (til=0; til < 96; til++)
678     {
679       int offx = (til * 50 - ((til / 12) * 600));
680       int offy = (til / 12) * 50;
681       int x, y;
682       for (x = 0; x < 50; x++)
683 	for (y = 0; y < 50; y++)
684 	  hm.x[offx +x].y[offy+y] = hmap.htile[  realhard(til)  ].x[x].y[y];
685     }
686 }
687 
688 /* Draw harness. Used by freedinkedit and updateFrame() in hard-coded
689    cheat mode. */
drawallhard(void)690 void drawallhard( void)
691 {
692 /*   rect box_crap; */
693 /*   int ddrval; */
694 /*   DDBLTFX     ddbltfx; */
695   int x1, y1;
696 
697   /* TODO: test me! Then factor the code */
698   for (x1=0; x1 < 600; x1++)
699     for (y1=0; y1 < 400; y1++)
700       {
701 	if (hm.x[x1].y[y1] == 1)
702 	  {
703 /* 	    ddbltfx.dwFillColor = 1; */
704 /* 	    ddbltfx.dwSize = sizeof(ddbltfx); */
705 /* 	    box_crap.top = y1; */
706 /* 	    box_crap.bottom = y1+1; */
707 /* 	    box_crap.left = x1+playl; //20 is to compensate for the border */
708 /* 	    box_crap.right = x1+1+playl; */
709 /* 	    ddrval = lpDDSBack->Blt(&box_crap ,NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); */
710 /* 	    if (ddrval != DD_OK) Msg("There was an error!"); */
711 	    // GFX
712 	    {
713 	      SDL_Rect GFX_box_crap;
714 	      GFX_box_crap.x = x1 + playl;
715 	      GFX_box_crap.y = y1;
716 	      GFX_box_crap.w = 1;
717 	      GFX_box_crap.h = 1;
718 	      SDL_FillRect(GFX_lpDDSBack, &GFX_box_crap,
719 			   SDL_MapRGB(GFX_lpDDSBack->format,
720 				      GFX_real_pal[1].r,
721 				      GFX_real_pal[1].g,
722 				      GFX_real_pal[1].b));
723 	    }
724 	  }
725 
726 	if (hm.x[x1].y[y1] == 2)
727 	  {
728 /* 	    ddbltfx.dwFillColor = 128; */
729 /* 	    ddbltfx.dwSize = sizeof(ddbltfx); */
730 /* 	    box_crap.top = y1; */
731 /* 	    box_crap.bottom = y1+1; */
732 /* 	    box_crap.left = x1+playl; //20 is to compensate for the border */
733 /* 	    box_crap.right = x1+1+playl; */
734 /* 	    ddrval = lpDDSBack->Blt(&box_crap ,NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); */
735 /* 	    if (ddrval != DD_OK) Msg("There was an error!"); */
736 	    // GFX
737 	    {
738 	      SDL_Rect GFX_box_crap;
739 	      GFX_box_crap.x = x1 + playl;
740 	      GFX_box_crap.y = y1;
741 	      GFX_box_crap.w = 1;
742 	      GFX_box_crap.h = 1;
743 	      SDL_FillRect(GFX_lpDDSBack, &GFX_box_crap,
744 			   SDL_MapRGB(GFX_lpDDSBack->format,
745 				      GFX_real_pal[128].r,
746 				      GFX_real_pal[128].g,
747 				      GFX_real_pal[128].b));
748 	    }
749 	  }
750 
751 	if (hm.x[x1].y[y1] == 3)
752 	  {
753 /* 	    ddbltfx.dwFillColor = 45; */
754 /* 	    ddbltfx.dwSize = sizeof(ddbltfx); */
755 /* 	    box_crap.top = y1; */
756 /* 	    box_crap.bottom = y1+1; */
757 /* 	    box_crap.left = x1+playl; //20 is to compensate for the border */
758 /* 	    box_crap.right = x1+1+playl; */
759 /* 	    ddrval = lpDDSBack->Blt(&box_crap ,NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); */
760 /* 	    if (ddrval != DD_OK) Msg("There was an error!"); */
761 	    // GFX
762 	    {
763 	      SDL_Rect GFX_box_crap;
764 	      GFX_box_crap.x = x1 + playl;
765 	      GFX_box_crap.y = y1;
766 	      GFX_box_crap.w = 1;
767 	      GFX_box_crap.h = 1;
768 	      SDL_FillRect(GFX_lpDDSBack, &GFX_box_crap,
769 			   SDL_MapRGB(GFX_lpDDSBack->format,
770 				      GFX_real_pal[45].r,
771 				      GFX_real_pal[45].g,
772 				      GFX_real_pal[45].b));
773 	    }
774 	  }
775 
776 	if (hm.x[x1].y[y1] > 100)
777 	  {
778 
779 	    if (pam.sprite[  (hm.x[x1].y[y1]) - 100].is_warp == 1)
780 	      {
781 		//draw a little pixel
782 /* 		ddbltfx.dwFillColor = 20; */
783 /* 		ddbltfx.dwSize = sizeof(ddbltfx); */
784 /* 		box_crap.top = y1; */
785 /* 		box_crap.bottom = y1+1; */
786 /* 		box_crap.left = x1+playl; //20 is to compensate for the border */
787 /* 		box_crap.right = x1+1+playl; */
788 /* 		ddrval = lpDDSBack->Blt(&box_crap ,NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); */
789 /* 		if (ddrval != DD_OK) Msg("There was an error!"); */
790 		// GFX
791 		{
792 		  SDL_Rect GFX_box_crap;
793 		  GFX_box_crap.x = x1 + playl;
794 		  GFX_box_crap.y = y1;
795 		  GFX_box_crap.w = 1;
796 		  GFX_box_crap.h = 1;
797 		  SDL_FillRect(GFX_lpDDSBack, &GFX_box_crap,
798 			       SDL_MapRGB(GFX_lpDDSBack->format,
799 					  GFX_real_pal[20].r,
800 					  GFX_real_pal[20].g,
801 					  GFX_real_pal[20].b));
802 		}
803 	      }
804 	    else
805 	      {
806 		//draw a little pixel
807 /* 		ddbltfx.dwFillColor = 23; */
808 /* 		ddbltfx.dwSize = sizeof(ddbltfx); */
809 /* 		box_crap.top = y1; */
810 /* 		box_crap.bottom = y1+1; */
811 /* 		box_crap.left = x1+playl; //20 is to compensate for the border */
812 /* 		box_crap.right = x1+1+playl; */
813 /* 		ddrval = lpDDSBack->Blt(&box_crap ,NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); */
814 /* 		if (ddrval != DD_OK) Msg("There was an error!"); */
815 		// GFX
816 		{
817 		  SDL_Rect GFX_box_crap;
818 		  GFX_box_crap.x = x1 + playl;
819 		  GFX_box_crap.y = y1;
820 		  GFX_box_crap.w = 1;
821 		  GFX_box_crap.h = 1;
822 		  SDL_FillRect(GFX_lpDDSBack, &GFX_box_crap,
823 			       SDL_MapRGB(GFX_lpDDSBack->format,
824 					  GFX_real_pal[23].r,
825 					  GFX_real_pal[23].g,
826 					  GFX_real_pal[23].b));
827 		}
828 	      }
829 	  }
830       }
831 }
832 
833 
834 /**
835  * Resurrect sprites that were temporarily disabled
836  * (editor_type(6/7/8))
837  */
fix_dead_sprites()838 void fix_dead_sprites()
839 {
840   int i;
841   if (dinkedit) return;
842 
843   for (i = 1; i < 100; i++)
844     {
845       int type = play.spmap[*pmap].type[i];
846 
847       // Resurrect sprites after 5mn
848       if (type == 6)
849 	{
850 	  if  ((thisTickCount > (play.spmap[*pmap].last_time + 300000))
851 	       || (thisTickCount + 400000 < play.spmap[*pmap].last_time + 300000))
852 	    {
853 	      //this sprite can come back online now
854 	      play.spmap[*pmap].type[i] = 0;
855 	    }
856 	}
857 
858       // Resurrect sprites after 3mn
859       if (type == 7)
860 	{
861 	  if (thisTickCount > (play.spmap[*pmap].last_time + 180000))
862 	    {
863 	      //this sprite can come back online now
864 	      play.spmap[*pmap].type[i] = 0;
865 	    }
866 	}
867 
868       // Resurrect sprites after 1mn
869       if (type == 8)
870 	{
871 	  if (thisTickCount > (play.spmap[*pmap].last_time + 60000))
872 	    {
873 	      //this sprite can come back online now
874 	      play.spmap[*pmap].type[i] = 0;
875 	    }
876 	}
877     }
878 }
879 
880 /**
881  * Load 1 screen from specified map.dat in specified memory buffer
882  */
load_map_to(char * path,const int num,struct small_map * screen)883 int load_map_to(char* path, const int num, struct small_map* screen)
884 {
885   /* Instead of using 'fseek(...)' when we want to skip a little bit
886      of data, we read it to this buffer - this is much faster on PSP
887      (1000ms -> 60ms), probably related to cache validation. No
888      noticeable change on PC (<1ms). */
889   char skipbuf[10000]; // more than any fseek we do
890 
891   FILE *f = NULL;
892   long holdme,lsize;
893   f = paths_dmodfile_fopen(path, "rb");
894   if (!f)
895     {
896       log_error("Cannot find %s file!!!", path);
897       return -1;
898     }
899   lsize = 31280; // sizeof(struct small_map); // under ia32, not portable
900   holdme = (lsize * (num-1));
901   fseek(f, holdme, SEEK_SET);
902   //Msg("Trying to read %d bytes with offset of %d",lsize,holdme);
903 
904   /* Portably load map structure from disk */
905   int i = 0;
906   fread(skipbuf, 20, 1, f); // unused 'name' field
907   for (i = 0; i < 97; i++)
908     {
909       screen->t[i].square_full_idx0 = read_lsb_int(f);
910       fread(skipbuf, 4, 1, f); // unused 'property' field
911       screen->t[i].althard = read_lsb_int(f);
912       fread(skipbuf, 6, 1, f); // unused 'more2', 'more3', 'more4' fields
913       fread(skipbuf, 2, 1, f); // reproduce memory alignment
914       fread(skipbuf, 60, 1, f); // unused 'buff' field
915     }
916   // offset 7780
917 
918   fread(skipbuf, 160, 1, f); // unused 'v' field
919   fread(skipbuf, 80, 1, f);  // unused 's' field
920   // offset 8020
921 
922   /* struct sprite_placement sprite[101]; */
923   /* size = 220 */
924   for (i = 0; i < 101; i++)
925     {
926       screen->sprite[i].x = read_lsb_int(f);
927       screen->sprite[i].y = read_lsb_int(f);
928       screen->sprite[i].seq = read_lsb_int(f);
929       screen->sprite[i].frame = read_lsb_int(f);
930       screen->sprite[i].type = read_lsb_int(f);
931       screen->sprite[i].size = read_lsb_int(f);
932 
933       screen->sprite[i].active = fgetc(f);
934       fread(skipbuf, 3, 1, f); // reproduce memory alignment
935       // offset 28
936 
937       screen->sprite[i].rotation = read_lsb_int(f);
938       screen->sprite[i].special = read_lsb_int(f);
939       screen->sprite[i].brain = read_lsb_int(f);
940 
941       fread(screen->sprite[i].script, 14, 1, f);
942       screen->sprite[i].script[14-1] = '\0'; // safety
943       fread(skipbuf, 38, 1, f); // unused hit/die/talk fields
944       // offset 92
945 
946       screen->sprite[i].speed = read_lsb_int(f);
947       screen->sprite[i].base_walk = read_lsb_int(f);
948       screen->sprite[i].base_idle = read_lsb_int(f);
949       screen->sprite[i].base_attack = read_lsb_int(f);
950       screen->sprite[i].base_hit = read_lsb_int(f);
951       screen->sprite[i].timer = read_lsb_int(f);
952       screen->sprite[i].que = read_lsb_int(f);
953       screen->sprite[i].hard = read_lsb_int(f);
954       // offset 124
955 
956       screen->sprite[i].alt.left = read_lsb_int(f);
957       screen->sprite[i].alt.top = read_lsb_int(f);
958       screen->sprite[i].alt.right = read_lsb_int(f);
959       screen->sprite[i].alt.bottom = read_lsb_int(f);
960       // offset 140
961 
962       screen->sprite[i].is_warp = read_lsb_int(f);
963       screen->sprite[i].warp_map = read_lsb_int(f);
964       screen->sprite[i].warp_x = read_lsb_int(f);
965       screen->sprite[i].warp_y = read_lsb_int(f);
966       screen->sprite[i].parm_seq = read_lsb_int(f);
967       // offset 160
968 
969       screen->sprite[i].base_die = read_lsb_int(f);
970       screen->sprite[i].gold = read_lsb_int(f);
971       screen->sprite[i].hitpoints = read_lsb_int(f);
972       screen->sprite[i].strength = read_lsb_int(f);
973       screen->sprite[i].defense = read_lsb_int(f);
974       screen->sprite[i].exp = read_lsb_int(f);
975       screen->sprite[i].sound = read_lsb_int(f);
976       screen->sprite[i].vision = read_lsb_int(f);
977       screen->sprite[i].nohit = read_lsb_int(f);
978       screen->sprite[i].touch_damage = read_lsb_int(f);
979       // offset 200
980 
981       int j = 0;
982       for (j = 0; j < 5; j++)
983 	screen->sprite[i].buff[j] = read_lsb_int(f);
984     }
985   // offset 30204
986 
987   fread(screen->script, 21, 1, f);
988   screen->script[21-1] = '\0'; // safety
989   fread(skipbuf, 1018, 1, f); // unused hit/die/talk fields
990   fread(skipbuf, 1, 1, f); // reproduce memory alignment
991   // offset 31280
992 
993   fclose(f);
994   return 0;
995 }
996 
997 /**
998  * Load 1 screen from map.dat, which contains all 768 game screens
999  */
load_map(const int num)1000 int load_map(const int num)
1001 {
1002   if (load_map_to(current_map, num, &pam) < 0)
1003     return -1;
1004 
1005   spr[1].move_active = 0;
1006   if (dversion >= 108)
1007     spr[1].move_nohard = 0;
1008   spr[1].freeze = 0;
1009   screenlock = 0;
1010   fill_whole_hard();
1011   fix_dead_sprites();
1012 
1013   if (!dinkedit)
1014     check_midi();
1015 
1016   //   draw_map_game();
1017   return 0;
1018 }
1019 
1020 /**
1021  * Save screen number 'num' in the map. Only used by the editor.
1022  */
save_map(const int num)1023 void save_map(const int num)
1024 {
1025   /* Instead of using 'fseek(...)' when we want to skip a little bit
1026      of data, we read it to this buffer - this is much faster on PSP
1027      (1000ms -> 60ms), probably related to cache validation. No
1028      noticeable change on PC (<1ms). */
1029   char skipbuf[10000]; // more than any fseek we do
1030   memset(skipbuf, 0, 10000);
1031 
1032   FILE *f = NULL;
1033   long holdme,lsize;
1034 
1035   log_info("Saving map data..");
1036   if (num > 0)
1037     {
1038       f = paths_dmodfile_fopen(current_map, "r+b");
1039       if (f == NULL)
1040 	{
1041 	  perror("Cannot save map");
1042 	  return;
1043 	}
1044       lsize = 31280; // sizeof(struct small_map); // under ia32, not portable
1045       holdme = (lsize * (num-1));
1046       fseek(f, holdme, SEEK_SET);
1047 
1048 
1049       /* Portably dump map structure */
1050       int i = 0;
1051       char name[20] = "Smallwood";
1052       fwrite(name, 20, 1, f);
1053       for (i = 0; i < 97; i++)
1054 	{
1055 	  write_lsb_int(pam.t[i].square_full_idx0, f);
1056 	  fwrite(skipbuf, 4, 1, f); // unused 'property' field
1057 	  write_lsb_int(pam.t[i].althard, f);
1058 	  fwrite(skipbuf, 6, 1, f); // unused 'more2', 'more3', 'more4' fields
1059 	  fwrite(skipbuf, 2, 1, f); // reproduce memory alignment
1060 	  fwrite(skipbuf, 60, 1, f); // unused 'buff' field
1061 	}
1062       // offset 7780
1063 
1064       fwrite(skipbuf, 160, 1, f); // unused 'v' field
1065       fwrite(skipbuf, 80, 1, f);  // unused 's' field
1066       // offset 8020
1067 
1068       /* struct sprite_placement sprite[101]; */
1069       /* size = 220 */
1070       for (i = 0; i < 101; i++)
1071 	{
1072 	  write_lsb_int(pam.sprite[i].x, f);
1073 	  write_lsb_int(pam.sprite[i].y, f);
1074 	  write_lsb_int(pam.sprite[i].seq, f);
1075 	  write_lsb_int(pam.sprite[i].frame, f);
1076 	  write_lsb_int(pam.sprite[i].type, f);
1077 	  write_lsb_int(pam.sprite[i].size, f);
1078 
1079 	  fputc(pam.sprite[i].active, f);
1080 	  fwrite(skipbuf, 3, 1, f); // reproduce memory alignment
1081 	  // offset 28
1082 
1083 	  write_lsb_int(pam.sprite[i].rotation, f);
1084 	  write_lsb_int(pam.sprite[i].special, f);
1085 	  write_lsb_int(pam.sprite[i].brain, f);
1086 
1087 	  fwrite(pam.sprite[i].script, 14, 1, f);
1088 	  fwrite(skipbuf, 38, 1, f); // reproduce memory alignment
1089 	  // offset 92
1090 
1091 	  write_lsb_int(pam.sprite[i].speed, f);
1092 	  write_lsb_int(pam.sprite[i].base_walk, f);
1093 	  write_lsb_int(pam.sprite[i].base_idle, f);
1094 	  write_lsb_int(pam.sprite[i].base_attack, f);
1095 	  write_lsb_int(pam.sprite[i].base_hit, f);
1096 	  write_lsb_int(pam.sprite[i].timer, f);
1097 	  write_lsb_int(pam.sprite[i].que, f);
1098 	  write_lsb_int(pam.sprite[i].hard, f);
1099 	  // offset 124
1100 
1101 	  write_lsb_int(pam.sprite[i].alt.left, f);
1102 	  write_lsb_int(pam.sprite[i].alt.top, f);
1103 	  write_lsb_int(pam.sprite[i].alt.right, f);
1104 	  write_lsb_int(pam.sprite[i].alt.bottom, f);
1105 	  // offset 140
1106 
1107 	  write_lsb_int(pam.sprite[i].is_warp, f);
1108 	  write_lsb_int(pam.sprite[i].warp_map, f);
1109 	  write_lsb_int(pam.sprite[i].warp_x, f);
1110 	  write_lsb_int(pam.sprite[i].warp_y, f);
1111 	  write_lsb_int(pam.sprite[i].parm_seq, f);
1112 	  // offset 160
1113 
1114 	  write_lsb_int(pam.sprite[i].base_die, f);
1115 	  write_lsb_int(pam.sprite[i].gold, f);
1116 	  write_lsb_int(pam.sprite[i].hitpoints, f);
1117 	  write_lsb_int(pam.sprite[i].strength, f);
1118 	  write_lsb_int(pam.sprite[i].defense, f);
1119 	  write_lsb_int(pam.sprite[i].exp, f);
1120 	  write_lsb_int(pam.sprite[i].sound, f);
1121 	  write_lsb_int(pam.sprite[i].vision, f);
1122 	  write_lsb_int(pam.sprite[i].nohit, f);
1123 	  write_lsb_int(pam.sprite[i].touch_damage, f);
1124 	  // offset 200
1125 
1126 	  int j = 0;
1127 	  for (j = 0; j < 5; j++)
1128 	    write_lsb_int(pam.sprite[i].buff[j], f);
1129 	}
1130       // offset 30204
1131 
1132       fwrite(pam.script, 21, 1, f);
1133       fwrite(skipbuf, 1018, 1, f); // unused random/load/buffer fields
1134       fwrite(skipbuf, 1, 1, f); // reproduce memory alignment
1135       // offset 31280
1136 
1137       fclose(f);
1138     }
1139 
1140   log_info("Done saving map data..");
1141 }
1142 
1143 
1144 
1145 /**
1146  * Save dink.dat (index of map offsets + midi# + indoor/outdoor)
1147  */
save_info(void)1148 void save_info(void)
1149 {
1150   FILE *f = paths_dmodfile_fopen(current_dat, "wb");
1151   if (f == NULL)
1152     {
1153       perror("Cannot save dink.dat");
1154       return;
1155     }
1156 
1157   /* Portably dump struct map_info to disk */
1158   int i = 0;
1159   char name[20] = "Smallwood";
1160   fwrite(name, 20, 1, f);
1161   for (i = 0; i < 769; i++)
1162     write_lsb_int(map.loc[i],    f);
1163   for (i = 0; i < 769; i++)
1164     write_lsb_int(map.music[i],  f);
1165   for (i = 0; i < 769; i++)
1166     write_lsb_int(map.indoor[i], f);
1167   fseek(f, 2240, SEEK_CUR); // unused field
1168 
1169   fclose(f);
1170 }
1171 
1172 
1173 
load_game(int num)1174 /*bool*/int load_game(int num)
1175 {
1176   /* Instead of using 'fseek(...)' when we want to skip a little bit
1177      of data, we read it to this buffer - this is much faster on PSP
1178      (1000ms -> 60ms), probably related to cache validation. No
1179      noticeable change on PC (<1ms). */
1180   char skipbuf[10000]; // more than any fseek we do
1181 
1182   FILE *f = NULL;
1183 
1184   //lets get rid of our magic and weapon scripts
1185   if (weapon_script != 0)
1186     {
1187       if (locate(weapon_script, "DISARM"))
1188 	{
1189 	  run_script(weapon_script);
1190 	}
1191     }
1192 
1193   if (magic_script != 0 && locate(magic_script, "DISARM"))
1194     run_script(magic_script);
1195 
1196   bow.active = /*false*/0;
1197   weapon_script = 0;
1198   magic_script = 0;
1199   midi_active = /*true*/1;
1200 
1201   if (last_saved_game > 0)
1202     {
1203       log_info("Modifying saved game.");
1204       if (!add_time_to_saved_game(last_saved_game))
1205 	log_error("Error modifying saved game.");
1206     }
1207   StopMidi();
1208 
1209   f = paths_savegame_fopen(num, "rb");
1210   if (!f)
1211     {
1212       log_error("Couldn't load save game %d", num);
1213       return /*false*/0;
1214     }
1215 
1216 
1217   /* Portably load struct player_info play from disk */
1218   int i = 0;
1219   // TODO: check 'version' field and warn/upgrade/downgrade if
1220   // savegame version != dversion
1221   fread(skipbuf, 4, 1, f);
1222   fread(skipbuf, 77+1, 1, f); // skip save_game_info, cf. save_game_small(...)
1223   fread(skipbuf, 118, 1, f); // unused
1224   // offset 200
1225   play.minutes = read_lsb_int(f);
1226   spr[1].x = read_lsb_int(f);
1227   spr[1].y = read_lsb_int(f);
1228   fread(skipbuf, 4, 1, f); // unused 'die' field
1229   spr[1].size = read_lsb_int(f);
1230   spr[1].defense = read_lsb_int(f);
1231   spr[1].dir = read_lsb_int(f);
1232   spr[1].pframe = read_lsb_int(f);
1233   spr[1].pseq = read_lsb_int(f);
1234   spr[1].seq = read_lsb_int(f);
1235   spr[1].frame = read_lsb_int(f);
1236   spr[1].strength = read_lsb_int(f);
1237   spr[1].base_walk = read_lsb_int(f);
1238   spr[1].base_idle = read_lsb_int(f);
1239   spr[1].base_hit = read_lsb_int(f);
1240   spr[1].que = read_lsb_int(f);
1241   // offset 264
1242 
1243   // skip first originally unused mitem entry
1244   fread(skipbuf, 20, 1, f);
1245   for (i = 0; i < NB_MITEMS; i++)
1246     {
1247       play.mitem[i].active = fgetc(f);
1248       fread(play.mitem[i].name, 11, 1, f);
1249       /* The item script could overflow, overwriting 'seq'; if */
1250       play.mitem[i].name[11-1] = '\0'; // safety
1251       play.mitem[i].seq = read_lsb_int(f);
1252       play.mitem[i].frame = read_lsb_int(f);
1253     }
1254   // skip first originally unused item entry
1255   fread(skipbuf, 20, 1, f);
1256   for (i = 0; i < NB_ITEMS; i++)
1257     {
1258       play.item[i].active = fgetc(f);
1259       fread(play.item[i].name, 11, 1, f);
1260       play.item[i].name[11-1] = '\0'; // safety
1261       play.item[i].seq = read_lsb_int(f);
1262       play.item[i].frame = read_lsb_int(f);
1263     }
1264   // offset 784
1265 
1266   play.curitem = read_lsb_int(f) - 1;
1267   fread(skipbuf, 4, 1, f); // reproduce unused 'unused' field
1268   fread(skipbuf, 4, 1, f); // reproduce unused 'counter' field
1269   fread(skipbuf, 1, 1, f); // reproduce unused 'idle' field
1270   fread(skipbuf, 3, 1, f); // reproduce memory alignment
1271   // offset 796
1272 
1273   for (i = 0; i < 769; i++)
1274     {
1275       /* Thoses are char arrays, not null-terminated strings */
1276       int j = 0;
1277       fread(play.spmap[i].type, 100, 1, f);
1278       for (j = 0; j < 100; j++)
1279 	play.spmap[i].seq[j] = read_lsb_short(f);
1280       fread(play.spmap[i].frame, 100, 1, f);
1281       play.spmap[i].last_time = read_lsb_int(f);
1282     }
1283 
1284   /* Here's we'll perform a few tricks to respect a misconception in
1285      the original savegame format */
1286   // skip first originally unused play.button entry
1287   fread(skipbuf, 4, 1, f);
1288   // first play.var entry (cf. below) was overwritten by
1289   // play.button[10], writing 10 play.button entries:
1290   for (i = 0; i < 10; i++) // use fixed 10 rather than NB_BUTTONS
1291     input_set_button_action(i, read_lsb_int(f));
1292   // skip the rest of first unused play.var entry
1293   fread(skipbuf, 32-4, 1, f);
1294 
1295   // reading the rest of play.var
1296   for (i = 1; i < MAX_VARS; i++)
1297     {
1298       play.var[i].var = read_lsb_int(f);
1299       fread(play.var[i].name, 20, 1, f);
1300       play.var[i].name[20-1] = '\0'; // safety
1301       play.var[i].scope = read_lsb_int(f);
1302       play.var[i].active = fgetc(f);
1303       fread(skipbuf, 3, 1, f); // reproduce memory alignment
1304     }
1305 
1306   play.push_active = fgetc(f);
1307   fread(skipbuf, 3, 1, f); // reproduce memory alignment
1308   play.push_dir = read_lsb_int(f);
1309 
1310   play.push_timer = read_lsb_int(f);
1311 
1312   play.last_talk = read_lsb_int(f);
1313   play.mouse = read_lsb_int(f);
1314   play.item_magic = fgetc(f);
1315   fread(skipbuf, 3, 1, f); // reproduce memory alignment
1316   play.last_map = read_lsb_int(f);
1317   fread(skipbuf, 4, 1, f); // reproduce unused 'crap' field
1318   fread(skipbuf, 95 * 4, 1, f); // reproduce unused 'buff' field
1319   fread(skipbuf, 20 * 4, 1, f); // reproduce unused 'dbuff' field
1320   fread(skipbuf, 10 * 4, 1, f); // reproduce unused 'lbuff' field
1321 
1322   /* v1.08: use wasted space for storing file location of map.dat,
1323      dink.dat, palette, and tiles */
1324   /* char cbuff[6000]; */
1325   /* Thoses are char arrays, not null-terminated strings */
1326   fread(play.mapdat, 50, 1, f);
1327   fread(play.dinkdat, 50, 1, f);
1328   fread(play.palette, 50, 1, f);
1329 
1330   for (i = 0; i < GFX_TILES_NB_SETS+1; i++)
1331     {
1332       fread(play.tile[i].file, 50, 1, f);
1333       play.tile[i].file[50-1] = '\0'; // safety
1334     }
1335   for (i = 0; i < 100; i++)
1336     {
1337       fread(play.func[i].file, 10, 1, f);
1338       play.func[i].file[10-1] = '\0'; // safety
1339       fread(play.func[i].func, 20, 1, f);
1340       play.func[i].func[20-1] = '\0'; // safety
1341     }
1342   /* Remains 750 unused chars at the end of the file. */
1343   /* fread(play.cbuff, 750, 1, f); */
1344 
1345   fclose(f);
1346 
1347 
1348   if (dversion >= 108)
1349     {
1350       // new map, if exist
1351       if (strlen (play.mapdat) > 0 && strlen (play.dinkdat) > 0)
1352 	{
1353 	  strcpy (current_map, play.mapdat);
1354 	  strcpy (current_dat, play.dinkdat);
1355 	  load_info();
1356 	}
1357 
1358       // load palette
1359       if (strlen(play.palette) > 0)
1360 	{
1361 	  if (gfx_palette_set_from_bmp(play.palette) < 0)
1362 	    log_error("Couldn't load palette from '%s': %s", play.palette, SDL_GetError());
1363 	  gfx_palette_get_phys(GFX_real_pal);
1364 	}
1365 
1366       /* Reload tiles */
1367       tiles_load_default();
1368 
1369       /* Replace with custom tiles if needed */
1370       for (i = 1; i <= GFX_TILES_NB_SETS; i++)
1371 	if (strlen(play.tile[i].file) > 0)
1372 	  tiles_load_slot(play.tile[i].file, i);
1373     }
1374 
1375 
1376   spr[1].damage = 0;
1377   walk_off_screen = 0;
1378   spr[1].nodraw = 0;
1379   push_active = 1;
1380 
1381   time(&time_start);
1382 
1383   int script = load_script("main", 0, /*true*/1);
1384   locate(script, "main");
1385   run_script(script);
1386   //lets attach our vars to the scripts
1387 
1388   attach();
1389   log_debug("Attached vars.");
1390   dinkspeed = 3;
1391 
1392   if (*pcur_weapon >= 1 && *pcur_weapon <= NB_ITEMS)
1393     {
1394       if (play.item[*pcur_weapon - 1].active == 0)
1395 	{
1396 	  *pcur_weapon = 1;
1397 	  weapon_script = 0;
1398 	  log_error("Loadgame error: Player doesn't have armed weapon - changed to 1.");
1399 	}
1400       else
1401 	{
1402 	  weapon_script = load_script(play.item[*pcur_weapon - 1].name, 1000, /*false*/0);
1403 	  if (locate(weapon_script, "DISARM"))
1404 	    run_script(weapon_script);
1405 	  weapon_script = load_script(play.item[*pcur_weapon - 1].name, 1000, /*false*/0);
1406 	  if (locate(weapon_script, "ARM"))
1407 	    run_script(weapon_script);
1408 	}
1409     }
1410   if (*pcur_magic >= 1 && *pcur_magic <= NB_MITEMS)
1411     {
1412       if (play.item[*pcur_magic - 1].active == /*false*/0)
1413 	{
1414 	  *pcur_magic = 0;
1415 	  magic_script = 0;
1416 	  log_error("Loadgame error: Player doesn't have armed magic - changed to 0.");
1417 	}
1418       else
1419 	{
1420 
1421 	  magic_script = load_script(play.mitem[*pcur_magic - 1].name, 1000, /*false*/0);
1422 	  if (locate(magic_script, "DISARM"))
1423 	    run_script(magic_script);
1424 	  magic_script = load_script(play.mitem[*pcur_magic - 1].name, 1000, /*false*/0);
1425 	  if (locate(magic_script, "ARM"))
1426 	    run_script(magic_script);
1427 	}
1428     }
1429   kill_repeat_sounds_all();
1430   load_map(map.loc[*pmap]);
1431   log_info("Loaded map.");
1432   draw_map_game();
1433   log_info("Map drawn.");
1434 
1435   last_saved_game = num;
1436 
1437   return /*true*/1;
1438 }
1439 
add_time_to_saved_game(int num)1440 /*bool*/int add_time_to_saved_game(int num)
1441 {
1442   FILE *f = NULL;
1443 
1444   f = paths_savegame_fopen(num, "rb");
1445   if (!f)
1446     {
1447       log_error("Couldn't load save game %d", num);
1448       return /*false*/0;
1449     }
1450 
1451   int minutes = 0;
1452   int minutes_offset = 200;
1453   fseek(f, minutes_offset, SEEK_SET);
1454   minutes = read_lsb_int(f);
1455   fclose(f);
1456 
1457   //great, now let's resave it with added time
1458   log_info("Ok, adding time.");
1459   time_t ct;
1460 
1461   time(&ct);
1462   minutes += (int) (difftime(ct,time_start) / 60);
1463 
1464   f = paths_savegame_fopen(num, "rb+");
1465   if (f)
1466     {
1467       fseek(f, minutes_offset, SEEK_SET);
1468       write_lsb_int(minutes, f);
1469       fclose(f);
1470     }
1471   log_info("Wrote it.(%d of time)", minutes);
1472 
1473   return /*true*/1;
1474 }
1475 
save_game(int num)1476 void save_game(int num)
1477 {
1478   /* Instead of using 'fseek(...)' when we want to skip a little bit
1479      of data, we read it to this buffer - this is much faster on PSP
1480      (1000ms -> 60ms), probably related to cache validation. No
1481      noticeable change on PC (<1ms). */
1482   char skipbuf[10000]; // more than any fseek we do
1483   memset(skipbuf, 0, 10000);
1484 
1485   FILE *f;
1486 
1487   //lets set some vars first
1488   time_t ct;
1489   time(&ct);
1490   play.minutes += (int) (difftime(ct,time_start) / 60);
1491         //reset timer
1492   time(&time_start);
1493 
1494   // save game things for storing new map, palette, and tile
1495   // information
1496   strncpy (play.mapdat, current_map, 50);
1497   strncpy (play.dinkdat, current_dat, 50);
1498 
1499   last_saved_game = num;
1500   f = paths_savegame_fopen(num, "wb");
1501   if (f == NULL)
1502     {
1503       perror("Cannot save game");
1504       return;
1505     }
1506 
1507   /* Portably dump struct player_info play to disk */
1508   int i = 0;
1509   write_lsb_int(dversion, f);
1510   // set_save_game_info() support:
1511   {
1512     char* info_temp = strdup(save_game_info);
1513     decipher_string(&info_temp, 0);
1514     fwrite(info_temp, 77+1, 1, f);
1515     free(info_temp);
1516   }
1517   fwrite(skipbuf, 118, 1, f); // unused
1518   // offset 200
1519   write_lsb_int(play.minutes, f);
1520   write_lsb_int(spr[1].x, f);
1521   write_lsb_int(spr[1].y, f);
1522   fwrite(skipbuf, 4, 1, f); // unused 'die' field
1523   write_lsb_int(spr[1].size, f);
1524   write_lsb_int(spr[1].defense, f);
1525   write_lsb_int(spr[1].dir, f);
1526   write_lsb_int(spr[1].pframe, f);
1527   write_lsb_int(spr[1].pseq, f);
1528   write_lsb_int(spr[1].seq, f);
1529   write_lsb_int(spr[1].frame, f);
1530   write_lsb_int(spr[1].strength, f);
1531   write_lsb_int(spr[1].base_walk, f);
1532   write_lsb_int(spr[1].base_idle, f);
1533   write_lsb_int(spr[1].base_hit, f);
1534   write_lsb_int(spr[1].que, f);
1535   // offset 264
1536 
1537   // skip first originally unused mitem entry
1538   fwrite(skipbuf, 20, 1, f);
1539   for (i = 0; i < NB_MITEMS; i++)
1540     {
1541       fputc(play.mitem[i].active, f);
1542       fwrite(play.mitem[i].name, 11, 1, f);
1543       write_lsb_int(play.mitem[i].seq, f);
1544       write_lsb_int(play.mitem[i].frame, f);
1545     }
1546   // skip first originally unused item entry
1547   fwrite(skipbuf, 20, 1, f);
1548   for (i = 0; i < NB_ITEMS; i++)
1549     {
1550       fputc(play.item[i].active, f);
1551       fwrite(play.item[i].name, 11, 1, f);
1552       write_lsb_int(play.item[i].seq, f);
1553       write_lsb_int(play.item[i].frame, f);
1554     }
1555   // offset 784
1556 
1557   write_lsb_int(play.curitem + 1, f);
1558   fwrite(skipbuf, 4, 1, f); // reproduce unused 'unused' field
1559   fwrite(skipbuf, 4, 1, f); // reproduce unused 'counter' field
1560   fwrite(skipbuf, 1, 1, f); // reproduce unused 'idle' field
1561   fwrite(skipbuf, 3, 1, f); // reproduce memory alignment
1562   // offset 796
1563 
1564   for (i = 0; i < 769; i++)
1565     {
1566       int j = 0;
1567       fwrite(play.spmap[i].type, 100, 1, f);
1568       for (j = 0; j < 100; j++)
1569 	write_lsb_short(play.spmap[i].seq[j], f);
1570       fwrite(play.spmap[i].frame, 100, 1, f);
1571       write_lsb_int(play.spmap[i].last_time, f);
1572     }
1573 
1574   /* Here's we'll perform a few tricks to respect a misconception in
1575      the original savegame format */
1576   // skip first originally unused play.button entry
1577   fwrite(skipbuf, 4, 1, f);
1578   // first play.var entry (cf. below) was overwritten by
1579   // play.button[10], writing 10 play.button entries:
1580   for (i = 0; i < 10; i++) // use fixed 10 rather than NB_BUTTONS
1581     write_lsb_int(input_get_button_action(i), f);
1582   // skip the rest of first unused play.var entry
1583   fwrite(skipbuf, 32-4, 1, f);
1584 
1585   // writing the rest of play.var
1586   for (i = 1; i < MAX_VARS; i++)
1587     {
1588       write_lsb_int(play.var[i].var, f);
1589       fwrite(play.var[i].name, 20, 1, f);
1590       write_lsb_int(play.var[i].scope, f);
1591       fputc(play.var[i].active, f);
1592       fwrite(skipbuf, 3, 1, f); // reproduce memory alignment
1593     }
1594 
1595   fputc(play.push_active, f);
1596   fwrite(skipbuf, 3, 1, f); // reproduce memory alignment
1597   write_lsb_int(play.push_dir, f);
1598 
1599   write_lsb_int(play.push_timer, f);
1600 
1601   write_lsb_int(play.last_talk, f);
1602   write_lsb_int(play.mouse, f);
1603   fputc(play.item_magic, f);
1604   fwrite(skipbuf, 3, 1, f); // reproduce memory alignment
1605   write_lsb_int(play.last_map, f);
1606   fwrite(skipbuf, 4, 1, f); // reproduce unused 'crap' field
1607   fwrite(skipbuf, 95 * 4, 1, f); // reproduce unused 'buff' field
1608   fwrite(skipbuf, 20 * 4, 1, f); // reproduce unused 'dbuff' field
1609   fwrite(skipbuf, 10 * 4, 1, f); // reproduce unused 'lbuff' field
1610 
1611   /* v1.08: use wasted space for storing file location of map.dat,
1612      dink.dat, palette, and tiles */
1613   /* char cbuff[6000];*/
1614   fwrite(play.mapdat, 50, 1, f);
1615   fwrite(play.dinkdat, 50, 1, f);
1616   fwrite(play.palette, 50, 1, f);
1617 
1618   for (i = 0; i < GFX_TILES_NB_SETS+1; i++)
1619     fwrite(play.tile[i].file, 50, 1, f);
1620   for (i = 0; i < 100; i++)
1621     {
1622       fwrite(play.func[i].file, 10, 1, f);
1623       fwrite(play.func[i].func, 20, 1, f);
1624     }
1625   fwrite(skipbuf, 750, 1, f);
1626 
1627   fclose(f);
1628 }
1629 
1630 
1631 
kill_all_vars()1632 void kill_all_vars()
1633 {
1634   memset(&play, 0, sizeof(play));
1635 }
1636 
kill_cur_item()1637 void kill_cur_item()
1638 {
1639   if (*pcur_weapon >= 1 && *pcur_weapon <= NB_ITEMS)
1640     {
1641       if (play.item[*pcur_weapon - 1].active == 1)
1642 	{
1643 	  if (weapon_script != 0 && locate(weapon_script, "DISARM"))
1644 	    run_script(weapon_script);
1645 	  weapon_script = load_script(play.item[*pcur_weapon - 1].name, 0, /*false*/0);
1646 	  play.item[*pcur_weapon - 1].active = 0;
1647 	  *pcur_weapon = 0;
1648 	  if (weapon_script != 0 && locate(weapon_script, "HOLDINGDROP"))
1649 	    run_script(weapon_script);
1650 	  if (weapon_script != 0 && locate(weapon_script, "DROP"))
1651 	    run_script(weapon_script);
1652 	  weapon_script = 0;
1653 	}
1654       else
1655 	{
1656 	  log_error("Can't kill cur item, none armed.");
1657 	}
1658     }
1659 }
1660 
kill_item_script(char * name)1661 void kill_item_script(char* name)
1662 {
1663   int select = 0;
1664   {
1665     int i = 0;
1666     for (; i < NB_ITEMS; i++)
1667       {
1668 	if (play.item[i].active)
1669 	  if (compare(play.item[i].name, name))
1670 	    {
1671 	      select = i;
1672 	      goto found;
1673 	    }
1674       }
1675   }
1676   return;
1677 
1678  found:
1679   if (*pcur_weapon - 1 == select)
1680     {
1681       //holding it right now
1682       if (locate(weapon_script, "HOLDINGDROP"))
1683 	run_script(weapon_script);
1684       if (locate(weapon_script, "DISARM"))
1685 	run_script(weapon_script);
1686 
1687       *pcur_weapon = 0;
1688       weapon_script = 0;
1689     }
1690 
1691   int script = load_script(play.item[select].name, 0, /*false*/0);
1692   play.item[select].active = /*false*/0;
1693 
1694   if (locate(script, "DROP"))
1695     run_script(script);
1696 
1697   draw_status_all();
1698 }
1699 
1700 
kill_mitem_script(char * name)1701 void kill_mitem_script(char* name)
1702 {
1703   int select = 0;
1704   {
1705     int i = 0;
1706     for (; i < NB_MITEMS; i++)
1707       {
1708 	if (play.mitem[i].active)
1709 	  if (compare(play.mitem[i].name, name))
1710 	    {
1711 	      select = i;
1712 	      goto found;
1713 	    }
1714       }
1715   }
1716   return;
1717 
1718  found:
1719   if (*pcur_magic - 1 == select)
1720     {
1721       //holding it right now
1722       if (locate(magic_script, "HOLDINGDROP"))
1723 	run_script(magic_script);
1724       if (locate(magic_script, "DISARM"))
1725 	run_script(magic_script);
1726 
1727       // TODO: this should be *pcur_magic; keeping for compatibility
1728       // for now:
1729       *pcur_weapon = 0;
1730       magic_script = 0;
1731     }
1732 
1733   int script = load_script(play.mitem[select].name, 0, /*false*/0);
1734   play.mitem[select].active = 0;
1735 
1736   if (locate(script, "DROP"))
1737     run_script(script);
1738 
1739   draw_status_all();
1740 }
1741 
1742 
kill_cur_magic()1743 void kill_cur_magic()
1744 {
1745   if (*pcur_magic >= 1 && *pcur_magic <= NB_MITEMS)
1746     {
1747       if (play.mitem[*pcur_magic - 1].active == 1)
1748 	{
1749 	  if (magic_script != 0 && locate(magic_script, "DISARM"))
1750 	    run_script(magic_script);
1751 	  magic_script = load_script(play.mitem[*pcur_magic - 1].name, 0, /*false*/0);
1752 	  play.mitem[*pcur_magic - 1].active = /*false*/0;
1753 	  *pcur_magic = 0;
1754 
1755 	  if (magic_script != 0 && locate(magic_script, "HOLDINGDROP"))
1756 	    run_script(magic_script);
1757 	  if (magic_script != 0 && locate(magic_script, "DROP"))
1758 	    run_script(magic_script);
1759 	  magic_script = 0;
1760 	}
1761       else
1762 	{
1763 	  log_error("Can't kill cur magic, none armed.");
1764 	}
1765     }
1766 }
1767 
1768 
1769 /**
1770  * Remember last time we entered this screen (so we can disable
1771  * sprites for some minutes, e.g. monsters)
1772  */
update_screen_time()1773 void update_screen_time()
1774 {
1775   //Msg("Cur time is %d", play.spmap[*pmap].last_time);
1776   //Msg("Map is %d..", *pmap);
1777   play.spmap[*pmap].last_time = thisTickCount;
1778   //Msg("Time was saved as %d", play.spmap[*pmap].last_time);
1779 }
1780 
1781 
1782 /**
1783  * Load dink.dat to specified memory buffer
1784  */
load_info_to(char * path,struct map_info * mymap)1785 int load_info_to(char* path, struct map_info *mymap)
1786 {
1787   FILE *f = NULL;
1788 
1789   f = paths_dmodfile_fopen(path, "rb");
1790   if (!f)
1791     return -1;
1792 
1793   log_info("World data loaded.");
1794 
1795   /* Portably load struct map_info from disk */
1796   int i = 0;
1797   fseek(f, 20, SEEK_CUR); // unused 'name' field
1798   for (i = 0; i < 769; i++)
1799     mymap->loc[i]    = read_lsb_int(f);
1800   for (i = 0; i < 769; i++)
1801     mymap->music[i]  = read_lsb_int(f);
1802   for (i = 0; i < 769; i++)
1803     mymap->indoor[i] = read_lsb_int(f);
1804   fseek(f, 2240, SEEK_CUR); // unused space
1805 
1806   fclose(f);
1807 
1808   return 0;
1809 }
1810 
1811 /**
1812  * Load dink.dat, an offsets index to screens stored in map.dat, with
1813  * some metadata (midi #, indoor/outdoor)
1814  */
load_info(void)1815 void load_info(void)
1816 {
1817   int result = load_info_to(current_dat, &map);
1818   if (result < 0)
1819     {
1820       //make new data file
1821       save_info();
1822       return;
1823     }
1824 }
1825 
1826 /***
1827  * Saves hard.dat (only used from the editor)
1828  */
save_hard(void)1829 void save_hard(void)
1830 {
1831   /* Instead of using 'fseek(...)' when we want to skip a little bit
1832      of data, we read it to this buffer - this is much faster on PSP
1833      (1000ms -> 60ms), probably related to cache validation. No
1834      noticeable change on PC (<1ms). */
1835   char skipbuf[10000]; // more than any fseek we do
1836   memset(skipbuf, 0, 10000);
1837 
1838   FILE *f = paths_dmodfile_fopen("hard.dat", "wb");
1839   if (!f)
1840     {
1841       perror("Couldn't save hard.dat");
1842       return;
1843     }
1844 
1845   /* Portably dump struct hardness hmap to disk */
1846   int i = 0;
1847   for (i = 0; i < HARDNESS_NB_TILES; i++)
1848     {
1849       int j = 0;
1850       for (j = 0; j < 51; j++)
1851 	fwrite(hmap.htile[i].x[j].y, 51, 1, f);
1852       fputc(hmap.htile[i].used, f);
1853       fwrite(skipbuf, 2, 1, f); // reproduce memory alignment
1854       fwrite(skipbuf, 4, 1, f); // unused 'hold' field
1855     }
1856   for (i = 0; i < GFX_TILES_NB_SQUARES; i++)
1857     write_lsb_int(hmap.btile_default[i], f);
1858   fseek(f, (8000-GFX_TILES_NB_SQUARES)*4, SEEK_CUR); // reproduce unused data
1859 
1860   fclose(f);
1861 }
1862 
1863 
1864 /**
1865  * Load hard.dat which contains tile hardness information.
1866  *
1867  * Unlike 1.08, don't reset and save hard.dat during game in case
1868  * e.g. it was just being written by an external editor.
1869  */
load_hard(void)1870 void load_hard(void)
1871 {
1872   /* Instead of using 'fseek(...)' when we want to skip a little bit
1873      of data, we read it to this buffer - this is much faster on PSP
1874      (1000ms -> 60ms), probably related to cache validation. No
1875      noticeable change on PC (<1ms). */
1876   char skipbuf[10000]; // more than any fseek we do
1877 
1878   FILE *f = NULL;
1879 
1880   /* Try loading the D-Mod hard.dat */
1881   f = paths_dmodfile_fopen("hard.dat", "rb");
1882 
1883   /* Fallback to the default hard.dat */
1884   if (f == NULL)
1885     f = paths_fallbackfile_fopen("hard.dat", "rb");
1886 
1887   if (f == NULL)
1888     {
1889       //make new data file
1890       memset(&hmap, 0, sizeof(struct hardness));
1891       return;
1892     }
1893 
1894   /* Portably load struct hardness hmap from disk */
1895   int i = 0;
1896   for (i = 0; i < HARDNESS_NB_TILES; i++)
1897     {
1898       int j = 0;
1899       for (j = 0; j < 51; j++)
1900 	fread(hmap.htile[i].x[j].y, 51, 1, f);
1901       hmap.htile[i].used = fgetc(f);
1902       fread(skipbuf, 2, 1, f); // reproduce memory alignment
1903       fread(skipbuf, 4, 1, f); // unused 'hold' field
1904     }
1905   for (i = 0; i < GFX_TILES_NB_SQUARES; i++)
1906     hmap.btile_default[i] = read_lsb_int(f);
1907   fseek(f, (8000-GFX_TILES_NB_SQUARES)*4, SEEK_CUR); // reproduce unused data
1908 
1909   fclose(f);
1910 }
1911 
1912 
1913 
1914 /**
1915  * Parse a dink.ini line, and store instructions for later processing
1916  * (used in game initialization through 'load_batch')
1917  */
pre_figure_out(char * line)1918 void pre_figure_out(char* line)
1919 {
1920   int i;
1921   char* ev[10];
1922   memset(&ev, 0, sizeof(ev));
1923   for (i = 0; i < 10; i++)
1924     ev[i] = separate_string(line, i+1, ' ');
1925   char *command = ev[0];
1926 
1927   // PLAYMIDI  filename
1928   if (compare(command, "playmidi"))
1929     {
1930       char* midi_filename = ev[1];
1931       if (!dinkedit)
1932 	PlayMidi(midi_filename);
1933     }
1934 
1935   // LOAD_SEQUENCE_NOW  path  seq  BLACK
1936   // LOAD_SEQUENCE_NOW  path  seq  LEFTALIGN
1937   // LOAD_SEQUENCE_NOW  path  seq  NOTANIM
1938   // LOAD_SEQUENCE_NOW  path  seq  speed
1939   // LOAD_SEQUENCE_NOW  path  seq  speed  offsetx offsety  hard.left hard.top hard.right hard.bottom
1940   else if (compare(command, "LOAD_SEQUENCE_NOW"))
1941     {
1942       rect hardbox;
1943       memset(&hardbox, 0, sizeof(rect));
1944 
1945       int myseq = atol(ev[2]);
1946       seq[myseq].is_active = 1;
1947       seq_set_ini(myseq, line);
1948 
1949       int flags = 0;
1950       if (compare(ev[3], "BLACK"))
1951 	{
1952 	  flags = DINKINI_NOTANIM | DINKINI_BLACK;
1953 	}
1954       else if (compare(ev[3], "LEFTALIGN"))
1955 	{
1956 	  flags = DINKINI_LEFTALIGN;
1957 	}
1958       else if (compare(ev[3], "NOTANIM"))
1959 	{
1960 	  //not an animation!
1961 	  flags = 0;
1962 	}
1963       else
1964 	{
1965 	  //yes, an animation!
1966 	  hardbox.left = atol(ev[6]);
1967 	  hardbox.top = atol(ev[7]);
1968 	  hardbox.right = atol(ev[8]);
1969 	  hardbox.bottom = atol(ev[9]);
1970 
1971 	  flags = DINKINI_NOTANIM;
1972 	}
1973 
1974       load_sprites(ev[1],atol(ev[2]),atol(ev[3]),atol(ev[4]),atol(ev[5]),
1975 		   hardbox, flags);
1976 
1977 
1978       /* In the original engine, due to a bug, make_idata() modifies
1979 	 unused sequence #0, but this isn't really important because
1980 	 sequence was already configured in was already done in
1981 	 'load_sprites'. This is consistent with 'figure_out', which
1982 	 doesn't call 'make_idata' at all. */
1983       /* We still call 'make_idata' for compatibility, to use the same
1984 	 number of idata, hence preserving the same max_idata. */
1985       make_idata(IDATA_SPRITE_INFO, 0,0, 0,0, hardbox);
1986     }
1987 
1988   // LOAD_SEQUENCE  path  seq  BLACK
1989   // LOAD_SEQUENCE  path  seq  LEFTALIGN
1990   // LOAD_SEQUENCE  path  seq  NOTANIM
1991   // LOAD_SEQUENCE  path  seq  speed
1992   // LOAD_SEQUENCE  path  seq  speed  offsetx offsety  hard.left hard.top hard.right hard.bottom
1993   else if (compare(command, "LOAD_SEQUENCE"))
1994     {
1995       int myseq = atol(ev[2]);
1996       seq_set_ini(myseq, line);
1997       seq[myseq].is_active = 1;
1998     }
1999 
2000   else if (compare(command, "SET_SPRITE_INFO"))
2001     {
2002       //           name   seq    speed       offsetx     offsety       hardx      hardy
2003       //if (k[seq[myseq].frame[myframe]].frame = 0) Msg("Changing sprite that doesn't exist...");
2004 
2005       rect hardbox;
2006       int myseq = atol(ev[1]);
2007       int myframe = atol(ev[2]);
2008       rect_set(&hardbox, atol(ev[5]), atol(ev[6]), atol(ev[7]), atol(ev[8]));
2009       make_idata(IDATA_SPRITE_INFO, myseq, myframe,atol(ev[3]), atol(ev[4]),hardbox);
2010     }
2011 
2012   else if (compare(command, "SET_FRAME_SPECIAL"))
2013     {
2014       rect hardbox;
2015       int myseq = atol(ev[1]);
2016       int myframe = atol(ev[2]);
2017       int special = atol(ev[3]);
2018       make_idata(IDATA_FRAME_SPECIAL, myseq, myframe, special, 0, hardbox);
2019     }
2020 
2021   else if (compare(command, "SET_FRAME_DELAY"))
2022     {
2023       rect hardbox;
2024       int myseq = atol(ev[1]);
2025       int myframe = atol(ev[2]);
2026       int delay = atol(ev[3]);
2027       make_idata(IDATA_FRAME_DELAY, myseq, myframe, delay, 0, hardbox);
2028     }
2029 
2030   // SET_FRAME_FRAME  seq frame  new_seq new_frame
2031   // SET_FRAME_FRAME  seq frame  -1
2032   else if (compare(command, "SET_FRAME_FRAME"))
2033     {
2034       rect hardbox;
2035       int myseq = atol(ev[1]);
2036       int myframe = atol(ev[2]);
2037       int new_seq = atol(ev[3]);
2038       int new_frame = atol(ev[4]);
2039 
2040       make_idata(IDATA_FRAME_FRAME, myseq, myframe, new_seq, new_frame, hardbox);
2041     }
2042 
2043   /* Clean-up */
2044   for (i = 0; i < 10; i++)
2045     free(ev[i]);
2046 }
2047 
2048 /**
2049  * Parse a delayed seq[].ini or a DinkC init("...") , and act
2050  * immediately
2051  */
figure_out(char * line)2052 void figure_out(char* line)
2053 {
2054   int myseq = 0, myframe = 0;
2055   int special = 0;
2056   int special2 = 0;
2057   int i;
2058   char* ev[10];
2059   memset(&ev, 0, sizeof(ev));
2060   for (i = 0; i < 10; i++)
2061     {
2062       ev[i] = separate_string(line, i+1, ' ');
2063       if (ev[i] == NULL)
2064 	ev[i] = strdup("");
2065     }
2066   char *command = ev[0];
2067 
2068   // LOAD_SEQUENCE_NOW  path  seq  BLACK
2069   // LOAD_SEQUENCE_NOW  path  seq  LEFTALIGN
2070   // LOAD_SEQUENCE_NOW  path  seq  NOTANIM
2071   // LOAD_SEQUENCE_NOW  path  seq  speed  offsetx offsety  hard.left hard.top hard.right hard.bottom
2072   if (compare(command, "LOAD_SEQUENCE_NOW") ||
2073       compare(command, "LOAD_SEQUENCE"))
2074     {
2075       rect hardbox;
2076       memset(&hardbox, 0, sizeof(rect));
2077 
2078       int myseq = atol(ev[2]);
2079       seq[myseq].is_active = 1;
2080       seq_set_ini(myseq, line);
2081 
2082       int flags = 0;
2083 
2084       if (compare(ev[3], "BLACK"))
2085 	{
2086 	  flags = DINKINI_NOTANIM | DINKINI_BLACK;
2087 	}
2088       else if (compare(ev[3], "LEFTALIGN"))
2089 	{
2090 	  flags = DINKINI_LEFTALIGN;
2091 	}
2092       else if (compare(ev[3], "NOTANIM"))
2093 	{
2094 	  //not an animation!
2095 	  flags = 0;
2096 	}
2097       else
2098 	{
2099 	  //yes, an animation!
2100 	  hardbox.left = atol(ev[6]);
2101 	  hardbox.top = atol(ev[7]);
2102 	  hardbox.right = atol(ev[8]);
2103 	  hardbox.bottom = atol(ev[9]);
2104 
2105 	  flags = DINKINI_NOTANIM;
2106 	}
2107 
2108       load_sprites(ev[1],atol(ev[2]),atol(ev[3]),atol(ev[4]),atol(ev[5]),
2109 		   hardbox, flags);
2110 
2111       program_idata();
2112     }
2113 
2114   else if (compare(command, "SET_SPRITE_INFO"))
2115     {
2116       //           name   seq    speed       offsetx     offsety       hardx      hardy
2117       myseq = atol(ev[1]);
2118       myframe = atol(ev[2]);
2119       k[seq[myseq].frame[myframe]].xoffset = atol(ev[3]);
2120       k[seq[myseq].frame[myframe]].yoffset = atol(ev[4]);
2121       k[seq[myseq].frame[myframe]].hardbox.left = atol(ev[5]);
2122       k[seq[myseq].frame[myframe]].hardbox.top = atol(ev[6]);
2123       k[seq[myseq].frame[myframe]].hardbox.right = atol(ev[7]);
2124       k[seq[myseq].frame[myframe]].hardbox.bottom = atol(ev[8]);
2125     }
2126 
2127   else if (compare(command, "SET_FRAME_SPECIAL"))
2128     {
2129       //           name   seq    speed       offsetx     offsety       hardx      hardy
2130       myseq = atol(ev[1]);
2131       myframe = atol(ev[2]);
2132       special = atol(ev[3]);
2133 
2134       seq[myseq].special[myframe] = special;
2135       log_debug("Set special.  %d %d %d", myseq, myframe, special);
2136     }
2137 
2138   else if (compare(command, "SET_FRAME_DELAY"))
2139     {
2140       //           name   seq    speed       offsetx     offsety       hardx      hardy
2141       myseq = atol(ev[1]);
2142       myframe = atol(ev[2]);
2143       special = atol(ev[3]);
2144 
2145       seq[myseq].delay[myframe] = special;
2146       log_debug("Set delay.  %d %d %d",myseq, myframe, special);
2147     }
2148 
2149   else if (compare(command, "SET_FRAME_FRAME"))
2150     {
2151       //           name   seq    speed       offsetx     offsety       hardx      hardy
2152       myseq = atol(ev[1]);
2153       myframe = atol(ev[2]);
2154       special = atol(ev[3]);
2155       special2 = atol(ev[4]);
2156 
2157       if (special == -1)
2158 	seq[myseq].frame[myframe] = special;
2159       else
2160 	seq[myseq].frame[myframe] = seq[special].frame[special2];
2161       log_debug("Set frame.  %d %d %d", myseq, myframe, special);
2162     }
2163 
2164   /* Clean-up */
2165   for (i = 0; i < 10; i++)
2166     free(ev[i]);
2167 }
2168 
2169 
draw_num(int mseq,char nums[50],int mx,int my)2170 int draw_num(int mseq, char nums[50], int mx, int my)
2171 {
2172   int length = 0;
2173 /*   HRESULT             ddrval; */
2174   int rnum = 0;
2175   int i;
2176 
2177   for (i=0; i < strlen(nums); i++)
2178     {
2179       if (nums[i] == '0') rnum = 10;
2180       else if (nums[i] == '1') rnum = 1;
2181       else if (nums[i] == '2') rnum = 2;
2182       else if (nums[i] == '3') rnum = 3;
2183       else if (nums[i] == '4') rnum = 4;
2184       else if (nums[i] == '5') rnum = 5;
2185       else if (nums[i] == '6') rnum = 6;
2186       else if (nums[i] == '7') rnum = 7;
2187       else if (nums[i] == '8') rnum = 8;
2188       else if (nums[i] == '9') rnum = 9;
2189       else if (nums[i] == '/') rnum = 11;
2190 /*     again: */
2191       if ((rnum != 11) && (!(mseq == SEQ_LEVEL_NUMS)))
2192 	{
2193 /* 	  ddrval = lpDDSTwo->BltFast(mx+length, my, k[seq[mseq].frame[rnum]].k, */
2194 /* 				     &k[seq[mseq].frame[rnum]].box, DDBLTFAST_NOCOLORKEY); */
2195 	  // GFX
2196 	  {
2197 	    SDL_Rect dst = {mx+length, my};
2198 	    gfx_blit_nocolorkey(GFX_k[seq[mseq].frame[rnum]].k, NULL, GFX_lpDDSTwo, &dst);
2199 	  }
2200 	}
2201       else
2202 	{
2203 /* 	  ddrval = lpDDSTwo->BltFast(mx+length, my, k[seq[mseq].frame[rnum]].k, */
2204 /* 				     &k[seq[mseq].frame[rnum]].box, DDBLTFAST_SRCCOLORKEY); */
2205 	  /* Draw experience level number _with_ transparency */
2206 	  // GFX
2207 	  {
2208 	    SDL_Rect dst = {mx+length, my};
2209 	    SDL_BlitSurface(GFX_k[seq[mseq].frame[rnum]].k, NULL, GFX_lpDDSTwo, &dst);
2210 	  }
2211 	}
2212 
2213 
2214 /*       if (ddrval != DD_OK) */
2215 /* 	{ */
2216 /* 	  if (ddrval == DDERR_WASSTILLDRAWING) goto again; */
2217 /* 	  //dderror(ddrval); */
2218 /* 	} */
2219 /*       else */
2220 /* 	{ */
2221 	  length += k[seq[mseq].frame[rnum]].box.right;
2222 /* 	} */
2223     }
2224   return(length);
2225 }
2226 
next_raise(void)2227 int next_raise(void)
2228 {
2229         int crap = *plevel;
2230         int num = ((100 * crap) * crap);
2231 
2232         if (num > 99999) num = 99999;
2233         return(num);
2234 
2235 }
2236 
2237 
draw_exp()2238 void draw_exp()
2239 {
2240         char buffer[30];
2241         char nums[30];
2242         char final[30];
2243 
2244         //Msg("Drawing exp.. which is %d and %d",fexp, *pexp);
2245         strcpy(final, "");
2246 	sprintf(buffer, "%d", fexp);
2247         strcpy(nums, buffer);
2248         if (strlen(nums) < 5)
2249 	  {
2250 	    int i;
2251 	    for (i = 1; i < (6 - strlen(nums)); i++)
2252 	      strcat(final, "0");
2253 	  }
2254 	strcat(final, nums);
2255 	strcat(final,"/");
2256 
2257 		sprintf(buffer, "%d", fraise);
2258                 strcpy(nums, buffer);
2259                 if (strlen(nums) < 5)
2260 		  {
2261 		    int i;
2262 		    for (i = 1; i < (6 - strlen(nums)); i++)
2263 		      strcat(final, "0");
2264 		  }
2265 		strcat(final, nums);
2266 		draw_num(181, final, 404, 459);
2267 
2268 }
2269 
2270 
draw_strength()2271 void draw_strength()
2272 {
2273         char final[30];
2274         char buffer[30];
2275         char nums[30];
2276         //Msg("Drawing exp.. which is %d and %d",fexp, *pexp);
2277         strcpy(final, "");
2278 
2279 	sprintf(buffer, "%d", fstrength);
2280         strcpy(nums, buffer);
2281         if (strlen(nums) < 3)
2282 	  {
2283 	    int i;
2284 	    for (i = 1; i < (4 - strlen(nums)); i++)
2285 	      strcat(final, "0");
2286 	  }
2287 	strcat(final, nums);
2288 	//Msg("Drawing %s..",final);
2289 	draw_num(182, final, 81, 415);
2290 }
2291 
2292 
draw_defense()2293 void draw_defense()
2294 {
2295         char final[30];
2296         char buffer[30];
2297         char nums[30];
2298         //Msg("Drawing exp.. which is %d and %d",fexp, *pexp);
2299         strcpy(final, "");
2300 	sprintf(buffer, "%d", fdefense);
2301         strcpy(nums, buffer);
2302         if (strlen(nums) < 3)
2303 	  {
2304 	    int i;
2305 	    for (i = 1; i < (4 - strlen(nums)); i++)
2306 	      strcat(final, "0");
2307 	  }
2308 	strcat(final, nums);
2309 	draw_num(183, final, 81, 437);
2310 }
2311 
2312 
draw_magic()2313 void draw_magic()
2314 {
2315         char final[30];
2316         char buffer[30];
2317         char nums[30];
2318         //Msg("Drawing exp.. which is %d and %d",fexp, *pexp);
2319         strcpy(final, "");
2320 	sprintf(buffer, "%d", fmagic);
2321         strcpy(nums, buffer);
2322         if (strlen(nums) < 3)
2323 	  {
2324 	    int i;
2325 	    for (i = 1; i < (4 - strlen(nums)); i++)
2326 	      strcat(final, "0");
2327 	  }
2328 	strcat(final, nums);
2329 	draw_num(184, final, 81, 459);
2330 }
2331 
2332 
draw_level()2333 void draw_level()
2334 {
2335         char final[30];
2336         char buffer[30];
2337         //*plevel = 15;
2338         //Msg("Drawing level.. which is %d ",*plevel);
2339 	sprintf(buffer, "%d", *plevel);
2340         strcpy(final, buffer);
2341 
2342         if (strlen(final) == 1)
2343 
2344                 draw_num(SEQ_LEVEL_NUMS, final, 528, 456); else
2345                 draw_num(SEQ_LEVEL_NUMS, final, 523, 456);
2346 
2347 }
2348 
2349 
draw_gold()2350 void draw_gold()
2351 {
2352         char final[30];
2353         char buffer[30];
2354         char nums[30];
2355         //Msg("Drawing exp.. which is %d and %d",fexp, *pexp);
2356         strcpy(final, "");
2357 	sprintf(buffer, "%d", fgold);
2358         strcpy(nums, buffer);
2359         if (strlen(nums) < 5)
2360 	  {
2361 	    int i;
2362 	    for (i = 1; i < (6 - strlen(nums)); i++)
2363 	      strcat(final, "0");
2364 	  }
2365 	strcat(final, nums);
2366 	draw_num(185, final, 298, 457);
2367 }
2368 
2369 
draw_bar(int life,int seqman)2370 void draw_bar(int life, int seqman)
2371 {
2372   int cur = 0;
2373   int curx = 284;
2374   int cury = 412;
2375   int rnum = 3;
2376   int curx_start = curx;
2377 
2378   rect box;
2379   while(1)
2380     {
2381       cur++;
2382       if (cur > life)
2383 	{
2384 	  cur--;
2385 	  int rem = (cur) - (cur / 10) * 10;
2386 	  if (rem != 0)
2387 	    {
2388 	      rect_copy(&box, &k[seq[seqman].frame[rnum]].box);
2389 	      //Msg("Drawing part bar . cur is %d", rem);
2390 	      box.right = (box.right * ((rem) * 10)/100);
2391 	      //woah, there is part of a bar remaining.  Lets do it.
2392 /* 	    again: */
2393 /* 	      ddrval = lpDDSTwo->BltFast(curx, cury, k[seq[seqman].frame[rnum]].k, */
2394 /* 					 &box, DDBLTFAST_NOCOLORKEY); */
2395 /* 	      if (ddrval == DDERR_WASSTILLDRAWING) */
2396 /* 		goto again; */
2397 	      // GFX
2398 	      {
2399 		SDL_Rect src, dst;
2400 		src.x = 0; src.y = 0;
2401 		src.w = GFX_k[seq[seqman].frame[rnum]].k->w * (rem * 10) / 100;
2402 		src.h = GFX_k[seq[seqman].frame[rnum]].k->h;
2403 		dst.x = curx; dst.y = cury;
2404 		gfx_blit_nocolorkey(GFX_k[seq[seqman].frame[rnum]].k, &src, GFX_lpDDSTwo, &dst);
2405 	      }
2406 	    }
2407 	  //are we done?
2408 	  return;
2409 	}
2410 
2411       rnum = 2;
2412       if (cur < 11) rnum = 1;
2413       if (cur == *plifemax) rnum = 3;
2414 
2415       if ((cur / 10) * 10 == cur)
2416 	{
2417 /* 	again2: */
2418 /* 	  ddrval = lpDDSTwo->BltFast( curx, cury, k[seq[seqman].frame[rnum]].k, */
2419 /* 				      &k[seq[seqman].frame[rnum]].box  , DDBLTFAST_NOCOLORKEY); */
2420 /* 	  if (ddrval == DDERR_WASSTILLDRAWING) goto again2; */
2421 	  // GFX
2422 	  {
2423 	    SDL_Rect dst;
2424 	    dst.x = curx;
2425 	    dst.y = cury;
2426 	    gfx_blit_nocolorkey(GFX_k[seq[seqman].frame[rnum]].k, NULL, GFX_lpDDSTwo, &dst);
2427 	  }
2428 
2429 	  //if (ddrval != DD_OK) dderror(ddrval);
2430 	  curx += k[seq[seqman].frame[rnum]].box.right;
2431 	  if (cur == 110)
2432 	    {cury += k[seq[seqman].frame[rnum]].box.bottom+5;
2433 	      curx = curx_start;
2434 
2435 	    }
2436 
2437 	  if (cur == 220) return;
2438 	}
2439     }
2440 }
2441 
2442 
draw_health(void)2443 void draw_health( void )
2444 {
2445         flifemax = *plifemax;
2446         draw_bar(flifemax, 190);
2447         flife = *plife;
2448         draw_bar(flife, 451);
2449 }
2450 
draw_icons()2451 void draw_icons()
2452 {
2453   if (*pcur_weapon >= 1 && *pcur_weapon <= NB_ITEMS && play.item[*pcur_weapon - 1].active)
2454     {
2455       //disarm old weapon
2456       check_seq_status(play.item[*pcur_weapon - 1].seq);
2457       SDL_Rect dst = {557, 413};
2458       SDL_BlitSurface(GFX_k[seq[play.item[*pcur_weapon - 1].seq].frame[play.item[*pcur_weapon - 1].frame]].k, NULL,
2459 		      GFX_lpDDSTwo, &dst);
2460     }
2461 
2462   if (*pcur_magic >= 1 && *pcur_magic <= NB_MITEMS && play.mitem[*pcur_magic - 1].active)
2463     {
2464       //disarm old weapon
2465       check_seq_status(play.mitem[*pcur_magic - 1].seq);
2466       SDL_Rect dst = {153, 413};
2467       SDL_BlitSurface(GFX_k[seq[play.mitem[*pcur_magic - 1].seq].frame[play.mitem[*pcur_magic - 1].frame]].k, NULL,
2468 		      GFX_lpDDSTwo, &dst);
2469     }
2470 }
2471 
2472 
2473 /** draw_virtical, draw_hor, draw_virt2, draw_hor2: used to draw the
2474     magic jauge (in that order) (dinkvar.cpp:draw_mlevel() only) **/
2475 
draw_virtical(int percent,int mx,int my,int mseq,int mframe)2476 void draw_virtical(int percent, int mx, int my, int mseq, int mframe)
2477 {
2478   int cut;
2479   if (percent > 25) percent = 25;
2480   percent = (percent * 4);
2481   rect myrect;
2482   rect_copy(&myrect, &k[seq[mseq].frame[mframe]].box);
2483   int full = myrect.bottom;
2484   cut = (full * percent) / 100;
2485   myrect.bottom = cut;
2486 
2487   my += (full - cut);
2488 
2489 /*   ddrval = lpDDSTwo->BltFast(mx, my, k[seq[mseq].frame[mframe]].k, */
2490 /* 			     &myrect, DDBLTFAST_NOCOLORKEY); */
2491   // GFX
2492   {
2493     /* TODO: test me! */
2494     SDL_Rect src, dst;
2495     src.x = src.y = 0;
2496     src.w = GFX_k[seq[mseq].frame[mframe]].k->w;
2497     src.h = GFX_k[seq[mseq].frame[mframe]].k->h * percent / 100;
2498     dst.x = mx;
2499     dst.y = my;
2500     gfx_blit_nocolorkey(GFX_k[seq[mseq].frame[mframe]].k, &src, GFX_lpDDSTwo, &dst);
2501   }
2502 }
2503 
draw_virt2(int percent,int mx,int my,int mseq,int mframe)2504 void draw_virt2(int percent, int mx, int my, int mseq, int mframe)
2505 {
2506   int cut;
2507   if (percent > 25) percent = 25;
2508   percent = (percent * 4);
2509   rect myrect;
2510   rect_copy(&myrect, &k[seq[mseq].frame[mframe]].box);
2511   int full = myrect.bottom;
2512   cut = (full * percent) / 100;
2513   myrect.bottom = cut;
2514 
2515 /*  again: */
2516 /*   ddrval = lpDDSTwo->BltFast( mx, my, k[seq[mseq].frame[mframe]].k, */
2517 /* 			      &myrect, DDBLTFAST_NOCOLORKEY); */
2518 /*   if (ddrval == DDERR_WASSTILLDRAWING) goto again; */
2519   // GFX
2520   {
2521     SDL_Rect src, dst;
2522     src.x = src.y = 0;
2523     src.w = GFX_k[seq[mseq].frame[mframe]].k->w;
2524     src.h = GFX_k[seq[mseq].frame[mframe]].k->h * percent / 100;
2525     dst.x = mx; dst.y = my;
2526     gfx_blit_nocolorkey(GFX_k[seq[mseq].frame[mframe]].k, &src, GFX_lpDDSTwo, &dst);
2527   }
2528 }
2529 
draw_hor(int percent,int mx,int my,int mseq,int mframe)2530 void draw_hor(int percent, int mx, int my, int mseq, int mframe)
2531 {
2532   int cut;
2533   if (percent > 25) percent = 25;
2534   percent = (percent * 4);
2535   rect myrect;
2536   rect_copy(&myrect, &k[seq[mseq].frame[mframe]].box);
2537   int full = myrect.right;
2538   cut = (full * percent) / 100;
2539   full = cut;
2540   myrect.right = full;
2541 /*  again: */
2542 /*   ddrval = lpDDSTwo->BltFast( mx, my, k[seq[mseq].frame[mframe]].k, */
2543 /* 			      &myrect, DDBLTFAST_NOCOLORKEY); */
2544 /*   if (ddrval == DDERR_WASSTILLDRAWING) goto again; */
2545   // GFX
2546   {
2547     /* TODO: test me! */
2548     SDL_Rect src, dst;
2549     src.x = src.y = 0;
2550     src.w = GFX_k[seq[mseq].frame[mframe]].k->w * percent / 100;
2551     src.h = GFX_k[seq[mseq].frame[mframe]].k->h;
2552     dst.x = mx; dst.y = my;
2553     gfx_blit_nocolorkey(GFX_k[seq[mseq].frame[mframe]].k, &src, GFX_lpDDSTwo, &dst);
2554   }
2555 }
2556 
draw_hor2(int percent,int mx,int my,int mseq,int mframe)2557 void draw_hor2(int percent, int mx, int my, int mseq, int mframe)
2558 {
2559   int cut;
2560   if (percent > 25) percent = 25;
2561   percent = (percent * 4);
2562   rect myrect;
2563   rect_copy(&myrect, &k[seq[mseq].frame[mframe]].box);
2564   int full = myrect.right;
2565   cut = (full * percent) / 100;
2566 
2567   myrect.right = cut;
2568   mx += (full - cut);
2569 
2570 /*  again: */
2571 /*   ddrval = lpDDSTwo->BltFast( mx, my, k[seq[mseq].frame[mframe]].k, */
2572 /* 			      &myrect, DDBLTFAST_NOCOLORKEY); */
2573 /*   if (ddrval == DDERR_WASSTILLDRAWING) goto again; */
2574   // GFX
2575   {
2576     SDL_Rect src, dst;
2577     src.x = src.y = 0;
2578     src.w = GFX_k[seq[mseq].frame[mframe]].k->w * percent / 100;
2579     src.h = GFX_k[seq[mseq].frame[mframe]].k->h;
2580     dst.x = mx;
2581     dst.y = my;
2582     gfx_blit_nocolorkey(GFX_k[seq[mseq].frame[mframe]].k, &src, GFX_lpDDSTwo, &dst);
2583   }
2584 }
2585 
draw_mlevel(int percent)2586 void draw_mlevel(int percent)
2587 {
2588   //if (*pmagic_level < 1) return;
2589 
2590   int mseq = 180;
2591   int bary = 6;
2592   int barx = 7;
2593 
2594   if (percent > 0) draw_virtical(percent, 149, 411, mseq, bary);
2595   percent -= 25;
2596   if (percent > 0) draw_hor(percent, 149, 409, mseq, barx);
2597   percent -= 25;
2598   if (percent > 0) draw_virt2(percent, 215, 411, mseq, bary);
2599   percent -= 25;
2600   if (percent > 0) draw_hor2(percent, 149, 466, mseq, barx);
2601 }
2602 
2603 
2604 /* Draw the status bar and the magic jauge */
draw_status_all(void)2605 void draw_status_all(void)
2606 {
2607 /*   RECT rcRect; */
2608 /*   rcRect.left = 0; */
2609 /*   rcRect.top = 0; */
2610 /*   rcRect.right = 640; */
2611 /*   rcRect.bottom = 80; */
2612 /*  again: */
2613 /*   ddrval = lpDDSTwo->BltFast(0, 400, k[seq[180].frame[3]].k, */
2614 /* 			     &rcRect, DDBLTFAST_NOCOLORKEY); */
2615 /*   if (ddrval == DDERR_WASSTILLDRAWING) goto again; */
2616   // GFX
2617   {
2618     SDL_Rect src = {0, 0, 640, 80}, dst = {0, 400};
2619     gfx_blit_nocolorkey(GFX_k[seq[180].frame[3]].k, &src, GFX_lpDDSTwo, &dst);
2620   }
2621 
2622 /*   rcRect.left = 0; */
2623 /*   rcRect.top = 0; */
2624 /*   rcRect.right = 20; */
2625 /*   rcRect.bottom = 400; */
2626 /*  again2: */
2627 /*   ddrval = lpDDSTwo->BltFast(0, 0, k[seq[180].frame[1]].k, */
2628 /* 			     &rcRect, DDBLTFAST_NOCOLORKEY); */
2629 /*   if (ddrval == DDERR_WASSTILLDRAWING) goto again2; */
2630 /*  again3: */
2631 /*   ddrval = lpDDSTwo->BltFast(620, 0, k[seq[180].frame[2]].k, */
2632 /* 			     &rcRect, DDBLTFAST_NOCOLORKEY); */
2633 /*   if (ddrval == DDERR_WASSTILLDRAWING) goto again3; */
2634   // GFX
2635   {
2636     SDL_Rect src = {0, 0, 20, 400}, dst1 = {0, 0}, dst2 = {620, 0};
2637     gfx_blit_nocolorkey(GFX_k[seq[180].frame[1]].k, &src, GFX_lpDDSTwo, &dst1);
2638     gfx_blit_nocolorkey(GFX_k[seq[180].frame[2]].k, &src, GFX_lpDDSTwo, &dst2);
2639   }
2640 
2641   fraise = next_raise();
2642   if (*pexper < fraise)
2643     fexp = *pexper;
2644   else
2645     fexp = fraise - 1;
2646   fstrength = *pstrength;
2647   fmagic = *pmagic;
2648   fgold = *pgold;
2649   fdefense = *pdefense;
2650   last_magic_draw = 0;
2651   draw_exp();
2652   draw_health();
2653   draw_strength();
2654   draw_defense();
2655   draw_magic();
2656   draw_gold();
2657   draw_level();
2658   draw_icons();
2659   if (*pmagic_cost > 0 && *pmagic_level > 0)
2660     draw_mlevel(*pmagic_level * 100 / *pmagic_cost);
2661 }
2662 
2663 
2664 
inside_box(int x1,int y1,rect box)2665 /*bool*/int inside_box(int x1, int y1, rect box)
2666 {
2667 
2668         if (x1 > box.right) return(/*false*/0);
2669         if (x1 < box.left) return(/*false*/0);
2670 
2671         if (y1 > box.bottom) return(/*false*/0);
2672         if (y1 < box.top) return(/*false*/0);
2673 
2674         return(/*true*/1);
2675 
2676 }
2677 
2678 
2679 
add_sprite_dumb(int x1,int y,int brain,int pseq,int pframe,int size)2680 int add_sprite_dumb(int x1, int y, int brain,int pseq, int pframe,int size )
2681 {
2682   int x;
2683     for (x = 1; x < MAX_SPRITES_AT_ONCE; x++)
2684         {
2685                 if (spr[x].active == /*FALSE*/0)
2686                 {
2687                         memset(&spr[x], 0, sizeof(spr[x]));
2688 
2689                         //Msg("Making sprite %d.",x);
2690                         spr[x].active = /*TRUE*/1;
2691                         spr[x].x = x1;
2692                         spr[x].y = y;
2693                         spr[x].my = 0;
2694                         spr[x].mx = 0;
2695                         spr[x].speed = 0;
2696                         spr[x].brain = brain;
2697                         spr[x].frame = 0;
2698                         spr[x].pseq = pseq;
2699                         spr[x].pframe = pframe;
2700                         spr[x].size = size;
2701                         spr[x].seq = 0;
2702                         if (x > last_sprite_created)
2703                                 last_sprite_created = x;
2704 
2705                         spr[x].timer = 0;
2706                         spr[x].wait = 0;
2707                         spr[x].lpx[0] = 0;
2708                         spr[x].lpy[0] = 0;
2709                         spr[x].moveman = 0;
2710                         spr[x].seq_orig = 0;
2711 
2712 
2713             spr[x].base_hit = -1;
2714                         spr[x].base_walk = -1;
2715                         spr[x].base_die = -1;
2716                         spr[x].base_idle = -1;
2717                         spr[x].base_attack = -1;
2718                         spr[x].last_sound = 0;
2719                         spr[x].hard = 1;
2720 
2721                         rect_set(&spr[x].alt, 0,0,0,0);
2722                         spr[x].althard = 0;
2723                         spr[x].sp_index = 0;
2724                         spr[x].nocontrol = 0;
2725                         spr[x].idle = 0;
2726                         spr[x].strength = 0;
2727                         spr[x].damage = 0;
2728                         spr[x].defense = 0;
2729 
2730 			if (dversion >= 108)
2731 			  {
2732 			    if (spr[x].custom == NULL)
2733 			      {
2734 				spr[x].custom = dinkc_sp_custom_new();
2735 			      }
2736 			    else
2737 			      {
2738 				dinkc_sp_custom_clear(spr[x].custom);
2739 			      }
2740 			  }
2741 
2742                         return(x);
2743                 }
2744 
2745         }
2746 
2747         return(0);
2748 }
2749 
2750 
get_box(int h,rect * box_scaled,rect * box_real)2751 /*bool*/int get_box (int h, rect * box_scaled, rect * box_real)
2752 {
2753   int x_offset, y_offset;
2754 
2755   int mplayx = playx;
2756   int mplayl = playl;
2757   int mplayy = playy;
2758 
2759   if (spr[h].noclip)
2760     {
2761       mplayx = 640;
2762       mplayl = 0;
2763       mplayy = 480;
2764     }
2765 
2766   // added to fix frame-not-in-memory immediately
2767   if (getpic(h) < 1)
2768     {
2769       if (spr[h].pseq != 0)
2770 	check_seq_status(spr[h].pseq);
2771     }
2772 
2773   // if frame is still not in memory:
2774   if (getpic(h) < 1)
2775     {
2776       if (dinkedit)
2777 	log_warn("Yo, sprite %d has a bad pic. (Map %d) Seq %d, Frame %d",
2778 		 h, cur_map, spr[h].pseq, spr[h].pframe);
2779       else
2780 	log_warn("Yo, sprite %d has a bad pic. (Map %d) Seq %d, Frame %d",
2781 		 h, *pmap, spr[h].pseq, spr[h].pframe);
2782       goto nodraw;
2783     }
2784 
2785   *box_real = k[getpic(h)].box;
2786 
2787   /* This doesn't really make sense, but that's the way the game was
2788      released, so we keep it for compatibility */
2789   {
2790     rect krect;
2791     rect_copy(&krect, &k[getpic(h)].box);
2792 
2793     double size_ratio = spr[h].size / 100.0;
2794     int x_compat = krect.right  * (size_ratio - 1) / 2;
2795     int y_compat = krect.bottom * (size_ratio - 1) / 2;
2796 
2797     int center_x = k[getpic(h)].xoffset;
2798     int center_y = k[getpic(h)].yoffset;
2799     box_scaled->left   = spr[h].x - center_x - x_compat;
2800     box_scaled->top    = spr[h].y - center_y - y_compat;
2801 
2802     box_scaled->right  = box_scaled->left + krect.right  * size_ratio;
2803     box_scaled->bottom = box_scaled->top  + krect.bottom * size_ratio;
2804   }
2805 
2806   if (spr[h].alt.right != 0 || spr[h].alt.left != 0 || spr[h].alt.top != 0)
2807     {
2808       // checks for correct box stuff
2809       if (spr[h].alt.left < 0)
2810 	spr[h].alt.left = 0;
2811       if (spr[h].alt.left > k[getpic(h)].box.right)
2812 	spr[h].alt.left = k[getpic(h)].box.right;
2813 
2814       if (spr[h].alt.top < 0)
2815 	spr[h].alt.top = 0;
2816       if (spr[h].alt.top > k[getpic(h)].box.bottom)
2817 	spr[h].alt.top = k[getpic(h)].box.bottom;
2818 
2819       if (spr[h].alt.right < 0)
2820 	spr[h].alt.right = 0;
2821       if (spr[h].alt.right > k[getpic(h)].box.right)
2822 	spr[h].alt.right = k[getpic(h)].box.right;
2823 
2824       if (spr[h].alt.bottom < 0)
2825 	spr[h].alt.bottom = 0;
2826       if (spr[h].alt.bottom > k[getpic(h)].box.bottom)
2827 	spr[h].alt.bottom = k[getpic(h)].box.bottom;
2828 
2829       box_scaled->left += spr[h].alt.left;
2830       box_scaled->top  += spr[h].alt.top;
2831       box_scaled->right  = box_scaled->right  - (k[getpic(h)].box.right  - spr[h].alt.right);
2832       box_scaled->bottom = box_scaled->bottom - (k[getpic(h)].box.bottom - spr[h].alt.bottom);
2833 
2834       rect_copy(box_real, &spr[h].alt);
2835     }
2836 
2837   //********* Check to see if they need to be cut down and do clipping
2838 
2839   if (spr[h].size == 0)
2840     spr[h].size = 100;
2841 
2842   if (dinkedit && (mode == 1 || mode == 5) && draw_map_tiny < 1)
2843     goto do_draw;
2844 
2845   if (box_scaled->left < mplayl)
2846     {
2847       x_offset = box_scaled->left * (-1) + mplayl;
2848       box_scaled->left = mplayl;
2849 
2850       if (spr[h].size == 100)
2851 	box_real->left += x_offset;
2852       else
2853 	box_real->left += (x_offset * 100) / spr[h].size;
2854 
2855       if (box_scaled->right - 1 < mplayl)
2856 	goto nodraw;
2857     }
2858 
2859   if (box_scaled->top < 0)
2860     {
2861       y_offset = box_scaled->top * (-1);
2862       box_scaled->top = 0;
2863 
2864       if (spr[h].size == 100)
2865 	box_real->top += y_offset;
2866       else
2867 	box_real->top += (y_offset * 100) / spr[h].size;
2868 
2869       if (box_scaled->bottom-1 < 0)
2870 	goto nodraw;
2871     }
2872 
2873   if (box_scaled->right > mplayx)
2874     {
2875       x_offset = (box_scaled->right) - mplayx;
2876       box_scaled->right = mplayx;
2877 
2878       if (spr[h].size == 100)
2879 	box_real->right -= x_offset;
2880       else
2881 	box_real->right -= (x_offset * 100) / spr[h].size;
2882 
2883       if (box_scaled->left+1 > mplayx)
2884 	goto nodraw;
2885     }
2886 
2887   if (box_scaled->bottom > mplayy)
2888     {
2889       y_offset = (box_scaled->bottom) - mplayy;
2890       box_scaled->bottom = mplayy;
2891 
2892       if (spr[h].size == 100)
2893 	box_real->bottom -= y_offset;
2894       else
2895 	box_real->bottom -= (y_offset * 100) / spr[h].size;
2896 
2897       if (box_scaled->top+1 > mplayy)
2898 	goto nodraw;
2899     }
2900 
2901  do_draw:
2902     return(/*true*/1);
2903 
2904  nodraw:
2905     return(/*false*/0);
2906 }
2907 
2908 
2909 /* void reload_sprites(char name[100], int nummy, int junk) */
2910 /* { */
2911 /*         HRESULT     ddrval; */
2912 /*     PALETTEENTRY    holdpal[256];          */
2913 
2914 /*         char crap[100],hold[10]; */
2915 /*         int n; */
2916 /*         n = 0;   */
2917 
2918 /*         lpDDPal->GetEntries(0,0,256,holdpal);      */
2919 /*         lpDDPal->SetEntries(0,0,256,real_pal); */
2920 
2921 
2922 /*         for (int oo = index[nummy].s+1; oo <= index[nummy].s + index[nummy].last; oo++) */
2923 /*         { */
2924 /*                 n++; */
2925 
2926                 //  Msg( "%s", crap);
2927 
2928                 //      initFail(hWndMain, crap);
2929 /*                 ddrval = k[oo].k->Restore(); */
2930 /*         if( ddrval == DD_OK ) */
2931 /*         { */
2932 
2933 
2934 /*                         if (n < 10) strcpy(hold, "0"); else strcpy(hold,""); */
2935 /*                         sprintf(crap, "%s%s%d.BMP",name,hold,n); */
2936 
2937 /*                         DDReLoadBitmap(k[oo].k, crap); */
2938                         //Msg("Sprite %s%d.bmp reloaded into area %d. ",name,n,oo);
2939 
2940 
2941 /*         } */
2942 /*         } */
2943 /*         lpDDPal->SetEntries(0,0,256,holdpal);    */
2944 /* } */
2945 
2946 
add_sprite(int x1,int y,int brain,int pseq,int pframe)2947 int add_sprite(int x1, int y, int brain,int pseq, int pframe )
2948 {
2949   int x;
2950     for (x = 1; x < MAX_SPRITES_AT_ONCE; x++)
2951         {
2952                 if (spr[x].active == /*FALSE*/0)
2953                 {
2954                         memset(&spr[x], 0, sizeof(spr[x]));
2955 
2956                         spr[x].active = /*TRUE*/1;
2957                         spr[x].x = x1;
2958                         spr[x].y = y;
2959                         spr[x].my = 0;
2960                         spr[x].mx = 0;
2961                         spr[x].speed = 1;
2962                         spr[x].brain = brain;
2963                         spr[x].frame = 0;
2964                         spr[x].pseq = pseq;
2965                         spr[x].pframe = pframe;
2966                         spr[x].seq = 0;
2967                         if (x > last_sprite_created)
2968                                 last_sprite_created = x;
2969                         spr[x].timer = 33;
2970                         spr[x].wait = 0;
2971                         spr[x].lpx[0] = 0;
2972                         spr[x].lpy[0] = 0;
2973                         spr[x].moveman = 0;
2974                         spr[x].size = 100;
2975                         spr[x].que = 0;
2976                         spr[x].strength = 0;
2977                         spr[x].damage = 0;
2978                         spr[x].defense = 0;
2979                         spr[x].hard = 1;
2980 
2981 			if (dversion >= 108)
2982 			  {
2983 			    if (spr[x].custom == NULL)
2984 			      {
2985 				spr[x].custom = dinkc_sp_custom_new();
2986 			      }
2987 			    else
2988 			      {
2989 				dinkc_sp_custom_clear(spr[x].custom);
2990 			      }
2991 			  }
2992 
2993                         return(x);
2994                 }
2995 
2996         }
2997 
2998         return(0);
2999 }
3000 
3001 /* Editor only */
check_sprite_status(int h)3002 void check_sprite_status(int h)
3003 {
3004 /*         HRESULT dderror; */
3005 /*         char word1[80]; */
3006         //is sprite in memory?
3007         if (spr[h].pseq > 0)
3008         {
3009                 // Msg("Smartload: Loading seq %d..", spr[h].seq);
3010                 if (seq[spr[h].pseq].frame[1] == 0)
3011                 {
3012 		  if (seq[spr[h].pseq].is_active)
3013 		    figure_out(seq[spr[h].pseq].ini);
3014 		  else
3015 		    log_error("Error: sprite %d on map %d references non-existent sequence %d",
3016 			      h, cur_map, spr[h].pseq);
3017                 }
3018                 else
3019                 {
3020                         //it's been loaded before.. is it lost or still there?
3021                         //Msg("Sprite %d's seq is %d",h,spr[h].seq);
3022 
3023 /*                         dderror = k[seq[spr[h].pseq].frame[1]].k->IsLost(); */
3024 
3025 /*                         if (dderror == DDERR_SURFACELOST) */
3026 /*                         { */
3027 /*                                 get_word(seq[spr[h].pseq].data, 2, word1); */
3028 
3029 /*                                 reload_sprites(word1, spr[h].pseq,0); */
3030 /*                                 //Msg("Reloaded seq %d with path of %s should be %s", spr[h].seq, word1,seq[spr[h].seq].data ); */
3031 /*                         } */
3032 
3033 
3034                 }
3035         }
3036 
3037 
3038 
3039 
3040 }
3041 
3042 /* Editor only */
check_frame_status(int h,int frame)3043 void check_frame_status(int h, int frame)
3044 
3045 {
3046 /*         HRESULT dderror; */
3047 /*         char word1[80]; */
3048 
3049         if (!seq[h].is_active) return;
3050 
3051         if (h > 0)
3052         {
3053                 // Msg("Smartload: Loading seq %d..", spr[h].seq);
3054                 if (seq[h].frame[1] == 0 || GFX_k[seq[h].frame[1]].k == NULL)
3055                 {
3056                         figure_out(seq[h].ini);
3057                 }
3058                 else
3059                 {
3060                         //it's been loaded before.. is it lost or still there?
3061                         //Msg("Sprite %d's seq is %d",h,spr[h].seq);
3062 
3063 /*                         dderror = k[seq[h].frame[1]].k->IsLost(); */
3064 
3065 /*                         if (dderror == DDERR_SURFACELOST) */
3066 /*                         { */
3067 /*                                 get_word(seq[h].data, 2, word1); */
3068 
3069 /*                                 reload_sprites(word1, h,0); */
3070 /*                                 //Msg("Reloaded seq %d with path of %s should be %s", spr[h].seq, word1,seq[spr[h].seq].data ); */
3071 /*                         } */
3072                 }
3073         }
3074 
3075 
3076 }
3077 
3078 /**
3079  * Load sequence in memory if not already, using cached dink.ini info
3080  */
check_seq_status(int seq_no)3081 void check_seq_status(int seq_no)
3082 {
3083   if (seq_no > 0 && seq_no < MAX_SEQUENCES)
3084     {
3085       /* Skip empty/unused sequences */
3086       if (!seq[seq_no].is_active)
3087 	return;
3088 
3089       if (seq[seq_no].frame[1] == 0 || GFX_k[seq[seq_no].frame[1]].k == NULL)
3090 	figure_out(seq[seq_no].ini);
3091     }
3092   else if (seq_no > 0)
3093     {
3094       log_error("Warning: check_seq_status: invalid sequence %d", seq_no);
3095     }
3096 }
3097 
3098 /**
3099  * Load all +1->+9 sequences from base sequence 'base' in memory,
3100  * useful to load all of a moving sprite sequences
3101  */
check_base(int base)3102 void check_base(int base)
3103 {
3104   int i;
3105   for (i = 1; i < 10; i++)
3106     if (seq[base+i].is_active)
3107       check_seq_status(base+i);
3108 }
3109 
3110 /**
3111  * Checks for all seq's used by the (base) commands
3112  */
check_sprite_status_full(int sprite_no)3113 void check_sprite_status_full(int sprite_no)
3114 {
3115   //is sprite in memory?
3116   check_seq_status(spr[sprite_no].pseq);
3117 
3118   if (spr[sprite_no].base_walk > -1)
3119     check_base(spr[sprite_no].base_walk);
3120 }
3121 
3122 
3123 /* say_text, say_text_xy: used by the game only (not the editor) */
add_text_sprite(char * text,int script,int sprite_owner,int mx,int my)3124 int add_text_sprite(char* text, int script, int sprite_owner, int mx, int my)
3125 {
3126   int tsprite = add_sprite(mx, my, 8, 0, 0);
3127   if (tsprite == 0)
3128     {
3129       log_error("Couldn't say something, out of sprites.");
3130       return 0;
3131     }
3132 
3133   strncpy(spr[tsprite].text, text, 200-1); // TODO: currently truncated to 199 chars
3134   spr[tsprite].text[200-1] = '\0';
3135 
3136   *plast_text = tsprite;
3137   spr[tsprite].kill = strlen(text) * TEXT_TIMER;
3138   if (spr[tsprite].kill < TEXT_MIN)
3139     spr[tsprite].kill = TEXT_MIN;
3140   spr[tsprite].damage = -1;
3141   spr[tsprite].owner = sprite_owner;
3142   spr[tsprite].hard = 1;
3143   spr[tsprite].script = script;
3144   spr[tsprite].nohit = 1;
3145 
3146   return tsprite;
3147 }
3148 
say_text(char * text,int sprite_owner,int script)3149 int say_text(char* text, int sprite_owner, int script)
3150 {
3151   int tsprite;
3152   if (sprite_owner == 1000)
3153     tsprite = add_text_sprite(text, script, 1000, 100, 100);
3154   else
3155     tsprite = add_text_sprite(text, script, sprite_owner,
3156 			      spr[sprite_owner].x, spr[sprite_owner].y);
3157 
3158   if (tsprite == 0)
3159     return 0;
3160 
3161   //set X offset for text, using strength var since it's unused
3162   spr[tsprite].strength = 75;
3163   check_seq_status(spr[spr[tsprite].owner].seq);
3164   spr[tsprite].defense = ( ( k[getpic(spr[tsprite].owner)].box.bottom
3165 			     - k[getpic(spr[tsprite].owner)].yoffset )
3166 			   + 100 );
3167 
3168   spr[tsprite].x = spr[spr[tsprite].owner].x - spr[tsprite].strength;
3169   spr[tsprite].y = spr[spr[tsprite].owner].y - spr[tsprite].defense;
3170 
3171   return tsprite;
3172 }
3173 
3174 
say_text_xy(char * text,int mx,int my,int script)3175 int say_text_xy(char* text, int mx, int my, int script)
3176 {
3177   int sprite_owner = 1000;
3178   return add_text_sprite(text, script, sprite_owner, mx, my);
3179 }
3180 
3181 
3182 
does_sprite_have_text(int sprite)3183 int does_sprite_have_text(int sprite)
3184 {
3185   int k;
3186         //Msg("getting callback # with %d..", sprite);
3187         for (k = 1; k <= MAX_SPRITES_AT_ONCE; k++)
3188         {
3189                 if (   spr[k].active) if (spr[k].owner == sprite) if (spr[k].brain == 8)
3190                 {
3191                         //Msg("Found it!  returning %d.", k);
3192 
3193                         return(k);
3194                 }
3195 
3196         }
3197 
3198         return(0);
3199 
3200 }
3201 
3202 
kill_text_owned_by(int sprite)3203 void kill_text_owned_by(int sprite)
3204 {
3205   int i;
3206   for (i = 1; i < MAX_SPRITES_AT_ONCE; i++)
3207     {
3208       if (spr[i].active && spr[i].brain == 8 && spr[i].owner == sprite)
3209 	spr[i].active = /*false*/0;
3210     }
3211 }
3212 
3213 /**
3214  * Is 'sprite' currently talking?
3215  * Returns 1 if a text sprite is owned by sprite number 'sprite'.
3216  */
text_owned_by(int sprite)3217 /*bool*/int text_owned_by(int sprite)
3218 {
3219   int i = 1;
3220   for (; i < MAX_SPRITES_AT_ONCE; i++)
3221     if (spr[i].active && spr[i].brain == 8 && spr[i].owner == sprite)
3222       return /*true*/1;
3223   return /*false*/0;
3224 }
3225 
3226 
kill_sprite_all(int sprite)3227 void kill_sprite_all (int sprite)
3228 {
3229         spr[sprite].active = /*false*/0;
3230 
3231         kill_text_owned_by(sprite);
3232         kill_scripts_owned_by(sprite);
3233 
3234 }
3235 
3236 
3237 /**
3238  * Find an editor sprite in active sprites
3239  */
find_sprite(int editor_sprite)3240 int find_sprite(int editor_sprite)
3241 {
3242   int k;
3243   for (k = 1; k <= last_sprite_created; k++)
3244     if (spr[k].sp_index == editor_sprite)
3245       return k;
3246   return 0;
3247 }
3248 
3249 
get_right(char line[200],char thing[100],char * ret)3250 void get_right(char line[200], char thing[100], char *ret)
3251         {
3252                 char *dumb;
3253                 int pos = strcspn(line, thing );
3254 
3255 
3256                 if (pos == 0){ strcpy(ret, ""); return; }
3257 
3258 
3259                 dumb = &ret[pos+1];
3260                 strcpy(ret, dumb);
3261         }
3262 
3263 
3264 
3265 
change_sprite(int h,int val,int * change)3266 int change_sprite(int h, int val, int *change)
3267 {
3268   //Msg("Searching sprite %s with val %d.  Cur is %d", h, val, *change);
3269   if (h < 1 || h >= MAX_SPRITES_AT_ONCE)
3270     {
3271       log_error("Error with an SP command - Sprite %d is invalid.", h);
3272       return -1;
3273     }
3274 
3275   if (spr[h].active == 0)
3276     return -1;
3277 
3278   if (val != -1)
3279     *change = val;
3280 
3281   return *change;
3282 
3283 }
3284 
change_edit(int h,int val,unsigned short * change)3285 int change_edit(int h, int val, unsigned short* change)
3286 {
3287   //Msg("Searching sprite %s with val %d.  Cur is %d", h, val, *change);
3288 
3289   if (h < 1 || h > 99)
3290     return -1;
3291 
3292   if (val != -1)
3293     *change = val;
3294 
3295   return *change;
3296 }
3297 
3298 /**
3299  * Sanity-check and set an editor variable (editor_type(),
3300  * editor_seq() and editor_frame())
3301  */
change_edit_char(int h,int val,unsigned char * change)3302 int change_edit_char(int h, int val, unsigned char* change)
3303 {
3304   //Msg("Searching sprite %s with val %d.  Cur is %d", h, val, *change);
3305   //  Msg("h is %d..",val);
3306   if (h < 1 || h > 99)
3307     return -1;
3308 
3309   if (val != -1)
3310     *change = val;
3311 
3312   return *change;
3313 }
3314 
change_sprite_noreturn(int h,int val,int * change)3315 int change_sprite_noreturn(int h, int val, int* change)
3316 {
3317   //Msg("Searching sprite %s with val %d.  Cur is %d", h, val, *change);
3318   if (h < 0
3319       || h >= MAX_SPRITES_AT_ONCE
3320       || spr[h].active == 0)
3321     return -1;
3322 
3323   *change = val;
3324 
3325   return(*change);
3326 }
3327 
3328 
draw_sprite_game(SDL_Surface * GFX_lpdest,int h)3329 void draw_sprite_game(SDL_Surface *GFX_lpdest, int h)
3330 {
3331   if (g_b_kill_app)
3332     return; //don't try, we're quitting
3333   if (spr[h].brain == 8)
3334     return; // text
3335   if (spr[h].nodraw == 1)
3336     return; // invisible
3337 
3338   rect box_crap,box_real;
3339 
3340   if (get_box(h, &box_crap, &box_real))
3341     {
3342       /* Generic scaling */
3343       /* Not perfectly accurate yet: move a 200% sprite to the border
3344 	 of the screen to it is clipped: it's scaled size will slighly
3345 	 vary. Maybe we need to clip the source zone before scaling
3346 	 it.. */
3347       // error checking for invalid rectangle
3348       if (box_crap.left >= box_crap.right || box_crap.top >= box_crap.bottom)
3349 	return;
3350 
3351       SDL_Rect src, dst;
3352       int retval = 0;
3353       src.x = box_real.left;
3354       src.y = box_real.top;
3355       src.w = box_real.right - box_real.left;
3356       src.h = box_real.bottom - box_real.top;
3357       dst.x = box_crap.left;
3358       dst.y = box_crap.top;
3359       dst.w = box_crap.right - box_crap.left;
3360       dst.h = box_crap.bottom - box_crap.top;
3361 
3362       retval = gfx_blit_stretch(GFX_k[getpic(h)].k, &src, GFX_lpdest, &dst);
3363 
3364       if (retval < 0) {
3365 	log_error("Could not draw sprite %d: %s", getpic(h), SDL_GetError());
3366 	/* If we failed, then maybe the sprite was actually loaded
3367 	   yet, let's try now */
3368 	if (spr[h].pseq != 0)
3369 	  check_seq_status(spr[h].pseq);
3370     }
3371   }
3372 }
3373 
3374 
changedir(int dir1,int k,int base)3375         void changedir( int dir1, int k,int base)
3376         {
3377                 int hspeed;
3378                 int speed_hold = spr[k].speed;
3379                 if (k > 1) if (spr[k].brain != 9) if (spr[k].brain != 10)
3380                 {
3381                         hspeed = spr[k].speed * (base_timing / 4);
3382                         if (hspeed > 49)
3383                         {
3384                                 log_debug("Speed was %d", hspeed);
3385                                 spr[k].speed = 49;
3386                         } else
3387                                 spr[k].speed = hspeed;
3388                 }
3389                 int old_seq = spr[k].seq;
3390                 spr[k].dir = dir1;
3391 
3392                 if (dir1 == 1)
3393                 {
3394                         spr[k].mx = (0 - spr[k].speed ) + (spr[k].speed / 3);
3395                         spr[k].my = spr[k].speed - (spr[k].speed / 3);
3396 
3397                         if (base != -1)
3398                         {
3399 
3400 
3401                                 spr[k].seq = base + 1;
3402                                 if (!seq[spr[k].seq].is_active)
3403                                 {
3404                                         spr[k].seq = base + 9;
3405 
3406                                 }
3407 
3408                         }
3409 
3410                         if (old_seq != spr[k].seq)
3411                         {
3412                                 spr[k].frame = 0;
3413                                 spr[k].delay = 0;
3414                         }
3415 
3416 
3417                 }
3418 
3419                 if (dir1 == 2)
3420                 {
3421                         spr[k].mx = 0;
3422                         spr[k].my = spr[k].speed;
3423                         if (base != -1)
3424                                 spr[k].seq = base + 2;
3425 
3426                         if (!seq[spr[k].seq].is_active && seq[base+3].is_active)
3427 			  spr[k].seq = base + 3;
3428                         if (!seq[spr[k].seq].is_active && seq[base+1].is_active)
3429 			  spr[k].seq = base + 1;
3430 
3431 
3432                         if (old_seq != spr[k].seq)
3433                         {
3434                                 spr[k].frame = 0;
3435                                 spr[k].delay = 0;
3436                         }
3437 
3438 
3439                 }
3440                 if (dir1 == 3)
3441                 {
3442                         spr[k].mx = spr[k].speed - (spr[k].speed / 3);
3443                         spr[k].my = spr[k].speed - (spr[k].speed / 3);
3444                         if (base != -1)
3445                         {
3446                                 spr[k].seq = base + 3;
3447                                 if (!seq[spr[k].seq].is_active)
3448                                         spr[k].seq = base + 7;
3449 
3450                         }
3451 
3452                         if (old_seq != spr[k].seq)
3453                         {
3454                                 spr[k].frame = 0;
3455                                 spr[k].delay = 0;
3456                         }
3457 
3458 
3459                 }
3460 
3461                 if (dir1 == 4)
3462                 {
3463 
3464                         //Msg("Changing %d to four..",k);
3465                         spr[k].mx = (0 - spr[k].speed);
3466                         spr[k].my = 0;
3467                         if (base != -1)
3468                                 spr[k].seq = base + 4;
3469                         if (!seq[spr[k].seq].is_active && seq[base+7].is_active)
3470 			  spr[k].seq = base + 7;
3471                         if (!seq[spr[k].seq].is_active && seq[base+1].is_active)
3472 			  spr[k].seq = base + 1;
3473                 }
3474 
3475                 if (dir1 == 6)
3476                 {
3477                         spr[k].mx = spr[k].speed;
3478                         spr[k].my = 0;
3479                         if (base != -1)
3480                                 spr[k].seq = base + 6;
3481 
3482                         if (!seq[spr[k].seq].is_active && seq[base+3].is_active)
3483 			  spr[k].seq = base + 3;
3484                         if (!seq[spr[k].seq].is_active && seq[base+9].is_active)
3485 			  spr[k].seq = base + 9;
3486 
3487                 }
3488 
3489                 if (dir1 == 7)
3490                 {
3491                         spr[k].mx = (0 - spr[k].speed) + (spr[k].speed / 3);
3492                         spr[k].my = (0 - spr[k].speed)+ (spr[k].speed / 3);
3493                         if (base != -1)
3494                         {
3495                                 spr[k].seq = base + 7;
3496 
3497 
3498                                 if (!seq[spr[k].seq].is_active)
3499 				  spr[k].seq = base + 3;
3500                         }
3501 
3502                 }
3503                 if (dir1 == 8)
3504                 {
3505                         spr[k].mx = 0;
3506                         spr[k].my = (0 - spr[k].speed);
3507                         if (base != -1)
3508                                 spr[k].seq = base + 8;
3509 
3510                         if (!seq[spr[k].seq].is_active && seq[base+7].is_active)
3511 			  spr[k].seq = base + 7;
3512                         if (!seq[spr[k].seq].is_active && seq[base+9].is_active)
3513 			  spr[k].seq = base + 9;
3514 
3515                 }
3516 
3517 
3518                 if (dir1 == 9)
3519                 {
3520                         spr[k].mx = spr[k].speed- (spr[k].speed / 3);
3521                         spr[k].my = (0 - spr[k].speed)+ (spr[k].speed / 3);
3522                         if (base != -1)
3523                         {
3524                                 spr[k].seq = base + 9;
3525                                 if (!seq[spr[k].seq].is_active)
3526                                         spr[k].seq = base + 1;
3527                         }
3528                 }
3529 
3530 
3531 
3532                 if (old_seq != spr[k].seq)
3533                 {
3534                         spr[k].frame = 0;
3535                         spr[k].delay = 0;
3536                 }
3537 
3538 
3539                 if (!seq[spr[k].seq].is_active)
3540                 {
3541                         //spr[k].mx = 0;
3542                         //spr[k].my = 0;
3543                         spr[k].seq = old_seq;
3544 
3545                 }
3546 
3547                 //Msg("Leaving with %d..", spr[k].dir);
3548 
3549                 //Msg("Changedir: Tried to switch sprite %d to dir %d",k,dir1);
3550 
3551                 spr[k].speed = speed_hold;
3552 
3553 }
3554 
3555 
update_play_changes(void)3556 void update_play_changes( void )
3557 {
3558   int j;
3559         for (j = 1; j < 100; j++)
3560         {
3561                 if (pam.sprite[j].active)
3562                         if (play.spmap[*pmap].type[j] != 0)
3563                         {
3564                                 //lets make some changes, player has extra info
3565                                 if (play.spmap[*pmap].type[j] == 1)
3566                                 {
3567                                         pam.sprite[j].active = 0;
3568 
3569                                 }
3570 
3571                                 if (play.spmap[*pmap].type[j] == 2)
3572                                 {
3573                                         pam.sprite[j].type = 1;
3574                     pam.sprite[j].hard = 1;
3575                                 }
3576                                 if (play.spmap[*pmap].type[j] == 3)
3577                                 {
3578 
3579                                         //              Msg("Changing sprite %d", j);
3580                                         pam.sprite[j].type = 0;
3581                                         pam.sprite[j].hard = 1;
3582 
3583                                 }
3584 
3585                                 if (play.spmap[*pmap].type[j] == 4)
3586                                 {
3587                                         pam.sprite[j].type = 1;
3588                     pam.sprite[j].hard = 0;
3589                                 }
3590 
3591                                 if (play.spmap[*pmap].type[j] == 5)
3592                                 {
3593                                         pam.sprite[j].type = 0;
3594                     pam.sprite[j].hard = 0;
3595                                 }
3596 
3597                                 if (play.spmap[*pmap].type[j] == 6)
3598                                 {
3599                                         pam.sprite[j].active = 0;
3600 
3601                                 }
3602                                 if (play.spmap[*pmap].type[j] == 7)
3603                                 {
3604                                         pam.sprite[j].active = 0;
3605 
3606                                 }
3607                                 if (play.spmap[*pmap].type[j] == 8)
3608                                 {
3609                                         pam.sprite[j].active = 0;
3610 
3611                                 }
3612 
3613                                 pam.sprite[j].seq = play.spmap[*pmap].seq[j];
3614                                 pam.sprite[j].frame = play.spmap[*pmap].frame[j];
3615                                 strcpy(pam.sprite[j].script, "");
3616 
3617 
3618                         }
3619 
3620 
3621         }
3622 }
3623 
update_status_all(void)3624 void update_status_all(void)
3625 {
3626         /*bool*/int drawexp = /*false*/0;
3627         int next = next_raise();
3628     int script;
3629         if (next != fraise)
3630         {
3631                 fraise += next / 40;
3632 
3633                 if (fraise > next) fraise = next;
3634                 //make noise here
3635                 drawexp = /*true*/1;
3636                 SoundPlayEffect( 13,15050, 0,0 ,0);
3637 
3638 
3639         }
3640 
3641         if (*pexper != fexp
3642 	    && ((talk.active == 0 && show_inventory == 0 && spr[1].freeze == 0)
3643 		|| fexp + 10 < fraise))
3644 
3645         {
3646                 //update screen experience
3647                 fexp += 10;
3648                 //make noise here
3649 
3650                 if (fexp > *pexper) fexp = *pexper;
3651                 drawexp = /*true*/1;
3652                 SoundPlayEffect( 13,29050, 0,0 ,0);
3653 
3654                 if (fexp >= fraise)
3655                 {
3656 
3657                         *pexper -= next;
3658                         fexp = 0;
3659 
3660                         script = load_script("lraise", 1, /*false*/0);
3661                         if (locate(script, "raise")) run_script(script);
3662                 }
3663         }
3664 
3665 
3666 
3667         if (drawexp)
3668         {
3669 
3670 
3671                 draw_exp();
3672         }
3673 
3674 
3675         if ( (flifemax != *plifemax) || (flife != *plife) )
3676         {
3677                 if (flifemax < *plifemax) flifemax++;
3678                 if (flifemax > *plifemax) flifemax--;
3679                 if (flife > *plife) flife--;
3680                 if (flife < *plife) flife++;
3681                 if (flife > *plife) flife--;
3682                 if (flife < *plife) flife++;
3683                 draw_bar(flifemax, 190);
3684                 draw_bar(flife, 451);
3685         }
3686 
3687         if ( fstrength != *pstrength)
3688         {
3689                 if (fstrength < *pstrength) fstrength++;
3690                 if (fstrength > *pstrength) fstrength--;
3691                 SoundPlayEffect( 22,22050, 0,0 ,0);
3692 
3693                 draw_strength();
3694         }
3695 
3696         if ( fdefense != *pdefense)
3697         {
3698                 if (fdefense < *pdefense) fdefense++;
3699                 if (fdefense > *pdefense) fdefense--;
3700                 SoundPlayEffect( 22,22050, 0,0 ,0);
3701                 draw_defense();
3702         }
3703         if ( fmagic != *pmagic)
3704         {
3705                 if (fmagic < *pmagic) fmagic++;
3706                 if (fmagic > *pmagic) fmagic--;
3707                 SoundPlayEffect( 22,22050, 0,0 ,0);
3708                 draw_magic();
3709         }
3710 
3711         if (fgold != *pgold)
3712         {
3713                 if (fgold < *pgold)
3714                 {
3715                         fgold += 20;
3716                         if (fgold > *pgold) fgold = *pgold;
3717                 }
3718 
3719                 if (fgold > *pgold)
3720                 {
3721                         fgold -= 20;
3722                         if (fgold < *pgold) fgold = *pgold;
3723                 }
3724                 SoundPlayEffect( 14,22050, 0,0 ,0);
3725                 draw_gold();
3726         }
3727 
3728         if (*pmagic_level < *pmagic_cost)
3729         {
3730                 if (show_inventory == 0)
3731                         *pmagic_level += *pmagic;
3732                 if (*pmagic_level > *pmagic_cost) *pmagic_level = *pmagic_cost;
3733         }
3734         if (*pmagic_cost > 0) if (*pmagic_level > 0)
3735         {
3736                 int mnum = *pmagic_level * 100 / *pmagic_cost;
3737                 if (mnum != last_magic_draw)
3738                 {
3739 
3740                         draw_mlevel(mnum);
3741 
3742                         //draw_status_all();
3743                         last_magic_draw = mnum;
3744 
3745 
3746                 }
3747         }
3748 
3749 
3750         spr[1].strength = fstrength;
3751         spr[1].defense = fdefense;
3752 
3753 
3754         if (flife < 1)
3755         {
3756                 script = load_script("dinfo", 1000, /*false*/0);
3757                 if (locate(script, "die")) run_script(script);
3758         }
3759 
3760 }
3761 
3762 
kill_last_sprite(void)3763 /*bool*/int kill_last_sprite(void)
3764 {
3765   int found = 0;
3766   /*bool*/int nosetlast = /*false*/0;
3767   int k;
3768   for (k=1; k < MAX_SPRITES_AT_ONCE; k++ )
3769     {
3770       if (spr[k].active)
3771         {
3772           if (spr[k].live)
3773             {
3774               nosetlast = /*true*/1;
3775             }
3776           else
3777             {
3778               found = k;
3779             }
3780         }
3781     }
3782 
3783   if (found > 1)
3784     {
3785       spr[found].active = /*FALSE*/0;
3786       if (nosetlast == /*false*/0)
3787 	last_sprite_created = found - 1;
3788       return(/*true*/1);
3789     }
3790 
3791   //we didn't kill any sprites, only 1 remains
3792   return(/*false*/0);
3793 }
3794 
3795 
show_bmp(char * name,int showdot,int script)3796 void show_bmp(char* name, int showdot, int script)
3797 {
3798   char* fullpath = paths_dmodfile(name);
3799   SDL_Surface* image = IMG_Load(fullpath);
3800   if (image == NULL)
3801     {
3802       log_error("Couldn't load '%s': %s", name, SDL_GetError());
3803       return;
3804     }
3805 
3806   /* Set physical screen palette */
3807   if (!truecolor)
3808     {
3809       gfx_palette_set_from_surface(image);
3810       SDL_Color phys_pal[256];
3811       gfx_palette_get_phys(phys_pal);
3812 
3813       /* In case the DX bug messed the palette, let's convert the
3814 	 image to the new palette. This also converts 24->8bit if
3815 	 necessary. */
3816       {
3817 	SDL_Surface* converted = SDL_DisplayFormat(image);
3818 	SDL_SetPalette(converted, SDL_LOGPAL, phys_pal, 0, 256);
3819 	SDL_BlitSurface(image, NULL, converted, NULL);
3820 	SDL_FreeSurface(image);
3821 	image = converted;
3822       }
3823 
3824       /* Next blit without palette conversion */
3825       SDL_SetPalette(image, SDL_LOGPAL, GFX_real_pal, 0, 256);
3826     }
3827 
3828   showb.active = /*true*/1;
3829   showb.showdot = showdot;
3830   showb.script = script;
3831 
3832   SDL_BlitSurface(image, NULL, GFX_lpDDSTrick, NULL);
3833   SDL_FreeSurface(image);
3834 
3835   // After show_bmp(), and before the flip_it() call in updateFrame(),
3836   // other parts of the code will draw sprites on lpDDSBack and mess
3837   // the showbmp(). So skip the next flip_it().
3838   abort_this_flip = /*true*/1;
3839 }
3840 
3841 
3842 /* Used to implement DinkC's copy_bmp_to_screen(). Difference with
3843    show_cmp: does not set showb.* (wait for button), install the image
3844    to lpDDSTwo (background) and not lpDDSBack (screen double
3845    buffer) */
copy_bmp(char * name)3846 void copy_bmp(char* name)
3847 {
3848   char* fullpath = paths_dmodfile(name);
3849   SDL_Surface* image = IMG_Load(fullpath);
3850   if (image == NULL)
3851     {
3852       log_error("Couldn't load '%s': %s", name, SDL_GetError());
3853       return;
3854     }
3855 
3856   /* Set physical screen palette */
3857   if (!truecolor)
3858     {
3859       gfx_palette_set_from_surface(image);
3860       SDL_Color phys_pal[256];
3861       gfx_palette_get_phys(phys_pal);
3862 
3863       /* In case the DX bug messed the palette, let's convert the
3864 	 image to the new palette. This also converts 24->8bit if
3865 	 necessary. */
3866       {
3867 	SDL_Surface* converted = SDL_DisplayFormat(image);
3868 	SDL_SetPalette(converted, SDL_LOGPAL, phys_pal, 0, 256);
3869 	SDL_BlitSurface(image, NULL, converted, NULL);
3870 	SDL_FreeSurface(image);
3871 	image = converted;
3872       }
3873 
3874       /* Next blit without palette conversion */
3875       SDL_SetPalette(image, SDL_LOGPAL, GFX_real_pal, 0, 256);
3876     }
3877 
3878   SDL_BlitSurface(image, NULL, GFX_lpDDSTwo, NULL);
3879   SDL_FreeSurface(image);
3880 
3881   abort_this_flip = /*true*/1;
3882 }
3883 
hurt_thing(int h,int damage,int special)3884         int hurt_thing(int h, int damage, int special)
3885         {
3886                 //lets hurt this sprite but good
3887                 if (damage < 1) return(0);
3888                 int num = damage - spr[h].defense;
3889 
3890                 //      Msg("num is %d.. defense was %d.of sprite %d", num, spr[h].defense, h);
3891                 if (num < 1) num = 0;
3892 
3893                 if (num == 0)
3894                 {
3895                         if ((rand() % 2)+1 == 1) num = 1;
3896                 }
3897 
3898                 spr[h].damage += num;
3899                 return(num);
3900                 //draw blood here
3901         }
3902 
random_blood(int mx,int my,int sprite)3903         void random_blood(int mx, int my, int sprite)
3904         {
3905                 int myseq;
3906                 /* v1.08 introduces custom blood sequence, as well as
3907                    a slightly different default (select blood in range
3908                    187-189 included, instead of 187-188 included) */
3909                 int randy;
3910                 if (spr[sprite].bloodseq > 0 && spr[sprite].bloodnum > 0)
3911                   {
3912                     myseq = spr[sprite].bloodseq;
3913                     randy = spr[sprite].bloodnum;
3914                   }
3915                 else
3916                   {
3917                     myseq = 187;
3918                     if (dversion >= 108)
3919                       randy = 3;
3920                     else
3921                       randy = 2;
3922                   }
3923                 myseq += (rand () % randy);
3924 
3925                 int crap2 = add_sprite(mx,my,5,myseq,1);
3926                 /* TODO: add_sprite might return 0, and the following
3927                    would trash spr[0] - cf. bugs.debian.org/688934 */
3928                 spr[crap2].speed = 0;
3929                 spr[crap2].base_walk = -1;
3930                 spr[crap2].nohit = 1;
3931                 spr[crap2].seq = myseq;
3932                 if (sprite > 0)
3933                         spr[crap2].que = spr[sprite].y+1;
3934 
3935         }
3936 
3937 
add_item(char * name,int mseq,int mframe,enum item_type type)3938 void add_item(char* name, int mseq, int mframe, enum item_type type)
3939 {
3940   if (type == ITEM_REGULAR)
3941     {
3942       //add reg item
3943       int i;
3944       for (i = 0; i < NB_ITEMS; i++)
3945 	{
3946 	  if (play.item[i].active == 0)
3947 	    {
3948 	      log_info("Weapon/item %s added to inventory.", name);
3949 	      play.item[i].seq = mseq;
3950 	      play.item[i].frame = mframe;
3951 	      strncpy(play.item[i].name, name, sizeof(play.item[i].name));
3952 	      play.item[i].name[sizeof(play.item[i].name)-1] = '\0';
3953 	      play.item[i].active = 1;
3954 
3955 	      int crap1 = load_script(play.item[i].name, 1000, /*false*/0);
3956 	      if (locate(crap1, "PICKUP"))
3957 		run_script(crap1);
3958 
3959 	      break;
3960 	    }
3961 	}
3962     }
3963   else
3964     {
3965       //add magic item
3966       int i;
3967       for (i = 0; i < NB_MITEMS; i++)
3968 	{
3969 	  if (play.mitem[i].active == 0)
3970 	    {
3971 	      log_info("Magic %s added to inventory.", name);
3972 	      play.mitem[i].seq = mseq;
3973 	      play.mitem[i].frame = mframe;
3974 	      strncpy(play.mitem[i].name, name, sizeof(play.mitem[i].name));
3975 	      play.mitem[i].name[sizeof(play.mitem[i].name)-1] = '\0';
3976 	      play.mitem[i].active = 1;
3977 
3978 	      int crap = load_script(play.mitem[i].name, 1000, /*false*/0);
3979 	      if (locate(crap, "PICKUP"))
3980 		run_script(crap);
3981 
3982 	      break;
3983 	    }
3984 	}
3985     }
3986 }
3987 
fill_screen(int num)3988 void fill_screen(int num)
3989 {
3990   /* Warning: palette indexes 0 and 255 are hard-coded
3991      to black and white (cf. gfx_palette.c). */
3992   if (!truecolor)
3993     SDL_FillRect(GFX_lpDDSTwo, NULL, num);
3994   else
3995     SDL_FillRect(GFX_lpDDSTwo, NULL, SDL_MapRGB(GFX_lpDDSTwo->format,
3996 						GFX_real_pal[num].r,
3997 						GFX_real_pal[num].g,
3998 						GFX_real_pal[num].b));
3999 }
4000 
4001