1 //=============================================================================
2 //
3 // Adventure Game Studio (AGS)
4 //
5 // Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
6 // The full list of copyright holders can be found in the Copyright.txt
7 // file, which is part of this source code distribution.
8 //
9 // The AGS source code is provided under the Artistic License 2.0.
10 // A copy of this license can be found in the file License.txt and at
11 // http://www.opensource.org/licenses/artistic-license-2.0.php
12 //
13 //=============================================================================
14 
15 #include <stdio.h>
16 #include "ac/roomstruct.h"
17 #include "ac/common.h"
18 #include "ac/wordsdictionary.h"
19 #include "util/string_utils.h"      // fputstring, etc
20 #include "util/compress.h"
21 #include "util/stream.h"
22 #include "core/assetmanager.h"
23 #include "gfx/bitmap.h"
24 
25 using namespace AGS::Common;
26 
27 Bitmap *backups[5];
28 int _acroom_bpp = 1;  // bytes per pixel of currently loading room
29 
ReadFromFile(Common::Stream * in)30 void sprstruc::ReadFromFile(Common::Stream *in)
31 {
32     sprnum = in->ReadInt16();
33     x = in->ReadInt16();
34     y = in->ReadInt16();
35     room = in->ReadInt16();
36     on = in->ReadInt16();
37 }
38 
roomstruct()39 roomstruct::roomstruct() {
40     ebscene[0] = NULL; walls = NULL; object = NULL; lookat = NULL; nummes = 0;
41     left = 0; right = 317; top = 40; bottom = 199; numobj = MAX_OBJ; numsprs = 0; password[0] = 0;
42     wasversion = kRoomVersion_Current; numanims = 0; regions = NULL; numwalkareas = 0;
43     numhotspots = 0;
44     memset(&objbaseline[0], 0xff, sizeof(int) * MAX_INIT_SPR);
45     memset(&objectFlags[0], 0, sizeof(short) * MAX_INIT_SPR);
46     width = 320; height = 200; scripts = NULL;
47     cscriptsize = 0;
48     memset(&walk_area_zoom[0], 0, sizeof(short) * (MAX_WALK_AREAS + 1));
49     memset(&walk_area_light[0], 0, sizeof(short) * (MAX_WALK_AREAS + 1));
50     resolution = 1; num_bscenes = 1; ebscene[0] = NULL;
51     bscene_anim_speed = 5; bytes_per_pixel = 1;
52     numLocalVars = 0;
53     localvars = NULL;
54     int i;
55     for (i = 0; i <= MAX_WALK_AREAS; i++) {
56         walk_area_zoom2[i] = NOT_VECTOR_SCALED;
57         walk_area_top[i] = -1;
58         walk_area_bottom[i] = -1;
59     }
60     for (i = 0; i < MAX_HOTSPOTS; i++) {
61         intrHotspot[i] = new Interaction();
62     }
63     for (i = 0; i < MAX_INIT_SPR; i++)
64         intrObject[i] = new Interaction();
65     for (i = 0; i < MAX_REGIONS; i++)
66         intrRegion[i] = new Interaction();
67     intrRoom = new Interaction();
68     gameId = 0;
69     numRegions = 0;
70     hotspotScripts = NULL;
71     regionScripts = NULL;
72     objectScripts = NULL;
73     roomScripts = NULL;
74 }
75 
freemessage()76 void roomstruct::freemessage() {
77     for (int f = 0; f < nummes; f++) {
78         if (message[f] != NULL)
79             free(message[f]);
80     }
81 }
82 
freescripts()83 void roomstruct::freescripts()
84 {
85     if (scripts != NULL)
86     {
87         free(scripts);
88         scripts = NULL;
89     }
90 
91     compiled_script.reset();
92 
93     if (roomScripts != NULL)
94     {
95         delete roomScripts;
96         roomScripts = NULL;
97     }
98     if (hotspotScripts != NULL)
99     {
100         for (int i = 0; i < numhotspots; i++)
101 	    {
102             delete hotspotScripts[i];
103         }
104         delete[] hotspotScripts;
105         hotspotScripts = NULL;
106     }
107     if (objectScripts != NULL)
108     {
109         for (int i = 0; i < numsprs; i++)
110 	    {
111             delete objectScripts[i];
112         }
113         delete[] objectScripts;
114         objectScripts = NULL;
115     }
116     if (regionScripts != NULL)
117     {
118         for (int i = 0; i < numRegions; i++)
119         {
120             delete regionScripts[i];
121         }
122         delete[] regionScripts;
123         regionScripts = NULL;
124     }
125 }
126 
has_region_lightlevel(int id) const127 bool roomstruct::has_region_lightlevel(int id) const
128 {
129     if (id >= 0 && id < MAX_REGIONS)
130         return regionTintLevel[id] == 0;
131     return false;
132 }
133 
has_region_tint(int id) const134 bool roomstruct::has_region_tint(int id) const
135 {
136     if (id >= 0 && id < MAX_REGIONS)
137         return regionTintLevel[id] != 0;
138     return false;
139 }
140 
get_region_lightlevel(int id) const141 int roomstruct::get_region_lightlevel(int id) const
142 {
143     if (id >= 0 && id < MAX_REGIONS)
144         return has_region_lightlevel(id) ? regionLightLevel[id] : 0;
145     return 0;
146 }
147 
get_region_tintluminance(int id) const148 int roomstruct::get_region_tintluminance(int id) const
149 {
150     if (id >= 0 && id < MAX_REGIONS)
151         return has_region_tint(id) ? (regionLightLevel[id] * 10) / 25 : 0;
152     return 0;
153 }
154 
ReadFromFile(Stream * in)155 void room_file_header::ReadFromFile(Stream *in)
156 {
157     version = (RoomFileVersion)in->ReadInt16();
158 }
159 
WriteFromFile(Common::Stream * out)160 void room_file_header::WriteFromFile(Common::Stream *out)
161 {
162     out->WriteInt16(version);
163 }
164 
165 int usesmisccond = 0;
166 
load_main_block(roomstruct * rstruc,const char * files,Stream * in,room_file_header rfh)167 void load_main_block(roomstruct *rstruc, const char *files, Stream *in, room_file_header rfh) {
168   int   f, gsmod, NUMREAD;
169   char  buffre[3000];
170   long  tesl;
171 
172   usesmisccond = 0;
173   rstruc->width = 320;
174   rstruc->height = 200;
175   rstruc->resolution = 1;
176   rstruc->numwalkareas = 0;
177   rstruc->numhotspots = 0;
178 
179   memset(&rstruc->shadinginfo[0], 0, sizeof(short) * 16);
180   memset(&rstruc->sprs[0], 0, sizeof(sprstruc) * MAX_INIT_SPR);
181   memset(&rstruc->objbaseline[0], 0xff, sizeof(int) * MAX_INIT_SPR);
182   memset(&rstruc->objectFlags[0], 0, sizeof(short) * MAX_INIT_SPR);
183   memset(&rstruc->hswalkto[0], 0, sizeof(_Point) * MAX_HOTSPOTS);
184   memset(&rstruc->walk_area_zoom[0], 0, sizeof(short) * (MAX_WALK_AREAS + 1));
185   memset(&rstruc->walk_area_light[0], 0, sizeof(short) * (MAX_WALK_AREAS + 1));
186 
187   for (f = 0; f < MAX_HOTSPOTS; f++) {
188     rstruc->hotspotScriptNames[f].Free();
189     if (f == 0)
190       rstruc->hotspotnames[f] = "No hotspot";
191     else
192       rstruc->hotspotnames[f].Format("Hotspot %d", f);
193   }
194 
195 /*  memset(&rstruc->hscond[0], 0, sizeof(EventBlock) * MAX_HOTSPOTS);
196   memset(&rstruc->objcond[0], 0, sizeof(EventBlock) * MAX_INIT_SPR);
197   memset(&rstruc->misccond, 0, sizeof(EventBlock));*/
198 
199   if (rfh.version >= kRoomVersion_208)
200     _acroom_bpp = in->ReadInt32();
201   else
202     _acroom_bpp = 1;
203 
204   if (_acroom_bpp < 1)
205     _acroom_bpp = 1;
206 
207   rstruc->bytes_per_pixel = _acroom_bpp;
208   rstruc->numobj = in->ReadInt16();
209   if (rstruc->numobj > MAX_OBJ)
210     quit("!room newer than this version - too many walk-behinds");
211 
212   NUMREAD = NUM_CONDIT;
213   in->ReadArrayOfInt16(&rstruc->objyval[0], rstruc->numobj);
214 
215   gsmod = 0;
216 
217   rstruc->numhotspots = in->ReadInt32();
218   if (rstruc->numhotspots == 0)
219     rstruc->numhotspots = 20;
220 	if (rstruc->numhotspots > MAX_HOTSPOTS)
221 		quit("room has too many hotspots: need newer version of AGS?");
222 
223     // Points are a pair of shorts
224     // [IKM] TODO: read/write member for _Point?
225     in->ReadArrayOfInt16((int16_t*)&rstruc->hswalkto[0], 2*rstruc->numhotspots);
226 
227   for (f = 0; f < rstruc->numhotspots; f++)
228   {
229     if (rfh.version >= kRoomVersion_3415)
230       rstruc->hotspotnames[f] = StrUtil::ReadString(in);
231     else if (rfh.version >= kRoomVersion_303a)
232       rstruc->hotspotnames[f] = String::FromStream(in);
233     else
234       rstruc->hotspotnames[f] = String::FromStreamCount(in, 30);
235    }
236 
237   if (rfh.version >= kRoomVersion_270)
238   {
239     for (int i = 0; i < rstruc->numhotspots; ++i)
240     {
241       if (rfh.version >= kRoomVersion_3415)
242         rstruc->hotspotScriptNames[i] = StrUtil::ReadString(in);
243       else
244         rstruc->hotspotScriptNames[i] = String::FromStreamCount(in, MAX_SCRIPT_NAME_LEN);
245     }
246   }
247 
248   rstruc->numwalkareas = in->ReadInt32();
249   for (int iteratorCount = 0; iteratorCount < rstruc->numwalkareas; ++iteratorCount)
250   {
251       rstruc->wallpoints[iteratorCount].ReadFromFile(in);
252   }
253 
254   update_polled_stuff_if_runtime();
255 
256   rstruc->top = in->ReadInt16();
257   rstruc->bottom = in->ReadInt16();
258   rstruc->left = in->ReadInt16();
259   rstruc->right = in->ReadInt16();
260 
261   rstruc->numsprs = in->ReadInt16();
262   for (int iteratorCount = 0; iteratorCount < rstruc->numsprs; ++iteratorCount)
263   {
264       rstruc->sprs[iteratorCount].ReadFromFile(in);
265   }
266 
267   if (rfh.version >= kRoomVersion_253) {
268     rstruc->numLocalVars = in->ReadInt32();
269     if (rstruc->numLocalVars > 0) {
270         rstruc->localvars = new InteractionVariable[rstruc->numLocalVars];
271 
272       for (int iteratorCount = 0; iteratorCount < rstruc->numLocalVars; ++iteratorCount)
273       {
274           rstruc->localvars[iteratorCount].Read(in);
275       }
276     }
277   }
278 
279   rstruc->numRegions = 0;
280 
281   if (rfh.version >= kRoomVersion_241) {
282     if ((rstruc->numhotspots > MAX_HOTSPOTS) || (rstruc->numsprs > MAX_INIT_SPR))
283       quit("load_room: room file created with newer version (too many hotspots/objects)");
284 
285     // free all of the old interactions
286     for (f = 0; f < MAX_HOTSPOTS; f++) {
287       if (rstruc->intrHotspot[f] != NULL) {
288         delete rstruc->intrHotspot[f];
289         rstruc->intrHotspot[f] = NULL;
290       }
291 
292 	  if (rfh.version < kRoomVersion_300a)
293 	  {
294 		  if (f < rstruc->numhotspots)
295 			rstruc->intrHotspot[f] = Interaction::CreateFromStream(in);
296 		  else
297 			rstruc->intrHotspot[f] = new Interaction();
298 	  }
299     }
300 
301     for (f = 0; f < MAX_INIT_SPR; f++) {
302       if (rstruc->intrObject[f] != NULL) {
303         delete rstruc->intrObject[f];
304         rstruc->intrObject[f] = NULL;
305       }
306 
307 	  if (rfh.version < kRoomVersion_300a)
308 	  {
309 		  if (f < rstruc->numsprs)
310 			rstruc->intrObject[f] = Interaction::CreateFromStream(in);
311 		  else
312 			rstruc->intrObject[f] = new Interaction();
313 	  }
314     }
315 
316 	if (rfh.version < kRoomVersion_300a)
317 	{
318 	    delete rstruc->intrRoom;
319 		rstruc->intrRoom = Interaction::CreateFromStream(in);
320 	}
321 
322     for (f = 0; f < MAX_REGIONS; f++) {
323       if (rstruc->intrRegion[f] != NULL)
324         delete rstruc->intrRegion[f];
325       rstruc->intrRegion[f] = new Interaction();
326     }
327 
328     if (rfh.version >= kRoomVersion_255b) {
329       rstruc->numRegions = in->ReadInt32();
330       if (rstruc->numRegions > MAX_REGIONS)
331         quit("load_room: needs newer version of AGS - too many regions");
332 
333   	  if (rfh.version < kRoomVersion_300a)
334 	  {
335         for (f = 0; f < rstruc->numRegions; f++) {
336           delete rstruc->intrRegion[f];
337           rstruc->intrRegion[f] = Interaction::CreateFromStream(in);
338 		}
339       }
340     }
341 
342 	if (rfh.version >= kRoomVersion_300a)
343 	{
344 	  rstruc->hotspotScripts = new InteractionScripts*[rstruc->numhotspots];
345 	  rstruc->objectScripts = new InteractionScripts*[rstruc->numsprs];
346       rstruc->regionScripts = new InteractionScripts*[rstruc->numRegions];
347       rstruc->roomScripts = InteractionScripts::CreateFromStream(in);
348 	  int bb;
349       for (bb = 0; bb < rstruc->numhotspots; bb++) {
350         rstruc->hotspotScripts[bb] = InteractionScripts::CreateFromStream(in);
351       }
352       for (bb = 0; bb < rstruc->numsprs; bb++) {
353         rstruc->objectScripts[bb] = InteractionScripts::CreateFromStream(in);
354       }
355 	  for (bb = 0; bb < rstruc->numRegions; bb++) {
356         rstruc->regionScripts[bb] = InteractionScripts::CreateFromStream(in);
357       }
358 
359 	}
360   }
361 
362   if (rfh.version >= kRoomVersion_200_alpha) {
363     in->ReadArrayOfInt32(&rstruc->objbaseline[0], rstruc->numsprs);
364     rstruc->width = in->ReadInt16();
365     rstruc->height = in->ReadInt16();
366   }
367 
368   if (rfh.version >= kRoomVersion_262)
369     in->ReadArrayOfInt16(&rstruc->objectFlags[0], rstruc->numsprs);
370 
371   if (rfh.version >= kRoomVersion_200_final)
372     rstruc->resolution = in->ReadInt16();
373 
374   int num_walk_areas = MAX_WALK_AREAS;
375   if (rfh.version >= kRoomVersion_240)
376     num_walk_areas = in->ReadInt32();
377 
378   if (num_walk_areas > MAX_WALK_AREAS + 1)
379     quit("load_room: Too many walkable areas, need newer version");
380 
381   if (rfh.version >= kRoomVersion_200_alpha7)
382     in->ReadArrayOfInt16(&rstruc->walk_area_zoom[0], num_walk_areas);
383 
384   if (rfh.version >= kRoomVersion_214)
385     in->ReadArrayOfInt16(&rstruc->walk_area_light[0], num_walk_areas);
386 
387   if (rfh.version >= kRoomVersion_251) {
388     in->ReadArrayOfInt16(&rstruc->walk_area_zoom2[0], num_walk_areas);
389     in->ReadArrayOfInt16(&rstruc->walk_area_top[0], num_walk_areas);
390     in->ReadArrayOfInt16(&rstruc->walk_area_bottom[0], num_walk_areas);
391 
392     for (f = 0; f < num_walk_areas; f++) {
393       // if they set a contiuously scaled area where the top
394       // and bottom zoom levels are identical, set it as a normal
395       // scaled area
396       if (rstruc->walk_area_zoom[f] == rstruc->walk_area_zoom2[f])
397         rstruc->walk_area_zoom2[f] = NOT_VECTOR_SCALED;
398     }
399   }
400 
401   in->Read(&rstruc->password[0], 11);
402   in->Read(&rstruc->options[0], 10);
403   rstruc->nummes = in->ReadInt16();
404 
405   if (rfh.version >= kRoomVersion_272)
406     rstruc->gameId = in->ReadInt32();
407 
408   if (rfh.version >= kRoomVersion_pre114_3)
409   {
410       for (int iteratorCount = 0; iteratorCount < rstruc->nummes; ++iteratorCount)
411       {
412           rstruc->msgi[iteratorCount].ReadFromFile(in);
413       }
414   }
415   else
416     memset(&rstruc->msgi[0], 0, sizeof(MessageInfo) * MAXMESS);
417 
418   for (f = 0;f < rstruc->nummes; f++) {
419     if (rfh.version >= kRoomVersion_261)
420       read_string_decrypt(in, buffre);
421     else
422       fgetstring_limit(buffre, in, 2999);
423 
424     int buffre_length = strlen(buffre);
425 
426     rstruc->message[f] = (char *)malloc(buffre_length + 2);
427     strcpy(rstruc->message[f], buffre);
428 
429     if ((buffre_length > 0) && (buffre[buffre_length-1] == (char)200)) {
430       rstruc->message[f][strlen(buffre)-1] = 0;
431       rstruc->msgi[f].flags |= MSG_DISPLAYNEXT;
432     }
433   }
434 
435   rstruc->numanims = 0;
436   if (rfh.version >= kRoomVersion_pre114_6) {
437     rstruc->numanims = in->ReadInt16();
438 
439     if (rstruc->numanims > 0)
440         // [IKM] CHECKME later: this will cause trouble if structure changes
441         in->Seek (sizeof(FullAnimation) * rstruc->numanims);
442 //      in->ReadArray(&rstruc->anims[0], sizeof(FullAnimation), rstruc->numanims);
443   }
444   else {
445     rstruc->numanims = 0;
446     memset(&rstruc->anims[0], 0, sizeof(FullAnimation) * MAXANIMS);
447   }
448 
449   if ((rfh.version >= kRoomVersion_pre114_4) && (rfh.version < kRoomVersion_250a)) {
450     load_script_configuration(in);
451     load_graphical_scripts(in, rstruc);
452   }
453 
454   if (rfh.version >= kRoomVersion_114)
455     in->ReadArrayOfInt16(&rstruc->shadinginfo[0], 16);
456 
457   if (rfh.version >= kRoomVersion_255b) {
458     in->ReadArrayOfInt16 (&rstruc->regionLightLevel[0], rstruc->numRegions);
459     in->ReadArrayOfInt32 (&rstruc->regionTintLevel[0], rstruc->numRegions);
460   }
461 
462   if (rfh.version < kRoomVersion_3404)
463   {
464     // Convert the old format tint saturation
465     for (int i = 0; i < MAX_REGIONS; ++i)
466     {
467       if ((rstruc->regionTintLevel[i] & LEGACY_TINT_IS_ENABLED) != 0)
468       {
469         rstruc->regionTintLevel[i] &= ~LEGACY_TINT_IS_ENABLED;
470         // older versions of the editor had a bug - work around it
471         int tint_amount = (rstruc->regionLightLevel[i] > 0 ? rstruc->regionLightLevel[i] : 50);
472         rstruc->regionTintLevel[i] |= (tint_amount & 0xFF) << 24;
473         rstruc->regionLightLevel[i] = 255;
474       }
475     }
476   }
477 
478   update_polled_stuff_if_runtime();
479 
480   if (rfh.version >= kRoomVersion_pre114_5) {
481     tesl = load_lzw(in, rstruc->ebscene[0], rstruc->pal);
482     rstruc->ebscene[0] = recalced;
483   }
484   else
485     tesl = loadcompressed_allegro(in, &rstruc->ebscene[0], rstruc->pal, in->GetPosition());
486 
487   if ((rstruc->ebscene[0]->GetWidth() > 320) & (rfh.version < kRoomVersion_200_final))
488     rstruc->resolution = 2;
489 
490   update_polled_stuff_if_runtime();
491   if (rfh.version >= kRoomVersion_255b)
492     tesl = loadcompressed_allegro(in, &rstruc->regions, rstruc->pal, tesl);
493   else if (rfh.version >= kRoomVersion_114) {
494     tesl = loadcompressed_allegro(in, &rstruc->regions, rstruc->pal, tesl);
495     // an old version - ->Clear the 'shadow' area into a blank regions bmp
496     delete rstruc->regions;
497     rstruc->regions = NULL;
498   }
499 
500   update_polled_stuff_if_runtime();
501   tesl = loadcompressed_allegro(in, &rstruc->walls, rstruc->pal, tesl);
502 
503   update_polled_stuff_if_runtime();
504   tesl = loadcompressed_allegro(in, &rstruc->object, rstruc->pal, tesl);
505 
506   update_polled_stuff_if_runtime();
507   tesl = loadcompressed_allegro(in, &rstruc->lookat, rstruc->pal, tesl);
508 
509   if (rfh.version < kRoomVersion_255b) {
510     // Old version - copy walkable areas to Regions
511     if (rstruc->regions == NULL)
512       rstruc->regions = BitmapHelper::CreateBitmap(rstruc->walls->GetWidth(), rstruc->walls->GetHeight(), 8);
513     rstruc->regions->Fill(0);
514     rstruc->regions->Blit (rstruc->walls, 0, 0, 0, 0, rstruc->regions->GetWidth(), rstruc->regions->GetHeight());
515     for (f = 0; f <= 15; f++) {
516       rstruc->regionLightLevel[f] = rstruc->walk_area_light[f];
517       rstruc->regionTintLevel[f] = 255;
518     }
519   }
520 
521   if (rfh.version < kRoomVersion_200_alpha) {
522     for (f = 0; f < 11; f++)
523       rstruc->password[f] += 60;
524   }
525   else {
526     for (f = 0; f < 11; f++)
527       rstruc->password[f] += passwencstring[f];
528   }
529 }
530 
531 extern bool load_room_is_version_bad(roomstruct *rstruc);
532 
load_room(const char * files,roomstruct * rstruc,bool gameIsHighRes)533 void load_room(const char *files, roomstruct *rstruc, bool gameIsHighRes) {
534   Common::Stream *opty; // CHECKME why "opty"??
535   room_file_header  rfh;
536   int i;
537 
538   rstruc->freemessage();
539   rstruc->freescripts();
540 
541   if (rstruc->num_bscenes > 1) {
542     int ff;
543 
544     for (ff = 1; ff < rstruc->num_bscenes; ff++) {
545       delete rstruc->ebscene[ff];
546       rstruc->ebscene[ff] = NULL;
547     }
548     update_polled_stuff_if_runtime();
549   }
550 
551   rstruc->num_bscenes = 1;
552   rstruc->bscene_anim_speed = 5;
553   for (size_t i = 0; i < MAX_INIT_SPR; ++i)
554   {
555     rstruc->objectnames[i].Free();
556     rstruc->objectscriptnames[i].Free();
557   }
558   memset (&rstruc->regionLightLevel[0], 0, sizeof(short) * MAX_REGIONS);
559   memset (&rstruc->regionTintLevel[0], 0, sizeof(int) * MAX_REGIONS);
560 
561   for (i = 0; i <= MAX_WALK_AREAS; i++) {
562     rstruc->walk_area_zoom2[i] = NOT_VECTOR_SCALED;
563     rstruc->walk_area_top[i] = -1;
564     rstruc->walk_area_bottom[i] = -1;
565   }
566 
567   for (i = 0; i < rstruc->numhotspots; i++)
568     rstruc->hsProps[i].clear();
569   for (i = 0; i < rstruc->numsprs; i++)
570     rstruc->objProps[i].clear();
571   rstruc->roomProps.clear();
572 
573   if (rstruc->localvars != NULL)
574     delete [] rstruc->localvars;
575   rstruc->localvars = NULL;
576   rstruc->numLocalVars = 0;
577 
578   memset(&rstruc->ebpalShared[0], 0, MAX_BSCENE);
579 
580   update_polled_stuff_if_runtime();
581 
582   opty = Common::AssetManager::OpenAsset(files);
583   if (opty == NULL) {
584     char errbuffr[500];
585     sprintf(errbuffr,"Load_room: Unable to load the room file '%s'\n"
586       "Make sure that you saved the room to the correct folder (it should be\n"
587       "in your game's sub-folder of the AGS directory).\n"
588       "Also check that the player character's starting room is set correctly.\n",files);
589     quit(errbuffr);
590   }
591   update_polled_stuff_if_runtime();  // it can take a while to load the file sometimes
592 
593   rfh.ReadFromFile(opty);
594   //fclose(opty);
595   rstruc->wasversion = rfh.version;
596 
597   if (load_room_is_version_bad(rstruc))
598   {
599     delete opty;
600     quit("Load_Room: Bad packed file. Either the file requires a newer or older version of\n"
601       "this program or the file is corrupt.\n");
602   }
603 
604   int   thisblock = 0;
605   int   bloklen;
606 
607   while (thisblock != BLOCKTYPE_EOF) {
608     update_polled_stuff_if_runtime();
609     thisblock = opty->ReadByte();
610 
611     if (thisblock == BLOCKTYPE_EOF)
612       break;
613 
614     bloklen = opty->ReadInt32();
615     bloklen += opty->GetPosition();  // make it the new position for after block read
616 
617     if (thisblock == BLOCKTYPE_MAIN)
618       load_main_block(rstruc, files, opty, rfh);
619     else if (thisblock == BLOCKTYPE_SCRIPT) {
620       int   lee;
621       int   hh;
622 
623       lee = opty->ReadInt32();
624       rstruc->scripts = (char *)malloc(lee + 5);
625       // MACPORT FIX: swap
626       opty->Read(rstruc->scripts, lee);
627       rstruc->scripts[lee] = 0;
628 
629       for (hh = 0; hh < lee; hh++)
630         rstruc->scripts[hh] += passwencstring[hh % 11];
631     }
632     else if (thisblock == BLOCKTYPE_COMPSCRIPT3) {
633       rstruc->compiled_script.reset(ccScript::CreateFromStream(opty));
634       if (rstruc->compiled_script == NULL)
635         quit("Load_room: Script load failed; need newer version?");
636     }
637     else if ((thisblock == BLOCKTYPE_COMPSCRIPT) || (thisblock == BLOCKTYPE_COMPSCRIPT2))
638 #ifdef LOADROOM_ALLOWOLD
639       rstruc->compiled_script = NULL;
640 #else
641       quit("Load_room: old room format. Please upgrade the room.");
642 #endif
643     else if (thisblock == BLOCKTYPE_OBJECTNAMES) {
644       if (opty->ReadByte() != rstruc->numsprs)
645         quit("Load_room: inconsistent blocks for object names");
646 
647       for (int i = 0; i < rstruc->numsprs; ++i)
648       {
649         if (rfh.version >= kRoomVersion_3415)
650           rstruc->objectnames[i] = StrUtil::ReadString(opty);
651         else
652           rstruc->objectnames[i].ReadCount(opty, LEGACY_MAXOBJNAMELEN);
653       }
654     }
655     else if (thisblock == BLOCKTYPE_OBJECTSCRIPTNAMES) {
656       if (opty->ReadByte() != rstruc->numsprs)
657         quit("Load_room: inconsistent blocks for object script names");
658 
659       for (int i = 0; i < rstruc->numsprs; ++i)
660       {
661         if (rfh.version >= kRoomVersion_3415)
662           rstruc->objectscriptnames[i] = StrUtil::ReadString(opty);
663         else
664           rstruc->objectscriptnames[i].ReadCount(opty, MAX_SCRIPT_NAME_LEN);
665       }
666     }
667     else if (thisblock == BLOCKTYPE_ANIMBKGRND) {
668       int   ct;
669       long  fpos;
670 
671       rstruc->num_bscenes = opty->ReadByte();
672       rstruc->bscene_anim_speed = opty->ReadByte();
673 
674       if (rfh.version >= kRoomVersion_255a)
675         opty->Read(&rstruc->ebpalShared[0], rstruc->num_bscenes);
676       else
677         memset (&rstruc->ebpalShared[0], 0, rstruc->num_bscenes);
678 
679       fpos = opty->GetPosition();
680 //        fclose(opty);
681 
682       for (ct = 1; ct < rstruc->num_bscenes; ct++) {
683         update_polled_stuff_if_runtime();
684 //          fpos = load_lzw(files,rstruc->ebscene[ct],rstruc->pal,fpos);
685         fpos = load_lzw(opty, rstruc->ebscene[ct], rstruc->bpalettes[ct]);
686         rstruc->ebscene[ct] = recalced;
687       }
688 //        opty = Common::AssetManager::OpenAsset(files, "rb");
689 //        Seek(opty, fpos, SEEK_SET);
690     }
691     else if (thisblock == BLOCKTYPE_PROPERTIES) {
692       // Read custom properties
693       if (opty->ReadInt32() != 1)
694         quit("LoadRoom: unknown Custom Properties block encountered");
695 
696       int errors = 0, gg;
697 
698       if (Properties::ReadValues(rstruc->roomProps, opty))
699         quit("LoadRoom: error reading custom properties block");
700 
701       for (gg = 0; gg < rstruc->numhotspots; gg++)
702         errors += Properties::ReadValues(rstruc->hsProps[gg], opty);
703       for (gg = 0; gg < rstruc->numsprs; gg++)
704         errors += Properties::ReadValues(rstruc->objProps[gg], opty);
705 
706       if (errors > 0)
707         quit("LoadRoom: errors encountered reading custom props");
708     }
709     else if (thisblock == -1)
710     {
711       delete opty;
712       quit("LoadRoom: unexpected end of file while loading room");
713       return;
714     }
715     else {
716       quitprintf("LoadRoom: unknown block type %d encountered in '%s'", thisblock, files);
717     }
718 
719     if (opty->GetPosition() != bloklen)
720       quitprintf("LoadRoom: unexpected end of block %d in in '%s'", thisblock, files);
721   }
722 
723   // sync bpalettes[0] with room.pal
724   memcpy (&rstruc->bpalettes[0][0], &rstruc->pal[0], sizeof(color) * 256);
725 
726   delete opty;
727 
728   if ((rfh.version < kRoomVersion_303b) && (gameIsHighRes))
729   {
730 	  // Pre-3.0.3, multiply up co-ordinates
731       // If you change this, also change convert_room_coordinates_to_low_res
732       // function in the engine
733 	  int f;
734 	  for (f = 0; f < rstruc->numsprs; f++)
735 	  {
736 		  rstruc->sprs[f].x *= 2;
737 		  rstruc->sprs[f].y *= 2;
738 		  if (rstruc->objbaseline[f] > 0)
739 		  {
740 			  rstruc->objbaseline[f] *= 2;
741 		  }
742 	  }
743 
744 	  for (f = 0; f < rstruc->numhotspots; f++)
745 	  {
746 		  rstruc->hswalkto[f].x *= 2;
747 		  rstruc->hswalkto[f].y *= 2;
748 	  }
749 
750 	  for (f = 0; f < rstruc->numobj; f++)
751 	  {
752 		  rstruc->objyval[f] *= 2;
753 	  }
754 
755 	  rstruc->left *= 2;
756 	  rstruc->top *= 2;
757 	  rstruc->bottom *= 2;
758 	  rstruc->right *= 2;
759 	  rstruc->width *= 2;
760 	  rstruc->height *= 2;
761   }
762 
763 }
764