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 #define USE_CLIB
16 #include "util/string_utils.h" //strlwr()
17 #include "ac/common.h"
18 #include "media/audio/audiodefines.h"
19 #include "ac/charactercache.h"
20 #include "ac/characterextras.h"
21 #include "ac/draw.h"
22 #include "ac/event.h"
23 #include "ac/game.h"
24 #include "ac/gamesetup.h"
25 #include "ac/gamesetupstruct.h"
26 #include "ac/gamestate.h"
27 #include "ac/global_audio.h"
28 #include "ac/global_character.h"
29 #include "ac/global_game.h"
30 #include "ac/global_object.h"
31 #include "ac/global_translation.h"
32 #include "ac/mouse.h"
33 #include "ac/objectcache.h"
34 #include "ac/overlay.h"
35 #include "ac/properties.h"
36 #include "ac/region.h"
37 #include "ac/record.h"
38 #include "ac/room.h"
39 #include "ac/roomobject.h"
40 #include "ac/roomstatus.h"
41 #include "ac/screen.h"
42 #include "ac/string.h"
43 #include "ac/system.h"
44 #include "ac/viewport.h"
45 #include "ac/walkablearea.h"
46 #include "ac/walkbehind.h"
47 #include "ac/dynobj/scriptobject.h"
48 #include "ac/dynobj/scripthotspot.h"
49 #include "gui/guidefines.h"
50 #include "script/cc_instance.h"
51 #include "debug/debug_log.h"
52 #include "debug/debugger.h"
53 #include "debug/out.h"
54 #include "device/mousew32.h"
55 #include "media/audio/audio.h"
56 #include "platform/base/agsplatformdriver.h"
57 #include "plugin/agsplugin.h"
58 #include "plugin/plugin_engine.h"
59 #include "script/script.h"
60 #include "script/script_runtime.h"
61 #include "ac/spritecache.h"
62 #include "util/stream.h"
63 #include "gfx/graphicsdriver.h"
64 #include "core/assetmanager.h"
65 #include "ac/dynobj/all_dynamicclasses.h"
66 #include "gfx/bitmap.h"
67 #include "gfx/gfxfilter.h"
68 #include "util/math.h"
69 #include "device/mousew32.h"
70 
71 using namespace AGS::Common;
72 using namespace AGS::Engine;
73 
74 #if !defined (WINDOWS_VERSION)
75 // for toupper
76 #include <ctype.h>
77 #endif
78 
79 extern GameSetup usetup;
80 extern GameSetupStruct game;
81 extern GameState play;
82 extern RoomStatus*croom;
83 extern RoomStatus troom;    // used for non-saveable rooms, eg. intro
84 extern int displayed_room;
85 extern RoomObject*objs;
86 extern ccInstance *roominst;
87 extern AGSPlatformDriver *platform;
88 extern int numevents;
89 extern CharacterCache *charcache;
90 extern ObjectCache objcache[MAX_INIT_SPR];
91 extern CharacterExtras *charextra;
92 extern int done_es_error;
93 extern int our_eip;
94 extern Bitmap *walkareabackup, *walkable_areas_temp;
95 extern ScriptObject scrObj[MAX_INIT_SPR];
96 extern SpriteCache spriteset;
97 extern int spritewidth[MAX_SPRITES],spriteheight[MAX_SPRITES];
98 extern int in_new_room, new_room_was;  // 1 in new room, 2 first time in new room, 3 loading saved game
99 extern ScriptHotspot scrHotspot[MAX_HOTSPOTS];
100 extern int in_leaves_screen;
101 extern CharacterInfo*playerchar;
102 extern int starting_room;
103 extern unsigned int loopcounter,lastcounter;
104 extern int ccError;
105 extern char ccErrorString[400];
106 extern IDriverDependantBitmap* roomBackgroundBmp;
107 extern IGraphicsDriver *gfxDriver;
108 extern Bitmap *raw_saved_screen;
109 extern int actSpsCount;
110 extern Bitmap **actsps;
111 extern IDriverDependantBitmap* *actspsbmp;
112 extern Bitmap **actspswb;
113 extern IDriverDependantBitmap* *actspswbbmp;
114 extern CachedActSpsData* actspswbcache;
115 extern color palette[256];
116 extern Bitmap *virtual_screen;
117 extern Bitmap *_old_screen;
118 extern Bitmap *_sub_screen;
119 extern int offsetx, offsety;
120 extern int mouse_z_was;
121 
122 extern Bitmap **guibg;
123 extern IDriverDependantBitmap **guibgbmp;
124 
125 extern CCHotspot ccDynamicHotspot;
126 extern CCObject ccDynamicObject;
127 
128 RGB_MAP rgb_table;  // for 256-col antialiasing
129 int new_room_flags=0;
130 int gs_to_newroom=-1;
131 
Room_GetDrawingSurfaceForBackground(int backgroundNumber)132 ScriptDrawingSurface* Room_GetDrawingSurfaceForBackground(int backgroundNumber)
133 {
134     if (displayed_room < 0)
135         quit("!Room.GetDrawingSurfaceForBackground: no room is currently loaded");
136 
137     if (backgroundNumber == SCR_NO_VALUE)
138     {
139         backgroundNumber = play.bg_frame;
140     }
141 
142     if ((backgroundNumber < 0) || (backgroundNumber >= thisroom.num_bscenes))
143         quit("!Room.GetDrawingSurfaceForBackground: invalid background number specified");
144 
145 
146     ScriptDrawingSurface *surface = new ScriptDrawingSurface();
147     surface->roomBackgroundNumber = backgroundNumber;
148     ccRegisterManagedObject(surface, surface);
149     return surface;
150 }
151 
152 
Room_GetObjectCount()153 int Room_GetObjectCount() {
154     return croom->numobj;
155 }
156 
Room_GetWidth()157 int Room_GetWidth() {
158     return thisroom.width;
159 }
160 
Room_GetHeight()161 int Room_GetHeight() {
162     return thisroom.height;
163 }
164 
Room_GetColorDepth()165 int Room_GetColorDepth() {
166     return thisroom.ebscene[0]->GetColorDepth();
167 }
168 
Room_GetLeftEdge()169 int Room_GetLeftEdge() {
170     return thisroom.left;
171 }
172 
Room_GetRightEdge()173 int Room_GetRightEdge() {
174     return thisroom.right;
175 }
176 
Room_GetTopEdge()177 int Room_GetTopEdge() {
178     return thisroom.top;
179 }
180 
Room_GetBottomEdge()181 int Room_GetBottomEdge() {
182     return thisroom.bottom;
183 }
184 
Room_GetMusicOnLoad()185 int Room_GetMusicOnLoad() {
186     return thisroom.options[ST_TUNE];
187 }
188 
Room_GetProperty(const char * property)189 int Room_GetProperty(const char *property)
190 {
191     return get_int_property(thisroom.roomProps, croom->roomProps, property);
192 }
193 
Room_GetTextProperty(const char * property)194 const char* Room_GetTextProperty(const char *property)
195 {
196     return get_text_property_dynamic_string(thisroom.roomProps, croom->roomProps, property);
197 }
198 
Room_SetProperty(const char * property,int value)199 bool Room_SetProperty(const char *property, int value)
200 {
201     return set_int_property(croom->roomProps, property, value);
202 }
203 
Room_SetTextProperty(const char * property,const char * value)204 bool Room_SetTextProperty(const char *property, const char *value)
205 {
206     return set_text_property(croom->roomProps, property, value);
207 }
208 
Room_GetMessages(int index)209 const char* Room_GetMessages(int index) {
210     if ((index < 0) || (index >= thisroom.nummes)) {
211         return NULL;
212     }
213     char buffer[STD_BUFFER_SIZE];
214     buffer[0]=0;
215     replace_tokens(get_translation(thisroom.message[index]), buffer, STD_BUFFER_SIZE);
216     return CreateNewScriptString(buffer);
217 }
218 
219 
220 //=============================================================================
221 
fix_bitmap_size(Bitmap * todubl)222 Bitmap *fix_bitmap_size(Bitmap *todubl) {
223     int oldw=todubl->GetWidth(), oldh=todubl->GetHeight();
224     int newWidth = multiply_up_coordinate(thisroom.width);
225     int newHeight = multiply_up_coordinate(thisroom.height);
226 
227     if ((oldw == newWidth) && (oldh == newHeight))
228         return todubl;
229 
230     //  Bitmap *tempb=BitmapHelper::CreateBitmap(play.viewport.GetWidth(),play.viewport.GetHeight());
231     //todubl->SetClip(Rect(0,0,oldw-1,oldh-1)); // CHECKME! [IKM] Not sure this is needed here
232     Bitmap *tempb=BitmapHelper::CreateBitmap(newWidth, newHeight, todubl->GetColorDepth());
233     tempb->SetClip(Rect(0,0,tempb->GetWidth()-1,tempb->GetHeight()-1));
234     tempb->Fill(0);
235     tempb->StretchBlt(todubl, RectWH(0,0,oldw,oldh), RectWH(0,0,tempb->GetWidth(),tempb->GetHeight()));
236     delete todubl;
237     return tempb;
238 }
239 
240 
241 
242 
save_room_data_segment()243 void save_room_data_segment () {
244     croom->FreeScriptData();
245 
246     croom->tsdatasize = roominst->globaldatasize;
247     if (croom->tsdatasize > 0) {
248         croom->tsdata=(char*)malloc(croom->tsdatasize+10);
249         memcpy(croom->tsdata,&roominst->globaldata[0],croom->tsdatasize);
250     }
251 
252 }
253 
unload_old_room()254 void unload_old_room() {
255     int ff;
256 
257     // if switching games on restore, don't do this
258     if (displayed_room < 0)
259         return;
260 
261     debug_script_log("Unloading room %d", displayed_room);
262 
263     current_fade_out_effect();
264 
265     Bitmap *ds = GetVirtualScreen();
266     ds->Fill(0);
267     for (ff=0;ff<croom->numobj;ff++)
268         objs[ff].moving = 0;
269 
270     if (!play.ambient_sounds_persist) {
271         for (ff = 1; ff < MAX_SOUND_CHANNELS; ff++)
272             StopAmbientSound(ff);
273     }
274 
275     cancel_all_scripts();
276     numevents = 0;  // cancel any pending room events
277 
278     if (roomBackgroundBmp != NULL)
279     {
280         gfxDriver->DestroyDDB(roomBackgroundBmp);
281         roomBackgroundBmp = NULL;
282     }
283 
284     if (croom==NULL) ;
285     else if (roominst!=NULL) {
286         save_room_data_segment();
287         delete roominstFork;
288         delete roominst;
289         roominstFork = NULL;
290         roominst=NULL;
291     }
292     else croom->tsdatasize=0;
293     memset(&play.walkable_areas_on[0],1,MAX_WALK_AREAS+1);
294     play.bg_frame=0;
295     play.bg_frame_locked=0;
296     play.offsets_locked=0;
297     remove_screen_overlay(-1);
298     delete raw_saved_screen;
299     raw_saved_screen = NULL;
300     for (ff = 0; ff < MAX_BSCENE; ff++)
301         play.raw_modified[ff] = 0;
302     for (ff = 0; ff < thisroom.numLocalVars; ff++)
303         croom->interactionVariableValues[ff] = thisroom.localvars[ff].Value;
304 
305     // wipe the character cache when we change rooms
306     for (ff = 0; ff < game.numcharacters; ff++) {
307         if (charcache[ff].inUse) {
308             delete charcache[ff].image;
309             charcache[ff].image = NULL;
310             charcache[ff].inUse = 0;
311         }
312         // ensure that any half-moves (eg. with scaled movement) are stopped
313         charextra[ff].xwas = INVALID_X;
314     }
315 
316     play.swap_portrait_lastchar = -1;
317     play.swap_portrait_lastlastchar = -1;
318 
319     for (ff = 0; ff < croom->numobj; ff++) {
320         // un-export the object's script object
321         if (objectScriptObjNames[ff].IsEmpty())
322             continue;
323 
324         ccRemoveExternalSymbol(objectScriptObjNames[ff]);
325     }
326 
327     for (ff = 0; ff < MAX_HOTSPOTS; ff++) {
328         if (thisroom.hotspotScriptNames[ff].IsEmpty())
329             continue;
330 
331         ccRemoveExternalSymbol(thisroom.hotspotScriptNames[ff]);
332     }
333 
334     croom_ptr_clear();
335 
336     // clear the object cache
337     for (ff = 0; ff < MAX_INIT_SPR; ff++) {
338         delete objcache[ff].image;
339         objcache[ff].image = NULL;
340     }
341     // clear the actsps buffers to save memory, since the
342     // objects/characters involved probably aren't on the
343     // new screen. this also ensures all cached data is flushed
344     for (ff = 0; ff < MAX_INIT_SPR + game.numcharacters; ff++) {
345         delete actsps[ff];
346         actsps[ff] = NULL;
347 
348         if (actspsbmp[ff] != NULL)
349             gfxDriver->DestroyDDB(actspsbmp[ff]);
350         actspsbmp[ff] = NULL;
351 
352         delete actspswb[ff];
353         actspswb[ff] = NULL;
354 
355         if (actspswbbmp[ff] != NULL)
356             gfxDriver->DestroyDDB(actspswbbmp[ff]);
357         actspswbbmp[ff] = NULL;
358 
359         actspswbcache[ff].valid = 0;
360     }
361 
362     // if Hide Player Character was ticked, restore it to visible
363     if (play.temporarily_turned_off_character >= 0) {
364         game.chars[play.temporarily_turned_off_character].on = 1;
365         play.temporarily_turned_off_character = -1;
366     }
367 
368 }
369 
370 
371 
convert_room_coordinates_to_low_res(roomstruct * rstruc)372 void convert_room_coordinates_to_low_res(roomstruct *rstruc)
373 {
374     int f;
375     for (f = 0; f < rstruc->numsprs; f++)
376     {
377         rstruc->sprs[f].x /= 2;
378         rstruc->sprs[f].y /= 2;
379         if (rstruc->objbaseline[f] > 0)
380         {
381             rstruc->objbaseline[f] /= 2;
382         }
383     }
384 
385     for (f = 0; f < rstruc->numhotspots; f++)
386     {
387         rstruc->hswalkto[f].x /= 2;
388         rstruc->hswalkto[f].y /= 2;
389     }
390 
391     for (f = 0; f < rstruc->numobj; f++)
392     {
393         rstruc->objyval[f] /= 2;
394     }
395 
396     rstruc->left /= 2;
397     rstruc->top /= 2;
398     rstruc->bottom /= 2;
399     rstruc->right /= 2;
400     rstruc->width /= 2;
401     rstruc->height /= 2;
402 }
403 
404 extern int convert_16bit_bgr;
405 
406 #define NO_GAME_ID_IN_ROOM_FILE 16325
407 // forchar = playerchar on NewRoom, or NULL if restore saved game
load_new_room(int newnum,CharacterInfo * forchar)408 void load_new_room(int newnum, CharacterInfo*forchar) {
409 
410     debug_script_log("Loading room %d", newnum);
411 
412     String room_filename;
413     int cc;
414     done_es_error = 0;
415     play.room_changes ++;
416     set_color_depth(8);
417     displayed_room=newnum;
418 
419     room_filename.Format("room%d.crm", newnum);
420     if (newnum == 0) {
421         // support both room0.crm and intro.crm
422         // 2.70: Renamed intro.crm to room0.crm, to stop it causing confusion
423         if (loaded_game_file_version < kGameVersion_270 && Common::AssetManager::DoesAssetExist("intro.crm") ||
424             loaded_game_file_version >= kGameVersion_270 && !Common::AssetManager::DoesAssetExist(room_filename))
425         {
426             room_filename = "intro.crm";
427         }
428     }
429     // reset these back, because they might have been changed.
430     delete thisroom.object;
431     thisroom.object=BitmapHelper::CreateBitmap(320,200);
432 
433     delete thisroom.ebscene[0];
434     thisroom.ebscene[0] = BitmapHelper::CreateBitmap(320,200);
435 
436     update_polled_stuff_if_runtime();
437 
438     // load the room from disk
439     our_eip=200;
440     thisroom.gameId = NO_GAME_ID_IN_ROOM_FILE;
441     load_room(room_filename, &thisroom, game.IsHiRes());
442 
443     if ((thisroom.gameId != NO_GAME_ID_IN_ROOM_FILE) &&
444         (thisroom.gameId != game.uniqueid)) {
445             quitprintf("!Unable to load '%s'. This room file is assigned to a different game.", room_filename.GetCStr());
446     }
447 
448     if (game.IsHiRes() && (game.options[OPT_NATIVECOORDINATES] == 0))
449     {
450         convert_room_coordinates_to_low_res(&thisroom);
451     }
452 
453     update_polled_stuff_if_runtime();
454     our_eip=201;
455     /*  // apparently, doing this stops volume spiking between tracks
456     if (thisroom.options[ST_TUNE]>0) {
457     stopmusic();
458     delay(100);
459     }*/
460 
461     play.room_width = thisroom.width;
462     play.room_height = thisroom.height;
463     play.anim_background_speed = thisroom.bscene_anim_speed;
464     play.bg_anim_delay = play.anim_background_speed;
465 
466     int dd;
467     // do the palette
468     for (cc=0;cc<256;cc++) {
469         if (game.paluses[cc]==PAL_BACKGROUND)
470             palette[cc]=thisroom.pal[cc];
471         else {
472             // copy the gamewide colours into the room palette
473             for (dd = 0; dd < thisroom.num_bscenes; dd++)
474                 thisroom.bpalettes[dd][cc] = palette[cc];
475         }
476     }
477 
478     for (cc=0;cc<thisroom.num_bscenes;cc++) {
479         update_polled_stuff_if_runtime();
480         thisroom.ebscene[cc] = PrepareSpriteForUse(thisroom.ebscene[cc], false);
481     }
482 
483     update_polled_stuff_if_runtime();
484 
485     our_eip=202;
486     const int real_room_height = multiply_up_coordinate(thisroom.height);
487     // Game viewport is updated when when room's size is smaller than game's size.
488     // NOTE: if "OPT_LETTERBOX" is false, altsize.Height = size.Height always.
489     if (real_room_height < game.size.Height || play.viewport.GetHeight() < game.size.Height) {
490         int abscreen=0;
491 
492         // [IKM] Here we remember what was set as virtual screen: either real screen bitmap, or virtual_screen bitmap
493         Bitmap *ds = GetVirtualScreen();
494         if (ds==BitmapHelper::GetScreenBitmap()) abscreen=1;
495         else if (ds==virtual_screen) abscreen=2;
496 
497         // Define what should be a new game viewport size
498         int newScreenHeight = game.size.Height;
499         // [IKM] 2015-05-04: in original engine the letterbox feature only allowed viewports of
500         // either 200 or 240 (400 and 480) pixels, if the room height was equal or greater than 200 (400).
501         const int viewport_height = real_room_height < game.altsize.Height ? real_room_height :
502             (real_room_height >= game.altsize.Height && real_room_height < game.size.Height) ? game.altsize.Height :
503             game.size.Height;
504         if (viewport_height < game.size.Height) {
505             clear_letterbox_borders();
506             newScreenHeight = viewport_height;
507         }
508 
509         // If this is the first time we got here, then the sub_screen does not exist at this point; so we create it here.
510         if (!_sub_screen)
511             _sub_screen = BitmapHelper::CreateSubBitmap(_old_screen, RectWH(game.size.Width / 2 - play.viewport.GetWidth() / 2, game.size.Height / 2-newScreenHeight/2, play.viewport.GetWidth(), newScreenHeight));
512 
513         // Reset screen bitmap
514         if (newScreenHeight == _sub_screen->GetHeight())
515         {
516             // requested viewport height is the same as existing subscreen
517 			BitmapHelper::SetScreenBitmap( _sub_screen );
518         }
519         // CHECKME: WTF is this for?
520         else if (_sub_screen->GetWidth() != game.size.Width)
521         {
522             // the height has changed and the width is not equal with game width
523             int subBitmapWidth = _sub_screen->GetWidth();
524             delete _sub_screen;
525             _sub_screen = BitmapHelper::CreateSubBitmap(_old_screen, RectWH(_old_screen->GetWidth() / 2 - subBitmapWidth / 2, _old_screen->GetHeight() / 2 - newScreenHeight / 2, subBitmapWidth, newScreenHeight));
526             BitmapHelper::SetScreenBitmap( _sub_screen );
527         }
528         else
529         {
530             // the height and width are equal to game native size: restore original screen
531             BitmapHelper::SetScreenBitmap( _old_screen );
532         }
533 
534         // Update viewport and mouse area
535         play.SetViewport(BitmapHelper::GetScreenBitmap()->GetSize());
536         Mouse::SetGraphicArea();
537 
538         // Reset virtual_screen bitmap
539         if (virtual_screen->GetHeight() != play.viewport.GetHeight()) {
540             int cdepth=virtual_screen->GetColorDepth();
541             delete virtual_screen;
542             virtual_screen=BitmapHelper::CreateBitmap(play.viewport.GetWidth(),play.viewport.GetHeight(),cdepth);
543             virtual_screen->Clear();
544             gfxDriver->SetMemoryBackBuffer(virtual_screen);
545         }
546 
547         // Adjust offsets for rendering sprites on virtual screen
548         gfxDriver->SetRenderOffset(play.viewport.Left, play.viewport.Top);
549 
550         // [IKM] Since both screen and virtual_screen bitmaps might have changed, we reset a virtual screen,
551         // with either first or second, depending on what was set as virtual screen before
552 		if (abscreen==1) // it was a screen bitmap
553             SetVirtualScreen( BitmapHelper::GetScreenBitmap() );
554         else if (abscreen==2) // it was a virtual_screen bitmap
555             SetVirtualScreen( virtual_screen );
556 
557         update_polled_stuff_if_runtime();
558     }
559     // update the script viewport height
560     scsystem.viewport_height = divide_down_coordinate(play.viewport.GetHeight());
561 
562     SetMouseBounds (0,0,0,0);
563 
564     our_eip=203;
565     in_new_room=1;
566 
567     // walkable_areas_temp is used by the pathfinder to generate a
568     // copy of the walkable areas - allocate it here to save time later
569     delete walkable_areas_temp;
570     walkable_areas_temp = BitmapHelper::CreateBitmap(thisroom.walls->GetWidth(), thisroom.walls->GetHeight(), 8);
571 
572     // Make a backup copy of the walkable areas prior to
573     // any RemoveWalkableArea commands
574     delete walkareabackup;
575     // copy the walls screen
576     walkareabackup=BitmapHelper::CreateBitmapCopy(thisroom.walls);
577 
578     our_eip=204;
579     update_polled_stuff_if_runtime();
580     redo_walkable_areas();
581     // fix walk-behinds to current screen resolution
582     thisroom.object = fix_bitmap_size(thisroom.object);
583     update_polled_stuff_if_runtime();
584 
585     set_color_depth(game.GetColorDepth());
586     // convert backgrounds to current res
587     if (thisroom.resolution != get_fixed_pixel_size(1)) {
588         for (cc=0;cc<thisroom.num_bscenes;cc++)
589             thisroom.ebscene[cc] = fix_bitmap_size(thisroom.ebscene[cc]);
590     }
591 
592     if ((thisroom.ebscene[0]->GetWidth() < play.viewport.GetWidth()) ||
593         (thisroom.ebscene[0]->GetHeight() < play.viewport.GetHeight()))
594     {
595         quitprintf("!The background scene for this room is smaller than the game resolution. If you have recently changed "
596             "the game resolution, you will need to re-import the background for this room. (Room: %d, BG Size: %d x %d)",
597             newnum, thisroom.ebscene[0]->GetWidth(), thisroom.ebscene[0]->GetHeight());
598     }
599 
600     recache_walk_behinds();
601 
602     our_eip=205;
603     // setup objects
604     if (forchar != NULL) {
605         // if not restoring a game, always reset this room
606         troom.beenhere=0;
607         troom.FreeScriptData();
608         troom.FreeProperties();
609         memset(&troom.hotspot_enabled[0],1,MAX_HOTSPOTS);
610         memset(&troom.region_enabled[0], 1, MAX_REGIONS);
611     }
612     if ((newnum>=0) & (newnum<MAX_ROOMS))
613         croom = getRoomStatus(newnum);
614     else croom=&troom;
615 
616     if (croom->beenhere > 0) {
617         // if we've been here before, save the Times Run information
618         // since we will overwrite the actual NewInteraction structs
619         // (cos they have pointers and this might have been loaded from
620         // a save game)
621         if (thisroom.roomScripts == NULL)
622         {
623             thisroom.intrRoom->CopyTimesRun(croom->intrRoom);
624             for (cc=0;cc < MAX_HOTSPOTS;cc++)
625                 thisroom.intrHotspot[cc]->CopyTimesRun(croom->intrHotspot[cc]);
626             for (cc=0;cc < MAX_INIT_SPR;cc++)
627                 thisroom.intrObject[cc]->CopyTimesRun(croom->intrObject[cc]);
628             for (cc=0;cc < MAX_REGIONS;cc++)
629                 thisroom.intrRegion[cc]->CopyTimesRun(croom->intrRegion[cc]);
630         }
631     }
632     if (croom->beenhere==0) {
633         croom->numobj=thisroom.numsprs;
634         croom->tsdatasize=0;
635         for (cc=0;cc<croom->numobj;cc++) {
636             croom->obj[cc].x=thisroom.sprs[cc].x;
637             croom->obj[cc].y=thisroom.sprs[cc].y;
638 
639             if (thisroom.wasversion <= kRoomVersion_300a)
640                 croom->obj[cc].y += divide_down_coordinate(spriteheight[thisroom.sprs[cc].sprnum]);
641 
642             croom->obj[cc].num=thisroom.sprs[cc].sprnum;
643             croom->obj[cc].on=thisroom.sprs[cc].on;
644             croom->obj[cc].view=-1;
645             croom->obj[cc].loop=0;
646             croom->obj[cc].frame=0;
647             croom->obj[cc].wait=0;
648             croom->obj[cc].transparent=0;
649             croom->obj[cc].moving=-1;
650             croom->obj[cc].flags = thisroom.objectFlags[cc];
651             croom->obj[cc].baseline=-1;
652             croom->obj[cc].last_zoom = 100;
653             croom->obj[cc].last_width = 0;
654             croom->obj[cc].last_height = 0;
655             croom->obj[cc].blocking_width = 0;
656             croom->obj[cc].blocking_height = 0;
657             if (thisroom.objbaseline[cc]>=0)
658                 //        croom->obj[cc].baseoffs=thisroom.objbaseline[cc]-thisroom.sprs[cc].y;
659                 croom->obj[cc].baseline=thisroom.objbaseline[cc];
660         }
661         memcpy(&croom->walkbehind_base[0],&thisroom.objyval[0],sizeof(short)*MAX_OBJ);
662         for (cc=0;cc<MAX_FLAGS;cc++) croom->flagstates[cc]=0;
663 
664         /*    // we copy these structs for the Score column to work
665         croom->misccond=thisroom.misccond;
666         for (cc=0;cc<MAX_HOTSPOTS;cc++)
667         croom->hscond[cc]=thisroom.hscond[cc];
668         for (cc=0;cc<MAX_INIT_SPR;cc++)
669         croom->objcond[cc]=thisroom.objcond[cc];*/
670 
671         for (cc=0;cc < MAX_HOTSPOTS;cc++) {
672             croom->hotspot_enabled[cc] = 1;
673         }
674         for (cc = 0; cc < MAX_REGIONS; cc++) {
675             croom->region_enabled[cc] = 1;
676         }
677 
678         croom->beenhere=1;
679         in_new_room=2;
680     }
681     else {
682         // We have been here before
683         for (int ff = 0; ff < thisroom.numLocalVars; ff++)
684             thisroom.localvars[ff].Value = croom->interactionVariableValues[ff];
685     }
686 
687     update_polled_stuff_if_runtime();
688 
689     if (thisroom.roomScripts == NULL)
690     {
691         // copy interactions from room file into our temporary struct
692         croom->intrRoom = thisroom.intrRoom[0];
693         for (cc=0;cc<MAX_HOTSPOTS;cc++)
694             croom->intrHotspot[cc] = thisroom.intrHotspot[cc][0];
695         for (cc=0;cc<MAX_INIT_SPR;cc++)
696             croom->intrObject[cc] = thisroom.intrObject[cc][0];
697         for (cc=0;cc<MAX_REGIONS;cc++)
698             croom->intrRegion[cc] = thisroom.intrRegion[cc][0];
699     }
700 
701     objs=&croom->obj[0];
702 
703     for (cc = 0; cc < MAX_INIT_SPR; cc++) {
704         // 64 bit: Using the id instead
705         // scrObj[cc].obj = &croom->obj[cc];
706         objectScriptObjNames[cc].Free();
707     }
708 
709     for (cc = 0; cc < croom->numobj; cc++) {
710         // export the object's script object
711         if (thisroom.objectscriptnames[cc].IsEmpty())
712             continue;
713 
714         if (thisroom.wasversion >= kRoomVersion_300a)
715         {
716             objectScriptObjNames[cc] = thisroom.objectscriptnames[cc];
717         }
718         else
719         {
720             objectScriptObjNames[cc].Format("o%s", thisroom.objectscriptnames[cc].GetCStr());
721             objectScriptObjNames[cc].MakeLower();
722             if (objectScriptObjNames[cc].GetLength() >= 2)
723                 objectScriptObjNames[cc].SetAt(1, toupper(objectScriptObjNames[cc].GetAt(1)));
724         }
725 
726         ccAddExternalDynamicObject(objectScriptObjNames[cc], &scrObj[cc], &ccDynamicObject);
727     }
728 
729     for (cc = 0; cc < MAX_HOTSPOTS; cc++) {
730         if (thisroom.hotspotScriptNames[cc].IsEmpty())
731             continue;
732 
733         ccAddExternalDynamicObject(thisroom.hotspotScriptNames[cc], &scrHotspot[cc], &ccDynamicHotspot);
734     }
735 
736     our_eip=206;
737     /*  THIS IS DONE IN THE EDITOR NOW
738     thisroom.ebpalShared[0] = 1;
739     for (dd = 1; dd < thisroom.num_bscenes; dd++) {
740     if (memcmp (&thisroom.bpalettes[dd][0], &palette[0], sizeof(color) * 256) == 0)
741     thisroom.ebpalShared[dd] = 1;
742     else
743     thisroom.ebpalShared[dd] = 0;
744     }
745     // only make the first frame shared if the last is
746     if (thisroom.ebpalShared[thisroom.num_bscenes - 1] == 0)
747     thisroom.ebpalShared[0] = 0;*/
748 
749     update_polled_stuff_if_runtime();
750 
751     our_eip = 210;
752     if (IS_ANTIALIAS_SPRITES) {
753         // sometimes the palette has corrupt entries, which crash
754         // the create_rgb_table call
755         // so, fix them
756         for (int ff = 0; ff < 256; ff++) {
757             if (palette[ff].r > 63)
758                 palette[ff].r = 63;
759             if (palette[ff].g > 63)
760                 palette[ff].g = 63;
761             if (palette[ff].b > 63)
762                 palette[ff].b = 63;
763         }
764         create_rgb_table (&rgb_table, palette, NULL);
765         rgb_map = &rgb_table;
766     }
767     our_eip = 211;
768     if (forchar!=NULL) {
769         // if it's not a Restore Game
770 
771         // if a following character is still waiting to come into the
772         // previous room, force it out so that the timer resets
773         for (int ff = 0; ff < game.numcharacters; ff++) {
774             if ((game.chars[ff].following >= 0) && (game.chars[ff].room < 0)) {
775                 if ((game.chars[ff].following == game.playercharacter) &&
776                     (forchar->prevroom == newnum))
777                     // the player went back to the previous room, so make sure
778                     // the following character is still there
779                     game.chars[ff].room = newnum;
780                 else
781                     game.chars[ff].room = game.chars[game.chars[ff].following].room;
782             }
783         }
784 
785         offsetx=0;
786         offsety=0;
787         forchar->prevroom=forchar->room;
788         forchar->room=newnum;
789         // only stop moving if it's a new room, not a restore game
790         for (cc=0;cc<game.numcharacters;cc++)
791             StopMoving(cc);
792 
793     }
794 
795     update_polled_stuff_if_runtime();
796 
797     roominst=NULL;
798     if (debug_flags & DBG_NOSCRIPT) ;
799     else if (thisroom.compiled_script!=NULL) {
800         compile_room_script();
801         if (croom->tsdatasize>0) {
802             if (croom->tsdatasize != roominst->globaldatasize)
803                 quit("room script data segment size has changed");
804             memcpy(&roominst->globaldata[0],croom->tsdata,croom->tsdatasize);
805         }
806     }
807     our_eip=207;
808     play.entered_edge = -1;
809 
810     if ((new_room_x != SCR_NO_VALUE) && (forchar != NULL))
811     {
812         forchar->x = new_room_x;
813         forchar->y = new_room_y;
814 
815 		if (new_room_loop != SCR_NO_VALUE)
816 			forchar->loop = new_room_loop;
817     }
818     new_room_x = SCR_NO_VALUE;
819 	new_room_loop = SCR_NO_VALUE;
820 
821     if ((new_room_pos>0) & (forchar!=NULL)) {
822         if (new_room_pos>=4000) {
823             play.entered_edge = 3;
824             forchar->y = thisroom.top + get_fixed_pixel_size(1);
825             forchar->x=new_room_pos%1000;
826             if (forchar->x==0) forchar->x=thisroom.width/2;
827             if (forchar->x <= thisroom.left)
828                 forchar->x = thisroom.left + 3;
829             if (forchar->x >= thisroom.right)
830                 forchar->x = thisroom.right - 3;
831             forchar->loop=0;
832         }
833         else if (new_room_pos>=3000) {
834             play.entered_edge = 2;
835             forchar->y = thisroom.bottom - get_fixed_pixel_size(1);
836             forchar->x=new_room_pos%1000;
837             if (forchar->x==0) forchar->x=thisroom.width/2;
838             if (forchar->x <= thisroom.left)
839                 forchar->x = thisroom.left + 3;
840             if (forchar->x >= thisroom.right)
841                 forchar->x = thisroom.right - 3;
842             forchar->loop=3;
843         }
844         else if (new_room_pos>=2000) {
845             play.entered_edge = 1;
846             forchar->x = thisroom.right - get_fixed_pixel_size(1);
847             forchar->y=new_room_pos%1000;
848             if (forchar->y==0) forchar->y=thisroom.height/2;
849             if (forchar->y <= thisroom.top)
850                 forchar->y = thisroom.top + 3;
851             if (forchar->y >= thisroom.bottom)
852                 forchar->y = thisroom.bottom - 3;
853             forchar->loop=1;
854         }
855         else if (new_room_pos>=1000) {
856             play.entered_edge = 0;
857             forchar->x = thisroom.left + get_fixed_pixel_size(1);
858             forchar->y=new_room_pos%1000;
859             if (forchar->y==0) forchar->y=thisroom.height/2;
860             if (forchar->y <= thisroom.top)
861                 forchar->y = thisroom.top + 3;
862             if (forchar->y >= thisroom.bottom)
863                 forchar->y = thisroom.bottom - 3;
864             forchar->loop=2;
865         }
866         // if starts on un-walkable area
867         if (get_walkable_area_pixel(forchar->x, forchar->y) == 0) {
868             if (new_room_pos>=3000) { // bottom or top of screen
869                 int tryleft=forchar->x - 1,tryright=forchar->x + 1;
870                 while (1) {
871                     if (get_walkable_area_pixel(tryleft, forchar->y) > 0) {
872                         forchar->x=tryleft; break; }
873                     if (get_walkable_area_pixel(tryright, forchar->y) > 0) {
874                         forchar->x=tryright; break; }
875                     int nowhere=0;
876                     if (tryleft>thisroom.left) { tryleft--; nowhere++; }
877                     if (tryright<thisroom.right) { tryright++; nowhere++; }
878                     if (nowhere==0) break;  // no place to go, so leave him
879                 }
880             }
881             else if (new_room_pos>=1000) { // left or right
882                 int tryleft=forchar->y - 1,tryright=forchar->y + 1;
883                 while (1) {
884                     if (get_walkable_area_pixel(forchar->x, tryleft) > 0) {
885                         forchar->y=tryleft; break; }
886                     if (get_walkable_area_pixel(forchar->x, tryright) > 0) {
887                         forchar->y=tryright; break; }
888                     int nowhere=0;
889                     if (tryleft>thisroom.top) { tryleft--; nowhere++; }
890                     if (tryright<thisroom.bottom) { tryright++; nowhere++; }
891                     if (nowhere==0) break;  // no place to go, so leave him
892                 }
893             }
894         }
895         new_room_pos=0;
896     }
897     if (forchar!=NULL) {
898         play.entered_at_x=forchar->x;
899         play.entered_at_y=forchar->y;
900         if (forchar->x >= thisroom.right)
901             play.entered_edge = 1;
902         else if (forchar->x <= thisroom.left)
903             play.entered_edge = 0;
904         else if (forchar->y >= thisroom.bottom)
905             play.entered_edge = 2;
906         else if (forchar->y <= thisroom.top)
907             play.entered_edge = 3;
908     }
909     /*  if ((playerchar->x > thisroom.width) | (playerchar->y > thisroom.height))
910     quit("!NewRoomEx: x/y co-ordinates are invalid");*/
911     if (thisroom.options[ST_TUNE]>0)
912         PlayMusicResetQueue(thisroom.options[ST_TUNE]);
913 
914     our_eip=208;
915     if (forchar!=NULL) {
916         if (thisroom.options[ST_MANDISABLED]==0) { forchar->on=1;
917         enable_cursor_mode(0); }
918         else {
919             forchar->on=0;
920             disable_cursor_mode(0);
921             // remember which character we turned off, in case they
922             // use SetPlyaerChracter within this room (so we re-enable
923             // the correct character when leaving the room)
924             play.temporarily_turned_off_character = game.playercharacter;
925         }
926         if (forchar->flags & CHF_FIXVIEW) ;
927         else if (thisroom.options[ST_MANVIEW]==0) forchar->view=forchar->defview;
928         else forchar->view=thisroom.options[ST_MANVIEW]-1;
929         forchar->frame=0;   // make him standing
930     }
931     color_map = NULL;
932 
933     our_eip = 209;
934     update_polled_stuff_if_runtime();
935     generate_light_table();
936     update_music_volume();
937     update_viewport();
938     our_eip = 212;
939     invalidate_screen();
940     for (cc=0;cc<croom->numobj;cc++) {
941         if (objs[cc].on == 2)
942             MergeObject(cc);
943     }
944     new_room_flags=0;
945     play.gscript_timer=-1;  // avoid screw-ups with changing screens
946     play.player_on_region = 0;
947     // trash any input which they might have done while it was loading
948     clear_input_buffer();
949     // no fade in, so set the palette immediately in case of 256-col sprites
950     if (game.color_depth > 1)
951         setpal();
952 
953     our_eip=220;
954     update_polled_stuff_if_runtime();
955     debug_script_log("Now in room %d", displayed_room);
956     guis_need_update = 1;
957     pl_run_plugin_hooks(AGSE_ENTERROOM, displayed_room);
958     //  MoveToWalkableArea(game.playercharacter);
959     //  MSS_CHECK_ALL_BLOCKS;
960 }
961 
962 extern int psp_clear_cache_on_room_change;
963 
964 // new_room: changes the current room number, and loads the new room from disk
new_room(int newnum,CharacterInfo * forchar)965 void new_room(int newnum,CharacterInfo*forchar) {
966     EndSkippingUntilCharStops();
967 
968     debug_script_log("Room change requested to room %d", newnum);
969 
970     update_polled_stuff_if_runtime();
971 
972     // we are currently running Leaves Screen scripts
973     in_leaves_screen = newnum;
974 
975     // player leaves screen event
976     run_room_event(8);
977     // Run the global OnRoomLeave event
978     run_on_event (GE_LEAVE_ROOM, RuntimeScriptValue().SetInt32(displayed_room));
979 
980     pl_run_plugin_hooks(AGSE_LEAVEROOM, displayed_room);
981 
982     // update the new room number if it has been altered by OnLeave scripts
983     newnum = in_leaves_screen;
984     in_leaves_screen = -1;
985 
986     if ((playerchar->following >= 0) &&
987         (game.chars[playerchar->following].room != newnum)) {
988             // the player character is following another character,
989             // who is not in the new room. therefore, abort the follow
990             playerchar->following = -1;
991     }
992     update_polled_stuff_if_runtime();
993 
994     // change rooms
995     unload_old_room();
996 
997     if (psp_clear_cache_on_room_change)
998     {
999         // Delete all cached sprites
1000         spriteset.removeAll();
1001 
1002         // Delete all gui background images
1003         for (int i = 0; i < game.numgui; i++)
1004         {
1005             delete guibg[i];
1006             guibg[i] = NULL;
1007 
1008             if (guibgbmp[i])
1009                 gfxDriver->DestroyDDB(guibgbmp[i]);
1010             guibgbmp[i] = NULL;
1011         }
1012         guis_need_update = 1;
1013     }
1014 
1015     update_polled_stuff_if_runtime();
1016 
1017     load_new_room(newnum,forchar);
1018 }
1019 
find_highest_room_entered()1020 int find_highest_room_entered() {
1021     int qq,fndas=-1;
1022     for (qq=0;qq<MAX_ROOMS;qq++) {
1023         if (isRoomStatusValid(qq) && (getRoomStatus(qq)->beenhere != 0))
1024             fndas = qq;
1025     }
1026     // This is actually legal - they might start in room 400 and save
1027     //if (fndas<0) quit("find_highest_room: been in no rooms?");
1028     return fndas;
1029 }
1030 
1031 extern long t1;  // defined in ac_main
1032 
first_room_initialization()1033 void first_room_initialization() {
1034     starting_room = displayed_room;
1035     t1 = time(NULL);
1036     lastcounter=0;
1037     loopcounter=0;
1038     mouse_z_was = mouse_z;
1039 }
1040 
check_new_room()1041 void check_new_room() {
1042     // if they're in a new room, run Player Enters Screen and on_event(ENTER_ROOM)
1043     if ((in_new_room>0) & (in_new_room!=3)) {
1044         EventHappened evh;
1045         evh.type = EV_RUNEVBLOCK;
1046         evh.data1 = EVB_ROOM;
1047         evh.data2 = 0;
1048         evh.data3 = 5;
1049         evh.player=game.playercharacter;
1050         // make sure that any script calls don't re-call enters screen
1051         int newroom_was = in_new_room;
1052         in_new_room = 0;
1053         play.disabled_user_interface ++;
1054         process_event(&evh);
1055         play.disabled_user_interface --;
1056         in_new_room = newroom_was;
1057         //    setevent(EV_RUNEVBLOCK,EVB_ROOM,0,5);
1058     }
1059 }
1060 
compile_room_script()1061 void compile_room_script() {
1062     ccError = 0;
1063 
1064     roominst = ccInstance::CreateFromScript(thisroom.compiled_script);
1065 
1066     if ((ccError!=0) || (roominst==NULL)) {
1067         char thiserror[400];
1068         sprintf(thiserror, "Unable to create local script: %s", ccErrorString);
1069         quit(thiserror);
1070     }
1071 
1072     roominstFork = roominst->Fork();
1073     if (roominstFork == NULL)
1074         quitprintf("Unable to create forked room instance: %s", ccErrorString);
1075 
1076     repExecAlways.roomHasFunction = true;
1077     lateRepExecAlways.roomHasFunction = true;
1078     getDialogOptionsDimensionsFunc.roomHasFunction = true;
1079 }
1080 
1081 int bg_just_changed = 0;
1082 
on_background_frame_change()1083 void on_background_frame_change () {
1084 
1085     invalidate_screen();
1086     mark_current_background_dirty();
1087     invalidate_cached_walkbehinds();
1088 
1089     // get the new frame's palette
1090     memcpy (palette, thisroom.bpalettes[play.bg_frame], sizeof(color) * 256);
1091 
1092     // hi-colour, update the palette. It won't have an immediate effect
1093     // but will be drawn properly when the screen fades in
1094     if (game.color_depth > 1)
1095         setpal();
1096 
1097     if (in_enters_screen)
1098         return;
1099 
1100     // Don't update the palette if it hasn't changed
1101     if (thisroom.ebpalShared[play.bg_frame])
1102         return;
1103 
1104     // 256-colours, tell it to update the palette (will actually be done as
1105     // close as possible to the screen update to prevent flicker problem)
1106     if (game.color_depth == 1)
1107         bg_just_changed = 1;
1108 }
1109 
croom_ptr_clear()1110 void croom_ptr_clear()
1111 {
1112     croom = NULL;
1113     objs = NULL;
1114 }
1115 
1116 //=============================================================================
1117 //
1118 // Script API Functions
1119 //
1120 //=============================================================================
1121 
1122 #include "debug/out.h"
1123 #include "script/script_api.h"
1124 #include "script/script_runtime.h"
1125 #include "ac/dynobj/scriptstring.h"
1126 
1127 extern ScriptString myScriptStringImpl;
1128 
1129 // ScriptDrawingSurface* (int backgroundNumber)
Sc_Room_GetDrawingSurfaceForBackground(const RuntimeScriptValue * params,int32_t param_count)1130 RuntimeScriptValue Sc_Room_GetDrawingSurfaceForBackground(const RuntimeScriptValue *params, int32_t param_count)
1131 {
1132     API_SCALL_OBJAUTO_PINT(ScriptDrawingSurface, Room_GetDrawingSurfaceForBackground);
1133 }
1134 
1135 // int (const char *property)
Sc_Room_GetProperty(const RuntimeScriptValue * params,int32_t param_count)1136 RuntimeScriptValue Sc_Room_GetProperty(const RuntimeScriptValue *params, int32_t param_count)
1137 {
1138     API_SCALL_INT_POBJ(Room_GetProperty, const char);
1139 }
1140 
1141 // const char* (const char *property)
Sc_Room_GetTextProperty(const RuntimeScriptValue * params,int32_t param_count)1142 RuntimeScriptValue Sc_Room_GetTextProperty(const RuntimeScriptValue *params, int32_t param_count)
1143 {
1144     API_SCALL_OBJ_POBJ(const char, myScriptStringImpl, Room_GetTextProperty, const char);
1145 }
1146 
Sc_Room_SetProperty(const RuntimeScriptValue * params,int32_t param_count)1147 RuntimeScriptValue Sc_Room_SetProperty(const RuntimeScriptValue *params, int32_t param_count)
1148 {
1149     API_SCALL_BOOL_POBJ_PINT(Room_SetProperty, const char);
1150 }
1151 
1152 // const char* (const char *property)
Sc_Room_SetTextProperty(const RuntimeScriptValue * params,int32_t param_count)1153 RuntimeScriptValue Sc_Room_SetTextProperty(const RuntimeScriptValue *params, int32_t param_count)
1154 {
1155     API_SCALL_BOOL_POBJ2(Room_SetTextProperty, const char, const char);
1156 }
1157 
1158 // int ()
Sc_Room_GetBottomEdge(const RuntimeScriptValue * params,int32_t param_count)1159 RuntimeScriptValue Sc_Room_GetBottomEdge(const RuntimeScriptValue *params, int32_t param_count)
1160 {
1161     API_SCALL_INT(Room_GetBottomEdge);
1162 }
1163 
1164 // int ()
Sc_Room_GetColorDepth(const RuntimeScriptValue * params,int32_t param_count)1165 RuntimeScriptValue Sc_Room_GetColorDepth(const RuntimeScriptValue *params, int32_t param_count)
1166 {
1167     API_SCALL_INT(Room_GetColorDepth);
1168 }
1169 
1170 // int ()
Sc_Room_GetHeight(const RuntimeScriptValue * params,int32_t param_count)1171 RuntimeScriptValue Sc_Room_GetHeight(const RuntimeScriptValue *params, int32_t param_count)
1172 {
1173     API_SCALL_INT(Room_GetHeight);
1174 }
1175 
1176 // int ()
Sc_Room_GetLeftEdge(const RuntimeScriptValue * params,int32_t param_count)1177 RuntimeScriptValue Sc_Room_GetLeftEdge(const RuntimeScriptValue *params, int32_t param_count)
1178 {
1179     API_SCALL_INT(Room_GetLeftEdge);
1180 }
1181 
1182 // const char* (int index)
Sc_Room_GetMessages(const RuntimeScriptValue * params,int32_t param_count)1183 RuntimeScriptValue Sc_Room_GetMessages(const RuntimeScriptValue *params, int32_t param_count)
1184 {
1185     API_SCALL_OBJ_PINT(const char, myScriptStringImpl, Room_GetMessages);
1186 }
1187 
1188 // int ()
Sc_Room_GetMusicOnLoad(const RuntimeScriptValue * params,int32_t param_count)1189 RuntimeScriptValue Sc_Room_GetMusicOnLoad(const RuntimeScriptValue *params, int32_t param_count)
1190 {
1191     API_SCALL_INT(Room_GetMusicOnLoad);
1192 }
1193 
1194 // int ()
Sc_Room_GetObjectCount(const RuntimeScriptValue * params,int32_t param_count)1195 RuntimeScriptValue Sc_Room_GetObjectCount(const RuntimeScriptValue *params, int32_t param_count)
1196 {
1197     API_SCALL_INT(Room_GetObjectCount);
1198 }
1199 
1200 // int ()
Sc_Room_GetRightEdge(const RuntimeScriptValue * params,int32_t param_count)1201 RuntimeScriptValue Sc_Room_GetRightEdge(const RuntimeScriptValue *params, int32_t param_count)
1202 {
1203     API_SCALL_INT(Room_GetRightEdge);
1204 }
1205 
1206 // int ()
Sc_Room_GetTopEdge(const RuntimeScriptValue * params,int32_t param_count)1207 RuntimeScriptValue Sc_Room_GetTopEdge(const RuntimeScriptValue *params, int32_t param_count)
1208 {
1209     API_SCALL_INT(Room_GetTopEdge);
1210 }
1211 
1212 // int ()
Sc_Room_GetWidth(const RuntimeScriptValue * params,int32_t param_count)1213 RuntimeScriptValue Sc_Room_GetWidth(const RuntimeScriptValue *params, int32_t param_count)
1214 {
1215     API_SCALL_INT(Room_GetWidth);
1216 }
1217 
1218 // void (int xx,int yy,int mood)
Sc_ProcessClick(const RuntimeScriptValue * params,int32_t param_count)1219 RuntimeScriptValue Sc_ProcessClick(const RuntimeScriptValue *params, int32_t param_count)
1220 {
1221     API_SCALL_VOID_PINT3(ProcessClick);
1222 }
1223 
1224 
RegisterRoomAPI()1225 void RegisterRoomAPI()
1226 {
1227     ccAddExternalStaticFunction("Room::GetDrawingSurfaceForBackground^1",   Sc_Room_GetDrawingSurfaceForBackground);
1228     ccAddExternalStaticFunction("Room::GetProperty^1",                      Sc_Room_GetProperty);
1229     ccAddExternalStaticFunction("Room::GetTextProperty^1",                  Sc_Room_GetTextProperty);
1230     ccAddExternalStaticFunction("Room::SetProperty^2",                      Sc_Room_SetProperty);
1231     ccAddExternalStaticFunction("Room::SetTextProperty^2",                  Sc_Room_SetTextProperty);
1232     ccAddExternalStaticFunction("Room::ProcessClick^3",                     Sc_ProcessClick);
1233     ccAddExternalStaticFunction("ProcessClick",                             Sc_ProcessClick);
1234     ccAddExternalStaticFunction("Room::get_BottomEdge",                     Sc_Room_GetBottomEdge);
1235     ccAddExternalStaticFunction("Room::get_ColorDepth",                     Sc_Room_GetColorDepth);
1236     ccAddExternalStaticFunction("Room::get_Height",                         Sc_Room_GetHeight);
1237     ccAddExternalStaticFunction("Room::get_LeftEdge",                       Sc_Room_GetLeftEdge);
1238     ccAddExternalStaticFunction("Room::geti_Messages",                      Sc_Room_GetMessages);
1239     ccAddExternalStaticFunction("Room::get_MusicOnLoad",                    Sc_Room_GetMusicOnLoad);
1240     ccAddExternalStaticFunction("Room::get_ObjectCount",                    Sc_Room_GetObjectCount);
1241     ccAddExternalStaticFunction("Room::get_RightEdge",                      Sc_Room_GetRightEdge);
1242     ccAddExternalStaticFunction("Room::get_TopEdge",                        Sc_Room_GetTopEdge);
1243     ccAddExternalStaticFunction("Room::get_Width",                          Sc_Room_GetWidth);
1244 
1245     /* ----------------------- Registering unsafe exports for plugins -----------------------*/
1246 
1247     ccAddExternalFunctionForPlugin("Room::GetDrawingSurfaceForBackground^1",   (void*)Room_GetDrawingSurfaceForBackground);
1248     ccAddExternalFunctionForPlugin("Room::GetProperty^1",                      (void*)Room_GetProperty);
1249     ccAddExternalFunctionForPlugin("Room::GetTextProperty^1",                  (void*)Room_GetTextProperty);
1250     ccAddExternalFunctionForPlugin("Room::get_BottomEdge",                     (void*)Room_GetBottomEdge);
1251     ccAddExternalFunctionForPlugin("Room::get_ColorDepth",                     (void*)Room_GetColorDepth);
1252     ccAddExternalFunctionForPlugin("Room::get_Height",                         (void*)Room_GetHeight);
1253     ccAddExternalFunctionForPlugin("Room::get_LeftEdge",                       (void*)Room_GetLeftEdge);
1254     ccAddExternalFunctionForPlugin("Room::geti_Messages",                      (void*)Room_GetMessages);
1255     ccAddExternalFunctionForPlugin("Room::get_MusicOnLoad",                    (void*)Room_GetMusicOnLoad);
1256     ccAddExternalFunctionForPlugin("Room::get_ObjectCount",                    (void*)Room_GetObjectCount);
1257     ccAddExternalFunctionForPlugin("Room::get_RightEdge",                      (void*)Room_GetRightEdge);
1258     ccAddExternalFunctionForPlugin("Room::get_TopEdge",                        (void*)Room_GetTopEdge);
1259     ccAddExternalFunctionForPlugin("Room::get_Width",                          (void*)Room_GetWidth);
1260 }
1261