1 /*
2
3 This is not the AGS Parallax plugin by Scorpiorus
4 but a workalike plugin created by JJS for the AGS engine ports.
5
6 */
7
8 #ifdef WIN32
9 #define WINDOWS_VERSION
10 #define WIN32_LEAN_AND_MEAN
11 #include <windows.h>
12 #pragma warning(disable : 4244)
13 #endif
14
15 #if !defined(BUILTIN_PLUGINS)
16 #define THIS_IS_THE_PLUGIN
17 #endif
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <math.h>
23
24 #include "plugin/agsplugin.h"
25
26 #if defined(BUILTIN_PLUGINS)
27 namespace ags_parallax {
28 #endif
29
30 //#define DEBUG
31
32 const unsigned int Magic = 0xCAFE0000;
33 const unsigned int Version = 2;
34 const unsigned int SaveMagic = Magic + Version;
35
36 int screen_width = 320;
37 int screen_height = 200;
38 int screen_color_depth = 32;
39
40 IAGSEngine* engine;
41
42 bool enabled = false;
43
44
45 typedef struct
46 {
47 int x;
48 int y;
49 int slot;
50 int speed;
51 } sprite_t;
52
53 #define MAX_SPEED 1000
54 #define MAX_SPRITES 100
55 sprite_t sprites[MAX_SPRITES];
56
57 // workaround to fix this error:
58 // psp-fixup-imports ags_parallax.elf
59 // Error, no .lib.stub section found
dummy()60 void dummy()
61 {
62 void *tmp = new int;
63 }
64
engineFileRead(void * ptr,size_t size,size_t count,long fileHandle)65 static size_t engineFileRead(void * ptr, size_t size, size_t count, long fileHandle) {
66 int totalBytes = engine->FRead(ptr, size*count, fileHandle);
67 return totalBytes/size;
68 }
69
engineFileWrite(const void * ptr,size_t size,size_t count,long fileHandle)70 static size_t engineFileWrite(const void *ptr, size_t size, size_t count, long fileHandle) {
71 int totalBytes = engine->FWrite(const_cast<void *>(ptr), size*count, fileHandle);
72 return totalBytes/size;
73 }
74
RestoreGame(long fileHandle)75 void RestoreGame(long fileHandle)
76 {
77 unsigned int SaveVersion = 0;
78 engineFileRead(&SaveVersion, sizeof(SaveVersion), 1, fileHandle);
79
80 if (SaveVersion != SaveMagic) {
81 engine->AbortGame("ags_parallax: bad save.");
82 }
83
84 engineFileRead(sprites, sizeof(sprite_t), MAX_SPRITES, fileHandle);
85 engineFileRead(&enabled, sizeof(bool), 1, fileHandle);
86 }
87
SaveGame(long file)88 void SaveGame(long file)
89 {
90 engineFileWrite(&SaveMagic, sizeof(SaveMagic), 1, file);
91 engineFileWrite(sprites, sizeof(sprite_t), MAX_SPRITES, file);
92 engineFileWrite(&enabled, sizeof(bool), 1, file);
93 }
94
95
Initialize()96 void Initialize()
97 {
98 memset(sprites, 0, sizeof(sprite_t) * MAX_SPRITES);
99
100 int i;
101 for (i = 0; i < MAX_SPRITES; i++)
102 sprites[i].slot = -1;
103
104 enabled = false;
105 }
106
107
Draw(bool foreground)108 void Draw(bool foreground)
109 {
110 if (!enabled)
111 return;
112
113 BITMAP *bmp;
114 int i;
115
116 int offsetX = 0;
117 int offsetY = 0;
118 engine->ViewportToRoom(&offsetX, &offsetY);
119
120 for (i = 0; i < MAX_SPRITES; i++)
121 {
122 if (sprites[i].slot > -1)
123 {
124 if (foreground)
125 {
126 if (sprites[i].speed > 0)
127 {
128 bmp = engine->GetSpriteGraphic(sprites[i].slot);
129 if (bmp)
130 engine->BlitBitmap(sprites[i].x - offsetX - (sprites[i].speed * offsetX / 100), sprites[i].y, bmp, 1);
131 }
132 }
133 else
134 {
135 if (sprites[i].speed <= 0)
136 {
137 bmp = engine->GetSpriteGraphic(sprites[i].slot);
138 if (bmp)
139 engine->BlitBitmap(sprites[i].x - offsetX - (sprites[i].speed * offsetX / 1000), sprites[i].y, bmp, 1);
140 }
141 }
142 }
143 }
144 }
145
146
147
148
149
150 // ********************************************
151 // ************ AGS Interface ***************
152 // ********************************************
153
pxDrawSprite(int id,int x,int y,int slot,int speed)154 void pxDrawSprite(int id, int x, int y, int slot, int speed)
155 {
156 #ifdef DEBUG
157 char buffer[200];
158 sprintf(buffer, "%s %d %d %d %d %d\n", "pxDrawSprite", id, x, y, slot, speed);
159 engine->PrintDebugConsole(buffer);
160 #endif
161
162 if ((id < 0) || (id >= MAX_SPRITES))
163 return;
164
165 if ((speed < -MAX_SPEED) || (speed > MAX_SPEED))
166 speed = 0;
167
168 sprites[id].x = x;
169 sprites[id].y = y;
170 sprites[id].slot = slot;
171 sprites[id].speed = speed;
172
173 engine->RoomToViewport(&sprites[id].x, &sprites[id].y);
174
175 enabled = true;
176 }
177
178
pxDeleteSprite(int id)179 void pxDeleteSprite(int id)
180 {
181 #ifdef DEBUG
182 char buffer[200];
183 sprintf(buffer, "%s %d\n", "pxDeleteSprite", id);
184 engine->PrintDebugConsole(buffer);
185 #endif
186
187 if ((id < 0) || (id >= MAX_SPRITES))
188 return;
189
190 sprites[id].slot = -1;
191 }
192
AGS_EngineStartup(IAGSEngine * lpEngine)193 void AGS_EngineStartup(IAGSEngine *lpEngine)
194 {
195 engine = lpEngine;
196
197 if (engine->version < 13)
198 engine->AbortGame("Engine interface is too old, need newer version of AGS.");
199
200 engine->RegisterScriptFunction("pxDrawSprite", (void*)&pxDrawSprite);
201 engine->RegisterScriptFunction("pxDeleteSprite", (void*)&pxDeleteSprite);
202
203 engine->RequestEventHook(AGSE_PREGUIDRAW);
204 engine->RequestEventHook(AGSE_PRESCREENDRAW);
205 engine->RequestEventHook(AGSE_ENTERROOM);
206 engine->RequestEventHook(AGSE_SAVEGAME);
207 engine->RequestEventHook(AGSE_RESTOREGAME);
208
209 Initialize();
210 }
211
AGS_EngineShutdown()212 void AGS_EngineShutdown()
213 {
214 }
215
AGS_EngineOnEvent(int event,int data)216 int AGS_EngineOnEvent(int event, int data)
217 {
218 if (event == AGSE_PREGUIDRAW)
219 {
220 Draw(true);
221 }
222 else if (event == AGSE_PRESCREENDRAW)
223 {
224 Draw(false);
225 }
226 else if (event == AGSE_ENTERROOM)
227 {
228 // Reset all sprites
229 Initialize();
230 }
231 else if (event == AGSE_PRESCREENDRAW)
232 {
233 // Get screen size once here
234 engine->GetScreenDimensions(&screen_width, &screen_height, &screen_color_depth);
235 engine->UnrequestEventHook(AGSE_PRESCREENDRAW);
236 }
237 else if (event == AGSE_RESTOREGAME)
238 {
239 RestoreGame(data);
240 }
241 else if (event == AGSE_SAVEGAME)
242 {
243 SaveGame(data);
244 }
245
246 return 0;
247 }
248
AGS_EngineDebugHook(const char * scriptName,int lineNum,int reserved)249 int AGS_EngineDebugHook(const char *scriptName, int lineNum, int reserved)
250 {
251 return 0;
252 }
253
AGS_EngineInitGfx(const char * driverID,void * data)254 void AGS_EngineInitGfx(const char *driverID, void *data)
255 {
256 }
257
258
259
260 #if defined(WINDOWS_VERSION) && !defined(BUILTIN_PLUGINS)
261
262 // ********************************************
263 // *********** Editor Interface *************
264 // ********************************************
265
266 const char* scriptHeader =
267 "import void pxDrawSprite(int ID, int X, int Y, int SlotNum, int Speed);\r\n"
268 "import void pxDeleteSprite(int ID);\r\n";
269
270 IAGSEditor* editor;
271
272
AGS_GetPluginName(void)273 LPCSTR AGS_GetPluginName(void)
274 {
275 // Return the plugin description
276 return "Parallax plugin recreation";
277 }
278
AGS_EditorStartup(IAGSEditor * lpEditor)279 int AGS_EditorStartup(IAGSEditor* lpEditor)
280 {
281 // User has checked the plugin to use it in their game
282
283 // If it's an earlier version than what we need, abort.
284 if (lpEditor->version < 1)
285 return -1;
286
287 editor = lpEditor;
288 editor->RegisterScriptHeader(scriptHeader);
289
290 // Return 0 to indicate success
291 return 0;
292 }
293
AGS_EditorShutdown()294 void AGS_EditorShutdown()
295 {
296 // User has un-checked the plugin from their game
297 editor->UnregisterScriptHeader(scriptHeader);
298 }
299
AGS_EditorProperties(HWND parent)300 void AGS_EditorProperties(HWND parent)
301 {
302 // User has chosen to view the Properties of the plugin
303 // We could load up an options dialog or something here instead
304 MessageBoxA(parent, "Parallax plugin recreation by JJS", "About", MB_OK | MB_ICONINFORMATION);
305 }
306
AGS_EditorSaveGame(char * buffer,int bufsize)307 int AGS_EditorSaveGame(char* buffer, int bufsize)
308 {
309 // We don't want to save any persistent data
310 return 0;
311 }
312
AGS_EditorLoadGame(char * buffer,int bufsize)313 void AGS_EditorLoadGame(char* buffer, int bufsize)
314 {
315 // Nothing to load for this plugin
316 }
317
318 #endif
319
320
321 #if defined(BUILTIN_PLUGINS)
322 } // namespace ags_parallax
323 #endif
324