comparison src/common/lua-engine.cpp @ 24:59790d015f25 works-incomplete

checkpoint
author Robert McIntyre <rlm@mit.edu>
date Sun, 04 Mar 2012 17:50:56 -0600
parents bf9169ad4222
children
comparison
equal deleted inserted replaced
23:bf9169ad4222 24:59790d015f25
13 #include <algorithm> 13 #include <algorithm>
14 14
15 using namespace std; 15 using namespace std;
16 16
17 #ifdef __linux 17 #ifdef __linux
18 #include <unistd.h> // for unlink 18 #include <unistd.h> // for unlink
19 #include <sys/types.h> 19 #include <sys/types.h>
20 #include <sys/wait.h> 20 #include <sys/wait.h>
21 #endif 21 #endif
22 #if (defined(WIN32) && !defined(SDL)) 22 #if (defined(WIN32) && !defined(SDL))
23 #include <direct.h> 23 #include <direct.h>
24 #include "../win32/stdafx.h" 24 #include "../win32/stdafx.h"
25 #include "../win32/Input.h" 25 #include "../win32/Input.h"
26 #include "../win32/MainWnd.h" 26 #include "../win32/MainWnd.h"
27 #include "../win32/VBA.h" 27 #include "../win32/VBA.h"
28 #include "../win32/LuaOpenDialog.h" 28 #include "../win32/LuaOpenDialog.h"
29 #else 29 #else
30 #define stricmp strcasecmp 30 #define stricmp strcasecmp
31 #define strnicmp strncasecmp 31 #define strnicmp strncasecmp
32 #endif 32 #endif
33 33
34 #include "../Port.h" 34 #include "../Port.h"
35 #include "System.h" 35 #include "System.h"
36 #include "movie.h" 36 #include "movie.h"
62 static void (*info_onstart)(int uid); 62 static void (*info_onstart)(int uid);
63 static void (*info_onstop)(int uid); 63 static void (*info_onstop)(int uid);
64 static int info_uid; 64 static int info_uid;
65 65
66 #ifndef countof 66 #ifndef countof
67 #define countof(a) (sizeof(a) / sizeof(a[0])) 67 #define countof(a) (sizeof(a) / sizeof(a[0]))
68 #endif 68 #endif
69 69
70 static lua_State *LUA; 70 static lua_State *LUA;
71 71
72 // Are we running any code right now? 72 // Are we running any code right now?
112 // number of registered memory functions (1 per hooked byte) 112 // number of registered memory functions (1 per hooked byte)
113 static unsigned int numMemHooks; 113 static unsigned int numMemHooks;
114 114
115 // Look in inputglobal.h for macros named like BUTTON_MASK_UP to determine the order. 115 // Look in inputglobal.h for macros named like BUTTON_MASK_UP to determine the order.
116 static const char *button_mappings[] = { 116 static const char *button_mappings[] = {
117 "A", "B", "select", "start", "right", "left", "up", "down", "R", "L" 117 "A", "B", "select", "start", "right", "left", "up", "down", "R", "L"
118 }; 118 };
119 119
120 #ifdef _MSC_VER 120 #ifdef _MSC_VER
121 #define snprintf _snprintf 121 #define snprintf _snprintf
122 #define vscprintf _vscprintf 122 #define vscprintf _vscprintf
123 #else 123 #else
124 #define stricmp strcasecmp 124 #define stricmp strcasecmp
125 #define strnicmp strncasecmp 125 #define strnicmp strncasecmp
126 #define __forceinline __attribute__((always_inline)) 126 #define __forceinline __attribute__((always_inline))
127 #endif 127 #endif
128 128
129 static const char *luaCallIDStrings[] = 129 static const char *luaCallIDStrings[] =
130 { 130 {
131 "CALL_BEFOREEMULATION", 131 "CALL_BEFOREEMULATION",
132 "CALL_AFTEREMULATION", 132 "CALL_AFTEREMULATION",
133 "CALL_BEFOREEXIT" 133 "CALL_BEFOREEXIT"
134 }; 134 };
135 135
136 //make sure we have the right number of strings 136 //make sure we have the right number of strings
137 CTASSERT(sizeof(luaCallIDStrings) / sizeof(*luaCallIDStrings) == LUACALL_COUNT) 137 CTASSERT(sizeof(luaCallIDStrings) / sizeof(*luaCallIDStrings) == LUACALL_COUNT)
138 138
139 static const char *luaMemHookTypeStrings [] = 139 static const char *luaMemHookTypeStrings [] =
140 { 140 {
141 "MEMHOOK_WRITE", 141 "MEMHOOK_WRITE",
142 "MEMHOOK_READ", 142 "MEMHOOK_READ",
143 "MEMHOOK_EXEC", 143 "MEMHOOK_EXEC",
144 144
145 "MEMHOOK_WRITE_SUB", 145 "MEMHOOK_WRITE_SUB",
146 "MEMHOOK_READ_SUB", 146 "MEMHOOK_READ_SUB",
147 "MEMHOOK_EXEC_SUB", 147 "MEMHOOK_EXEC_SUB",
148 }; 148 };
149 149
150 //make sure we have the right number of strings 150 //make sure we have the right number of strings
151 CTASSERT(sizeof(luaMemHookTypeStrings) / sizeof(*luaMemHookTypeStrings) == LUAMEMHOOK_COUNT) 151 CTASSERT(sizeof(luaMemHookTypeStrings) / sizeof(*luaMemHookTypeStrings) == LUAMEMHOOK_COUNT)
152 152
154 static const char *toCString(lua_State *L, int idx = 0); 154 static const char *toCString(lua_State *L, int idx = 0);
155 155
156 // GBA memory I/O functions copied from win32/MemoryViewerDlg.cpp 156 // GBA memory I/O functions copied from win32/MemoryViewerDlg.cpp
157 static inline u8 CPUReadByteQuick(u32 addr) 157 static inline u8 CPUReadByteQuick(u32 addr)
158 { 158 {
159 return ::map[addr >> 24].address[addr & ::map[addr >> 24].mask]; 159 return ::map[addr >> 24].address[addr & ::map[addr >> 24].mask];
160 } 160 }
161 161
162 static inline void CPUWriteByteQuick(u32 addr, u8 b) 162 static inline void CPUWriteByteQuick(u32 addr, u8 b)
163 { 163 {
164 ::map[addr >> 24].address[addr & ::map[addr >> 24].mask] = b; 164 ::map[addr >> 24].address[addr & ::map[addr >> 24].mask] = b;
165 } 165 }
166 166
167 static inline u16 CPUReadHalfWordQuick(u32 addr) 167 static inline u16 CPUReadHalfWordQuick(u32 addr)
168 { 168 {
169 return *((u16 *) &::map[addr >> 24].address[addr & ::map[addr >> 24].mask]); 169 return *((u16 *) &::map[addr >> 24].address[addr & ::map[addr >> 24].mask]);
170 } 170 }
171 171
172 static inline void CPUWriteHalfWordQuick(u32 addr, u16 b) 172 static inline void CPUWriteHalfWordQuick(u32 addr, u16 b)
173 { 173 {
174 *((u16 *) &::map[addr >> 24].address[addr & ::map[addr >> 24].mask]) = b; 174 *((u16 *) &::map[addr >> 24].address[addr & ::map[addr >> 24].mask]) = b;
175 } 175 }
176 176
177 static inline u32 CPUReadMemoryQuick(u32 addr) 177 static inline u32 CPUReadMemoryQuick(u32 addr)
178 { 178 {
179 return *((u32 *) &::map[addr >> 24].address[addr & ::map[addr >> 24].mask]); 179 return *((u32 *) &::map[addr >> 24].address[addr & ::map[addr >> 24].mask]);
180 } 180 }
181 181
182 static inline void CPUWriteMemoryQuick(u32 addr, u32 b) 182 static inline void CPUWriteMemoryQuick(u32 addr, u32 b)
183 { 183 {
184 *((u32 *) &::map[addr >> 24].address[addr & ::map[addr >> 24].mask]) = b; 184 *((u32 *) &::map[addr >> 24].address[addr & ::map[addr >> 24].mask]) = b;
185 } 185 }
186 186
187 // GB 187 // GB
188 static inline u8 gbReadMemoryQuick8(u16 addr) 188 static inline u8 gbReadMemoryQuick8(u16 addr)
189 { 189 {
190 return gbReadMemoryQuick(addr); 190 return gbReadMemoryQuick(addr);
191 } 191 }
192 192
193 static inline void gbWriteMemoryQuick8(u16 addr, u8 b) 193 static inline void gbWriteMemoryQuick8(u16 addr, u8 b)
194 { 194 {
195 gbWriteMemoryQuick(addr, b); 195 gbWriteMemoryQuick(addr, b);
196 } 196 }
197 197
198 static inline u16 gbReadMemoryQuick16(u16 addr) 198 static inline u16 gbReadMemoryQuick16(u16 addr)
199 { 199 {
200 return (gbReadMemoryQuick(addr + 1) << 8) | gbReadMemoryQuick(addr); 200 return (gbReadMemoryQuick(addr + 1) << 8) | gbReadMemoryQuick(addr);
201 } 201 }
202 202
203 static inline void gbWriteMemoryQuick16(u16 addr, u16 b) 203 static inline void gbWriteMemoryQuick16(u16 addr, u16 b)
204 { 204 {
205 gbWriteMemoryQuick(addr, b & 0xff); 205 gbWriteMemoryQuick(addr, b & 0xff);
206 gbWriteMemoryQuick(addr + 1, (b >> 8) & 0xff); 206 gbWriteMemoryQuick(addr + 1, (b >> 8) & 0xff);
207 } 207 }
208 208
209 static inline u32 gbReadMemoryQuick32(u16 addr) 209 static inline u32 gbReadMemoryQuick32(u16 addr)
210 { 210 {
211 return (gbReadMemoryQuick(addr + 3) << 24) | 211 return (gbReadMemoryQuick(addr + 3) << 24) |
212 (gbReadMemoryQuick(addr + 2) << 16) | 212 (gbReadMemoryQuick(addr + 2) << 16) |
213 (gbReadMemoryQuick(addr + 1) << 8) | 213 (gbReadMemoryQuick(addr + 1) << 8) |
214 gbReadMemoryQuick(addr); 214 gbReadMemoryQuick(addr);
215 } 215 }
216 216
217 static inline void gbWriteMemoryQuick32(u16 addr, u32 b) 217 static inline void gbWriteMemoryQuick32(u16 addr, u32 b)
218 { 218 {
219 gbWriteMemoryQuick(addr, b & 0xff); 219 gbWriteMemoryQuick(addr, b & 0xff);
220 gbWriteMemoryQuick(addr + 1, (b >> 8) & 0xff); 220 gbWriteMemoryQuick(addr + 1, (b >> 8) & 0xff);
221 gbWriteMemoryQuick(addr + 2, (b >> 16) & 0xff); 221 gbWriteMemoryQuick(addr + 2, (b >> 16) & 0xff);
222 gbWriteMemoryQuick(addr + 1, (b >> 24) & 0xff); 222 gbWriteMemoryQuick(addr + 1, (b >> 24) & 0xff);
223 } 223 }
224 224
225 static inline u8 gbReadROMQuick8(u32 addr) 225 static inline u8 gbReadROMQuick8(u32 addr)
226 { 226 {
227 return gbReadROMQuick(addr & gbRomSizeMask); 227 return gbReadROMQuick(addr & gbRomSizeMask);
228 } 228 }
229 229
230 static inline u8 gbReadROMQuick16(u32 addr) 230 static inline u8 gbReadROMQuick16(u32 addr)
231 { 231 {
232 return (gbReadROMQuick(addr+1 & gbRomSizeMask) << 8) | gbReadROMQuick(addr & gbRomSizeMask); 232 return (gbReadROMQuick(addr+1 & gbRomSizeMask) << 8) | gbReadROMQuick(addr & gbRomSizeMask);
233 } 233 }
234 234
235 static inline u8 gbReadROMQuick32(u32 addr) 235 static inline u8 gbReadROMQuick32(u32 addr)
236 { 236 {
237 return (gbReadROMQuick(addr+3 & gbRomSizeMask) << 24) | 237 return (gbReadROMQuick(addr+3 & gbRomSizeMask) << 24) |
238 (gbReadROMQuick(addr+2 & gbRomSizeMask) << 16) | 238 (gbReadROMQuick(addr+2 & gbRomSizeMask) << 16) |
239 (gbReadROMQuick(addr+1 & gbRomSizeMask) << 8) | 239 (gbReadROMQuick(addr+1 & gbRomSizeMask) << 8) |
240 gbReadROMQuick(addr & gbRomSizeMask); 240 gbReadROMQuick(addr & gbRomSizeMask);
241 } 241 }
242 242
243 typedef void (*GetColorFunc)(const uint8 *, uint8 *, uint8 *, uint8 *); 243 typedef void (*GetColorFunc)(const uint8 *, uint8 *, uint8 *, uint8 *);
244 typedef void (*SetColorFunc)(uint8 *, uint8, uint8, uint8); 244 typedef void (*SetColorFunc)(uint8 *, uint8, uint8, uint8);
245 245
246 static void getColor16(const uint8 *s, uint8 *r, uint8 *g, uint8 *b) 246 static void getColor16(const uint8 *s, uint8 *r, uint8 *g, uint8 *b)
247 { 247 {
248 u16 v = *(const uint16 *)s; 248 u16 v = *(const uint16 *)s;
249 *r = ((v >> systemBlueShift) & 0x001f) << 3; 249 *r = ((v >> systemBlueShift) & 0x001f) << 3;
250 *g = ((v >> systemGreenShift) & 0x001f) << 3; 250 *g = ((v >> systemGreenShift) & 0x001f) << 3;
251 *b = ((v >> systemRedShift) & 0x001f) << 3; 251 *b = ((v >> systemRedShift) & 0x001f) << 3;
252 } 252 }
253 253
254 static void getColor24(const uint8 *s, uint8 *r, uint8 *g, uint8 *b) 254 static void getColor24(const uint8 *s, uint8 *r, uint8 *g, uint8 *b)
255 { 255 {
256 if (systemRedShift > systemBlueShift) 256 if (systemRedShift > systemBlueShift)
257 *b = s[0], *g = s[1], *r = s[2]; 257 *b = s[0], *g = s[1], *r = s[2];
258 else 258 else
259 *r = s[0], *g = s[1], *b = s[2]; 259 *r = s[0], *g = s[1], *b = s[2];
260 } 260 }
261 261
262 static void getColor32(const uint8 *s, uint8 *r, uint8 *g, uint8 *b) 262 static void getColor32(const uint8 *s, uint8 *r, uint8 *g, uint8 *b)
263 { 263 {
264 u32 v = *(const uint32 *)s; 264 u32 v = *(const uint32 *)s;
265 *b = ((v >> systemBlueShift) & 0x001f) << 3; 265 *b = ((v >> systemBlueShift) & 0x001f) << 3;
266 *g = ((v >> systemGreenShift) & 0x001f) << 3; 266 *g = ((v >> systemGreenShift) & 0x001f) << 3;
267 *r = ((v >> systemRedShift) & 0x001f) << 3; 267 *r = ((v >> systemRedShift) & 0x001f) << 3;
268 } 268 }
269 269
270 static void setColor16(uint8 *s, uint8 r, uint8 g, uint8 b) 270 static void setColor16(uint8 *s, uint8 r, uint8 g, uint8 b)
271 { 271 {
272 *(uint16 *)s = ((b >> 3) & 0x01f) << 272 *(uint16 *)s = ((b >> 3) & 0x01f) <<
273 systemBlueShift | 273 systemBlueShift |
274 ((g >> 3) & 0x01f) << 274 ((g >> 3) & 0x01f) <<
275 systemGreenShift | 275 systemGreenShift |
276 ((r >> 3) & 0x01f) << 276 ((r >> 3) & 0x01f) <<
277 systemRedShift; 277 systemRedShift;
278 } 278 }
279 279
280 static void setColor24(uint8 *s, uint8 r, uint8 g, uint8 b) 280 static void setColor24(uint8 *s, uint8 r, uint8 g, uint8 b)
281 { 281 {
282 if (systemRedShift > systemBlueShift) 282 if (systemRedShift > systemBlueShift)
283 s[0] = b, s[1] = g, s[2] = r; 283 s[0] = b, s[1] = g, s[2] = r;
284 else 284 else
285 s[0] = r, s[1] = g, s[2] = b; 285 s[0] = r, s[1] = g, s[2] = b;
286 } 286 }
287 287
288 static void setColor32(uint8 *s, uint8 r, uint8 g, uint8 b) 288 static void setColor32(uint8 *s, uint8 r, uint8 g, uint8 b)
289 { 289 {
290 *(uint32 *)s = ((b >> 3) & 0x01f) << 290 *(uint32 *)s = ((b >> 3) & 0x01f) <<
291 systemBlueShift | 291 systemBlueShift |
292 ((g >> 3) & 0x01f) << 292 ((g >> 3) & 0x01f) <<
293 systemGreenShift | 293 systemGreenShift |
294 ((r >> 3) & 0x01f) << 294 ((r >> 3) & 0x01f) <<
295 systemRedShift; 295 systemRedShift;
296 } 296 }
297 297
298 static bool getColorIOFunc(int depth, GetColorFunc *getColor, SetColorFunc *setColor) 298 static bool getColorIOFunc(int depth, GetColorFunc *getColor, SetColorFunc *setColor)
299 { 299 {
300 switch (depth) 300 switch (depth)
301 { 301 {
302 case 16: 302 case 16:
303 if (getColor) 303 if (getColor)
304 *getColor = getColor16; 304 *getColor = getColor16;
305 if (setColor) 305 if (setColor)
306 *setColor = setColor16; 306 *setColor = setColor16;
307 return true; 307 return true;
308 case 24: 308 case 24:
309 if (getColor) 309 if (getColor)
310 *getColor = getColor24; 310 *getColor = getColor24;
311 if (setColor) 311 if (setColor)
312 *setColor = setColor24; 312 *setColor = setColor24;
313 return true; 313 return true;
314 case 32: 314 case 32:
315 if (getColor) 315 if (getColor)
316 *getColor = getColor32; 316 *getColor = getColor32;
317 if (setColor) 317 if (setColor)
318 *setColor = setColor32; 318 *setColor = setColor32;
319 return true; 319 return true;
320 default: 320 default:
321 return false; 321 return false;
322 } 322 }
323 } 323 }
324 324
325 /** 325 /**
326 * Resets emulator speed / pause states after script exit. 326 * Resets emulator speed / pause states after script exit.
327 */ 327 */
328 static void VBALuaOnStop(void) 328 static void VBALuaOnStop(void)
329 { 329 {
330 luaRunning = false; 330 luaRunning = false;
331 lua_joypads_used = 0; 331 lua_joypads_used = 0;
332 gui_used = false; 332 gui_used = false;
333 //if (wasPaused) 333 //if (wasPaused)
334 // systemSetPause(true); 334 // systemSetPause(true);
335 } 335 }
336 336
337 /** 337 /**
338 * Asks Lua if it wants control of the emulator's speed. 338 * Asks Lua if it wants control of the emulator's speed.
339 * Returns 0 if no, 1 if yes. If yes, we also tamper with the 339 * Returns 0 if no, 1 if yes. If yes, we also tamper with the
340 * IPPU's settings for speed ourselves, so the calling code 340 * IPPU's settings for speed ourselves, so the calling code
341 * need not do anything. 341 * need not do anything.
342 */ 342 */
343 int VBALuaSpeed(void) 343 int VBALuaSpeed(void)
344 { 344 {
345 if (!LUA || !luaRunning) 345 if (!LUA || !luaRunning)
346 return 0; 346 return 0;
347 347
348 //printf("%d\n", speedmode); 348 //printf("%d\n", speedmode);
349 switch (speedmode) 349 switch (speedmode)
350 { 350 {
351 /* 351 /*
352 case SPEED_NORMAL: 352 case SPEED_NORMAL:
353 return 0; 353 return 0;
354 case SPEED_NOTHROTTLE: 354 case SPEED_NOTHROTTLE:
355 IPPU.RenderThisFrame = true; 355 IPPU.RenderThisFrame = true;
356 return 1; 356 return 1;
357 357
358 case SPEED_TURBO: 358 case SPEED_TURBO:
359 IPPU.SkippedFrames++; 359 IPPU.SkippedFrames++;
360 if (IPPU.SkippedFrames >= 40) { 360 if (IPPU.SkippedFrames >= 40) {
361 IPPU.SkippedFrames = 0; 361 IPPU.SkippedFrames = 0;
362 IPPU.RenderThisFrame = true; 362 IPPU.RenderThisFrame = true;
363 } 363 }
364 else 364 else
365 IPPU.RenderThisFrame = false; 365 IPPU.RenderThisFrame = false;
366 return 1; 366 return 1;
367 367
368 // In mode 3, SkippedFrames is set to zero so that the frame 368 // In mode 3, SkippedFrames is set to zero so that the frame
369 // skipping code doesn't try anything funny. 369 // skipping code doesn't try anything funny.
370 case SPEED_MAXIMUM: 370 case SPEED_MAXIMUM:
371 IPPU.SkippedFrames=0; 371 IPPU.SkippedFrames=0;
372 IPPU.RenderThisFrame = false; 372 IPPU.RenderThisFrame = false;
373 return 1; 373 return 1;
374 */ 374 */
375 case 0: // FIXME: to get rid of the warning 375 case 0: // FIXME: to get rid of the warning
376 default: 376 default:
377 assert(false); 377 assert(false);
378 return 0; 378 return 0;
379 } 379 }
380 } 380 }
381 381
382 /////////////////////////// 382 ///////////////////////////
383 // vba.speedmode(string mode) 383 // vba.speedmode(string mode)
384 // 384 //
388 // turbo renders only a few frames in order to speed up emulation, 388 // turbo renders only a few frames in order to speed up emulation,
389 389
390 // maximum renders no frames 390 // maximum renders no frames
391 static int vba_speedmode(lua_State *L) 391 static int vba_speedmode(lua_State *L)
392 { 392 {
393 const char *mode = luaL_checkstring(L, 1); 393 const char *mode = luaL_checkstring(L, 1);
394 394
395 if (strcasecmp(mode, "normal") == 0) 395 if (strcasecmp(mode, "normal") == 0)
396 { 396 {
397 speedmode = SPEED_NORMAL; 397 speedmode = SPEED_NORMAL;
398 } 398 }
399 else if (strcasecmp(mode, "nothrottle") == 0) 399 else if (strcasecmp(mode, "nothrottle") == 0)
400 { 400 {
401 speedmode = SPEED_NOTHROTTLE; 401 speedmode = SPEED_NOTHROTTLE;
402 } 402 }
403 else if (strcasecmp(mode, "turbo") == 0) 403 else if (strcasecmp(mode, "turbo") == 0)
404 { 404 {
405 speedmode = SPEED_TURBO; 405 speedmode = SPEED_TURBO;
406 } 406 }
407 else if (strcasecmp(mode, "maximum") == 0) 407 else if (strcasecmp(mode, "maximum") == 0)
408 { 408 {
409 speedmode = SPEED_MAXIMUM; 409 speedmode = SPEED_MAXIMUM;
410 } 410 }
411 else 411 else
412 luaL_error(L, "Invalid mode %s to vba.speedmode", mode); 412 luaL_error(L, "Invalid mode %s to vba.speedmode", mode);
413 413
414 //printf("new speed mode: %d\n", speedmode); 414 //printf("new speed mode: %d\n", speedmode);
415 return 0; 415 return 0;
416 } 416 }
417 417
418 // vba.frameadvnace() 418 // vba.frameadvnace()
419 // 419 //
420 // Executes a frame advance. Occurs by yielding the coroutine, then re-running 420 // Executes a frame advance. Occurs by yielding the coroutine, then re-running
421 421
422 // when we break out. 422 // when we break out.
423 static int vba_frameadvance(lua_State *L) 423 static int vba_frameadvance(lua_State *L)
424 { 424 {
425 // We're going to sleep for a frame-advance. Take notes. 425 // We're going to sleep for a frame-advance. Take notes.
426 if (frameAdvanceWaiting) 426 if (frameAdvanceWaiting)
427 return luaL_error(L, "can't call vba.frameadvance() from here"); 427 return luaL_error(L, "can't call vba.frameadvance() from here");
428 428
429 frameAdvanceWaiting = true; 429 frameAdvanceWaiting = true;
430 430
431 // Don't do this! The user won't like us sending their emulator out of control! 431 // Don't do this! The user won't like us sending their emulator out of control!
432 // Settings.FrameAdvance = true; 432 // Settings.FrameAdvance = true;
433 // Now we can yield to the main 433 // Now we can yield to the main
434 return lua_yield(L, 0); 434 return lua_yield(L, 0);
435 435
436 // It's actually rather disappointing... 436 // It's actually rather disappointing...
437 } 437 }
438 438
439 // vba.pause() 439 // vba.pause()
440 // 440 //
441 // Pauses the emulator, function "waits" until the user unpauses. 441 // Pauses the emulator, function "waits" until the user unpauses.
442 // This function MAY be called from a non-frame boundary, but the frame 442 // This function MAY be called from a non-frame boundary, but the frame
443 443
444 // finishes executing anwyays. In this case, the function returns immediately. 444 // finishes executing anwyays. In this case, the function returns immediately.
445 static int vba_pause(lua_State *L) 445 static int vba_pause(lua_State *L)
446 { 446 {
447 systemSetPause(true); 447 systemSetPause(true);
448 speedmode = SPEED_NORMAL; 448 speedmode = SPEED_NORMAL;
449 449
450 // Return control if we're midway through a frame. We can't pause here. 450 // Return control if we're midway through a frame. We can't pause here.
451 if (frameAdvanceWaiting) 451 if (frameAdvanceWaiting)
452 { 452 {
453 return 0; 453 return 0;
454 } 454 }
455 455
456 // If it's on a frame boundary, we also yield. 456 // If it's on a frame boundary, we also yield.
457 frameAdvanceWaiting = true; 457 frameAdvanceWaiting = true;
458 return lua_yield(L, 0); 458 return lua_yield(L, 0);
459 } 459 }
460 460
461 static int vba_registerbefore(lua_State *L) 461 static int vba_registerbefore(lua_State *L)
462 { 462 {
463 if (!lua_isnil(L, 1)) 463 if (!lua_isnil(L, 1))
464 luaL_checktype(L, 1, LUA_TFUNCTION); 464 luaL_checktype(L, 1, LUA_TFUNCTION);
465 lua_settop(L, 1); 465 lua_settop(L, 1);
466 lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFOREEMULATION]); 466 lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFOREEMULATION]);
467 lua_insert(L, 1); 467 lua_insert(L, 1);
468 lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFOREEMULATION]); 468 lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFOREEMULATION]);
469 469
470 //StopScriptIfFinished(luaStateToUIDMap[L]); 470 //StopScriptIfFinished(luaStateToUIDMap[L]);
471 return 1; 471 return 1;
472 } 472 }
473 473
474 static int vba_registerafter(lua_State *L) 474 static int vba_registerafter(lua_State *L)
475 { 475 {
476 if (!lua_isnil(L, 1)) 476 if (!lua_isnil(L, 1))
477 luaL_checktype(L, 1, LUA_TFUNCTION); 477 luaL_checktype(L, 1, LUA_TFUNCTION);
478 lua_settop(L, 1); 478 lua_settop(L, 1);
479 lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_AFTEREMULATION]); 479 lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_AFTEREMULATION]);
480 lua_insert(L, 1); 480 lua_insert(L, 1);
481 lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_AFTEREMULATION]); 481 lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_AFTEREMULATION]);
482 482
483 //StopScriptIfFinished(luaStateToUIDMap[L]); 483 //StopScriptIfFinished(luaStateToUIDMap[L]);
484 return 1; 484 return 1;
485 } 485 }
486 486
487 static int vba_registerexit(lua_State *L) 487 static int vba_registerexit(lua_State *L)
488 { 488 {
489 if (!lua_isnil(L, 1)) 489 if (!lua_isnil(L, 1))
490 luaL_checktype(L, 1, LUA_TFUNCTION); 490 luaL_checktype(L, 1, LUA_TFUNCTION);
491 lua_settop(L, 1); 491 lua_settop(L, 1);
492 lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFOREEXIT]); 492 lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFOREEXIT]);
493 lua_insert(L, 1); 493 lua_insert(L, 1);
494 lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFOREEXIT]); 494 lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFOREEXIT]);
495 495
496 //StopScriptIfFinished(luaStateToUIDMap[L]); 496 //StopScriptIfFinished(luaStateToUIDMap[L]);
497 return 1; 497 return 1;
498 } 498 }
499 499
500 static inline bool isalphaorunderscore(char c) 500 static inline bool isalphaorunderscore(char c)
501 { 501 {
502 return isalpha(c) || c == '_'; 502 return isalpha(c) || c == '_';
503 } 503 }
504 504
505 static std::vector<const void *> s_tableAddressStack; // prevents infinite recursion of a table within a table (when cycle is 505 static std::vector<const void *> s_tableAddressStack; // prevents infinite recursion of a table within a table (when cycle is
506 // found, print something like table:parent) 506 // found, print something like table:parent)
507 static std::vector<const void *> s_metacallStack; // prevents infinite recursion if something's __tostring returns another table 507 static std::vector<const void *> s_metacallStack; // prevents infinite recursion if something's __tostring returns another table
510 510
511 #define APPENDPRINT { int _n = snprintf(ptr, remaining, 511 #define APPENDPRINT { int _n = snprintf(ptr, remaining,
512 #define END ); if (_n >= 0) { ptr += _n; remaining -= _n; } else { remaining = 0; } } 512 #define END ); if (_n >= 0) { ptr += _n; remaining -= _n; } else { remaining = 0; } }
513 static void toCStringConverter(lua_State *L, int i, char * &ptr, int &remaining) 513 static void toCStringConverter(lua_State *L, int i, char * &ptr, int &remaining)
514 { 514 {
515 if (remaining <= 0) 515 if (remaining <= 0)
516 return; 516 return;
517 517
518 const char *str = ptr; // for debugging 518 const char *str = ptr; // for debugging
519 519
520 // if there is a __tostring metamethod then call it 520 // if there is a __tostring metamethod then call it
521 int usedMeta = luaL_callmeta(L, i, "__tostring"); 521 int usedMeta = luaL_callmeta(L, i, "__tostring");
522 if (usedMeta) 522 if (usedMeta)
523 { 523 {
524 std::vector<const void *>::const_iterator foundCycleIter = std::find(s_metacallStack.begin(), s_metacallStack.end(), lua_topointer(L, i)); 524 std::vector<const void *>::const_iterator foundCycleIter = std::find(s_metacallStack.begin(), s_metacallStack.end(), lua_topointer(L, i));
525 if (foundCycleIter != s_metacallStack.end()) 525 if (foundCycleIter != s_metacallStack.end())
526 { 526 {
527 lua_pop(L, 1); 527 lua_pop(L, 1);
528 usedMeta = false; 528 usedMeta = false;
529 } 529 }
530 else 530 else
531 { 531 {
532 s_metacallStack.push_back(lua_topointer(L, i)); 532 s_metacallStack.push_back(lua_topointer(L, i));
533 i = lua_gettop(L); 533 i = lua_gettop(L);
534 } 534 }
535 } 535 }
536 536
537 switch (lua_type(L, i)) 537 switch (lua_type(L, i))
538 { 538 {
539 case LUA_TNONE: 539 case LUA_TNONE:
540 break; 540 break;
541 case LUA_TNIL: 541 case LUA_TNIL:
542 APPENDPRINT "nil" END break; 542 APPENDPRINT "nil" END break;
543 case LUA_TBOOLEAN: 543 case LUA_TBOOLEAN:
544 APPENDPRINT lua_toboolean(L, i) ? "true" : "false" END break; 544 APPENDPRINT lua_toboolean(L, i) ? "true" : "false" END break;
545 case LUA_TSTRING : APPENDPRINT "%s", lua_tostring(L, i) END break; 545 case LUA_TSTRING : APPENDPRINT "%s", lua_tostring(L, i) END break;
546 case LUA_TNUMBER: 546 case LUA_TNUMBER:
547 APPENDPRINT "%.12Lg", lua_tonumber(L, i) END break; 547 APPENDPRINT "%.12Lg", lua_tonumber(L, i) END break;
548 case LUA_TFUNCTION: 548 case LUA_TFUNCTION:
549 if ((L->base + i - 1)->value.gc->cl.c.isC) 549 if ((L->base + i - 1)->value.gc->cl.c.isC)
550 { 550 {
551 //lua_CFunction func = lua_tocfunction(L, i); 551 //lua_CFunction func = lua_tocfunction(L, i);
552 //std::map<lua_CFunction, const char*>::iterator iter = s_cFuncInfoMap.find(func); 552 //std::map<lua_CFunction, const char*>::iterator iter = s_cFuncInfoMap.find(func);
553 //if(iter == s_cFuncInfoMap.end()) 553 //if(iter == s_cFuncInfoMap.end())
554 goto defcase; 554 goto defcase;
555 //APPENDPRINT "function(%s)", iter->second END 555 //APPENDPRINT "function(%s)", iter->second END
556 } 556 }
557 else
558 {
559 APPENDPRINT "function(" END
560 Proto * p = (L->base + i - 1)->value.gc->cl.l.p;
561 int numParams = p->numparams + (p->is_vararg ? 1 : 0);
562 for (int n = 0; n < p->numparams; n++)
563 {
564 APPENDPRINT "%s", getstr(p->locvars[n].varname) END
565 if (n != numParams - 1)
566 APPENDPRINT "," END
567 }
568 if (p->is_vararg)
569 APPENDPRINT "..." END
570 APPENDPRINT ")" END
571 }
572 break;
573 defcase: default:
574 APPENDPRINT "%s:%p", luaL_typename(L, i), lua_topointer(L, i) END break;
575 case LUA_TTABLE:
576 {
577 // first make sure there's enough stack space
578 if (!lua_checkstack(L, 4))
579 {
580 // note that even if lua_checkstack never returns false,
581 // that doesn't mean we didn't need to call it,
582 // because calling it retrieves stack space past LUA_MINSTACK
583 goto defcase;
584 }
585
586 std::vector<const void *>::const_iterator foundCycleIter =
587 std::find(s_tableAddressStack.begin(), s_tableAddressStack.end(), lua_topointer(L, i));
588 if (foundCycleIter != s_tableAddressStack.end())
589 {
590 int parentNum = s_tableAddressStack.end() - foundCycleIter;
591 if (parentNum > 1)
592 APPENDPRINT "%s:parent^%d", luaL_typename(L, i), parentNum END
593 else
594 APPENDPRINT "%s:parent", luaL_typename(L, i) END
595 }
596 else
597 {
598 s_tableAddressStack.push_back(lua_topointer(L, i));
599 struct Scope { ~Scope(){ s_tableAddressStack. pop_back(); } } scope;
600
601 APPENDPRINT "{" END
602
603 lua_pushnil(L); // first key
604 int keyIndex = lua_gettop(L);
605 int valueIndex = keyIndex + 1;
606 bool first = true;
607 bool skipKey = true; // true if we're still in the "array part" of the table
608 lua_Number arrayIndex = (lua_Number)0;
609 while (lua_next(L, i))
610 {
611 if (first)
612 first = false;
557 else 613 else
558 { 614 APPENDPRINT ", " END
559 APPENDPRINT "function(" END 615 if (skipKey)
560 Proto * p = (L->base + i - 1)->value.gc->cl.l.p; 616 {
561 int numParams = p->numparams + (p->is_vararg ? 1 : 0); 617 arrayIndex += (lua_Number)1;
562 for (int n = 0; n < p->numparams; n++) 618 bool keyIsNumber = (lua_type(L, keyIndex) == LUA_TNUMBER);
563 { 619 skipKey = keyIsNumber && (lua_tonumber(L, keyIndex) == arrayIndex);
564 APPENDPRINT "%s", getstr(p->locvars[n].varname) END 620 }
565 if (n != numParams - 1) 621 if (!skipKey)
566 APPENDPRINT "," END 622 {
567 } 623 bool keyIsString = (lua_type(L, keyIndex) == LUA_TSTRING);
568 if (p->is_vararg) 624 bool invalidLuaIdentifier = (!keyIsString || !isalphaorunderscore(*lua_tostring(L, keyIndex)));
569 APPENDPRINT "..." END 625 if (invalidLuaIdentifier)
570 APPENDPRINT ")" END 626 if (keyIsString)
571 } 627 APPENDPRINT "['" END
572 break; 628 else
573 defcase: default: 629 APPENDPRINT "[" END
574 APPENDPRINT "%s:%p", luaL_typename(L, i), lua_topointer(L, i) END break; 630
575 case LUA_TTABLE: 631 toCStringConverter(L, keyIndex, ptr, remaining);
576 { 632 // key
577 // first make sure there's enough stack space 633
578 if (!lua_checkstack(L, 4)) 634 if (invalidLuaIdentifier)
579 { 635 if (keyIsString)
580 // note that even if lua_checkstack never returns false, 636 APPENDPRINT "']=" END
581 // that doesn't mean we didn't need to call it, 637 else
582 // because calling it retrieves stack space past LUA_MINSTACK 638 APPENDPRINT "]=" END
583 goto defcase; 639 else
584 } 640 APPENDPRINT "=" END
585 641 }
586 std::vector<const void *>::const_iterator foundCycleIter = 642
587 std::find(s_tableAddressStack.begin(), s_tableAddressStack.end(), lua_topointer(L, i)); 643 bool valueIsString = (lua_type(L, valueIndex) == LUA_TSTRING);
588 if (foundCycleIter != s_tableAddressStack.end()) 644 if (valueIsString)
589 { 645 APPENDPRINT "'" END
590 int parentNum = s_tableAddressStack.end() - foundCycleIter; 646
591 if (parentNum > 1) 647 toCStringConverter(L, valueIndex, ptr, remaining); // value
592 APPENDPRINT "%s:parent^%d", luaL_typename(L, i), parentNum END 648
593 else 649 if (valueIsString)
594 APPENDPRINT "%s:parent", luaL_typename(L, i) END 650 APPENDPRINT "'" END
595 } 651
596 else 652 lua_pop(L, 1);
597 { 653
598 s_tableAddressStack.push_back(lua_topointer(L, i)); 654 if (remaining <= 0)
599 struct Scope { ~Scope(){ s_tableAddressStack. pop_back(); } } scope; 655 {
600 656 lua_settop(L, keyIndex - 1); // stack might not be clean yet if we're breaking
601 APPENDPRINT "{" END 657 // early
602 658 break;
603 lua_pushnil(L); // first key 659 }
604 int keyIndex = lua_gettop(L); 660 }
605 int valueIndex = keyIndex + 1; 661 APPENDPRINT "}" END
606 bool first = true; 662 }
607 bool skipKey = true; // true if we're still in the "array part" of the table 663 }
608 lua_Number arrayIndex = (lua_Number)0; 664 break;
609 while (lua_next(L, i)) 665 }
610 { 666
611 if (first) 667 if (usedMeta)
612 first = false; 668 {
613 else 669 s_metacallStack.pop_back();
614 APPENDPRINT ", " END 670 lua_pop(L, 1);
615 if (skipKey) 671 }
616 { 672 }
617 arrayIndex += (lua_Number)1; 673
618 bool keyIsNumber = (lua_type(L, keyIndex) == LUA_TNUMBER); 674 static const int s_tempStrMaxLen = 64 * 1024;
619 skipKey = keyIsNumber && (lua_tonumber(L, keyIndex) == arrayIndex); 675 static char s_tempStr [s_tempStrMaxLen];
620 } 676
621 if (!skipKey) 677 static char *rawToCString(lua_State *L, int idx)
622 { 678 {
623 bool keyIsString = (lua_type(L, keyIndex) == LUA_TSTRING); 679 int a = idx > 0 ? idx : 1;
624 bool invalidLuaIdentifier = (!keyIsString || !isalphaorunderscore(*lua_tostring(L, keyIndex))); 680 int n = idx > 0 ? idx : lua_gettop(L);
625 if (invalidLuaIdentifier) 681
626 if (keyIsString) 682 char *ptr = s_tempStr;
627 APPENDPRINT "['" END 683 *ptr = 0;
628 else 684
629 APPENDPRINT "[" END 685 int remaining = s_tempStrMaxLen;
630 686 for (int i = a; i <= n; i++)
631 toCStringConverter(L, keyIndex, ptr, remaining); 687 {
632 // key 688 toCStringConverter(L, i, ptr, remaining);
633 689 if (i != n)
634 if (invalidLuaIdentifier) 690 APPENDPRINT " " END
635 if (keyIsString) 691 }
636 APPENDPRINT "']=" END 692
637 else 693 if (remaining < 3)
638 APPENDPRINT "]=" END 694 {
639 else 695 while (remaining < 6)
640 APPENDPRINT "=" END 696 remaining++, ptr--;
641 } 697 APPENDPRINT "..." END
642 698 }
643 bool valueIsString = (lua_type(L, valueIndex) == LUA_TSTRING); 699 APPENDPRINT "\r\n" END
644 if (valueIsString) 700 // the trailing newline is so print() can avoid having to do wasteful things to print its newline
645 APPENDPRINT "'" END 701 // (string copying would be wasteful and calling info.print() twice can be extremely slow)
646 702 // at the cost of functions that don't want the newline needing to trim off the last two characters
647 toCStringConverter(L, valueIndex, ptr, remaining); // value 703 // (which is a very fast operation and thus acceptable in this case)
648 704
649 if (valueIsString) 705 return s_tempStr;
650 APPENDPRINT "'" END 706 }
651
652 lua_pop(L, 1);
653
654 if (remaining <= 0)
655 {
656 lua_settop(L, keyIndex - 1); // stack might not be clean yet if we're breaking
657 // early
658 break;
659 }
660 }
661 APPENDPRINT "}" END
662 }
663 }
664 break;
665 }
666
667 if (usedMeta)
668 {
669 s_metacallStack.pop_back();
670 lua_pop(L, 1);
671 }
672 }
673
674 static const int s_tempStrMaxLen = 64 * 1024;
675 static char s_tempStr [s_tempStrMaxLen];
676
677 static char *rawToCString(lua_State *L, int idx)
678 {
679 int a = idx > 0 ? idx : 1;
680 int n = idx > 0 ? idx : lua_gettop(L);
681
682 char *ptr = s_tempStr;
683 *ptr = 0;
684
685 int remaining = s_tempStrMaxLen;
686 for (int i = a; i <= n; i++)
687 {
688 toCStringConverter(L, i, ptr, remaining);
689 if (i != n)
690 APPENDPRINT " " END
691 }
692
693 if (remaining < 3)
694 {
695 while (remaining < 6)
696 remaining++, ptr--;
697 APPENDPRINT "..." END
698 }
699 APPENDPRINT "\r\n" END
700 // the trailing newline is so print() can avoid having to do wasteful things to print its newline
701 // (string copying would be wasteful and calling info.print() twice can be extremely slow)
702 // at the cost of functions that don't want the newline needing to trim off the last two characters
703 // (which is a very fast operation and thus acceptable in this case)
704
705 return s_tempStr;
706 }
707 #undef APPENDPRINT 707 #undef APPENDPRINT
708 #undef END 708 #undef END
709 709
710 // replacement for luaB_tostring() that is able to show the contents of tables (and formats numbers better, and show function 710 // replacement for luaB_tostring() that is able to show the contents of tables (and formats numbers better, and show function
711 // prototypes) 711 // prototypes)
712 // can be called directly from lua via tostring(), assuming tostring hasn't been reassigned 712 // can be called directly from lua via tostring(), assuming tostring hasn't been reassigned
713 static int tostring(lua_State *L) 713 static int tostring(lua_State *L)
714 { 714 {
715 char *str = rawToCString(L); 715 char *str = rawToCString(L);
716 str[strlen(str) - 2] = 0; // hack: trim off the \r\n (which is there to simplify the print function's 716 str[strlen(str) - 2] = 0; // hack: trim off the \r\n (which is there to simplify the print function's
717 // task) 717 // task)
718 lua_pushstring(L, str); 718 lua_pushstring(L, str);
719 return 1; 719 return 1;
720 } 720 }
721 721
722 // like rawToCString, but will check if the global Lua function tostring() 722 // like rawToCString, but will check if the global Lua function tostring()
723 // has been replaced with a custom function, and call that instead if so 723 // has been replaced with a custom function, and call that instead if so
724 static const char *toCString(lua_State *L, int idx) 724 static const char *toCString(lua_State *L, int idx)
725 { 725 {
726 int a = idx > 0 ? idx : 1; 726 int a = idx > 0 ? idx : 1;
727 int n = idx > 0 ? idx : lua_gettop(L); 727 int n = idx > 0 ? idx : lua_gettop(L);
728 lua_getglobal(L, "tostring"); 728 lua_getglobal(L, "tostring");
729 lua_CFunction cf = lua_tocfunction(L, -1); 729 lua_CFunction cf = lua_tocfunction(L, -1);
730 if (cf == tostring || lua_isnil(L, -1)) // optimization: if using our own C tostring function, we can 730 if (cf == tostring || lua_isnil(L, -1)) // optimization: if using our own C tostring function, we can
731 // bypass the call through Lua and all the string object 731 // bypass the call through Lua and all the string object
732 // allocation that would entail 732 // allocation that would entail
733 { 733 {
734 lua_pop(L, 1); 734 lua_pop(L, 1);
735 return rawToCString(L, idx); 735 return rawToCString(L, idx);
736 } 736 }
737 else // if the user overrided the tostring function, we have to actually call it and store the 737 else // if the user overrided the tostring function, we have to actually call it and store the
738 // temporarily allocated string it returns 738 // temporarily allocated string it returns
739 { 739 {
740 lua_pushstring(L, ""); 740 lua_pushstring(L, "");
741 for (int i = a; i <= n; i++) 741 for (int i = a; i <= n; i++)
742 { 742 {
743 lua_pushvalue(L, -2); // function to be called 743 lua_pushvalue(L, -2); // function to be called
744 lua_pushvalue(L, i); // value to print 744 lua_pushvalue(L, i); // value to print
745 lua_call(L, 1, 1); 745 lua_call(L, 1, 1);
746 if (lua_tostring(L, -1) == NULL) 746 if (lua_tostring(L, -1) == NULL)
747 luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("print")); 747 luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("print"));
748 lua_pushstring(L, (i < n) ? " " : "\r\n"); 748 lua_pushstring(L, (i < n) ? " " : "\r\n");
749 lua_concat(L, 3); 749 lua_concat(L, 3);
750 } 750 }
751 const char *str = lua_tostring(L, -1); 751 const char *str = lua_tostring(L, -1);
752 strncpy(s_tempStr, str, s_tempStrMaxLen); 752 strncpy(s_tempStr, str, s_tempStrMaxLen);
753 s_tempStr[s_tempStrMaxLen - 1] = 0; 753 s_tempStr[s_tempStrMaxLen - 1] = 0;
754 lua_pop(L, 2); 754 lua_pop(L, 2);
755 return s_tempStr; 755 return s_tempStr;
756 } 756 }
757 } 757 }
758 758
759 // replacement for luaB_print() that goes to the appropriate textbox instead of stdout 759 // replacement for luaB_print() that goes to the appropriate textbox instead of stdout
760 static int print(lua_State *L) 760 static int print(lua_State *L)
761 { 761 {
762 const char *str = toCString(L); 762 const char *str = toCString(L);
763 763
764 int uid = info_uid; //luaStateToUIDMap[L->l_G->mainthread]; 764 int uid = info_uid; //luaStateToUIDMap[L->l_G->mainthread];
765 //LuaContextInfo& info = GetCurrentInfo(); 765 //LuaContextInfo& info = GetCurrentInfo();
766 766
767 if (info_print) 767 if (info_print)
768 info_print(uid, str); 768 info_print(uid, str);
769 else 769 else
770 puts(str); 770 puts(str);
771 771
772 //worry(L, 100); 772 //worry(L, 100);
773 return 0; 773 return 0;
774 } 774 }
775 775
776 static int printerror(lua_State *L, int idx) 776 static int printerror(lua_State *L, int idx)
777 { 777 {
778 lua_checkstack(L, lua_gettop(L) + 4); 778 lua_checkstack(L, lua_gettop(L) + 4);
779 779
780 if (idx < 0) 780 if (idx < 0)
781 idx = lua_gettop(L) + 1 + idx; 781 idx = lua_gettop(L) + 1 + idx;
782 782
783 const char *str = rawToCString(L, idx); 783 const char *str = rawToCString(L, idx);
784 784
785 int uid = info_uid; //luaStateToUIDMap[L->l_G->mainthread]; 785 int uid = info_uid; //luaStateToUIDMap[L->l_G->mainthread];
786 //LuaContextInfo& info = GetCurrentInfo(); 786 //LuaContextInfo& info = GetCurrentInfo();
787 787
788 if (info_print) 788 if (info_print)
789 info_print(uid, str); 789 info_print(uid, str);
790 else 790 else
791 fputs(str, stderr); 791 fputs(str, stderr);
792 792
793 //worry(L, 100); 793 //worry(L, 100);
794 return 0; 794 return 0;
795 } 795 }
796 796
797 // vba.message(string msg) 797 // vba.message(string msg)
798 // 798 //
799 // Displays the given message on the screen. 799 // Displays the given message on the screen.
800 static int vba_message(lua_State *L) 800 static int vba_message(lua_State *L)
801 { 801 {
802 const char *msg = luaL_checkstring(L, 1); 802 const char *msg = luaL_checkstring(L, 1);
803 systemScreenMessage(msg); 803 systemScreenMessage(msg);
804 804
805 return 0; 805 return 0;
806 } 806 }
807 807
808 // provides an easy way to copy a table from Lua 808 // provides an easy way to copy a table from Lua
809 // (simple assignment only makes an alias, but sometimes an independent table is desired) 809 // (simple assignment only makes an alias, but sometimes an independent table is desired)
810 // currently this function only performs a shallow copy, 810 // currently this function only performs a shallow copy,
811 // but I think it should be changed to do a deep copy (possibly of configurable depth?) 811 // but I think it should be changed to do a deep copy (possibly of configurable depth?)
812 // that maintains the internal table reference structure 812 // that maintains the internal table reference structure
813 static int copytable(lua_State *L) 813 static int copytable(lua_State *L)
814 { 814 {
815 int origIndex = 1; // we only care about the first argument 815 int origIndex = 1; // we only care about the first argument
816 int origType = lua_type(L, origIndex); 816 int origType = lua_type(L, origIndex);
817 if (origType == LUA_TNIL) 817 if (origType == LUA_TNIL)
818 { 818 {
819 lua_pushnil(L); 819 lua_pushnil(L);
820 return 1; 820 return 1;
821 } 821 }
822 if (origType != LUA_TTABLE) 822 if (origType != LUA_TTABLE)
823 { 823 {
824 luaL_typerror(L, 1, lua_typename(L, LUA_TTABLE)); 824 luaL_typerror(L, 1, lua_typename(L, LUA_TTABLE));
825 lua_pushnil(L); 825 lua_pushnil(L);
826 return 1; 826 return 1;
827 } 827 }
828 828
829 lua_createtable(L, lua_objlen(L, 1), 0); 829 lua_createtable(L, lua_objlen(L, 1), 0);
830 int copyIndex = lua_gettop(L); 830 int copyIndex = lua_gettop(L);
831 831
832 lua_pushnil(L); // first key 832 lua_pushnil(L); // first key
833 int keyIndex = lua_gettop(L); 833 int keyIndex = lua_gettop(L);
834 int valueIndex = keyIndex + 1; 834 int valueIndex = keyIndex + 1;
835 835
836 while (lua_next(L, origIndex)) 836 while (lua_next(L, origIndex))
837 { 837 {
838 lua_pushvalue(L, keyIndex); 838 lua_pushvalue(L, keyIndex);
839 lua_pushvalue(L, valueIndex); 839 lua_pushvalue(L, valueIndex);
840 lua_rawset(L, copyIndex); // copytable[key] = value 840 lua_rawset(L, copyIndex); // copytable[key] = value
841 lua_pop(L, 1); 841 lua_pop(L, 1);
842 } 842 }
843 843
844 // copy the reference to the metatable as well, if any 844 // copy the reference to the metatable as well, if any
845 if (lua_getmetatable(L, origIndex)) 845 if (lua_getmetatable(L, origIndex))
846 lua_setmetatable(L, copyIndex); 846 lua_setmetatable(L, copyIndex);
847 847
848 return 1; // return the new table 848 return 1; // return the new table
849 } 849 }
850 850
851 // because print traditionally shows the address of tables, 851 // because print traditionally shows the address of tables,
852 // and the print function I provide instead shows the contents of tables, 852 // and the print function I provide instead shows the contents of tables,
853 // I also provide this function 853 // I also provide this function
854 // (otherwise there would be no way to see a table's address, AFAICT) 854 // (otherwise there would be no way to see a table's address, AFAICT)
855 static int addressof(lua_State *L) 855 static int addressof(lua_State *L)
856 { 856 {
857 const void *ptr = lua_topointer(L, -1); 857 const void *ptr = lua_topointer(L, -1);
858 lua_pushinteger(L, (lua_Integer)ptr); 858 lua_pushinteger(L, (lua_Integer)ptr);
859 return 1; 859 return 1;
860 } 860 }
861 861
862 struct registerPointerMap 862 struct registerPointerMap
863 { 863 {
864 const char * registerName; 864 const char * registerName;
865 unsigned int *pointer; 865 unsigned int *pointer;
866 int dataSize; 866 int dataSize;
867 }; 867 };
868 868
869 #define RPM_ENTRY(name, var) \ 869 #define RPM_ENTRY(name, var) \
870 { name, (unsigned int *)&var, sizeof(var) \ 870 { name, (unsigned int *)&var, sizeof(var) \
871 } \ 871 } \
872 , 872 ,
873 873
874 extern gbRegister AF; 874 extern gbRegister AF;
875 extern gbRegister BC; 875 extern gbRegister BC;
876 extern gbRegister DE; 876 extern gbRegister DE;
877 extern gbRegister HL; 877 extern gbRegister HL;
878 extern gbRegister SP; 878 extern gbRegister SP;
879 extern gbRegister PC; 879 extern gbRegister PC;
880 extern u16 IFF; 880 extern u16 IFF;
881 881
882 registerPointerMap regPointerMap [] = { 882 registerPointerMap regPointerMap [] = {
883 // gba registers 883 // gba registers
884 RPM_ENTRY("r0", reg[0].I) 884 RPM_ENTRY("r0", reg[0].I)
885 RPM_ENTRY("r1", reg[1].I) 885 RPM_ENTRY("r1", reg[1].I)
886 RPM_ENTRY("r2", reg[2].I) 886 RPM_ENTRY("r2", reg[2].I)
887 RPM_ENTRY("r3", reg[3].I) 887 RPM_ENTRY("r3", reg[3].I)
888 RPM_ENTRY("r4", reg[4].I) 888 RPM_ENTRY("r4", reg[4].I)
889 RPM_ENTRY("r5", reg[5].I) 889 RPM_ENTRY("r5", reg[5].I)
890 RPM_ENTRY("r6", reg[6].I) 890 RPM_ENTRY("r6", reg[6].I)
891 RPM_ENTRY("r7", reg[7].I) 891 RPM_ENTRY("r7", reg[7].I)
892 RPM_ENTRY("r8", reg[8].I) 892 RPM_ENTRY("r8", reg[8].I)
893 RPM_ENTRY("r9", reg[9].I) 893 RPM_ENTRY("r9", reg[9].I)
894 RPM_ENTRY("r10", reg[10].I) 894 RPM_ENTRY("r10", reg[10].I)
895 RPM_ENTRY("r11", reg[11].I) 895 RPM_ENTRY("r11", reg[11].I)
896 RPM_ENTRY("r12", reg[12].I) 896 RPM_ENTRY("r12", reg[12].I)
897 RPM_ENTRY("r13", reg[13].I) 897 RPM_ENTRY("r13", reg[13].I)
898 RPM_ENTRY("r14", reg[14].I) 898 RPM_ENTRY("r14", reg[14].I)
899 RPM_ENTRY("r15", reg[15].I) 899 RPM_ENTRY("r15", reg[15].I)
900 RPM_ENTRY("cpsr", reg[16].I) 900 RPM_ENTRY("cpsr", reg[16].I)
901 RPM_ENTRY("spsr", reg[17].I) 901 RPM_ENTRY("spsr", reg[17].I)
902 // gb registers 902 // gb registers
903 RPM_ENTRY("a", AF.B.B1) 903 RPM_ENTRY("a", AF.B.B1)
904 RPM_ENTRY("f", AF.B.B0) 904 RPM_ENTRY("f", AF.B.B0)
905 RPM_ENTRY("b", BC.B.B1) 905 RPM_ENTRY("b", BC.B.B1)
906 RPM_ENTRY("c", BC.B.B0) 906 RPM_ENTRY("c", BC.B.B0)
907 RPM_ENTRY("d", DE.B.B1) 907 RPM_ENTRY("d", DE.B.B1)
908 RPM_ENTRY("e", DE.B.B0) 908 RPM_ENTRY("e", DE.B.B0)
909 RPM_ENTRY("h", HL.B.B1) 909 RPM_ENTRY("h", HL.B.B1)
910 RPM_ENTRY("l", HL.B.B0) 910 RPM_ENTRY("l", HL.B.B0)
911 RPM_ENTRY("af", AF.W) 911 RPM_ENTRY("af", AF.W)
912 RPM_ENTRY("bc", BC.W) 912 RPM_ENTRY("bc", BC.W)
913 RPM_ENTRY("de", DE.W) 913 RPM_ENTRY("de", DE.W)
914 RPM_ENTRY("hl", HL.W) 914 RPM_ENTRY("hl", HL.W)
915 RPM_ENTRY("sp", SP.W) 915 RPM_ENTRY("sp", SP.W)
916 RPM_ENTRY("pc", PC.W) 916 RPM_ENTRY("pc", PC.W)
917 {} 917 {}
918 }; 918 };
919 919
920 struct cpuToRegisterMap 920 struct cpuToRegisterMap
921 { 921 {
922 const char *cpuName; 922 const char *cpuName;
923 registerPointerMap *rpmap; 923 registerPointerMap *rpmap;
924 } 924 }
925 cpuToRegisterMaps [] = 925 cpuToRegisterMaps [] =
926 { 926 {
927 { "", regPointerMap }, 927 { "", regPointerMap },
928 }; 928 };
929 929
930 //DEFINE_LUA_FUNCTION(memory_getregister, "cpu_dot_registername_string") 930 //DEFINE_LUA_FUNCTION(memory_getregister, "cpu_dot_registername_string")
931 static int memory_getregister(lua_State *L) 931 static int memory_getregister(lua_State *L)
932 { 932 {
933 const char *qualifiedRegisterName = luaL_checkstring(L, 1); 933 const char *qualifiedRegisterName = luaL_checkstring(L, 1);
934 lua_settop(L, 0); 934 lua_settop(L, 0);
935 for (int cpu = 0; cpu < sizeof(cpuToRegisterMaps) / sizeof(*cpuToRegisterMaps); cpu++) 935 for (int cpu = 0; cpu < sizeof(cpuToRegisterMaps) / sizeof(*cpuToRegisterMaps); cpu++)
936 { 936 {
937 cpuToRegisterMap ctrm = cpuToRegisterMaps[cpu]; 937 cpuToRegisterMap ctrm = cpuToRegisterMaps[cpu];
938 int cpuNameLen = strlen(ctrm.cpuName); 938 int cpuNameLen = strlen(ctrm.cpuName);
939 if (!strnicmp(qualifiedRegisterName, ctrm.cpuName, cpuNameLen)) 939 if (!strnicmp(qualifiedRegisterName, ctrm.cpuName, cpuNameLen))
940 { 940 {
941 qualifiedRegisterName += cpuNameLen; 941 qualifiedRegisterName += cpuNameLen;
942 for (int reg = 0; ctrm.rpmap[reg].dataSize; reg++) 942 for (int reg = 0; ctrm.rpmap[reg].dataSize; reg++)
943 { 943 {
944 registerPointerMap rpm = ctrm.rpmap[reg]; 944 registerPointerMap rpm = ctrm.rpmap[reg];
945 if (!stricmp(qualifiedRegisterName, rpm.registerName)) 945 if (!stricmp(qualifiedRegisterName, rpm.registerName))
946 { 946 {
947 switch (rpm.dataSize) 947 switch (rpm.dataSize)
948 { 948 {
949 default: 949 default:
950 case 1: 950 case 1:
951 lua_pushinteger(L, *(unsigned char *)rpm.pointer); break; 951 lua_pushinteger(L, *(unsigned char *)rpm.pointer); break;
952 case 2: 952 case 2:
953 lua_pushinteger(L, *(unsigned short *)rpm.pointer); break; 953 lua_pushinteger(L, *(unsigned short *)rpm.pointer); break;
954 case 4: 954 case 4:
955 lua_pushinteger(L, *(unsigned long *)rpm.pointer); break; 955 lua_pushinteger(L, *(unsigned long *)rpm.pointer); break;
956 } 956 }
957 return 1; 957 return 1;
958 } 958 }
959 } 959 }
960 lua_pushnil(L); 960 lua_pushnil(L);
961 return 1; 961 return 1;
962 } 962 }
963 } 963 }
964 lua_pushnil(L); 964 lua_pushnil(L);
965 return 1; 965 return 1;
966 } 966 }
967 967
968 //DEFINE_LUA_FUNCTION(memory_setregister, "cpu_dot_registername_string,value") 968 //DEFINE_LUA_FUNCTION(memory_setregister, "cpu_dot_registername_string,value")
969 static int memory_setregister(lua_State *L) 969 static int memory_setregister(lua_State *L)
970 { 970 {
971 const char * qualifiedRegisterName = luaL_checkstring(L, 1); 971 const char * qualifiedRegisterName = luaL_checkstring(L, 1);
972 unsigned long value = (unsigned long)(luaL_checkinteger(L, 2)); 972 unsigned long value = (unsigned long)(luaL_checkinteger(L, 2));
973 lua_settop(L, 0); 973 lua_settop(L, 0);
974 for (int cpu = 0; cpu < sizeof(cpuToRegisterMaps) / sizeof(*cpuToRegisterMaps); cpu++) 974 for (int cpu = 0; cpu < sizeof(cpuToRegisterMaps) / sizeof(*cpuToRegisterMaps); cpu++)
975 { 975 {
976 cpuToRegisterMap ctrm = cpuToRegisterMaps[cpu]; 976 cpuToRegisterMap ctrm = cpuToRegisterMaps[cpu];
977 int cpuNameLen = strlen(ctrm.cpuName); 977 int cpuNameLen = strlen(ctrm.cpuName);
978 if (!strnicmp(qualifiedRegisterName, ctrm.cpuName, cpuNameLen)) 978 if (!strnicmp(qualifiedRegisterName, ctrm.cpuName, cpuNameLen))
979 { 979 {
980 qualifiedRegisterName += cpuNameLen; 980 qualifiedRegisterName += cpuNameLen;
981 for (int reg = 0; ctrm.rpmap[reg].dataSize; reg++) 981 for (int reg = 0; ctrm.rpmap[reg].dataSize; reg++)
982 { 982 {
983 registerPointerMap rpm = ctrm.rpmap[reg]; 983 registerPointerMap rpm = ctrm.rpmap[reg];
984 if (!stricmp(qualifiedRegisterName, rpm.registerName)) 984 if (!stricmp(qualifiedRegisterName, rpm.registerName))
985 { 985 {
986 switch (rpm.dataSize) 986 switch (rpm.dataSize)
987 { 987 {
988 default: 988 default:
989 case 1: 989 case 1:
990 *(unsigned char *)rpm.pointer = (unsigned char)(value & 0xFF); break; 990 *(unsigned char *)rpm.pointer = (unsigned char)(value & 0xFF); break;
991 case 2: 991 case 2:
992 *(unsigned short *)rpm.pointer = (unsigned short)(value & 0xFFFF); break; 992 *(unsigned short *)rpm.pointer = (unsigned short)(value & 0xFFFF); break;
993 case 4: 993 case 4:
994 *(unsigned long *)rpm.pointer = value; break; 994 *(unsigned long *)rpm.pointer = value; break;
995 } 995 }
996 return 0; 996 return 0;
997 } 997 }
998 } 998 }
999 return 0; 999 return 0;
1000 } 1000 }
1001 } 1001 }
1002 return 0; 1002 return 0;
1003 } 1003 }
1004 1004
1005 void HandleCallbackError(lua_State *L) 1005 void HandleCallbackError(lua_State *L)
1006 { 1006 {
1007 if (L->errfunc || L->errorJmp) 1007 if (L->errfunc || L->errorJmp)
1008 luaL_error(L, "%s", lua_tostring(L, -1)); 1008 luaL_error(L, "%s", lua_tostring(L, -1));
1009 else 1009 else
1010 { 1010 {
1011 lua_pushnil(LUA); 1011 lua_pushnil(LUA);
1012 lua_setfield(LUA, LUA_REGISTRYINDEX, guiCallbackTable); 1012 lua_setfield(LUA, LUA_REGISTRYINDEX, guiCallbackTable);
1013 1013
1014 // Error? 1014 // Error?
1015 //#if (defined(WIN32) && !defined(SDL)) 1015 //#if (defined(WIN32) && !defined(SDL))
1016 // info_print(info_uid, lua_tostring(LUA, -1)); //Clear_Sound_Buffer(); 1016 // info_print(info_uid, lua_tostring(LUA, -1)); //Clear_Sound_Buffer();
1017 // AfxGetApp()->m_pMainWnd->MessageBox(lua_tostring(LUA, -1), "Lua run error", MB_OK | MB_ICONSTOP); 1017 // AfxGetApp()->m_pMainWnd->MessageBox(lua_tostring(LUA, -1), "Lua run error", MB_OK | MB_ICONSTOP);
1018 //#else 1018 //#else
1019 // fprintf(stderr, "Lua thread bombed out: %s\n", lua_tostring(LUA, -1)); 1019 // fprintf(stderr, "Lua thread bombed out: %s\n", lua_tostring(LUA, -1));
1020 //#endif 1020 //#endif
1021 printerror(LUA, -1); 1021 printerror(LUA, -1);
1022 VBALuaStop(); 1022 VBALuaStop();
1023 } 1023 }
1024 } 1024 }
1025 1025
1026 void CallRegisteredLuaFunctions(LuaCallID calltype) 1026 void CallRegisteredLuaFunctions(LuaCallID calltype)
1027 { 1027 {
1028 assert((unsigned int)calltype < (unsigned int)LUACALL_COUNT); 1028 assert((unsigned int)calltype < (unsigned int)LUACALL_COUNT);
1029 1029
1030 const char *idstring = luaCallIDStrings[calltype]; 1030 const char *idstring = luaCallIDStrings[calltype];
1031 1031
1032 if (!LUA) 1032 if (!LUA)
1033 return; 1033 return;
1034 1034
1035 lua_settop(LUA, 0); 1035 lua_settop(LUA, 0);
1036 lua_getfield(LUA, LUA_REGISTRYINDEX, idstring); 1036 lua_getfield(LUA, LUA_REGISTRYINDEX, idstring);
1037 1037
1038 int errorcode = 0; 1038 int errorcode = 0;
1039 if (lua_isfunction(LUA, -1)) 1039 if (lua_isfunction(LUA, -1))
1040 { 1040 {
1041 errorcode = lua_pcall(LUA, 0, 0, 0); 1041 errorcode = lua_pcall(LUA, 0, 0, 0);
1042 if (errorcode) 1042 if (errorcode)
1043 HandleCallbackError(LUA); 1043 HandleCallbackError(LUA);
1044 } 1044 }
1045 else 1045 else
1046 { 1046 {
1047 lua_pop(LUA, 1); 1047 lua_pop(LUA, 1);
1048 } 1048 }
1049 } 1049 }
1050 1050
1051 // the purpose of this structure is to provide a way of 1051 // the purpose of this structure is to provide a way of
1052 // QUICKLY determining whether a memory address range has a hook associated with it, 1052 // QUICKLY determining whether a memory address range has a hook associated with it,
1053 // with a bias toward fast rejection because the majority of addresses will not be hooked. 1053 // with a bias toward fast rejection because the majority of addresses will not be hooked.
1054 // (it must not use any part of Lua or perform any per-script operations, 1054 // (it must not use any part of Lua or perform any per-script operations,
1055 // otherwise it would definitely be too slow.) 1055 // otherwise it would definitely be too slow.)
1056 // calculating the regions when a hook is added/removed may be slow, 1056 // calculating the regions when a hook is added/removed may be slow,
1057 // but this is an intentional tradeoff to obtain a high speed of checking during later execution 1057 // but this is an intentional tradeoff to obtain a high speed of checking during later execution
1058 struct TieredRegion 1058 struct TieredRegion
1059 { 1059 {
1060 template<unsigned int maxGap> 1060 template<unsigned int maxGap>
1061 struct Region 1061 struct Region
1062 { 1062 {
1063 struct Island 1063 struct Island
1064 { 1064 {
1065 unsigned int start; 1065 unsigned int start;
1066 unsigned int end; 1066 unsigned int end;
1067 __forceinline bool Contains(unsigned int address, int size) const { return address < end && address + size > start; } 1067 __forceinline bool Contains(unsigned int address, int size) const { return address < end && address + size > start; }
1068 }; 1068 };
1069 std::vector<Island> islands; 1069 std::vector<Island> islands;
1070 1070
1071 void Calculate(const std::vector<unsigned int> &bytes) 1071 void Calculate(const std::vector<unsigned int> &bytes)
1072 { 1072 {
1073 islands. clear(); 1073 islands. clear();
1074 1074
1075 unsigned int lastEnd = ~0; 1075 unsigned int lastEnd = ~0;
1076 1076
1077 std::vector<unsigned int>::const_iterator iter = bytes.begin(); 1077 std::vector<unsigned int>::const_iterator iter = bytes.begin();
1078 std::vector<unsigned int>::const_iterator end = bytes.end(); 1078 std::vector<unsigned int>::const_iterator end = bytes.end();
1079 for (; iter != end; ++iter) 1079 for (; iter != end; ++iter)
1080 { 1080 {
1081 unsigned int addr = *iter; 1081 unsigned int addr = *iter;
1082 if (addr < lastEnd || addr > lastEnd + (long long)maxGap) 1082 if (addr < lastEnd || addr > lastEnd + (long long)maxGap)
1083 { 1083 {
1084 islands. push_back(Island()); 1084 islands. push_back(Island());
1085 islands. back().start = addr; 1085 islands. back().start = addr;
1086 } 1086 }
1087 islands.back(). end = addr + 1; 1087 islands.back(). end = addr + 1;
1088 lastEnd = addr + 1; 1088 lastEnd = addr + 1;
1089 } 1089 }
1090 } 1090 }
1091 1091
1092 bool Contains(unsigned int address, int size) const 1092 bool Contains(unsigned int address, int size) const
1093 { 1093 {
1094 for (size_t i = 0; i != islands.size(); ++i) 1094 for (size_t i = 0; i != islands.size(); ++i)
1095 { 1095 {
1096 if (islands[i].Contains(address, size)) 1096 if (islands[i].Contains(address, size))
1097 return true; 1097 return true;
1098 } 1098 }
1099 return false; 1099 return false;
1100 } 1100 }
1101 }; 1101 };
1102 1102
1103 Region<0xFFFFFFFF> broad; 1103 Region<0xFFFFFFFF> broad;
1104 Region<0x1000> mid; 1104 Region<0x1000> mid;
1105 Region<0> narrow; 1105 Region<0> narrow;
1106 1106
1107 void Calculate(std::vector<unsigned int> &bytes) 1107 void Calculate(std::vector<unsigned int> &bytes)
1108 { 1108 {
1109 std:: sort(bytes.begin(), bytes.end()); 1109 std:: sort(bytes.begin(), bytes.end());
1110 1110
1111 broad. Calculate(bytes); 1111 broad. Calculate(bytes);
1112 mid. Calculate(bytes); 1112 mid. Calculate(bytes);
1113 narrow. Calculate(bytes); 1113 narrow. Calculate(bytes);
1114 } 1114 }
1115 1115
1116 TieredRegion() 1116 TieredRegion()
1117 { 1117 {
1118 std::vector <unsigned int> temp; 1118 std::vector <unsigned int> temp;
1119 Calculate(temp); 1119 Calculate(temp);
1120 } 1120 }
1121 1121
1122 __forceinline int NotEmpty() 1122 __forceinline int NotEmpty()
1123 { 1123 {
1124 return broad.islands.size(); 1124 return broad.islands.size();
1125 } 1125 }
1126 1126
1127 // note: it is illegal to call this if NotEmpty() returns 0 1127 // note: it is illegal to call this if NotEmpty() returns 0
1128 __forceinline bool Contains(unsigned int address, int size) 1128 __forceinline bool Contains(unsigned int address, int size)
1129 { 1129 {
1130 return broad.islands[0].Contains(address, size) && 1130 return broad.islands[0].Contains(address, size) &&
1131 mid.Contains(address, size) && 1131 mid.Contains(address, size) &&
1132 narrow.Contains(address, size); 1132 narrow.Contains(address, size);
1133 } 1133 }
1134 }; 1134 };
1135 TieredRegion hookedRegions [LUAMEMHOOK_COUNT]; 1135 TieredRegion hookedRegions [LUAMEMHOOK_COUNT];
1136 1136
1137 static void CalculateMemHookRegions(LuaMemHookType hookType) 1137 static void CalculateMemHookRegions(LuaMemHookType hookType)
1138 { 1138 {
1139 std::vector<unsigned int> hookedBytes; 1139 std::vector<unsigned int> hookedBytes;
1140 // std::map<int, LuaContextInfo*>::iterator iter = luaContextInfo.begin(); 1140 // std::map<int, LuaContextInfo*>::iterator iter = luaContextInfo.begin();
1141 // std::map<int, LuaContextInfo*>::iterator end = luaContextInfo.end(); 1141 // std::map<int, LuaContextInfo*>::iterator end = luaContextInfo.end();
1142 // while(iter != end) 1142 // while(iter != end)
1143 // { 1143 // {
1144 // LuaContextInfo& info = *iter->second; 1144 // LuaContextInfo& info = *iter->second;
1145 if (/*info.*/ numMemHooks) 1145 if (/*info.*/ numMemHooks)
1146 { 1146 {
1147 lua_State *L = LUA /*info.L*/; 1147 lua_State *L = LUA /*info.L*/;
1148 if (L) 1148 if (L)
1149 { 1149 {
1150 lua_settop(L, 0); 1150 lua_settop(L, 0);
1151 lua_getfield(L, LUA_REGISTRYINDEX, luaMemHookTypeStrings[hookType]); 1151 lua_getfield(L, LUA_REGISTRYINDEX, luaMemHookTypeStrings[hookType]);
1152 lua_pushnil(L); 1152 lua_pushnil(L);
1153 while (lua_next(L, -2)) 1153 while (lua_next(L, -2))
1154 { 1154 {
1155 if (lua_isfunction(L, -1)) 1155 if (lua_isfunction(L, -1))
1156 { 1156 {
1157 unsigned int addr = lua_tointeger(L, -2); 1157 unsigned int addr = lua_tointeger(L, -2);
1158 hookedBytes.push_back(addr); 1158 hookedBytes.push_back(addr);
1159 } 1159 }
1160 lua_pop(L, 1); 1160 lua_pop(L, 1);
1161 } 1161 }
1162 lua_settop(L, 0); 1162 lua_settop(L, 0);
1163 } 1163 }
1164 } 1164 }
1165 // ++iter; 1165 // ++iter;
1166 // } 1166 // }
1167 hookedRegions[hookType].Calculate(hookedBytes); 1167 hookedRegions[hookType].Calculate(hookedBytes);
1168 } 1168 }
1169 1169
1170 static void CallRegisteredLuaMemHook_LuaMatch(unsigned int address, int size, unsigned int value, LuaMemHookType hookType) 1170 static void CallRegisteredLuaMemHook_LuaMatch(unsigned int address, int size, unsigned int value, LuaMemHookType hookType)
1171 { 1171 {
1172 // std::map<int, LuaContextInfo*>::iterator iter = luaContextInfo.begin(); 1172 // std::map<int, LuaContextInfo*>::iterator iter = luaContextInfo.begin();
1173 // std::map<int, LuaContextInfo*>::iterator end = luaContextInfo.end(); 1173 // std::map<int, LuaContextInfo*>::iterator end = luaContextInfo.end();
1174 // while(iter != end) 1174 // while(iter != end)
1175 // { 1175 // {
1176 // LuaContextInfo& info = *iter->second; 1176 // LuaContextInfo& info = *iter->second;
1177 if (/*info.*/ numMemHooks) 1177 if (/*info.*/ numMemHooks)
1178 { 1178 {
1179 lua_State *L = LUA /*info.L*/; 1179 lua_State *L = LUA /*info.L*/;
1180 if (L /* && !info.panic*/) 1180 if (L /* && !info.panic*/)
1181 { 1181 {
1182 #ifdef USE_INFO_STACK 1182 #ifdef USE_INFO_STACK
1183 infoStack.insert(infoStack.begin(), &info); 1183 infoStack.insert(infoStack.begin(), &info);
1184 struct Scope { ~Scope(){ infoStack. erase(infoStack.begin()); } } scope; 1184 struct Scope { ~Scope(){ infoStack. erase(infoStack.begin()); } } scope;
1185 #endif 1185 #endif
1186 lua_settop(L, 0); 1186 lua_settop(L, 0);
1187 lua_getfield(L, LUA_REGISTRYINDEX, luaMemHookTypeStrings[hookType]); 1187 lua_getfield(L, LUA_REGISTRYINDEX, luaMemHookTypeStrings[hookType]);
1188 for (int i = address; i != address + size; i++) 1188 for (int i = address; i != address + size; i++)
1189 { 1189 {
1190 lua_rawgeti(L, -1, i); 1190 lua_rawgeti(L, -1, i);
1191 if (lua_isfunction(L, -1)) 1191 if (lua_isfunction(L, -1))
1192 { 1192 {
1193 bool wasRunning = (luaRunning != 0) /*info.running*/; 1193 bool wasRunning = (luaRunning != 0) /*info.running*/;
1194 luaRunning /*info.running*/ = true; 1194 luaRunning /*info.running*/ = true;
1195 //RefreshScriptSpeedStatus(); 1195 //RefreshScriptSpeedStatus();
1196 lua_pushinteger(L, address); 1196 lua_pushinteger(L, address);
1197 lua_pushinteger(L, size); 1197 lua_pushinteger(L, size);
1198 int errorcode = lua_pcall(L, 2, 0, 0); 1198 int errorcode = lua_pcall(L, 2, 0, 0);
1199 luaRunning /*info.running*/ = wasRunning; 1199 luaRunning /*info.running*/ = wasRunning;
1200 //RefreshScriptSpeedStatus(); 1200 //RefreshScriptSpeedStatus();
1201 if (errorcode) 1201 if (errorcode)
1202 { 1202 {
1203 HandleCallbackError(L); 1203 HandleCallbackError(L);
1204 //int uid = iter->first; 1204 //int uid = iter->first;
1205 //HandleCallbackError(L,info,uid,true); 1205 //HandleCallbackError(L,info,uid,true);
1206 } 1206 }
1207 break; 1207 break;
1208 } 1208 }
1209 else 1209 else
1210 { 1210 {
1211 lua_pop(L, 1); 1211 lua_pop(L, 1);
1212 } 1212 }
1213 } 1213 }
1214 lua_settop(L, 0); 1214 lua_settop(L, 0);
1215 } 1215 }
1216 } 1216 }
1217 // ++iter; 1217 // ++iter;
1218 // } 1218 // }
1219 } 1219 }
1220 1220
1221 void CallRegisteredLuaMemHook(unsigned int address, int size, unsigned int value, LuaMemHookType hookType) 1221 void CallRegisteredLuaMemHook(unsigned int address, int size, unsigned int value, LuaMemHookType hookType)
1222 { 1222 {
1223 // performance critical! (called VERY frequently) 1223 // performance critical! (called VERY frequently)
1224 // I suggest timing a large number of calls to this function in Release if you change anything in here, 1224 // I suggest timing a large number of calls to this function in Release if you change anything in here,
1225 // before and after, because even the most innocent change can make it become 30% to 400% slower. 1225 // before and after, because even the most innocent change can make it become 30% to 400% slower.
1226 // a good amount to test is: 100000000 calls with no hook set, and another 100000000 with a hook set. 1226 // a good amount to test is: 100000000 calls with no hook set, and another 100000000 with a hook set.
1227 // (on my system that consistently took 200 ms total in the former case and 350 ms total in the latter 1227 // (on my system that consistently took 200 ms total in the former case and 350 ms total in the latter
1228 // case) 1228 // case)
1229 if (hookedRegions[hookType].NotEmpty()) 1229 if (hookedRegions[hookType].NotEmpty())
1230 { 1230 {
1231 //if((hookType <= LUAMEMHOOK_EXEC) && (address >= 0xE00000)) 1231 //if((hookType <= LUAMEMHOOK_EXEC) && (address >= 0xE00000))
1232 // address |= 0xFF0000; // account for mirroring of RAM 1232 // address |= 0xFF0000; // account for mirroring of RAM
1233 if (hookedRegions[hookType].Contains(address, size)) 1233 if (hookedRegions[hookType].Contains(address, size))
1234 CallRegisteredLuaMemHook_LuaMatch(address, size, value, hookType); // something has hooked this 1234 CallRegisteredLuaMemHook_LuaMatch(address, size, value, hookType); // something has hooked this
1235 // specific address 1235 // specific address
1236 } 1236 }
1237 } 1237 }
1238 1238
1239 static int memory_registerHook(lua_State *L, LuaMemHookType hookType, int defaultSize) 1239 static int memory_registerHook(lua_State *L, LuaMemHookType hookType, int defaultSize)
1240 { 1240 {
1241 // get first argument: address 1241 // get first argument: address
1242 unsigned int addr = luaL_checkinteger(L, 1); 1242 unsigned int addr = luaL_checkinteger(L, 1);
1243 //if((addr & ~0xFFFFFF) == ~0xFFFFFF) 1243 //if((addr & ~0xFFFFFF) == ~0xFFFFFF)
1244 // addr &= 0xFFFFFF; 1244 // addr &= 0xFFFFFF;
1245 1245
1246 // get optional second argument: size 1246 // get optional second argument: size
1247 int size = defaultSize; 1247 int size = defaultSize;
1248 int funcIdx = 2; 1248 int funcIdx = 2;
1249 if (lua_isnumber(L, 2)) 1249 if (lua_isnumber(L, 2))
1250 { 1250 {
1251 size = luaL_checkinteger(L, 2); 1251 size = luaL_checkinteger(L, 2);
1252 if (size < 0) 1252 if (size < 0)
1253 { 1253 {
1254 size = -size; 1254 size = -size;
1255 addr -= size; 1255 addr -= size;
1256 } 1256 }
1257 funcIdx++; 1257 funcIdx++;
1258 } 1258 }
1259 1259
1260 // check last argument: callback function 1260 // check last argument: callback function
1261 bool clearing = lua_isnil(L, funcIdx); 1261 bool clearing = lua_isnil(L, funcIdx);
1262 if (!clearing) 1262 if (!clearing)
1263 luaL_checktype(L, funcIdx, LUA_TFUNCTION); 1263 luaL_checktype(L, funcIdx, LUA_TFUNCTION);
1264 lua_settop(L, funcIdx); 1264 lua_settop(L, funcIdx);
1265 1265
1266 // get the address-to-callback table for this hook type of the current script 1266 // get the address-to-callback table for this hook type of the current script
1267 lua_getfield(L, LUA_REGISTRYINDEX, luaMemHookTypeStrings[hookType]); 1267 lua_getfield(L, LUA_REGISTRYINDEX, luaMemHookTypeStrings[hookType]);
1268 1268
1269 // count how many callback functions we'll be displacing 1269 // count how many callback functions we'll be displacing
1270 int numFuncsAfter = clearing ? 0 : size; 1270 int numFuncsAfter = clearing ? 0 : size;
1271 int numFuncsBefore = 0; 1271 int numFuncsBefore = 0;
1272 for (unsigned int i = addr; i != addr + size; i++) 1272 for (unsigned int i = addr; i != addr + size; i++)
1273 { 1273 {
1274 lua_rawgeti(L, -1, i); 1274 lua_rawgeti(L, -1, i);
1275 if (lua_isfunction(L, -1)) 1275 if (lua_isfunction(L, -1))
1276 numFuncsBefore++; 1276 numFuncsBefore++;
1277 lua_pop(L, 1); 1277 lua_pop(L, 1);
1278 } 1278 }
1279 1279
1280 // put the callback function in the address slots 1280 // put the callback function in the address slots
1281 for (unsigned int i = addr; i != addr + size; i++) 1281 for (unsigned int i = addr; i != addr + size; i++)
1282 { 1282 {
1283 lua_pushvalue(L, -2); 1283 lua_pushvalue(L, -2);
1284 lua_rawseti(L, -2, i); 1284 lua_rawseti(L, -2, i);
1285 } 1285 }
1286 1286
1287 // adjust the count of active hooks 1287 // adjust the count of active hooks
1288 //LuaContextInfo& info = GetCurrentInfo(); 1288 //LuaContextInfo& info = GetCurrentInfo();
1289 /*info.*/ numMemHooks += numFuncsAfter - numFuncsBefore; 1289 /*info.*/ numMemHooks += numFuncsAfter - numFuncsBefore;
1290 1290
1291 // re-cache regions of hooked memory across all scripts 1291 // re-cache regions of hooked memory across all scripts
1292 CalculateMemHookRegions(hookType); 1292 CalculateMemHookRegions(hookType);
1293 1293
1294 //StopScriptIfFinished(luaStateToUIDMap[L]); 1294 //StopScriptIfFinished(luaStateToUIDMap[L]);
1295 return 0; 1295 return 0;
1296 } 1296 }
1297 1297
1298 LuaMemHookType MatchHookTypeToCPU(lua_State *L, LuaMemHookType hookType) 1298 LuaMemHookType MatchHookTypeToCPU(lua_State *L, LuaMemHookType hookType)
1299 { 1299 {
1300 int cpuID = 0; 1300 int cpuID = 0;
1301 1301
1302 int cpunameIndex = 0; 1302 int cpunameIndex = 0;
1303 if (lua_type(L, 2) == LUA_TSTRING) 1303 if (lua_type(L, 2) == LUA_TSTRING)
1304 cpunameIndex = 2; 1304 cpunameIndex = 2;
1305 else if (lua_type(L, 3) == LUA_TSTRING) 1305 else if (lua_type(L, 3) == LUA_TSTRING)
1306 cpunameIndex = 3; 1306 cpunameIndex = 3;
1307 1307
1308 if (cpunameIndex) 1308 if (cpunameIndex)
1309 { 1309 {
1310 const char *cpuName = lua_tostring(L, cpunameIndex); 1310 const char *cpuName = lua_tostring(L, cpunameIndex);
1311 if (!stricmp(cpuName, "sub")) 1311 if (!stricmp(cpuName, "sub"))
1312 cpuID = 1; 1312 cpuID = 1;
1313 lua_remove(L, cpunameIndex); 1313 lua_remove(L, cpunameIndex);
1314 } 1314 }
1315 1315
1316 switch (cpuID) 1316 switch (cpuID)
1317 { 1317 {
1318 case 0: 1318 case 0:
1319 return hookType; 1319 return hookType;
1320 1320
1321 case 1: 1321 case 1:
1322 switch (hookType) 1322 switch (hookType)
1323 { 1323 {
1324 case LUAMEMHOOK_WRITE: 1324 case LUAMEMHOOK_WRITE:
1325 return LUAMEMHOOK_WRITE_SUB; 1325 return LUAMEMHOOK_WRITE_SUB;
1326 case LUAMEMHOOK_READ: 1326 case LUAMEMHOOK_READ:
1327 return LUAMEMHOOK_READ_SUB; 1327 return LUAMEMHOOK_READ_SUB;
1328 case LUAMEMHOOK_EXEC: 1328 case LUAMEMHOOK_EXEC:
1329 return LUAMEMHOOK_EXEC_SUB; 1329 return LUAMEMHOOK_EXEC_SUB;
1330 } 1330 }
1331 } 1331 }
1332 return hookType; 1332 return hookType;
1333 } 1333 }
1334 1334
1335 static int memory_registerwrite(lua_State *L) 1335 static int memory_registerwrite(lua_State *L)
1336 { 1336 {
1337 return memory_registerHook(L, MatchHookTypeToCPU(L, LUAMEMHOOK_WRITE), 1); 1337 return memory_registerHook(L, MatchHookTypeToCPU(L, LUAMEMHOOK_WRITE), 1);
1338 } 1338 }
1339 1339
1340 static int memory_registerread(lua_State *L) 1340 static int memory_registerread(lua_State *L)
1341 { 1341 {
1342 return memory_registerHook(L, MatchHookTypeToCPU(L, LUAMEMHOOK_READ), 1); 1342 return memory_registerHook(L, MatchHookTypeToCPU(L, LUAMEMHOOK_READ), 1);
1343 } 1343 }
1344 1344
1345 static int memory_registerexec(lua_State *L) 1345 static int memory_registerexec(lua_State *L)
1346 { 1346 {
1347 return memory_registerHook(L, MatchHookTypeToCPU(L, LUAMEMHOOK_EXEC), 1); 1347 return memory_registerHook(L, MatchHookTypeToCPU(L, LUAMEMHOOK_EXEC), 1);
1348 } 1348 }
1349 1349
1350 //int vba.lagcount 1350 //int vba.lagcount
1351 // 1351 //
1352 1352
1353 //Returns the lagcounter variable 1353 //Returns the lagcounter variable
1354 static int vba_getlagcount(lua_State *L) 1354 static int vba_getlagcount(lua_State *L)
1355 { 1355 {
1356 lua_pushinteger(L, systemCounters.lagCount); 1356 lua_pushinteger(L, systemCounters.lagCount);
1357 return 1; 1357 return 1;
1358 } 1358 }
1359 1359
1360 //int vba.lagged 1360 //int vba.lagged
1361 // 1361 //
1362 //Returns true if the current frame is a lag frame 1362 //Returns true if the current frame is a lag frame
1363 static int vba_lagged(lua_State *L) 1363 static int vba_lagged(lua_State *L)
1364 { 1364 {
1365 lua_pushboolean(L, systemCounters.laggedLast); 1365 lua_pushboolean(L, systemCounters.laggedLast);
1366 return 1; 1366 return 1;
1367 } 1367 }
1368 1368
1369 // boolean vba.emulating() 1369 // boolean vba.emulating()
1370 int vba_emulating(lua_State *L) 1370 int vba_emulating(lua_State *L)
1371 { 1371 {
1372 lua_pushboolean(L, systemIsEmulating()); 1372 lua_pushboolean(L, systemIsEmulating());
1373 return 1; 1373 return 1;
1374 } 1374 }
1375 1375
1376 int movie_isactive(lua_State *L) 1376 int movie_isactive(lua_State *L)
1377 { 1377 {
1378 lua_pushboolean(L, VBAMovieActive()); 1378 lua_pushboolean(L, VBAMovieActive());
1379 return 1; 1379 return 1;
1380 } 1380 }
1381 1381
1382 int movie_isrecording(lua_State *L) 1382 int movie_isrecording(lua_State *L)
1383 { 1383 {
1384 lua_pushboolean(L, VBAMovieRecording()); 1384 lua_pushboolean(L, VBAMovieRecording());
1385 return 1; 1385 return 1;
1386 } 1386 }
1387 1387
1388 int movie_isplaying(lua_State *L) 1388 int movie_isplaying(lua_State *L)
1389 { 1389 {
1390 lua_pushboolean(L, VBAMoviePlaying()); 1390 lua_pushboolean(L, VBAMoviePlaying());
1391 return 1; 1391 return 1;
1392 } 1392 }
1393 1393
1394 int movie_getlength(lua_State *L) 1394 int movie_getlength(lua_State *L)
1395 { 1395 {
1396 if (VBAMovieActive()) 1396 if (VBAMovieActive())
1397 lua_pushinteger(L, VBAMovieGetLength()); 1397 lua_pushinteger(L, VBAMovieGetLength());
1398 else 1398 else
1399 lua_pushinteger(L, 0); 1399 lua_pushinteger(L, 0);
1400 return 1; 1400 return 1;
1401 } 1401 }
1402 1402
1403 static int memory_readbyte(lua_State *L) 1403 static int memory_readbyte(lua_State *L)
1404 { 1404 {
1405 u32 addr; 1405 u32 addr;
1406 u8 val; 1406 u8 val;
1407 1407
1408 addr = luaL_checkinteger(L, 1); 1408 addr = luaL_checkinteger(L, 1);
1409 if (systemIsRunningGBA()) 1409 if (systemIsRunningGBA())
1410 { 1410 {
1411 val = CPUReadByteQuick(addr); 1411 val = CPUReadByteQuick(addr);
1412 } 1412 }
1413 else 1413 else
1414 { 1414 {
1415 val = gbReadMemoryQuick8(addr); 1415 val = gbReadMemoryQuick8(addr);
1416 } 1416 }
1417 1417
1418 lua_pushinteger(L, val); 1418 lua_pushinteger(L, val);
1419 return 1; 1419 return 1;
1420 } 1420 }
1421 1421
1422 static int memory_readbytesigned(lua_State *L) 1422 static int memory_readbytesigned(lua_State *L)
1423 { 1423 {
1424 u32 addr; 1424 u32 addr;
1425 s8 val; 1425 s8 val;
1426 1426
1427 addr = luaL_checkinteger(L, 1); 1427 addr = luaL_checkinteger(L, 1);
1428 if (systemIsRunningGBA()) 1428 if (systemIsRunningGBA())
1429 { 1429 {
1430 val = (s8) CPUReadByteQuick(addr); 1430 val = (s8) CPUReadByteQuick(addr);
1431 } 1431 }
1432 else 1432 else
1433 { 1433 {
1434 val = (s8) gbReadMemoryQuick8(addr); 1434 val = (s8) gbReadMemoryQuick8(addr);
1435 } 1435 }
1436 1436
1437 lua_pushinteger(L, val); 1437 lua_pushinteger(L, val);
1438 return 1; 1438 return 1;
1439 } 1439 }
1440 1440
1441 static int memory_readword(lua_State *L) 1441 static int memory_readword(lua_State *L)
1442 { 1442 {
1443 u32 addr; 1443 u32 addr;
1444 u16 val; 1444 u16 val;
1445 1445
1446 addr = luaL_checkinteger(L, 1); 1446 addr = luaL_checkinteger(L, 1);
1447 if (systemIsRunningGBA()) 1447 if (systemIsRunningGBA())
1448 { 1448 {
1449 val = CPUReadHalfWordQuick(addr); 1449 val = CPUReadHalfWordQuick(addr);
1450 } 1450 }
1451 else 1451 else
1452 { 1452 {
1453 val = gbReadMemoryQuick16(addr & 0x0000FFFF); 1453 val = gbReadMemoryQuick16(addr & 0x0000FFFF);
1454 } 1454 }
1455 1455
1456 lua_pushinteger(L, val); 1456 lua_pushinteger(L, val);
1457 return 1; 1457 return 1;
1458 } 1458 }
1459 1459
1460 static int memory_readwordsigned(lua_State *L) 1460 static int memory_readwordsigned(lua_State *L)
1461 { 1461 {
1462 u32 addr; 1462 u32 addr;
1463 s16 val; 1463 s16 val;
1464 1464
1465 addr = luaL_checkinteger(L, 1); 1465 addr = luaL_checkinteger(L, 1);
1466 if (systemIsRunningGBA()) 1466 if (systemIsRunningGBA())
1467 { 1467 {
1468 val = (s16) CPUReadHalfWordQuick(addr); 1468 val = (s16) CPUReadHalfWordQuick(addr);
1469 } 1469 }
1470 else 1470 else
1471 { 1471 {
1472 val = (s16) gbReadMemoryQuick16(addr); 1472 val = (s16) gbReadMemoryQuick16(addr);
1473 } 1473 }
1474 1474
1475 lua_pushinteger(L, val); 1475 lua_pushinteger(L, val);
1476 return 1; 1476 return 1;
1477 } 1477 }
1478 1478
1479 static int memory_readdword(lua_State *L) 1479 static int memory_readdword(lua_State *L)
1480 { 1480 {
1481 u32 addr; 1481 u32 addr;
1482 u32 val; 1482 u32 val;
1483 1483
1484 addr = luaL_checkinteger(L, 1); 1484 addr = luaL_checkinteger(L, 1);
1485 if (systemIsRunningGBA()) 1485 if (systemIsRunningGBA())
1486 { 1486 {
1487 val = CPUReadMemoryQuick(addr); 1487 val = CPUReadMemoryQuick(addr);
1488 } 1488 }
1489 else 1489 else
1490 { 1490 {
1491 val = gbReadMemoryQuick32(addr & 0x0000FFFF); 1491 val = gbReadMemoryQuick32(addr & 0x0000FFFF);
1492 } 1492 }
1493 1493
1494 // lua_pushinteger doesn't work properly for 32bit system, does it? 1494 // lua_pushinteger doesn't work properly for 32bit system, does it?
1495 if (val >= 0x80000000 && sizeof(int) <= 4) 1495 if (val >= 0x80000000 && sizeof(int) <= 4)
1496 lua_pushnumber(L, val); 1496 lua_pushnumber(L, val);
1497 else 1497 else
1498 lua_pushinteger(L, val); 1498 lua_pushinteger(L, val);
1499 return 1; 1499 return 1;
1500 } 1500 }
1501 1501
1502 static int memory_readdwordsigned(lua_State *L) 1502 static int memory_readdwordsigned(lua_State *L)
1503 { 1503 {
1504 u32 addr; 1504 u32 addr;
1505 s32 val; 1505 s32 val;
1506 1506
1507 addr = luaL_checkinteger(L, 1); 1507 addr = luaL_checkinteger(L, 1);
1508 if (systemIsRunningGBA()) 1508 if (systemIsRunningGBA())
1509 { 1509 {
1510 val = (s32) CPUReadMemoryQuick(addr); 1510 val = (s32) CPUReadMemoryQuick(addr);
1511 } 1511 }
1512 else 1512 else
1513 { 1513 {
1514 val = (s32) gbReadMemoryQuick32(addr); 1514 val = (s32) gbReadMemoryQuick32(addr);
1515 } 1515 }
1516 1516
1517 lua_pushinteger(L, val); 1517 lua_pushinteger(L, val);
1518 return 1; 1518 return 1;
1519 } 1519 }
1520 1520
1521 static int memory_readbyterange(lua_State *L) 1521 static int memory_readbyterange(lua_State *L)
1522 { 1522 {
1523 uint32 address = luaL_checkinteger(L, 1); 1523 uint32 address = luaL_checkinteger(L, 1);
1524 int length = luaL_checkinteger(L, 2); 1524 int length = luaL_checkinteger(L, 2);
1525 1525
1526 if (length < 0) 1526 if (length < 0)
1527 { 1527 {
1528 address += length; 1528 address += length;
1529 length = -length; 1529 length = -length;
1530 } 1530 }
1531 1531
1532 // push the array 1532 // push the array
1533 lua_createtable(L, abs(length), 0); 1533 lua_createtable(L, abs(length), 0);
1534 1534
1535 // put all the values into the (1-based) array 1535 // put all the values into the (1-based) array
1536 for (int a = address, n = 1; n <= length; a++, n++) 1536 for (int a = address, n = 1; n <= length; a++, n++)
1537 { 1537 {
1538 unsigned char value; 1538 unsigned char value;
1539 1539
1540 if (systemIsRunningGBA()) 1540 if (systemIsRunningGBA())
1541 { 1541 {
1542 value = CPUReadByteQuick(a); 1542 value = CPUReadByteQuick(a);
1543 } 1543 }
1544 else 1544 else
1545 { 1545 {
1546 value = gbReadMemoryQuick8(a); 1546 value = gbReadMemoryQuick8(a);
1547 } 1547 }
1548 1548
1549 lua_pushinteger(L, value); 1549 lua_pushinteger(L, value);
1550 lua_rawseti(L, -2, n); 1550 lua_rawseti(L, -2, n);
1551 } 1551 }
1552 1552
1553 return 1; 1553 return 1;
1554 } 1554 }
1555 1555
1556 static int memory_writebyte(lua_State *L) 1556 static int memory_writebyte(lua_State *L)
1557 { 1557 {
1558 u32 addr; 1558 u32 addr;
1559 int val; 1559 int val;
1560 1560
1561 addr = luaL_checkinteger(L, 1); 1561 addr = luaL_checkinteger(L, 1);
1562 val = luaL_checkinteger(L, 2); 1562 val = luaL_checkinteger(L, 2);
1563 if (systemIsRunningGBA()) 1563 if (systemIsRunningGBA())
1564 { 1564 {
1565 CPUWriteByteQuick(addr, val); 1565 CPUWriteByteQuick(addr, val);
1566 } 1566 }
1567 else 1567 else
1568 { 1568 {
1569 gbWriteMemoryQuick8(addr, val); 1569 gbWriteMemoryQuick8(addr, val);
1570 } 1570 }
1571 1571
1572 CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE); 1572 CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE);
1573 return 0; 1573 return 0;
1574 } 1574 }
1575 1575
1576 static int memory_writeword(lua_State *L) 1576 static int memory_writeword(lua_State *L)
1577 { 1577 {
1578 u32 addr; 1578 u32 addr;
1579 int val; 1579 int val;
1580 1580
1581 addr = luaL_checkinteger(L, 1); 1581 addr = luaL_checkinteger(L, 1);
1582 val = luaL_checkinteger(L, 2); 1582 val = luaL_checkinteger(L, 2);
1583 if (systemIsRunningGBA()) 1583 if (systemIsRunningGBA())
1584 { 1584 {
1585 CPUWriteHalfWordQuick(addr, val); 1585 CPUWriteHalfWordQuick(addr, val);
1586 } 1586 }
1587 else 1587 else
1588 { 1588 {
1589 gbWriteMemoryQuick16(addr, val); 1589 gbWriteMemoryQuick16(addr, val);
1590 } 1590 }
1591 1591
1592 CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE); 1592 CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE);
1593 return 0; 1593 return 0;
1594 } 1594 }
1595 1595
1596 static int memory_writedword(lua_State *L) 1596 static int memory_writedword(lua_State *L)
1597 { 1597 {
1598 u32 addr; 1598 u32 addr;
1599 int val; 1599 int val;
1600 1600
1601 addr = luaL_checkinteger(L, 1); 1601 addr = luaL_checkinteger(L, 1);
1602 val = luaL_checkinteger(L, 2); 1602 val = luaL_checkinteger(L, 2);
1603 if (systemIsRunningGBA()) 1603 if (systemIsRunningGBA())
1604 { 1604 {
1605 CPUWriteMemoryQuick(addr, val); 1605 CPUWriteMemoryQuick(addr, val);
1606 } 1606 }
1607 else 1607 else
1608 { 1608 {
1609 gbWriteMemoryQuick32(addr, val); 1609 gbWriteMemoryQuick32(addr, val);
1610 } 1610 }
1611 1611
1612 CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE); 1612 CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE);
1613 return 0; 1613 return 0;
1614 } 1614 }
1615 1615
1616 static int memory_gbromreadbyte(lua_State *L) 1616 static int memory_gbromreadbyte(lua_State *L)
1617 { 1617 {
1618 u32 addr; 1618 u32 addr;
1619 u8 val; 1619 u8 val;
1620 1620
1621 addr = luaL_checkinteger(L, 1); 1621 addr = luaL_checkinteger(L, 1);
1622 if (systemIsRunningGBA()) 1622 if (systemIsRunningGBA())
1623 { 1623 {
1624 lua_pushnil(L); 1624 lua_pushnil(L);
1625 return 1; 1625 return 1;
1626 } 1626 }
1627 else 1627 else
1628 { 1628 {
1629 val = gbReadROMQuick8(addr); 1629 val = gbReadROMQuick8(addr);
1630 } 1630 }
1631 1631
1632 lua_pushinteger(L, val); 1632 lua_pushinteger(L, val);
1633 return 1; 1633 return 1;
1634 } 1634 }
1635 1635
1636 static int memory_gbromreadbytesigned(lua_State *L) 1636 static int memory_gbromreadbytesigned(lua_State *L)
1637 { 1637 {
1638 u32 addr; 1638 u32 addr;
1639 s8 val; 1639 s8 val;
1640 1640
1641 addr = luaL_checkinteger(L, 1); 1641 addr = luaL_checkinteger(L, 1);
1642 if (systemIsRunningGBA()) 1642 if (systemIsRunningGBA())
1643 { 1643 {
1644 lua_pushnil(L); 1644 lua_pushnil(L);
1645 return 1; 1645 return 1;
1646 } 1646 }
1647 else 1647 else
1648 { 1648 {
1649 val = (s8) gbReadROMQuick8(addr); 1649 val = (s8) gbReadROMQuick8(addr);
1650 } 1650 }
1651 1651
1652 lua_pushinteger(L, val); 1652 lua_pushinteger(L, val);
1653 return 1; 1653 return 1;
1654 } 1654 }
1655 1655
1656 static int memory_gbromreadword(lua_State *L) 1656 static int memory_gbromreadword(lua_State *L)
1657 { 1657 {
1658 u32 addr; 1658 u32 addr;
1659 u16 val; 1659 u16 val;
1660 1660
1661 addr = luaL_checkinteger(L, 1); 1661 addr = luaL_checkinteger(L, 1);
1662 if (systemIsRunningGBA()) 1662 if (systemIsRunningGBA())
1663 { 1663 {
1664 lua_pushnil(L); 1664 lua_pushnil(L);
1665 return 1; 1665 return 1;
1666 } 1666 }
1667 else 1667 else
1668 { 1668 {
1669 val = gbReadROMQuick16(addr); 1669 val = gbReadROMQuick16(addr);
1670 } 1670 }
1671 1671
1672 lua_pushinteger(L, val); 1672 lua_pushinteger(L, val);
1673 return 1; 1673 return 1;
1674 } 1674 }
1675 1675
1676 static int memory_gbromreadwordsigned(lua_State *L) 1676 static int memory_gbromreadwordsigned(lua_State *L)
1677 { 1677 {
1678 u32 addr; 1678 u32 addr;
1679 s16 val; 1679 s16 val;
1680 1680
1681 addr = luaL_checkinteger(L, 1); 1681 addr = luaL_checkinteger(L, 1);
1682 if (systemIsRunningGBA()) 1682 if (systemIsRunningGBA())
1683 { 1683 {
1684 lua_pushnil(L); 1684 lua_pushnil(L);
1685 return 1; 1685 return 1;
1686 } 1686 }
1687 else 1687 else
1688 { 1688 {
1689 val = (s16) gbReadROMQuick16(addr); 1689 val = (s16) gbReadROMQuick16(addr);
1690 } 1690 }
1691 1691
1692 lua_pushinteger(L, val); 1692 lua_pushinteger(L, val);
1693 return 1; 1693 return 1;
1694 } 1694 }
1695 1695
1696 static int memory_gbromreaddword(lua_State *L) 1696 static int memory_gbromreaddword(lua_State *L)
1697 { 1697 {
1698 u32 addr; 1698 u32 addr;
1699 u32 val; 1699 u32 val;
1700 1700
1701 addr = luaL_checkinteger(L, 1); 1701 addr = luaL_checkinteger(L, 1);
1702 if (systemIsRunningGBA()) 1702 if (systemIsRunningGBA())
1703 { 1703 {
1704 lua_pushnil(L); 1704 lua_pushnil(L);
1705 return 1; 1705 return 1;
1706 } 1706 }
1707 else 1707 else
1708 { 1708 {
1709 val = gbReadROMQuick32(addr); 1709 val = gbReadROMQuick32(addr);
1710 } 1710 }
1711 1711
1712 // lua_pushinteger doesn't work properly for 32bit system, does it? 1712 // lua_pushinteger doesn't work properly for 32bit system, does it?
1713 if (val >= 0x80000000 && sizeof(int) <= 4) 1713 if (val >= 0x80000000 && sizeof(int) <= 4)
1714 lua_pushnumber(L, val); 1714 lua_pushnumber(L, val);
1715 else 1715 else
1716 lua_pushinteger(L, val); 1716 lua_pushinteger(L, val);
1717 return 1; 1717 return 1;
1718 } 1718 }
1719 1719
1720 static int memory_gbromreaddwordsigned(lua_State *L) 1720 static int memory_gbromreaddwordsigned(lua_State *L)
1721 { 1721 {
1722 u32 addr; 1722 u32 addr;
1723 s32 val; 1723 s32 val;
1724 1724
1725 addr = luaL_checkinteger(L, 1); 1725 addr = luaL_checkinteger(L, 1);
1726 if (systemIsRunningGBA()) 1726 if (systemIsRunningGBA())
1727 { 1727 {
1728 lua_pushnil(L); 1728 lua_pushnil(L);
1729 return 1; 1729 return 1;
1730 } 1730 }
1731 else 1731 else
1732 { 1732 {
1733 val = (s32) gbReadROMQuick32(addr); 1733 val = (s32) gbReadROMQuick32(addr);
1734 } 1734 }
1735 1735
1736 lua_pushinteger(L, val); 1736 lua_pushinteger(L, val);
1737 return 1; 1737 return 1;
1738 } 1738 }
1739 1739
1740 static int memory_gbromreadbyterange(lua_State *L) 1740 static int memory_gbromreadbyterange(lua_State *L)
1741 { 1741 {
1742 uint32 address = luaL_checkinteger(L, 1); 1742 uint32 address = luaL_checkinteger(L, 1);
1743 int length = luaL_checkinteger(L, 2); 1743 int length = luaL_checkinteger(L, 2);
1744 1744
1745 if (length < 0) 1745 if (length < 0)
1746 { 1746 {
1747 address += length; 1747 address += length;
1748 length = -length; 1748 length = -length;
1749 } 1749 }
1750 1750
1751 // push the array 1751 // push the array
1752 lua_createtable(L, abs(length), 0); 1752 lua_createtable(L, abs(length), 0);
1753 1753
1754 // put all the values into the (1-based) array 1754 // put all the values into the (1-based) array
1755 for (int a = address, n = 1; n <= length; a++, n++) 1755 for (int a = address, n = 1; n <= length; a++, n++)
1756 { 1756 {
1757 unsigned char value; 1757 unsigned char value;
1758 1758
1759 if (systemIsRunningGBA()) 1759 if (systemIsRunningGBA())
1760 { 1760 {
1761 lua_pushnil(L); 1761 lua_pushnil(L);
1762 return 1; 1762 return 1;
1763 } 1763 }
1764 else 1764 else
1765 { 1765 {
1766 value = gbReadROMQuick8(a); 1766 value = gbReadROMQuick8(a);
1767 } 1767 }
1768 1768
1769 lua_pushinteger(L, value); 1769 lua_pushinteger(L, value);
1770 lua_rawseti(L, -2, n); 1770 lua_rawseti(L, -2, n);
1771 } 1771 }
1772 1772
1773 return 1; 1773 return 1;
1774 } 1774 }
1775 1775
1776 // table joypad.get(int which = 1) 1776 // table joypad.get(int which = 1)
1777 // 1777 //
1778 // Reads the joypads as inputted by the user. 1778 // Reads the joypads as inputted by the user.
1779 static int joy_get_internal(lua_State *L, bool reportUp, bool reportDown) 1779 static int joy_get_internal(lua_State *L, bool reportUp, bool reportDown)
1780 { 1780 {
1781 // Reads the joypads as inputted by the user 1781 // Reads the joypads as inputted by the user
1782 int which = luaL_checkinteger(L, 1); 1782 int which = luaL_checkinteger(L, 1);
1783 1783
1784 if (which < 0 || which > 4) 1784 if (which < 0 || which > 4)
1785 { 1785 {
1786 luaL_error(L, "Invalid input port (valid range 0-4, specified %d)", which); 1786 luaL_error(L, "Invalid input port (valid range 0-4, specified %d)", which);
1787 } 1787 }
1788 1788
1789 uint32 buttons = systemGetOriginalJoypad(which - 1, false); 1789 uint32 buttons = systemGetOriginalJoypad(which - 1, false);
1790 1790
1791 lua_newtable(L); 1791 lua_newtable(L);
1792 1792
1793 int i; 1793 int i;
1794 for (i = 0; i < 10; i++) 1794 for (i = 0; i < 10; i++)
1795 { 1795 {
1796 bool pressed = (buttons & (1 << i)) != 0; 1796 bool pressed = (buttons & (1 << i)) != 0;
1797 if ((pressed && reportDown) || (!pressed && reportUp)) 1797 if ((pressed && reportDown) || (!pressed && reportUp))
1798 { 1798 {
1799 lua_pushboolean(L, pressed); 1799 lua_pushboolean(L, pressed);
1800 lua_setfield(L, -2, button_mappings[i]); 1800 lua_setfield(L, -2, button_mappings[i]);
1801 } 1801 }
1802 } 1802 }
1803 1803
1804 return 1; 1804 return 1;
1805 } 1805 }
1806 1806
1807 // joypad.get(which) 1807 // joypad.get(which)
1808 // returns a table of every game button, 1808 // returns a table of every game button,
1809 // true meaning currently-held and false meaning not-currently-held 1809 // true meaning currently-held and false meaning not-currently-held
1810 // (as of last frame boundary) 1810 // (as of last frame boundary)
1811 // this WILL read input from a currently-playing movie 1811 // this WILL read input from a currently-playing movie
1812 static int joypad_get(lua_State *L) 1812 static int joypad_get(lua_State *L)
1813 { 1813 {
1814 return joy_get_internal(L, true, true); 1814 return joy_get_internal(L, true, true);
1815 } 1815 }
1816 1816
1817 // joypad.getdown(which) 1817 // joypad.getdown(which)
1818 // returns a table of every game button that is currently held 1818 // returns a table of every game button that is currently held
1819 static int joypad_getdown(lua_State *L) 1819 static int joypad_getdown(lua_State *L)
1820 { 1820 {
1821 return joy_get_internal(L, false, true); 1821 return joy_get_internal(L, false, true);
1822 } 1822 }
1823 1823
1824 // joypad.getup(which) 1824 // joypad.getup(which)
1825 // returns a table of every game button that is not currently held 1825 // returns a table of every game button that is not currently held
1826 static int joypad_getup(lua_State *L) 1826 static int joypad_getup(lua_State *L)
1827 { 1827 {
1828 return joy_get_internal(L, true, false); 1828 return joy_get_internal(L, true, false);
1829 } 1829 }
1830 1830
1831 // joypad.set(int which, table buttons) 1831 // joypad.set(int which, table buttons)
1832 // 1832 //
1833 // Sets the given buttons to be pressed during the next 1833 // Sets the given buttons to be pressed during the next
1834 // frame advance. The table should have the right 1834 // frame advance. The table should have the right
1835 1835
1836 // keys (no pun intended) set. 1836 // keys (no pun intended) set.
1837 static int joypad_set(lua_State *L) 1837 static int joypad_set(lua_State *L)
1838 { 1838 {
1839 // Which joypad we're tampering with 1839 // Which joypad we're tampering with
1840 int which = luaL_checkinteger(L, 1); 1840 int which = luaL_checkinteger(L, 1);
1841 if (which < 0 || which > 4) 1841 if (which < 0 || which > 4)
1842 { 1842 {
1843 luaL_error(L, "Invalid output port (valid range 0-4, specified %d)", which); 1843 luaL_error(L, "Invalid output port (valid range 0-4, specified %d)", which);
1844 } 1844 }
1845 1845
1846 if (which == 0) 1846 if (which == 0)
1847 which = systemGetDefaultJoypad(); 1847 which = systemGetDefaultJoypad();
1848 1848
1849 // And the table of buttons. 1849 // And the table of buttons.
1850 luaL_checktype(L, 2, LUA_TTABLE); 1850 luaL_checktype(L, 2, LUA_TTABLE);
1851 1851
1852 // Set up for taking control of the indicated controller 1852 // Set up for taking control of the indicated controller
1853 lua_joypads_used |= 1 << (which - 1); 1853 lua_joypads_used |= 1 << (which - 1);
1854 lua_joypads[which - 1] = 0; 1854 lua_joypads[which - 1] = 0;
1855 1855
1856 for (int i = 0; i < 10; i++) 1856 for (int i = 0; i < 10; i++)
1857 { 1857 {
1858 const char *name = button_mappings[i]; 1858 const char *name = button_mappings[i];
1859 lua_getfield(L, 2, name); 1859 lua_getfield(L, 2, name);
1860 if (!lua_isnil(L, -1)) 1860 if (!lua_isnil(L, -1))
1861 { 1861 {
1862 bool pressed = lua_toboolean(L, -1) != 0; 1862 bool pressed = lua_toboolean(L, -1) != 0;
1863 if (pressed) 1863 if (pressed)
1864 lua_joypads[which - 1] |= 1 << i; 1864 lua_joypads[which - 1] |= 1 << i;
1865 else 1865 else
1866 lua_joypads[which - 1] &= ~(1 << i); 1866 lua_joypads[which - 1] &= ~(1 << i);
1867 } 1867 }
1868 lua_pop(L, 1); 1868 lua_pop(L, 1);
1869 } 1869 }
1870 1870
1871 return 0; 1871 return 0;
1872 } 1872 }
1873 1873
1874 // Helper function to convert a savestate object to the filename it represents. 1874 // Helper function to convert a savestate object to the filename it represents.
1875 static const char *savestateobj2filename(lua_State *L, int offset) 1875 static const char *savestateobj2filename(lua_State *L, int offset)
1876 { 1876 {
1877 // First we get the metatable of the indicated object 1877 // First we get the metatable of the indicated object
1878 int result = lua_getmetatable(L, offset); 1878 int result = lua_getmetatable(L, offset);
1879 1879
1880 if (!result) 1880 if (!result)
1881 luaL_error(L, "object not a savestate object"); 1881 luaL_error(L, "object not a savestate object");
1882 1882
1883 // Also check that the type entry is set 1883 // Also check that the type entry is set
1884 lua_getfield(L, -1, "__metatable"); 1884 lua_getfield(L, -1, "__metatable");
1885 if (strcmp(lua_tostring(L, -1), "vba Savestate") != 0) 1885 if (strcmp(lua_tostring(L, -1), "vba Savestate") != 0)
1886 luaL_error(L, "object not a savestate object"); 1886 luaL_error(L, "object not a savestate object");
1887 lua_pop(L, 1); 1887 lua_pop(L, 1);
1888 1888
1889 // Now, get the field we want 1889 // Now, get the field we want
1890 lua_getfield(L, -1, "filename"); 1890 lua_getfield(L, -1, "filename");
1891 1891
1892 // Return it 1892 // Return it
1893 return lua_tostring(L, -1); 1893 return lua_tostring(L, -1);
1894 } 1894 }
1895 1895
1896 // Helper function for garbage collection. 1896 // Helper function for garbage collection.
1897 static int savestate_gc(lua_State *L) 1897 static int savestate_gc(lua_State *L)
1898 { 1898 {
1899 // The object we're collecting is on top of the stack 1899 // The object we're collecting is on top of the stack
1900 lua_getmetatable(L, 1); 1900 lua_getmetatable(L, 1);
1901 1901
1902 // Get the filename 1902 // Get the filename
1903 const char *filename; 1903 const char *filename;
1904 lua_getfield(L, -1, "filename"); 1904 lua_getfield(L, -1, "filename");
1905 filename = lua_tostring(L, -1); 1905 filename = lua_tostring(L, -1);
1906 1906
1907 // Delete the file 1907 // Delete the file
1908 remove(filename); 1908 remove(filename);
1909 1909
1910 // We exit, and the garbage collector takes care of the rest. 1910 // We exit, and the garbage collector takes care of the rest.
1911 // Edit: Visual Studio needs a return value anyway, so returns 0. 1911 // Edit: Visual Studio needs a return value anyway, so returns 0.
1912 return 0; 1912 return 0;
1913 } 1913 }
1914 1914
1915 // object savestate.create(int which = nil) 1915 // object savestate.create(int which = nil)
1916 // 1916 //
1917 // Creates an object used for savestates. 1917 // Creates an object used for savestates.
1918 // The object can be associated with a player-accessible savestate 1918 // The object can be associated with a player-accessible savestate
1919 1919
1920 // ("which" between 1 and 12) or not (which == nil). 1920 // ("which" between 1 and 12) or not (which == nil).
1921 static int savestate_create(lua_State *L) 1921 static int savestate_create(lua_State *L)
1922 { 1922 {
1923 int which = -1; 1923 int which = -1;
1924 if (lua_gettop(L) >= 1) 1924 if (lua_gettop(L) >= 1)
1925 { 1925 {
1926 which = luaL_checkinteger(L, 1); 1926 which = luaL_checkinteger(L, 1);
1927 if (which < 1 || which > 12) 1927 if (which < 1 || which > 12)
1928 { 1928 {
1929 luaL_error(L, "invalid player's savestate %d", which); 1929 luaL_error(L, "invalid player's savestate %d", which);
1930 } 1930 }
1931 } 1931 }
1932 1932
1933 char stateName[2048]; 1933 char stateName[2048];
1934 1934
1935 if (which > 0) 1935 if (which > 0)
1936 { 1936 {
1937 // Find an appropriate filename. This is OS specific, unfortunately. 1937 // Find an appropriate filename. This is OS specific, unfortunately.
1938 #if (defined(WIN32) && !defined(SDL)) 1938 #if (defined(WIN32) && !defined(SDL))
1939 CString stateName = winGetSavestateFilename(theApp.gameFilename, which); 1939 CString stateName = winGetSavestateFilename(theApp.gameFilename, which);
1940 #else 1940 #else
1941 extern char saveDir[2048]; 1941 extern char saveDir[2048];
1942 extern char filename[2048]; 1942 extern char filename[2048];
1943 extern char *sdlGetFilename(char *name); 1943 extern char *sdlGetFilename(char *name);
1944 1944
1945 if (saveDir[0]) 1945 if (saveDir[0])
1946 sprintf(stateName, "%s/%s%d.sgm", saveDir, sdlGetFilename(filename), which); 1946 sprintf(stateName, "%s/%s%d.sgm", saveDir, sdlGetFilename(filename), which);
1947 else 1947 else
1948 sprintf(stateName, "%s%d.sgm", filename, which); 1948 sprintf(stateName, "%s%d.sgm", filename, which);
1949 #endif 1949 #endif
1950 } 1950 }
1951 else 1951 else
1952 { 1952 {
1953 char *stateNameTemp = tempnam(NULL, "snlua"); 1953 char *stateNameTemp = tempnam(NULL, "snlua");
1954 strcpy(stateName, stateNameTemp); 1954 strcpy(stateName, stateNameTemp);
1955 if (stateNameTemp) 1955 if (stateNameTemp)
1956 free(stateNameTemp); 1956 free(stateNameTemp);
1957 } 1957 }
1958 1958
1959 // Our "object". We don't care about the type, we just need the memory and GC services. 1959 // Our "object". We don't care about the type, we just need the memory and GC services.
1960 lua_newuserdata(L, 1); 1960 lua_newuserdata(L, 1);
1961 1961
1962 // The metatable we use, protected from Lua and contains garbage collection info and stuff. 1962 // The metatable we use, protected from Lua and contains garbage collection info and stuff.
1963 lua_newtable(L); 1963 lua_newtable(L);
1964 1964
1965 // First, we must protect it 1965 // First, we must protect it
1966 lua_pushstring(L, "vba Savestate"); 1966 lua_pushstring(L, "vba Savestate");
1967 lua_setfield(L, -2, "__metatable"); 1967 lua_setfield(L, -2, "__metatable");
1968 1968
1969 // Now we need to save the file itself. 1969 // Now we need to save the file itself.
1970 lua_pushstring(L, stateName); 1970 lua_pushstring(L, stateName);
1971 lua_setfield(L, -2, "filename"); 1971 lua_setfield(L, -2, "filename");
1972 1972
1973 // If it's an anonymous savestate, we must delete the file from disk should it be gargage collected 1973 // If it's an anonymous savestate, we must delete the file from disk should it be gargage collected
1974 if (which < 0) 1974 if (which < 0)
1975 { 1975 {
1976 lua_pushcfunction(L, savestate_gc); 1976 lua_pushcfunction(L, savestate_gc);
1977 lua_setfield(L, -2, "__gc"); 1977 lua_setfield(L, -2, "__gc");
1978 } 1978 }
1979 1979
1980 // Set the metatable 1980 // Set the metatable
1981 lua_setmetatable(L, -2); 1981 lua_setmetatable(L, -2);
1982 1982
1983 // Awesome. Return the object 1983 // Awesome. Return the object
1984 return 1; 1984 return 1;
1985 } 1985 }
1986 1986
1987 // savestate.save(object state) 1987 // savestate.save(object state)
1988 // 1988 //
1989 1989
1990 // Saves a state to the given object. 1990 // Saves a state to the given object.
1991 static int savestate_save(lua_State *L) 1991 static int savestate_save(lua_State *L)
1992 { 1992 {
1993 const char *filename = savestateobj2filename(L, 1); 1993 const char *filename = savestateobj2filename(L, 1);
1994 1994
1995 // printf("saving %s\n", filename); 1995 // printf("saving %s\n", filename);
1996 // Save states are very expensive. They take time. 1996 // Save states are very expensive. They take time.
1997 numTries--; 1997 numTries--;
1998 1998
1999 bool8 retvalue = theEmulator.emuWriteState ? theEmulator.emuWriteState(filename) : false; 1999 bool8 retvalue = theEmulator.emuWriteState ? theEmulator.emuWriteState(filename) : false;
2000 if (!retvalue) 2000 if (!retvalue)
2001 { 2001 {
2002 // Uh oh 2002 // Uh oh
2003 luaL_error(L, "savestate failed"); 2003 luaL_error(L, "savestate failed");
2004 } 2004 }
2005 2005
2006 return 0; 2006 return 0;
2007 } 2007 }
2008 2008
2009 // savestate.load(object state) 2009 // savestate.load(object state)
2010 // 2010 //
2011 2011
2012 // Loads the given state 2012 // Loads the given state
2013 static int savestate_load(lua_State *L) 2013 static int savestate_load(lua_State *L)
2014 { 2014 {
2015 const char *filename = savestateobj2filename(L, 1); 2015 const char *filename = savestateobj2filename(L, 1);
2016 2016
2017 numTries--; 2017 numTries--;
2018 2018
2019 // printf("loading %s\n", filename); 2019 // printf("loading %s\n", filename);
2020 bool8 retvalue = theEmulator.emuReadState ? theEmulator.emuReadState(filename) : false; 2020 bool8 retvalue = theEmulator.emuReadState ? theEmulator.emuReadState(filename) : false;
2021 if (!retvalue) 2021 if (!retvalue)
2022 { 2022 {
2023 // Uh oh 2023 // Uh oh
2024 luaL_error(L, "loadstate failed"); 2024 luaL_error(L, "loadstate failed");
2025 } 2025 }
2026 2026
2027 return 0; 2027 return 0;
2028 } 2028 }
2029 2029
2030 // int vba.framecount() 2030 // int vba.framecount()
2031 // 2031 //
2032 2032
2033 // Gets the frame counter for the movie, or the number of frames since last reset. 2033 // Gets the frame counter for the movie, or the number of frames since last reset.
2034 int vba_framecount(lua_State *L) 2034 int vba_framecount(lua_State *L)
2035 { 2035 {
2036 if (!VBAMovieActive()) 2036 if (!VBAMovieActive())
2037 { 2037 {
2038 lua_pushinteger(L, systemCounters.frameCount); 2038 lua_pushinteger(L, systemCounters.frameCount);
2039 } 2039 }
2040 else 2040 else
2041 { 2041 {
2042 lua_pushinteger(L, VBAMovieGetFrameCounter()); 2042 lua_pushinteger(L, VBAMovieGetFrameCounter());
2043 } 2043 }
2044 2044
2045 return 1; 2045 return 1;
2046 } 2046 }
2047 2047
2048 //string movie.getauthor 2048 //string movie.getauthor
2049 // 2049 //
2050 2050
2051 // returns author info field of .vbm file 2051 // returns author info field of .vbm file
2052 int movie_getauthor(lua_State *L) 2052 int movie_getauthor(lua_State *L)
2053 { 2053 {
2054 if (!VBAMovieActive()) 2054 if (!VBAMovieActive())
2055 { 2055 {
2056 //lua_pushnil(L); 2056 //lua_pushnil(L);
2057 lua_pushstring(L, ""); 2057 lua_pushstring(L, "");
2058 return 1; 2058 return 1;
2059 } 2059 }
2060 2060
2061 lua_pushstring(L, VBAMovieGetAuthorInfo().c_str()); 2061 lua_pushstring(L, VBAMovieGetAuthorInfo().c_str());
2062 return 1; 2062 return 1;
2063 } 2063 }
2064 2064
2065 //string movie.filename 2065 //string movie.filename
2066 int movie_getfilename(lua_State *L) 2066 int movie_getfilename(lua_State *L)
2067 { 2067 {
2068 if (!VBAMovieActive()) 2068 if (!VBAMovieActive())
2069 { 2069 {
2070 //lua_pushnil(L); 2070 //lua_pushnil(L);
2071 lua_pushstring(L, ""); 2071 lua_pushstring(L, "");
2072 return 1; 2072 return 1;
2073 } 2073 }
2074 2074
2075 lua_pushstring(L, VBAMovieGetFilename().c_str()); 2075 lua_pushstring(L, VBAMovieGetFilename().c_str());
2076 return 1; 2076 return 1;
2077 } 2077 }
2078 2078
2079 // string movie.mode() 2079 // string movie.mode()
2080 // 2080 //
2081 2081
2082 // "record", "playback" or nil 2082 // "record", "playback" or nil
2083 int movie_getmode(lua_State *L) 2083 int movie_getmode(lua_State *L)
2084 { 2084 {
2085 assert(!VBAMovieLoading()); 2085 assert(!VBAMovieLoading());
2086 if (!VBAMovieActive()) 2086 if (!VBAMovieActive())
2087 { 2087 {
2088 lua_pushnil(L); 2088 lua_pushnil(L);
2089 return 1; 2089 return 1;
2090 } 2090 }
2091 2091
2092 if (VBAMovieRecording()) 2092 if (VBAMovieRecording())
2093 lua_pushstring(L, "record"); 2093 lua_pushstring(L, "record");
2094 else 2094 else
2095 lua_pushstring(L, "playback"); 2095 lua_pushstring(L, "playback");
2096 return 1; 2096 return 1;
2097 } 2097 }
2098 2098
2099 static int movie_rerecordcount(lua_State *L) 2099 static int movie_rerecordcount(lua_State *L)
2100 { 2100 {
2101 if (VBAMovieActive()) 2101 if (VBAMovieActive())
2102 lua_pushinteger(L, VBAMovieGetRerecordCount()); 2102 lua_pushinteger(L, VBAMovieGetRerecordCount());
2103 else 2103 else
2104 lua_pushinteger(L, 0); 2104 lua_pushinteger(L, 0);
2105 return 1; 2105 return 1;
2106 } 2106 }
2107 2107
2108 static int movie_setrerecordcount(lua_State *L) 2108 static int movie_setrerecordcount(lua_State *L)
2109 { 2109 {
2110 if (VBAMovieActive()) 2110 if (VBAMovieActive())
2111 VBAMovieSetRerecordCount(luaL_checkinteger(L, 1)); 2111 VBAMovieSetRerecordCount(luaL_checkinteger(L, 1));
2112 return 0; 2112 return 0;
2113 } 2113 }
2114 2114
2115 static int movie_rerecordcounting(lua_State *L) 2115 static int movie_rerecordcounting(lua_State *L)
2116 { 2116 {
2117 if (lua_gettop(L) == 0) 2117 if (lua_gettop(L) == 0)
2118 luaL_error(L, "no parameters specified"); 2118 luaL_error(L, "no parameters specified");
2119 2119
2120 skipRerecords = lua_toboolean(L, 1); 2120 skipRerecords = lua_toboolean(L, 1);
2121 return 0; 2121 return 0;
2122 } 2122 }
2123 2123
2124 // movie.stop() 2124 // movie.stop()
2125 // 2125 //
2126 2126
2127 // Stops movie playback/recording. Bombs out if movie is not running. 2127 // Stops movie playback/recording. Bombs out if movie is not running.
2128 static int movie_stop(lua_State *L) 2128 static int movie_stop(lua_State *L)
2129 { 2129 {
2130 if (!VBAMovieActive()) 2130 if (!VBAMovieActive())
2131 luaL_error(L, "no movie"); 2131 luaL_error(L, "no movie");
2132 2132
2133 VBAMovieStop(false); 2133 VBAMovieStop(false);
2134 return 0; 2134 return 0;
2135 } 2135 }
2136 2136
2137 #define LUA_SCREEN_WIDTH 256 2137 #define LUA_SCREEN_WIDTH 256
2138 #define LUA_SCREEN_HEIGHT 239 2138 #define LUA_SCREEN_HEIGHT 239
2139 2139
2140 // Common code by the gui library: make sure the screen array is ready 2140 // Common code by the gui library: make sure the screen array is ready
2141 static void gui_prepare(void) 2141 static void gui_prepare(void)
2142 { 2142 {
2143 if (!gui_data) 2143 if (!gui_data)
2144 gui_data = (uint8 *)malloc(LUA_SCREEN_WIDTH * LUA_SCREEN_HEIGHT * 4); 2144 gui_data = (uint8 *)malloc(LUA_SCREEN_WIDTH * LUA_SCREEN_HEIGHT * 4);
2145 if (!gui_used) 2145 if (!gui_used)
2146 memset(gui_data, 0, LUA_SCREEN_WIDTH * LUA_SCREEN_HEIGHT * 4); 2146 memset(gui_data, 0, LUA_SCREEN_WIDTH * LUA_SCREEN_HEIGHT * 4);
2147 gui_used = true; 2147 gui_used = true;
2148 } 2148 }
2149 2149
2150 // pixform for lua graphics 2150 // pixform for lua graphics
2151 #define BUILD_PIXEL_ARGB8888(A, R, G, B) (((int)(A) << 24) | ((int)(R) << 16) | ((int)(G) << 8) | (int)(B)) 2151 #define BUILD_PIXEL_ARGB8888(A, R, G, B) (((int)(A) << 24) | ((int)(R) << 16) | ((int)(G) << 8) | (int)(B))
2152 #define DECOMPOSE_PIXEL_ARGB8888(PIX, A, R, G, B) \ 2152 #define DECOMPOSE_PIXEL_ARGB8888(PIX, A, R, G, B) \
2153 { \ 2153 { \
2154 (A) = ((PIX) >> 24) & 0xff; \ 2154 (A) = ((PIX) >> 24) & 0xff; \
2155 (R) = ((PIX) >> 16) & 0xff; \ 2155 (R) = ((PIX) >> 16) & 0xff; \
2156 (G) = ((PIX) >> 8) & 0xff; \ 2156 (G) = ((PIX) >> 8) & 0xff; \
2157 (B) = (PIX) & 0xff; \ 2157 (B) = (PIX) & 0xff; \
2158 } 2158 }
2159 #define LUA_BUILD_PIXEL BUILD_PIXEL_ARGB8888 2159 #define LUA_BUILD_PIXEL BUILD_PIXEL_ARGB8888
2160 #define LUA_DECOMPOSE_PIXEL DECOMPOSE_PIXEL_ARGB8888 2160 #define LUA_DECOMPOSE_PIXEL DECOMPOSE_PIXEL_ARGB8888
2161 #define LUA_PIXEL_A(PIX) (((PIX) >> 24) & 0xff) 2161 #define LUA_PIXEL_A(PIX) (((PIX) >> 24) & 0xff)
2162 #define LUA_PIXEL_R(PIX) (((PIX) >> 16) & 0xff) 2162 #define LUA_PIXEL_R(PIX) (((PIX) >> 16) & 0xff)
2163 #define LUA_PIXEL_G(PIX) (((PIX) >> 8) & 0xff) 2163 #define LUA_PIXEL_G(PIX) (((PIX) >> 8) & 0xff)
2164 #define LUA_PIXEL_B(PIX) ((PIX) & 0xff) 2164 #define LUA_PIXEL_B(PIX) ((PIX) & 0xff)
2165 2165
2166 template<class T> 2166 template<class T>
2167 static void swap(T &one, T &two) 2167 static void swap(T &one, T &two)
2168 { 2168 {
2169 T temp = one; 2169 T temp = one;
2170 one = two; 2170 one = two;
2171 two = temp; 2171 two = temp;
2172 } 2172 }
2173 2173
2174 // write a pixel to buffer 2174 // write a pixel to buffer
2175 static inline void blend32(uint32 *dstPixel, uint32 colour) 2175 static inline void blend32(uint32 *dstPixel, uint32 colour)
2176 { 2176 {
2177 uint8 *dst = (uint8 *)dstPixel; 2177 uint8 *dst = (uint8 *)dstPixel;
2178 int a, r, g, b; 2178 int a, r, g, b;
2179 LUA_DECOMPOSE_PIXEL(colour, a, r, g, b); 2179 LUA_DECOMPOSE_PIXEL(colour, a, r, g, b);
2180 2180
2181 if (a == 255 || dst[3] == 0) 2181 if (a == 255 || dst[3] == 0)
2182 { 2182 {
2183 // direct copy 2183 // direct copy
2184 *(uint32 *) (dst) = colour; 2184 *(uint32 *) (dst) = colour;
2185 } 2185 }
2186 else if (a == 0) 2186 else if (a == 0)
2187 { 2187 {
2188 // do not copy 2188 // do not copy
2189 } 2189 }
2190 else 2190 else
2191 { 2191 {
2192 // alpha-blending 2192 // alpha-blending
2193 int a_dst = ((255 - a) * dst[3] + 128) / 255; 2193 int a_dst = ((255 - a) * dst[3] + 128) / 255;
2194 int a_new = a + a_dst; 2194 int a_new = a + a_dst;
2195 2195
2196 dst[0] = (uint8) (((dst[0] * a_dst + b * a) + (a_new / 2)) / a_new); 2196 dst[0] = (uint8) (((dst[0] * a_dst + b * a) + (a_new / 2)) / a_new);
2197 dst[1] = (uint8) (((dst[1] * a_dst + g * a) + (a_new / 2)) / a_new); 2197 dst[1] = (uint8) (((dst[1] * a_dst + g * a) + (a_new / 2)) / a_new);
2198 dst[2] = (uint8) (((dst[2] * a_dst + r * a) + (a_new / 2)) / a_new); 2198 dst[2] = (uint8) (((dst[2] * a_dst + r * a) + (a_new / 2)) / a_new);
2199 dst[3] = (uint8) a_new; 2199 dst[3] = (uint8) a_new;
2200 } 2200 }
2201 } 2201 }
2202 2202
2203 // check if a pixel is in the lua canvas 2203 // check if a pixel is in the lua canvas
2204 static inline bool gui_check_boundary(int x, int y) 2204 static inline bool gui_check_boundary(int x, int y)
2205 { 2205 {
2206 return !(x < 0 || x >= LUA_SCREEN_WIDTH || y < 0 || y >= LUA_SCREEN_HEIGHT); 2206 return !(x < 0 || x >= LUA_SCREEN_WIDTH || y < 0 || y >= LUA_SCREEN_HEIGHT);
2207 } 2207 }
2208 2208
2209 // check if any part of a box is in the lua canvas 2209 // check if any part of a box is in the lua canvas
2210 static inline bool gui_checkbox(int x1, int y1, int x2, int y2) 2210 static inline bool gui_checkbox(int x1, int y1, int x2, int y2)
2211 { 2211 {
2212 if ((x1 < 0 && x2 < 0) 2212 if ((x1 < 0 && x2 < 0)
2213 || (x1 >= LUA_SCREEN_WIDTH && x2 >= LUA_SCREEN_WIDTH) 2213 || (x1 >= LUA_SCREEN_WIDTH && x2 >= LUA_SCREEN_WIDTH)
2214 || (y1 < 0 && y2 < 0) 2214 || (y1 < 0 && y2 < 0)
2215 || (y1 >= LUA_SCREEN_HEIGHT && y2 >= LUA_SCREEN_HEIGHT)) 2215 || (y1 >= LUA_SCREEN_HEIGHT && y2 >= LUA_SCREEN_HEIGHT))
2216 return false; 2216 return false;
2217 return true; 2217 return true;
2218 } 2218 }
2219 2219
2220 // write a pixel to gui_data (do not check boundaries for speedup) 2220 // write a pixel to gui_data (do not check boundaries for speedup)
2221 static inline void gui_drawpixel_fast(int x, int y, uint32 colour) 2221 static inline void gui_drawpixel_fast(int x, int y, uint32 colour)
2222 { 2222 {
2223 //gui_prepare(); 2223 //gui_prepare();
2224 blend32((uint32 *) &gui_data[(y * LUA_SCREEN_WIDTH + x) * 4], colour); 2224 blend32((uint32 *) &gui_data[(y * LUA_SCREEN_WIDTH + x) * 4], colour);
2225 } 2225 }
2226 2226
2227 // write a pixel to gui_data (check boundaries) 2227 // write a pixel to gui_data (check boundaries)
2228 static inline void gui_drawpixel_internal(int x, int y, uint32 colour) 2228 static inline void gui_drawpixel_internal(int x, int y, uint32 colour)
2229 { 2229 {
2230 //gui_prepare(); 2230 //gui_prepare();
2231 if (gui_check_boundary(x, y)) 2231 if (gui_check_boundary(x, y))
2232 gui_drawpixel_fast(x, y, colour); 2232 gui_drawpixel_fast(x, y, colour);
2233 } 2233 }
2234 2234
2235 // draw a line on gui_data (checks boundaries) 2235 // draw a line on gui_data (checks boundaries)
2236 static void gui_drawline_internal(int x1, int y1, int x2, int y2, bool lastPixel, uint32 colour) 2236 static void gui_drawline_internal(int x1, int y1, int x2, int y2, bool lastPixel, uint32 colour)
2237 { 2237 {
2238 //gui_prepare(); 2238 //gui_prepare();
2239 // Note: New version of Bresenham's Line Algorithm 2239 // Note: New version of Bresenham's Line Algorithm
2240 // 2240 //
2241 // 2241 //
2242 // http://groups.google.co.jp/group/rec.games.roguelike.development/browse_thread/thread/345f4c42c3b25858/29e07a3af3a450e6?show_docid=29e07a3af3a450e6 2242 // http://groups.google.co.jp/group/rec.games.roguelike.development/browse_thread/thread/345f4c42c3b25858/29e07a3af3a450e6?show_docid=29e07a3af3a450e6
2243 int swappedx = 0; 2243 int swappedx = 0;
2244 int swappedy = 0; 2244 int swappedy = 0;
2245 2245
2246 int xtemp = x1 - x2; 2246 int xtemp = x1 - x2;
2247 int ytemp = y1 - y2; 2247 int ytemp = y1 - y2;
2248 if (xtemp == 0 && ytemp == 0) 2248 if (xtemp == 0 && ytemp == 0)
2249 { 2249 {
2250 gui_drawpixel_internal(x1, y1, colour); 2250 gui_drawpixel_internal(x1, y1, colour);
2251 return; 2251 return;
2252 } 2252 }
2253 2253
2254 if (xtemp < 0) 2254 if (xtemp < 0)
2255 { 2255 {
2256 xtemp = -xtemp; 2256 xtemp = -xtemp;
2257 swappedx = 1; 2257 swappedx = 1;
2258 } 2258 }
2259 2259
2260 if (ytemp < 0) 2260 if (ytemp < 0)
2261 { 2261 {
2262 ytemp = -ytemp; 2262 ytemp = -ytemp;
2263 swappedy = 1; 2263 swappedy = 1;
2264 } 2264 }
2265 2265
2266 int delta_x = xtemp << 1; 2266 int delta_x = xtemp << 1;
2267 int delta_y = ytemp << 1; 2267 int delta_y = ytemp << 1;
2268 2268
2269 signed char ix = x1 > x2 ? 1 : -1; 2269 signed char ix = x1 > x2 ? 1 : -1;
2270 signed char iy = y1 > y2 ? 1 : -1; 2270 signed char iy = y1 > y2 ? 1 : -1;
2271 2271
2272 if (lastPixel) 2272 if (lastPixel)
2273 gui_drawpixel_internal(x2, y2, colour); 2273 gui_drawpixel_internal(x2, y2, colour);
2274 2274
2275 if (delta_x >= delta_y) 2275 if (delta_x >= delta_y)
2276 { 2276 {
2277 int error = delta_y - (delta_x >> 1); 2277 int error = delta_y - (delta_x >> 1);
2278 2278
2279 while (x2 != x1) 2279 while (x2 != x1)
2280 { 2280 {
2281 if (error == 0 && !swappedx) 2281 if (error == 0 && !swappedx)
2282 gui_drawpixel_internal(x2 + ix, y2, colour); 2282 gui_drawpixel_internal(x2 + ix, y2, colour);
2283 if (error >= 0) 2283 if (error >= 0)
2284 { 2284 {
2285 if (error || (ix > 0)) 2285 if (error || (ix > 0))
2286 { 2286 {
2287 y2 += iy; 2287 y2 += iy;
2288 error -= delta_x; 2288 error -= delta_x;
2289 } 2289 }
2290 } 2290 }
2291 2291
2292 x2 += ix; 2292 x2 += ix;
2293 gui_drawpixel_internal(x2, y2, colour); 2293 gui_drawpixel_internal(x2, y2, colour);
2294 if (error == 0 && swappedx) 2294 if (error == 0 && swappedx)
2295 gui_drawpixel_internal(x2, y2 + iy, colour); 2295 gui_drawpixel_internal(x2, y2 + iy, colour);
2296 error += delta_y; 2296 error += delta_y;
2297 } 2297 }
2298 } 2298 }
2299 else 2299 else
2300 { 2300 {
2301 int error = delta_x - (delta_y >> 1); 2301 int error = delta_x - (delta_y >> 1);
2302 2302
2303 while (y2 != y1) 2303 while (y2 != y1)
2304 { 2304 {
2305 if (error == 0 && !swappedy) 2305 if (error == 0 && !swappedy)
2306 gui_drawpixel_internal(x2, y2 + iy, colour); 2306 gui_drawpixel_internal(x2, y2 + iy, colour);
2307 if (error >= 0) 2307 if (error >= 0)
2308 { 2308 {
2309 if (error || (iy > 0)) 2309 if (error || (iy > 0))
2310 { 2310 {
2311 x2 += ix; 2311 x2 += ix;
2312 error -= delta_y; 2312 error -= delta_y;
2313 } 2313 }
2314 } 2314 }
2315 2315
2316 y2 += iy; 2316 y2 += iy;
2317 gui_drawpixel_internal(x2, y2, colour); 2317 gui_drawpixel_internal(x2, y2, colour);
2318 if (error == 0 && swappedy) 2318 if (error == 0 && swappedy)
2319 gui_drawpixel_internal(x2 + ix, y2, colour); 2319 gui_drawpixel_internal(x2 + ix, y2, colour);
2320 error += delta_x; 2320 error += delta_x;
2321 } 2321 }
2322 } 2322 }
2323 } 2323 }
2324 2324
2325 // draw a rect on gui_data 2325 // draw a rect on gui_data
2326 static void gui_drawbox_internal(int x1, int y1, int x2, int y2, uint32 colour) 2326 static void gui_drawbox_internal(int x1, int y1, int x2, int y2, uint32 colour)
2327 { 2327 {
2328 if (x1 > x2) 2328 if (x1 > x2)
2329 std::swap(x1, x2); 2329 std::swap(x1, x2);
2330 if (y1 > y2) 2330 if (y1 > y2)
2331 std::swap(y1, y2); 2331 std::swap(y1, y2);
2332 if (x1 < 0) 2332 if (x1 < 0)
2333 x1 = -1; 2333 x1 = -1;
2334 if (y1 < 0) 2334 if (y1 < 0)
2335 y1 = -1; 2335 y1 = -1;
2336 if (x2 >= LUA_SCREEN_WIDTH) 2336 if (x2 >= LUA_SCREEN_WIDTH)
2337 x2 = LUA_SCREEN_WIDTH; 2337 x2 = LUA_SCREEN_WIDTH;
2338 if (y2 >= LUA_SCREEN_HEIGHT) 2338 if (y2 >= LUA_SCREEN_HEIGHT)
2339 y2 = LUA_SCREEN_HEIGHT; 2339 y2 = LUA_SCREEN_HEIGHT;
2340 2340
2341 if (!gui_checkbox(x1, y1, x2, y2)) 2341 if (!gui_checkbox(x1, y1, x2, y2))
2342 return; 2342 return;
2343 2343
2344 //gui_prepare(); 2344 //gui_prepare();
2345 gui_drawline_internal(x1, y1, x2, y1, true, colour); 2345 gui_drawline_internal(x1, y1, x2, y1, true, colour);
2346 gui_drawline_internal(x1, y2, x2, y2, true, colour); 2346 gui_drawline_internal(x1, y2, x2, y2, true, colour);
2347 gui_drawline_internal(x1, y1, x1, y2, true, colour); 2347 gui_drawline_internal(x1, y1, x1, y2, true, colour);
2348 gui_drawline_internal(x2, y1, x2, y2, true, colour); 2348 gui_drawline_internal(x2, y1, x2, y2, true, colour);
2349 } 2349 }
2350 2350
2351 // draw a circle on gui_data 2351 // draw a circle on gui_data
2352 static void gui_drawcircle_internal(int x0, int y0, int radius, uint32 colour) 2352 static void gui_drawcircle_internal(int x0, int y0, int radius, uint32 colour)
2353 { 2353 {
2354 //gui_prepare(); 2354 //gui_prepare();
2355 if (radius < 0) 2355 if (radius < 0)
2356 radius = -radius; 2356 radius = -radius;
2357 if (radius == 0) 2357 if (radius == 0)
2358 return; 2358 return;
2359 if (radius == 1) 2359 if (radius == 1)
2360 { 2360 {
2361 gui_drawpixel_internal(x0, y0, colour); 2361 gui_drawpixel_internal(x0, y0, colour);
2362 return; 2362 return;
2363 } 2363 }
2364 2364
2365 // http://en.wikipedia.org/wiki/Midpoint_circle_algorithm 2365 // http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
2366 int f = 1 - radius; 2366 int f = 1 - radius;
2367 int ddF_x = 1; 2367 int ddF_x = 1;
2368 int ddF_y = -2 * radius; 2368 int ddF_y = -2 * radius;
2369 int x = 0; 2369 int x = 0;
2370 int y = radius; 2370 int y = radius;
2371 2371
2372 if (!gui_checkbox(x0 - radius, y0 - radius, x0 + radius, y0 + radius)) 2372 if (!gui_checkbox(x0 - radius, y0 - radius, x0 + radius, y0 + radius))
2373 return; 2373 return;
2374 2374
2375 gui_drawpixel_internal(x0, y0 + radius, colour); 2375 gui_drawpixel_internal(x0, y0 + radius, colour);
2376 gui_drawpixel_internal(x0, y0 - radius, colour); 2376 gui_drawpixel_internal(x0, y0 - radius, colour);
2377 gui_drawpixel_internal(x0 + radius, y0, colour); 2377 gui_drawpixel_internal(x0 + radius, y0, colour);
2378 gui_drawpixel_internal(x0 - radius, y0, colour); 2378 gui_drawpixel_internal(x0 - radius, y0, colour);
2379 2379
2380 // same pixel shouldn't be drawed twice, 2380 // same pixel shouldn't be drawed twice,
2381 // because each pixel has opacity. 2381 // because each pixel has opacity.
2382 // so now the routine gets ugly. 2382 // so now the routine gets ugly.
2383 while (true) 2383 while (true)
2384 { 2384 {
2385 assert(ddF_x == 2 * x + 1); 2385 assert(ddF_x == 2 * x + 1);
2386 assert(ddF_y == -2 * y); 2386 assert(ddF_y == -2 * y);
2387 assert(f == x * x + y * y - radius * radius + 2 * x - y + 1); 2387 assert(f == x * x + y * y - radius * radius + 2 * x - y + 1);
2388 if (f >= 0) 2388 if (f >= 0)
2389 { 2389 {
2390 y--; 2390 y--;
2391 ddF_y += 2; 2391 ddF_y += 2;
2392 f += ddF_y; 2392 f += ddF_y;
2393 } 2393 }
2394 2394
2395 x++; 2395 x++;
2396 ddF_x += 2; 2396 ddF_x += 2;
2397 f += ddF_x; 2397 f += ddF_x;
2398 if (x < y) 2398 if (x < y)
2399 { 2399 {
2400 gui_drawpixel_internal(x0 + x, y0 + y, colour); 2400 gui_drawpixel_internal(x0 + x, y0 + y, colour);
2401 gui_drawpixel_internal(x0 - x, y0 + y, colour); 2401 gui_drawpixel_internal(x0 - x, y0 + y, colour);
2402 gui_drawpixel_internal(x0 + x, y0 - y, colour); 2402 gui_drawpixel_internal(x0 + x, y0 - y, colour);
2403 gui_drawpixel_internal(x0 - x, y0 - y, colour); 2403 gui_drawpixel_internal(x0 - x, y0 - y, colour);
2404 gui_drawpixel_internal(x0 + y, y0 + x, colour); 2404 gui_drawpixel_internal(x0 + y, y0 + x, colour);
2405 gui_drawpixel_internal(x0 - y, y0 + x, colour); 2405 gui_drawpixel_internal(x0 - y, y0 + x, colour);
2406 gui_drawpixel_internal(x0 + y, y0 - x, colour); 2406 gui_drawpixel_internal(x0 + y, y0 - x, colour);
2407 gui_drawpixel_internal(x0 - y, y0 - x, colour); 2407 gui_drawpixel_internal(x0 - y, y0 - x, colour);
2408 } 2408 }
2409 else if (x == y) 2409 else if (x == y)
2410 { 2410 {
2411 gui_drawpixel_internal(x0 + x, y0 + y, colour); 2411 gui_drawpixel_internal(x0 + x, y0 + y, colour);
2412 gui_drawpixel_internal(x0 - x, y0 + y, colour); 2412 gui_drawpixel_internal(x0 - x, y0 + y, colour);
2413 gui_drawpixel_internal(x0 + x, y0 - y, colour); 2413 gui_drawpixel_internal(x0 + x, y0 - y, colour);
2414 gui_drawpixel_internal(x0 - x, y0 - y, colour); 2414 gui_drawpixel_internal(x0 - x, y0 - y, colour);
2415 break; 2415 break;
2416 } 2416 }
2417 else 2417 else
2418 break; 2418 break;
2419 } 2419 }
2420 } 2420 }
2421 2421
2422 // draw fill rect on gui_data 2422 // draw fill rect on gui_data
2423 static void gui_fillbox_internal(int x1, int y1, int x2, int y2, uint32 colour) 2423 static void gui_fillbox_internal(int x1, int y1, int x2, int y2, uint32 colour)
2424 { 2424 {
2425 if (x1 > x2) 2425 if (x1 > x2)
2426 std::swap(x1, x2); 2426 std::swap(x1, x2);
2427 if (y1 > y2) 2427 if (y1 > y2)
2428 std::swap(y1, y2); 2428 std::swap(y1, y2);
2429 if (x1 < 0) 2429 if (x1 < 0)
2430 x1 = 0; 2430 x1 = 0;
2431 if (y1 < 0) 2431 if (y1 < 0)
2432 y1 = 0; 2432 y1 = 0;
2433 if (x2 >= LUA_SCREEN_WIDTH) 2433 if (x2 >= LUA_SCREEN_WIDTH)
2434 x2 = LUA_SCREEN_WIDTH - 1; 2434 x2 = LUA_SCREEN_WIDTH - 1;
2435 if (y2 >= LUA_SCREEN_HEIGHT) 2435 if (y2 >= LUA_SCREEN_HEIGHT)
2436 y2 = LUA_SCREEN_HEIGHT - 1; 2436 y2 = LUA_SCREEN_HEIGHT - 1;
2437 2437
2438 //gui_prepare(); 2438 //gui_prepare();
2439 int ix, iy; 2439 int ix, iy;
2440 for (iy = y1; iy <= y2; iy++) 2440 for (iy = y1; iy <= y2; iy++)
2441 { 2441 {
2442 for (ix = x1; ix <= x2; ix++) 2442 for (ix = x1; ix <= x2; ix++)
2443 { 2443 {
2444 gui_drawpixel_fast(ix, iy, colour); 2444 gui_drawpixel_fast(ix, iy, colour);
2445 } 2445 }
2446 } 2446 }
2447 } 2447 }
2448 2448
2449 // fill a circle on gui_data 2449 // fill a circle on gui_data
2450 static void gui_fillcircle_internal(int x0, int y0, int radius, uint32 colour) 2450 static void gui_fillcircle_internal(int x0, int y0, int radius, uint32 colour)
2451 { 2451 {
2452 //gui_prepare(); 2452 //gui_prepare();
2453 if (radius < 0) 2453 if (radius < 0)
2454 radius = -radius; 2454 radius = -radius;
2455 if (radius == 0) 2455 if (radius == 0)
2456 return; 2456 return;
2457 if (radius == 1) 2457 if (radius == 1)
2458 { 2458 {
2459 gui_drawpixel_internal(x0, y0, colour); 2459 gui_drawpixel_internal(x0, y0, colour);
2460 return; 2460 return;
2461 } 2461 }
2462 2462
2463 // http://en.wikipedia.org/wiki/Midpoint_circle_algorithm 2463 // http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
2464 int f = 1 - radius; 2464 int f = 1 - radius;
2465 int ddF_x = 1; 2465 int ddF_x = 1;
2466 int ddF_y = -2 * radius; 2466 int ddF_y = -2 * radius;
2467 int x = 0; 2467 int x = 0;
2468 int y = radius; 2468 int y = radius;
2469 2469
2470 if (!gui_checkbox(x0 - radius, y0 - radius, x0 + radius, y0 + radius)) 2470 if (!gui_checkbox(x0 - radius, y0 - radius, x0 + radius, y0 + radius))
2471 return; 2471 return;
2472 2472
2473 gui_drawline_internal(x0, y0 - radius, x0, y0 + radius, true, colour); 2473 gui_drawline_internal(x0, y0 - radius, x0, y0 + radius, true, colour);
2474 2474
2475 while (true) 2475 while (true)
2476 { 2476 {
2477 assert(ddF_x == 2 * x + 1); 2477 assert(ddF_x == 2 * x + 1);
2478 assert(ddF_y == -2 * y); 2478 assert(ddF_y == -2 * y);
2479 assert(f == x * x + y * y - radius * radius + 2 * x - y + 1); 2479 assert(f == x * x + y * y - radius * radius + 2 * x - y + 1);
2480 if (f >= 0) 2480 if (f >= 0)
2481 { 2481 {
2482 y--; 2482 y--;
2483 ddF_y += 2; 2483 ddF_y += 2;
2484 f += ddF_y; 2484 f += ddF_y;
2485 } 2485 }
2486 2486
2487 x++; 2487 x++;
2488 ddF_x += 2; 2488 ddF_x += 2;
2489 f += ddF_x; 2489 f += ddF_x;
2490 2490
2491 if (x < y) 2491 if (x < y)
2492 { 2492 {
2493 gui_drawline_internal(x0 + x, y0 - y, x0 + x, y0 + y, true, colour); 2493 gui_drawline_internal(x0 + x, y0 - y, x0 + x, y0 + y, true, colour);
2494 gui_drawline_internal(x0 - x, y0 - y, x0 - x, y0 + y, true, colour); 2494 gui_drawline_internal(x0 - x, y0 - y, x0 - x, y0 + y, true, colour);
2495 if (f >= 0) 2495 if (f >= 0)
2496 { 2496 {
2497 gui_drawline_internal(x0 + y, y0 - x, x0 + y, y0 + x, true, colour); 2497 gui_drawline_internal(x0 + y, y0 - x, x0 + y, y0 + x, true, colour);
2498 gui_drawline_internal(x0 - y, y0 - x, x0 - y, y0 + x, true, colour); 2498 gui_drawline_internal(x0 - y, y0 - x, x0 - y, y0 + x, true, colour);
2499 } 2499 }
2500 } 2500 }
2501 else if (x == y) 2501 else if (x == y)
2502 { 2502 {
2503 gui_drawline_internal(x0 + x, y0 - y, x0 + x, y0 + y, true, colour); 2503 gui_drawline_internal(x0 + x, y0 - y, x0 + x, y0 + y, true, colour);
2504 gui_drawline_internal(x0 - x, y0 - y, x0 - x, y0 + y, true, colour); 2504 gui_drawline_internal(x0 - x, y0 - y, x0 - x, y0 + y, true, colour);
2505 break; 2505 break;
2506 } 2506 }
2507 else 2507 else
2508 break; 2508 break;
2509 } 2509 }
2510 } 2510 }
2511 2511
2512 // Helper for a simple hex parser 2512 // Helper for a simple hex parser
2513 static int hex2int(lua_State *L, char c) 2513 static int hex2int(lua_State *L, char c)
2514 { 2514 {
2515 if (c >= '0' && c <= '9') 2515 if (c >= '0' && c <= '9')
2516 return c - '0'; 2516 return c - '0';
2517 if (c >= 'a' && c <= 'f') 2517 if (c >= 'a' && c <= 'f')
2518 return c - 'a' + 10; 2518 return c - 'a' + 10;
2519 if (c >= 'A' && c <= 'F') 2519 if (c >= 'A' && c <= 'F')
2520 return c - 'A' + 10; 2520 return c - 'A' + 10;
2521 return luaL_error(L, "invalid hex in colour"); 2521 return luaL_error(L, "invalid hex in colour");
2522 } 2522 }
2523 2523
2524 static const struct ColorMapping 2524 static const struct ColorMapping
2525 { 2525 {
2526 const char *name; 2526 const char *name;
2527 int value; 2527 int value;
2528 } 2528 }
2529 s_colorMapping[] = 2529 s_colorMapping[] =
2530 { 2530 {
2531 { "white", 0xFFFFFFFF }, 2531 { "white", 0xFFFFFFFF },
2532 { "black", 0x000000FF }, 2532 { "black", 0x000000FF },
2533 { "clear", 0x00000000 }, 2533 { "clear", 0x00000000 },
2534 { "gray", 0x7F7F7FFF }, 2534 { "gray", 0x7F7F7FFF },
2535 { "grey", 0x7F7F7FFF }, 2535 { "grey", 0x7F7F7FFF },
2536 { "red", 0xFF0000FF }, 2536 { "red", 0xFF0000FF },
2537 { "orange", 0xFF7F00FF }, 2537 { "orange", 0xFF7F00FF },
2538 { "yellow", 0xFFFF00FF }, 2538 { "yellow", 0xFFFF00FF },
2539 { "chartreuse", 0x7FFF00FF }, 2539 { "chartreuse", 0x7FFF00FF },
2540 { "green", 0x00FF00FF }, 2540 { "green", 0x00FF00FF },
2541 { "teal", 0x00FF7FFF }, 2541 { "teal", 0x00FF7FFF },
2542 { "cyan", 0x00FFFFFF }, 2542 { "cyan", 0x00FFFFFF },
2543 { "blue", 0x0000FFFF }, 2543 { "blue", 0x0000FFFF },
2544 { "purple", 0x7F00FFFF }, 2544 { "purple", 0x7F00FFFF },
2545 { "magenta", 0xFF00FFFF }, 2545 { "magenta", 0xFF00FFFF },
2546 }; 2546 };
2547 2547
2548 /** 2548 /**
2549 * Converts an integer or a string on the stack at the given 2549 * Converts an integer or a string on the stack at the given
2550 * offset to a RGB32 colour. Several encodings are supported. 2550 * offset to a RGB32 colour. Several encodings are supported.
2551 * The user may construct their own RGB value, given a simple colour name, 2551 * The user may construct their own RGB value, given a simple colour name,
2552 * or an HTML-style "#09abcd" colour. 16 bit reduction doesn't occur at this time. 2552 * or an HTML-style "#09abcd" colour. 16 bit reduction doesn't occur at this time.
2553 */ 2553 */
2554 static inline bool str2colour(uint32 *colour, lua_State *L, const char *str) 2554 static inline bool str2colour(uint32 *colour, lua_State *L, const char *str)
2555 { 2555 {
2556 if (str[0] == '#') 2556 if (str[0] == '#')
2557 { 2557 {
2558 int color; 2558 int color;
2559 sscanf(str + 1, "%X", &color); 2559 sscanf(str + 1, "%X", &color);
2560 2560
2561 int len = strlen(str + 1); 2561 int len = strlen(str + 1);
2562 int missing = max(0, 8 - len); 2562 int missing = max(0, 8 - len);
2563 color <<= missing << 2; 2563 color <<= missing << 2;
2564 if (missing >= 2) 2564 if (missing >= 2)
2565 color |= 0xFF; 2565 color |= 0xFF;
2566 *colour = color; 2566 *colour = color;
2567 return true; 2567 return true;
2568 } 2568 }
2569 else 2569 else
2570 { 2570 {
2571 if (!strnicmp(str, "rand", 4)) 2571 if (!strnicmp(str, "rand", 4))
2572 { 2572 {
2573 *colour = gen_rand32() | 0xFF; //((rand()*255/RAND_MAX) << 8) | ((rand()*255/RAND_MAX) << 16) | 2573 *colour = gen_rand32() | 0xFF; //((rand()*255/RAND_MAX) << 8) | ((rand()*255/RAND_MAX) << 16) |
2574 // ((rand()*255/RAND_MAX) << 24) | 0xFF; 2574 // ((rand()*255/RAND_MAX) << 24) | 0xFF;
2575 return true; 2575 return true;
2576 } 2576 }
2577 2577
2578 for (int i = 0; i < sizeof(s_colorMapping) / sizeof(*s_colorMapping); i++) 2578 for (int i = 0; i < sizeof(s_colorMapping) / sizeof(*s_colorMapping); i++)
2579 { 2579 {
2580 if (!stricmp(str, s_colorMapping[i].name)) 2580 if (!stricmp(str, s_colorMapping[i].name))
2581 { 2581 {
2582 *colour = s_colorMapping[i].value; 2582 *colour = s_colorMapping[i].value;
2583 return true; 2583 return true;
2584 } 2584 }
2585 } 2585 }
2586 } 2586 }
2587 2587
2588 return false; 2588 return false;
2589 } 2589 }
2590 2590
2591 static inline uint32 gui_getcolour_wrapped(lua_State *L, int offset, bool hasDefaultValue, uint32 defaultColour) 2591 static inline uint32 gui_getcolour_wrapped(lua_State *L, int offset, bool hasDefaultValue, uint32 defaultColour)
2592 { 2592 {
2593 switch (lua_type(L, offset)) 2593 switch (lua_type(L, offset))
2594 { 2594 {
2595 case LUA_TSTRING: 2595 case LUA_TSTRING:
2596 { 2596 {
2597 const char *str = lua_tostring(L, offset); 2597 const char *str = lua_tostring(L, offset);
2598 uint32 colour; 2598 uint32 colour;
2599 2599
2600 if (str2colour(&colour, L, str)) 2600 if (str2colour(&colour, L, str))
2601 return colour; 2601 return colour;
2602 else 2602 else
2603 { 2603 {
2604 if (hasDefaultValue) 2604 if (hasDefaultValue)
2605 return defaultColour; 2605 return defaultColour;
2606 else 2606 else
2607 return luaL_error(L, "unknown colour %s", str); 2607 return luaL_error(L, "unknown colour %s", str);
2608 } 2608 }
2609 } 2609 }
2610 2610
2611 case LUA_TNUMBER: 2611 case LUA_TNUMBER:
2612 { 2612 {
2613 uint32 colour = (uint32) lua_tointeger(L, offset); 2613 uint32 colour = (uint32) lua_tointeger(L, offset);
2614 return colour; 2614 return colour;
2615 } 2615 }
2616 2616
2617 case LUA_TTABLE: 2617 case LUA_TTABLE:
2618 { 2618 {
2619 int color = 0xFF; 2619 int color = 0xFF;
2620 lua_pushnil(L); // first key 2620 lua_pushnil(L); // first key
2621 int keyIndex = lua_gettop(L); 2621 int keyIndex = lua_gettop(L);
2622 int valueIndex = keyIndex + 1; 2622 int valueIndex = keyIndex + 1;
2623 bool first = true; 2623 bool first = true;
2624 while (lua_next(L, offset)) 2624 while (lua_next(L, offset))
2625 { 2625 {
2626 bool keyIsString = (lua_type(L, keyIndex) == LUA_TSTRING); 2626 bool keyIsString = (lua_type(L, keyIndex) == LUA_TSTRING);
2627 bool keyIsNumber = (lua_type(L, keyIndex) == LUA_TNUMBER); 2627 bool keyIsNumber = (lua_type(L, keyIndex) == LUA_TNUMBER);
2628 int key = keyIsString ? tolower(*lua_tostring(L, keyIndex)) : (keyIsNumber ? lua_tointeger(L, keyIndex) : 0); 2628 int key = keyIsString ? tolower(*lua_tostring(L, keyIndex)) : (keyIsNumber ? lua_tointeger(L, keyIndex) : 0);
2629 int value = lua_tointeger(L, valueIndex); 2629 int value = lua_tointeger(L, valueIndex);
2630 if (value < 0) value = 0; 2630 if (value < 0) value = 0;
2631 if (value > 255) value = 255; 2631 if (value > 255) value = 255;
2632 switch (key) 2632 switch (key)
2633 { 2633 {
2634 case 1: 2634 case 1:
2635 case 'r': 2635 case 'r':
2636 color |= value << 24; break; 2636 color |= value << 24; break;
2637 case 2: 2637 case 2:
2638 case 'g': 2638 case 'g':
2639 color |= value << 16; break; 2639 color |= value << 16; break;
2640 case 3: 2640 case 3:
2641 case 'b': 2641 case 'b':
2642 color |= value << 8; break; 2642 color |= value << 8; break;
2643 case 4: 2643 case 4:
2644 case 'a': 2644 case 'a':
2645 color = (color & ~0xFF) | value; break; 2645 color = (color & ~0xFF) | value; break;
2646 } 2646 }
2647 lua_pop(L, 1); 2647 lua_pop(L, 1);
2648 } 2648 }
2649 return color; 2649 return color;
2650 } break; 2650 } break;
2651 2651
2652 case LUA_TFUNCTION: 2652 case LUA_TFUNCTION:
2653 luaL_error(L, "invalid colour"); // NYI 2653 luaL_error(L, "invalid colour"); // NYI
2654 return 0; 2654 return 0;
2655 2655
2656 default: 2656 default:
2657 if (hasDefaultValue) 2657 if (hasDefaultValue)
2658 return defaultColour; 2658 return defaultColour;
2659 else 2659 else
2660 return luaL_error(L, "invalid colour"); 2660 return luaL_error(L, "invalid colour");
2661 } 2661 }
2662 } 2662 }
2663 2663
2664 static uint32 gui_getcolour(lua_State *L, int offset) 2664 static uint32 gui_getcolour(lua_State *L, int offset)
2665 { 2665 {
2666 uint32 colour; 2666 uint32 colour;
2667 int a, r, g, b; 2667 int a, r, g, b;
2668 2668
2669 colour = gui_getcolour_wrapped(L, offset, false, 0); 2669 colour = gui_getcolour_wrapped(L, offset, false, 0);
2670 a = ((colour & 0xff) * transparencyModifier) / 255; 2670 a = ((colour & 0xff) * transparencyModifier) / 255;
2671 if (a > 255) 2671 if (a > 255)
2672 a = 255; 2672 a = 255;
2673 b = (colour >> 8) & 0xff; 2673 b = (colour >> 8) & 0xff;
2674 g = (colour >> 16) & 0xff; 2674 g = (colour >> 16) & 0xff;
2675 r = (colour >> 24) & 0xff; 2675 r = (colour >> 24) & 0xff;
2676 return LUA_BUILD_PIXEL(a, r, g, b); 2676 return LUA_BUILD_PIXEL(a, r, g, b);
2677 } 2677 }
2678 2678
2679 static uint32 gui_optcolour(lua_State *L, int offset, uint32 defaultColour) 2679 static uint32 gui_optcolour(lua_State *L, int offset, uint32 defaultColour)
2680 { 2680 {
2681 uint32 colour; 2681 uint32 colour;
2682 int a, r, g, b; 2682 int a, r, g, b;
2683 uint8 defA, defB, defG, defR; 2683 uint8 defA, defB, defG, defR;
2684 2684
2685 LUA_DECOMPOSE_PIXEL(defaultColour, defA, defR, defG, defB); 2685 LUA_DECOMPOSE_PIXEL(defaultColour, defA, defR, defG, defB);
2686 defaultColour = (defR << 24) | (defG << 16) | (defB << 8) | defA; 2686 defaultColour = (defR << 24) | (defG << 16) | (defB << 8) | defA;
2687 2687
2688 colour = gui_getcolour_wrapped(L, offset, true, defaultColour); 2688 colour = gui_getcolour_wrapped(L, offset, true, defaultColour);
2689 a = ((colour & 0xff) * transparencyModifier) / 255; 2689 a = ((colour & 0xff) * transparencyModifier) / 255;
2690 if (a > 255) 2690 if (a > 255)
2691 a = 255; 2691 a = 255;
2692 b = (colour >> 8) & 0xff; 2692 b = (colour >> 8) & 0xff;
2693 g = (colour >> 16) & 0xff; 2693 g = (colour >> 16) & 0xff;
2694 r = (colour >> 24) & 0xff; 2694 r = (colour >> 24) & 0xff;
2695 return LUA_BUILD_PIXEL(a, r, g, b); 2695 return LUA_BUILD_PIXEL(a, r, g, b);
2696 } 2696 }
2697 2697
2698 // gui.drawpixel(x,y,colour) 2698 // gui.drawpixel(x,y,colour)
2699 static int gui_drawpixel(lua_State *L) 2699 static int gui_drawpixel(lua_State *L)
2700 { 2700 {
2701 int x = luaL_checkinteger(L, 1); 2701 int x = luaL_checkinteger(L, 1);
2702 int y = luaL_checkinteger(L, 2); 2702 int y = luaL_checkinteger(L, 2);
2703 2703
2704 uint32 colour = gui_getcolour(L, 3); 2704 uint32 colour = gui_getcolour(L, 3);
2705 2705
2706 // if (!gui_check_boundary(x, y)) 2706 // if (!gui_check_boundary(x, y))
2707 // luaL_error(L,"bad coordinates"); 2707 // luaL_error(L,"bad coordinates");
2708 gui_prepare(); 2708 gui_prepare();
2709 2709
2710 gui_drawpixel_internal(x, y, colour); 2710 gui_drawpixel_internal(x, y, colour);
2711 2711
2712 return 0; 2712 return 0;
2713 } 2713 }
2714 2714
2715 // gui.drawline(x1,y1,x2,y2,color,skipFirst) 2715 // gui.drawline(x1,y1,x2,y2,color,skipFirst)
2716 static int gui_drawline(lua_State *L) 2716 static int gui_drawline(lua_State *L)
2717 { 2717 {
2718 int x1, y1, x2, y2; 2718 int x1, y1, x2, y2;
2719 uint32 color; 2719 uint32 color;
2720 x1 = luaL_checkinteger(L, 1); 2720 x1 = luaL_checkinteger(L, 1);
2721 y1 = luaL_checkinteger(L, 2); 2721 y1 = luaL_checkinteger(L, 2);
2722 x2 = luaL_checkinteger(L, 3); 2722 x2 = luaL_checkinteger(L, 3);
2723 y2 = luaL_checkinteger(L, 4); 2723 y2 = luaL_checkinteger(L, 4);
2724 color = gui_optcolour(L, 5, LUA_BUILD_PIXEL(255, 255, 255, 255)); 2724 color = gui_optcolour(L, 5, LUA_BUILD_PIXEL(255, 255, 255, 255));
2725 int skipFirst = lua_toboolean(L, 6); 2725 int skipFirst = lua_toboolean(L, 6);
2726 2726
2727 gui_prepare(); 2727 gui_prepare();
2728 2728
2729 gui_drawline_internal(x2, y2, x1, y1, !skipFirst, color); 2729 gui_drawline_internal(x2, y2, x1, y1, !skipFirst, color);
2730 2730
2731 return 0; 2731 return 0;
2732 } 2732 }
2733 2733
2734 // gui.drawbox(x1, y1, x2, y2, fillcolor, outlinecolor) 2734 // gui.drawbox(x1, y1, x2, y2, fillcolor, outlinecolor)
2735 static int gui_drawbox(lua_State *L) 2735 static int gui_drawbox(lua_State *L)
2736 { 2736 {
2737 int x1, y1, x2, y2; 2737 int x1, y1, x2, y2;
2738 uint32 fillcolor; 2738 uint32 fillcolor;
2739 uint32 outlinecolor; 2739 uint32 outlinecolor;
2740 2740
2741 x1 = luaL_checkinteger(L, 1); 2741 x1 = luaL_checkinteger(L, 1);
2742 y1 = luaL_checkinteger(L, 2); 2742 y1 = luaL_checkinteger(L, 2);
2743 x2 = luaL_checkinteger(L, 3); 2743 x2 = luaL_checkinteger(L, 3);
2744 y2 = luaL_checkinteger(L, 4); 2744 y2 = luaL_checkinteger(L, 4);
2745 fillcolor = gui_optcolour(L, 5, LUA_BUILD_PIXEL(63, 255, 255, 255)); 2745 fillcolor = gui_optcolour(L, 5, LUA_BUILD_PIXEL(63, 255, 255, 255));
2746 outlinecolor = gui_optcolour(L, 6, LUA_BUILD_PIXEL(255, LUA_PIXEL_R(fillcolor), LUA_PIXEL_G(fillcolor), LUA_PIXEL_B(fillcolor))); 2746 outlinecolor = gui_optcolour(L, 6, LUA_BUILD_PIXEL(255, LUA_PIXEL_R(fillcolor), LUA_PIXEL_G(fillcolor), LUA_PIXEL_B(fillcolor)));
2747 2747
2748 if (x1 > x2) 2748 if (x1 > x2)
2749 std::swap(x1, x2); 2749 std::swap(x1, x2);
2750 if (y1 > y2) 2750 if (y1 > y2)
2751 std::swap(y1, y2); 2751 std::swap(y1, y2);
2752 2752
2753 gui_prepare(); 2753 gui_prepare();
2754 2754
2755 gui_drawbox_internal(x1, y1, x2, y2, outlinecolor); 2755 gui_drawbox_internal(x1, y1, x2, y2, outlinecolor);
2756 if ((x2 - x1) >= 2 && (y2 - y1) >= 2) 2756 if ((x2 - x1) >= 2 && (y2 - y1) >= 2)
2757 gui_fillbox_internal(x1 + 1, y1 + 1, x2 - 1, y2 - 1, fillcolor); 2757 gui_fillbox_internal(x1 + 1, y1 + 1, x2 - 1, y2 - 1, fillcolor);
2758 2758
2759 return 0; 2759 return 0;
2760 } 2760 }
2761 2761
2762 // gui.drawcircle(x0, y0, radius, colour) 2762 // gui.drawcircle(x0, y0, radius, colour)
2763 static int gui_drawcircle(lua_State *L) 2763 static int gui_drawcircle(lua_State *L)
2764 { 2764 {
2765 int x, y, r; 2765 int x, y, r;
2766 uint32 colour; 2766 uint32 colour;
2767 2767
2768 x = luaL_checkinteger(L, 1); 2768 x = luaL_checkinteger(L, 1);
2769 y = luaL_checkinteger(L, 2); 2769 y = luaL_checkinteger(L, 2);
2770 r = luaL_checkinteger(L, 3); 2770 r = luaL_checkinteger(L, 3);
2771 colour = gui_getcolour(L, 4); 2771 colour = gui_getcolour(L, 4);
2772 2772
2773 gui_prepare(); 2773 gui_prepare();
2774 2774
2775 gui_drawcircle_internal(x, y, r, colour); 2775 gui_drawcircle_internal(x, y, r, colour);
2776 2776
2777 return 0; 2777 return 0;
2778 } 2778 }
2779 2779
2780 // gui.fillbox(x1, y1, x2, y2, colour) 2780 // gui.fillbox(x1, y1, x2, y2, colour)
2781 static int gui_fillbox(lua_State *L) 2781 static int gui_fillbox(lua_State *L)
2782 { 2782 {
2783 int x1, y1, x2, y2; 2783 int x1, y1, x2, y2;
2784 uint32 colour; 2784 uint32 colour;
2785 2785
2786 x1 = luaL_checkinteger(L, 1); 2786 x1 = luaL_checkinteger(L, 1);
2787 y1 = luaL_checkinteger(L, 2); 2787 y1 = luaL_checkinteger(L, 2);
2788 x2 = luaL_checkinteger(L, 3); 2788 x2 = luaL_checkinteger(L, 3);
2789 y2 = luaL_checkinteger(L, 4); 2789 y2 = luaL_checkinteger(L, 4);
2790 colour = gui_getcolour(L, 5); 2790 colour = gui_getcolour(L, 5);
2791 2791
2792 // if (!gui_check_boundary(x1, y1)) 2792 // if (!gui_check_boundary(x1, y1))
2793 // luaL_error(L,"bad coordinates"); 2793 // luaL_error(L,"bad coordinates");
2794 // 2794 //
2795 // if (!gui_check_boundary(x2, y2)) 2795 // if (!gui_check_boundary(x2, y2))
2796 // luaL_error(L,"bad coordinates"); 2796 // luaL_error(L,"bad coordinates");
2797 gui_prepare(); 2797 gui_prepare();
2798 2798
2799 if (!gui_checkbox(x1, y1, x2, y2)) 2799 if (!gui_checkbox(x1, y1, x2, y2))
2800 return 0; 2800 return 0;
2801 2801
2802 gui_fillbox_internal(x1, y1, x2, y2, colour); 2802 gui_fillbox_internal(x1, y1, x2, y2, colour);
2803 2803
2804 return 0; 2804 return 0;
2805 } 2805 }
2806 2806
2807 // gui.fillcircle(x0, y0, radius, colour) 2807 // gui.fillcircle(x0, y0, radius, colour)
2808 static int gui_fillcircle(lua_State *L) 2808 static int gui_fillcircle(lua_State *L)
2809 { 2809 {
2810 int x, y, r; 2810 int x, y, r;
2811 uint32 colour; 2811 uint32 colour;
2812 2812
2813 x = luaL_checkinteger(L, 1); 2813 x = luaL_checkinteger(L, 1);
2814 y = luaL_checkinteger(L, 2); 2814 y = luaL_checkinteger(L, 2);
2815 r = luaL_checkinteger(L, 3); 2815 r = luaL_checkinteger(L, 3);
2816 colour = gui_getcolour(L, 4); 2816 colour = gui_getcolour(L, 4);
2817 2817
2818 gui_prepare(); 2818 gui_prepare();
2819 2819
2820 gui_fillcircle_internal(x, y, r, colour); 2820 gui_fillcircle_internal(x, y, r, colour);
2821 2821
2822 return 0; 2822 return 0;
2823 } 2823 }
2824 2824
2825 static int gui_getpixel(lua_State *L) 2825 static int gui_getpixel(lua_State *L)
2826 { 2826 {
2827 int x = luaL_checkinteger(L, 1); 2827 int x = luaL_checkinteger(L, 1);
2828 int y = luaL_checkinteger(L, 2); 2828 int y = luaL_checkinteger(L, 2);
2829 2829
2830 int pixWidth = 240, pixHeight = 160; 2830 int pixWidth = 240, pixHeight = 160;
2831 int scrWidth = 240, scrHeight = 160; 2831 int scrWidth = 240, scrHeight = 160;
2832 int scrOffsetX = 0, scrOffsetY = 0; 2832 int scrOffsetX = 0, scrOffsetY = 0;
2833 int pitch; 2833 int pitch;
2834 if (!systemIsRunningGBA()) 2834 if (!systemIsRunningGBA())
2835 { 2835 {
2836 if (gbBorderOn) 2836 if (gbBorderOn)
2837 { 2837 {
2838 pixWidth = 256, pixHeight = 224; 2838 pixWidth = 256, pixHeight = 224;
2839 scrOffsetX = 48, scrOffsetY = 40; 2839 scrOffsetX = 48, scrOffsetY = 40;
2840 } 2840 }
2841 else 2841 else
2842 { 2842 {
2843 pixWidth = 160, pixHeight = 144; 2843 pixWidth = 160, pixHeight = 144;
2844 } 2844 }
2845 scrWidth = 160, scrHeight = 144; 2845 scrWidth = 160, scrHeight = 144;
2846 } 2846 }
2847 pitch = pixWidth * (systemColorDepth / 8) + (systemColorDepth == 24 ? 0 : 4); 2847 pitch = pixWidth * (systemColorDepth / 8) + (systemColorDepth == 24 ? 0 : 4);
2848 scrOffsetY++; // don't know why it's needed 2848 scrOffsetY++; // don't know why it's needed
2849 2849
2850 if (!(x >= 0 && y >= 0 && x < scrWidth && y < scrHeight) /*!gui_check_boundary(x,y)*/) 2850 if (!(x >= 0 && y >= 0 && x < scrWidth && y < scrHeight) /*!gui_check_boundary(x,y)*/)
2851 { 2851 {
2852 lua_pushinteger(L, 0); 2852 lua_pushinteger(L, 0);
2853 lua_pushinteger(L, 0); 2853 lua_pushinteger(L, 0);
2854 lua_pushinteger(L, 0); 2854 lua_pushinteger(L, 0);
2855 } 2855 }
2856 else 2856 else
2857 { 2857 {
2858 switch (systemColorDepth) 2858 switch (systemColorDepth)
2859 { 2859 {
2860 case 16: 2860 case 16:
2861 { 2861 {
2862 uint16 *screen = (uint16 *) (&pix[scrOffsetY * pitch + scrOffsetX * 2]); 2862 uint16 *screen = (uint16 *) (&pix[scrOffsetY * pitch + scrOffsetX * 2]);
2863 uint16 pixColor = screen[y * pitch / 2 + x]; 2863 uint16 pixColor = screen[y * pitch / 2 + x];
2864 lua_pushinteger(L, (pixColor >> 8) & 0xF8); // red 2864 lua_pushinteger(L, (pixColor >> 8) & 0xF8); // red
2865 lua_pushinteger(L, (pixColor >> 3) & 0xFC); // green 2865 lua_pushinteger(L, (pixColor >> 3) & 0xFC); // green
2866 lua_pushinteger(L, (pixColor << 3) & 0xF8); // blue 2866 lua_pushinteger(L, (pixColor << 3) & 0xF8); // blue
2867 } 2867 }
2868 break; 2868 break;
2869 case 24: 2869 case 24:
2870 { 2870 {
2871 uint8 *screen = &pix[scrOffsetY * pitch + scrOffsetX * 3]; 2871 uint8 *screen = &pix[scrOffsetY * pitch + scrOffsetX * 3];
2872 lua_pushinteger(L, screen[y * pitch + x * 3 + 2]); // red 2872 lua_pushinteger(L, screen[y * pitch + x * 3 + 2]); // red
2873 lua_pushinteger(L, screen[y * pitch + x * 3 + 1]); // green 2873 lua_pushinteger(L, screen[y * pitch + x * 3 + 1]); // green
2874 lua_pushinteger(L, screen[y * pitch + x * 3 + 0]); // blue 2874 lua_pushinteger(L, screen[y * pitch + x * 3 + 0]); // blue
2875 } 2875 }
2876 break; 2876 break;
2877 case 32: 2877 case 32:
2878 { 2878 {
2879 uint8 *screen = &pix[scrOffsetY * pitch + scrOffsetX * 4]; 2879 uint8 *screen = &pix[scrOffsetY * pitch + scrOffsetX * 4];
2880 lua_pushinteger(L, screen[y * pitch + x * 4 + 2]); // red 2880 lua_pushinteger(L, screen[y * pitch + x * 4 + 2]); // red
2881 lua_pushinteger(L, screen[y * pitch + x * 4 + 1]); // green 2881 lua_pushinteger(L, screen[y * pitch + x * 4 + 1]); // green
2882 lua_pushinteger(L, screen[y * pitch + x * 4 + 0]); // blue 2882 lua_pushinteger(L, screen[y * pitch + x * 4 + 0]); // blue
2883 } 2883 }
2884 break; 2884 break;
2885 default: 2885 default:
2886 lua_pushinteger(L, 0); 2886 lua_pushinteger(L, 0);
2887 lua_pushinteger(L, 0); 2887 lua_pushinteger(L, 0);
2888 lua_pushinteger(L, 0); 2888 lua_pushinteger(L, 0);
2889 break; 2889 break;
2890 } 2890 }
2891 } 2891 }
2892 return 3; 2892 return 3;
2893 } 2893 }
2894 2894
2895 static int gui_parsecolor(lua_State *L) 2895 static int gui_parsecolor(lua_State *L)
2896 { 2896 {
2897 int r, g, b, a; 2897 int r, g, b, a;
2898 uint32 color = gui_getcolour(L, 1); 2898 uint32 color = gui_getcolour(L, 1);
2899 LUA_DECOMPOSE_PIXEL(color, a, r, g, b); 2899 LUA_DECOMPOSE_PIXEL(color, a, r, g, b);
2900 lua_pushinteger(L, r); 2900 lua_pushinteger(L, r);
2901 lua_pushinteger(L, g); 2901 lua_pushinteger(L, g);
2902 lua_pushinteger(L, b); 2902 lua_pushinteger(L, b);
2903 lua_pushinteger(L, a); 2903 lua_pushinteger(L, a);
2904 return 4; 2904 return 4;
2905 } 2905 }
2906 2906
2907 // gui.gdscreenshot() 2907 // gui.gdscreenshot()
2908 // 2908 //
2909 // Returns a screen shot as a string in gd's v1 file format. 2909 // Returns a screen shot as a string in gd's v1 file format.
2910 // This allows us to make screen shots available without gd installed locally. 2910 // This allows us to make screen shots available without gd installed locally.
2913 // I think... Does lua support grabbing byte values from a string? // yes, string.byte(str,offset) 2913 // I think... Does lua support grabbing byte values from a string? // yes, string.byte(str,offset)
2914 // Well, either way, just install gd and do what you like with it. 2914 // Well, either way, just install gd and do what you like with it.
2915 // It really is easier that way. 2915 // It really is easier that way.
2916 2916
2917 // example: gd.createFromGdStr(gui.gdscreenshot()):png("outputimage.png") 2917 // example: gd.createFromGdStr(gui.gdscreenshot()):png("outputimage.png")
2918 static int gui_gdscreenshot(lua_State *L) 2918 static int gui_gdscreenshot(lua_State *L)
2919 { 2919 {
2920 int xofs = 0, yofs = 0, ppl = 240, width = 240, height = 160; 2920 int xofs = 0, yofs = 0, ppl = 240, width = 240, height = 160;
2921 if (!systemIsRunningGBA()) 2921 if (!systemIsRunningGBA())
2922 { 2922 {
2923 if (gbBorderOn) 2923 if (gbBorderOn)
2924 xofs = 48, yofs = 40, ppl = 256; 2924 xofs = 48, yofs = 40, ppl = 256;
2925 else 2925 else
2926 ppl = 160; 2926 ppl = 160;
2927 width = 160, height = 144; 2927 width = 160, height = 144;
2928 } 2928 }
2929 2929
2930 yofs++; 2930 yofs++;
2931 2931
2932 //int pitch = (((ppl * systemColorDepth + 7)>>3)+3)&~3; 2932 //int pitch = (((ppl * systemColorDepth + 7)>>3)+3)&~3;
2933 int pitch = ppl * (systemColorDepth / 8) + (systemColorDepth == 24 ? 0 : 4); 2933 int pitch = ppl * (systemColorDepth / 8) + (systemColorDepth == 24 ? 0 : 4);
2934 uint8 *screen = &pix[yofs * pitch + xofs * (systemColorDepth / 8)]; 2934 uint8 *screen = &pix[yofs * pitch + xofs * (systemColorDepth / 8)];
2935 2935
2936 int size = 11 + width * height * 4; 2936 int size = 11 + width * height * 4;
2937 char *str = new char[size + 1]; 2937 char *str = new char[size + 1];
2938 str[size] = 0; 2938 str[size] = 0;
2939 2939
2940 unsigned char *ptr = (unsigned char *)str; 2940 unsigned char *ptr = (unsigned char *)str;
2941 2941
2942 // GD format header for truecolor image (11 bytes) 2942 // GD format header for truecolor image (11 bytes)
2943 *ptr++ = (65534 >> 8) & 0xFF; 2943 *ptr++ = (65534 >> 8) & 0xFF;
2944 *ptr++ = (65534) & 0xFF; 2944 *ptr++ = (65534) & 0xFF;
2945 *ptr++ = (width >> 8) & 0xFF; 2945 *ptr++ = (width >> 8) & 0xFF;
2946 *ptr++ = (width) & 0xFF; 2946 *ptr++ = (width) & 0xFF;
2947 *ptr++ = (height >> 8) & 0xFF; 2947 *ptr++ = (height >> 8) & 0xFF;
2948 *ptr++ = (height) & 0xFF; 2948 *ptr++ = (height) & 0xFF;
2949 *ptr++ = 1; 2949 *ptr++ = 1;
2950 *ptr++ = 255; 2950 *ptr++ = 255;
2951 *ptr++ = 255; 2951 *ptr++ = 255;
2952 *ptr++ = 255; 2952 *ptr++ = 255;
2953 *ptr++ = 255; 2953 *ptr++ = 255;
2954 2954
2955 GetColorFunc getColor; 2955 GetColorFunc getColor;
2956 getColorIOFunc(systemColorDepth, &getColor, NULL); 2956 getColorIOFunc(systemColorDepth, &getColor, NULL);
2957 2957
2958 int x, y; 2958 int x, y;
2959 for (y = 0; y < height; y++) 2959 for (y = 0; y < height; y++)
2960 { 2960 {
2961 uint8 *s = &screen[y * pitch]; 2961 uint8 *s = &screen[y * pitch];
2962 for (x = 0; x < width; x++, s += systemColorDepth / 8) 2962 for (x = 0; x < width; x++, s += systemColorDepth / 8)
2963 { 2963 {
2964 uint8 r, g, b; 2964 uint8 r, g, b;
2965 getColor(s, &r, &g, &b); 2965 getColor(s, &r, &g, &b);
2966 2966
2967 *ptr++ = 0; 2967 *ptr++ = 0;
2968 *ptr++ = r; 2968 *ptr++ = r;
2969 *ptr++ = g; 2969 *ptr++ = g;
2970 *ptr++ = b; 2970 *ptr++ = b;
2971 } 2971 }
2972 } 2972 }
2973 2973
2974 lua_pushlstring(L, str, size); 2974 lua_pushlstring(L, str, size);
2975 delete[] str; 2975 delete[] str;
2976 return 1; 2976 return 1;
2977 } 2977 }
2978 2978
2979 // gui.opacity(number alphaValue) 2979 // gui.opacity(number alphaValue)
2980 // sets the transparency of subsequent draw calls 2980 // sets the transparency of subsequent draw calls
2981 // 0.0 is completely transparent, 1.0 is completely opaque 2981 // 0.0 is completely transparent, 1.0 is completely opaque
2982 // non-integer values are supported and meaningful, as are values greater than 1.0 2982 // non-integer values are supported and meaningful, as are values greater than 1.0
2983 // it is not necessary to use this function to get transparency (or the less-recommended gui.transparency() either), 2983 // it is not necessary to use this function to get transparency (or the less-recommended gui.transparency() either),
2984 // because you can provide an alpha value in the color argument of each draw call. 2984 // because you can provide an alpha value in the color argument of each draw call.
2985 2985
2986 // however, it can be convenient to be able to globally modify the drawing transparency 2986 // however, it can be convenient to be able to globally modify the drawing transparency
2987 static int gui_setopacity(lua_State *L) 2987 static int gui_setopacity(lua_State *L)
2988 { 2988 {
2989 double opacF = luaL_checknumber(L, 1); 2989 double opacF = luaL_checknumber(L, 1);
2990 transparencyModifier = (int)(opacF * 255); 2990 transparencyModifier = (int)(opacF * 255);
2991 if (transparencyModifier < 0) 2991 if (transparencyModifier < 0)
2992 transparencyModifier = 0; 2992 transparencyModifier = 0;
2993 return 0; 2993 return 0;
2994 } 2994 }
2995 2995
2996 // gui.transparency(int strength) 2996 // gui.transparency(int strength)
2997 // 2997 //
2998 2998
2999 // 0 = solid, 2999 // 0 = solid,
3000 static int gui_transparency(lua_State *L) 3000 static int gui_transparency(lua_State *L)
3001 { 3001 {
3002 double trans = luaL_checknumber(L, 1); 3002 double trans = luaL_checknumber(L, 1);
3003 transparencyModifier = (int)((4.0 - trans) / 4.0 * 255); 3003 transparencyModifier = (int)((4.0 - trans) / 4.0 * 255);
3004 if (transparencyModifier < 0) 3004 if (transparencyModifier < 0)
3005 transparencyModifier = 0; 3005 transparencyModifier = 0;
3006 return 0; 3006 return 0;
3007 } 3007 }
3008 3008
3009 static const uint32 Small_Font_Data[] = 3009 static const uint32 Small_Font_Data[] =
3010 { 3010 {
3011 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // 32 3011 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // 32
3012 0x00000000, 0x00000300, 0x00000400, 0x00000500, 0x00000000, 0x00000700, 0x00000000, // 33 ! 3012 0x00000000, 0x00000300, 0x00000400, 0x00000500, 0x00000000, 0x00000700, 0x00000000, // 33 !
3013 0x00000000, 0x00040002, 0x00050003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // 34 " 3013 0x00000000, 0x00040002, 0x00050003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // 34 "
3014 0x00000000, 0x00040002, 0x00050403, 0x00060004, 0x00070605, 0x00080006, 0x00000000, // 35 # 3014 0x00000000, 0x00040002, 0x00050403, 0x00060004, 0x00070605, 0x00080006, 0x00000000, // 35 #
3015 0x00000000, 0x00040300, 0x00000403, 0x00000500, 0x00070600, 0x00000706, 0x00000000, // 36 $ 3015 0x00000000, 0x00040300, 0x00000403, 0x00000500, 0x00070600, 0x00000706, 0x00000000, // 36 $
3016 0x00000000, 0x00000002, 0x00050000, 0x00000500, 0x00000005, 0x00080000, 0x00000000, // 37 % 3016 0x00000000, 0x00000002, 0x00050000, 0x00000500, 0x00000005, 0x00080000, 0x00000000, // 37 %
3017 0x00000000, 0x00000300, 0x00050003, 0x00000500, 0x00070005, 0x00080700, 0x00000000, // 38 & 3017 0x00000000, 0x00000300, 0x00050003, 0x00000500, 0x00070005, 0x00080700, 0x00000000, // 38 &
3018 0x00000000, 0x00000300, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // 39 ' 3018 0x00000000, 0x00000300, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // 39 '
3019 0x00000000, 0x00000300, 0x00000003, 0x00000004, 0x00000005, 0x00000700, 0x00000000, // 40 ( 3019 0x00000000, 0x00000300, 0x00000003, 0x00000004, 0x00000005, 0x00000700, 0x00000000, // 40 (
3020 0x00000000, 0x00000300, 0x00050000, 0x00060000, 0x00070000, 0x00000700, 0x00000000, // 41 ) 3020 0x00000000, 0x00000300, 0x00050000, 0x00060000, 0x00070000, 0x00000700, 0x00000000, // 41 )
3021 0x00000000, 0x00000000, 0x00000400, 0x00060504, 0x00000600, 0x00080006, 0x00000000, // 42 * 3021 0x00000000, 0x00000000, 0x00000400, 0x00060504, 0x00000600, 0x00080006, 0x00000000, // 42 *
3022 0x00000000, 0x00000000, 0x00000400, 0x00060504, 0x00000600, 0x00000000, 0x00000000, // 43 + 3022 0x00000000, 0x00000000, 0x00000400, 0x00060504, 0x00000600, 0x00000000, 0x00000000, // 43 +
3023 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000600, 0x00000700, 0x00000007, // 44 , 3023 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000600, 0x00000700, 0x00000007, // 44 ,
3024 0x00000000, 0x00000000, 0x00000000, 0x00060504, 0x00000000, 0x00000000, 0x00000000, // 45 - 3024 0x00000000, 0x00000000, 0x00000000, 0x00060504, 0x00000000, 0x00000000, 0x00000000, // 45 -
3025 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000700, 0x00000000, // 46 . 3025 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000700, 0x00000000, // 46 .
3026 0x00030000, 0x00040000, 0x00000400, 0x00000500, 0x00000005, 0x00000006, 0x00000000, // 47 / 3026 0x00030000, 0x00040000, 0x00000400, 0x00000500, 0x00000005, 0x00000006, 0x00000000, // 47 /
3027 0x00000000, 0x00000300, 0x00050003, 0x00060004, 0x00070005, 0x00000700, 0x00000000, // 48 0 3027 0x00000000, 0x00000300, 0x00050003, 0x00060004, 0x00070005, 0x00000700, 0x00000000, // 48 0
3028 0x00000000, 0x00000300, 0x00000403, 0x00000500, 0x00000600, 0x00000700, 0x00000000, // 49 1 3028 0x00000000, 0x00000300, 0x00000403, 0x00000500, 0x00000600, 0x00000700, 0x00000000, // 49 1
3029 0x00000000, 0x00000302, 0x00050000, 0x00000500, 0x00000005, 0x00080706, 0x00000000, // 50 2 3029 0x00000000, 0x00000302, 0x00050000, 0x00000500, 0x00000005, 0x00080706, 0x00000000, // 50 2
3030 0x00000000, 0x00000302, 0x00050000, 0x00000504, 0x00070000, 0x00000706, 0x00000000, // 51 3 3030 0x00000000, 0x00000302, 0x00050000, 0x00000504, 0x00070000, 0x00000706, 0x00000000, // 51 3
3031 0x00000000, 0x00000300, 0x00000003, 0x00060004, 0x00070605, 0x00080000, 0x00000000, // 52 4 3031 0x00000000, 0x00000300, 0x00000003, 0x00060004, 0x00070605, 0x00080000, 0x00000000, // 52 4
3032 0x00000000, 0x00040302, 0x00000003, 0x00000504, 0x00070000, 0x00000706, 0x00000000, // 53 5 3032 0x00000000, 0x00040302, 0x00000003, 0x00000504, 0x00070000, 0x00000706, 0x00000000, // 53 5
3033 0x00000000, 0x00000300, 0x00000003, 0x00000504, 0x00070005, 0x00000700, 0x00000000, // 54 6 3033 0x00000000, 0x00000300, 0x00000003, 0x00000504, 0x00070005, 0x00000700, 0x00000000, // 54 6
3034 0x00000000, 0x00040302, 0x00050000, 0x00000500, 0x00000600, 0x00000700, 0x00000000, // 55 7 3034 0x00000000, 0x00040302, 0x00050000, 0x00000500, 0x00000600, 0x00000700, 0x00000000, // 55 7
3035 0x00000000, 0x00000300, 0x00050003, 0x00000500, 0x00070005, 0x00000700, 0x00000000, // 56 8 3035 0x00000000, 0x00000300, 0x00050003, 0x00000500, 0x00070005, 0x00000700, 0x00000000, // 56 8
3036 0x00000000, 0x00000300, 0x00050003, 0x00060500, 0x00070000, 0x00000700, 0x00000000, // 57 9 3036 0x00000000, 0x00000300, 0x00050003, 0x00060500, 0x00070000, 0x00000700, 0x00000000, // 57 9
3037 0x00000000, 0x00000000, 0x00000400, 0x00000000, 0x00000000, 0x00000700, 0x00000000, // 58 : 3037 0x00000000, 0x00000000, 0x00000400, 0x00000000, 0x00000000, 0x00000700, 0x00000000, // 58 :
3038 0x00000000, 0x00000000, 0x00000000, 0x00000500, 0x00000000, 0x00000700, 0x00000007, // 59 ; 3038 0x00000000, 0x00000000, 0x00000000, 0x00000500, 0x00000000, 0x00000700, 0x00000007, // 59 ;
3039 0x00000000, 0x00040000, 0x00000400, 0x00000004, 0x00000600, 0x00080000, 0x00000000, // 60 < 3039 0x00000000, 0x00040000, 0x00000400, 0x00000004, 0x00000600, 0x00080000, 0x00000000, // 60 <
3040 0x00000000, 0x00000000, 0x00050403, 0x00000000, 0x00070605, 0x00000000, 0x00000000, // 61 = 3040 0x00000000, 0x00000000, 0x00050403, 0x00000000, 0x00070605, 0x00000000, 0x00000000, // 61 =
3041 0x00000000, 0x00000002, 0x00000400, 0x00060000, 0x00000600, 0x00000006, 0x00000000, // 62 > 3041 0x00000000, 0x00000002, 0x00000400, 0x00060000, 0x00000600, 0x00000006, 0x00000000, // 62 >
3042 0x00000000, 0x00000302, 0x00050000, 0x00000500, 0x00000000, 0x00000700, 0x00000000, // 63 ? 3042 0x00000000, 0x00000302, 0x00050000, 0x00000500, 0x00000000, 0x00000700, 0x00000000, // 63 ?
3043 0x00000000, 0x00000300, 0x00050400, 0x00060004, 0x00070600, 0x00000000, 0x00000000, // 64 @ 3043 0x00000000, 0x00000300, 0x00050400, 0x00060004, 0x00070600, 0x00000000, 0x00000000, // 64 @
3044 0x00000000, 0x00000300, 0x00050003, 0x00060504, 0x00070005, 0x00080006, 0x00000000, // 65 A 3044 0x00000000, 0x00000300, 0x00050003, 0x00060504, 0x00070005, 0x00080006, 0x00000000, // 65 A
3045 0x00000000, 0x00000302, 0x00050003, 0x00000504, 0x00070005, 0x00000706, 0x00000000, // 66 B 3045 0x00000000, 0x00000302, 0x00050003, 0x00000504, 0x00070005, 0x00000706, 0x00000000, // 66 B
3046 0x00000000, 0x00040300, 0x00000003, 0x00000004, 0x00000005, 0x00080700, 0x00000000, // 67 C 3046 0x00000000, 0x00040300, 0x00000003, 0x00000004, 0x00000005, 0x00080700, 0x00000000, // 67 C
3047 0x00000000, 0x00000302, 0x00050003, 0x00060004, 0x00070005, 0x00000706, 0x00000000, // 68 D 3047 0x00000000, 0x00000302, 0x00050003, 0x00060004, 0x00070005, 0x00000706, 0x00000000, // 68 D
3048 0x00000000, 0x00040302, 0x00000003, 0x00000504, 0x00000005, 0x00080706, 0x00000000, // 69 E 3048 0x00000000, 0x00040302, 0x00000003, 0x00000504, 0x00000005, 0x00080706, 0x00000000, // 69 E
3049 0x00000000, 0x00040302, 0x00000003, 0x00000504, 0x00000005, 0x00000006, 0x00000000, // 70 F 3049 0x00000000, 0x00040302, 0x00000003, 0x00000504, 0x00000005, 0x00000006, 0x00000000, // 70 F
3050 0x00000000, 0x00040300, 0x00000003, 0x00060004, 0x00070005, 0x00080700, 0x00000000, // 71 G 3050 0x00000000, 0x00040300, 0x00000003, 0x00060004, 0x00070005, 0x00080700, 0x00000000, // 71 G
3051 0x00000000, 0x00040002, 0x00050003, 0x00060504, 0x00070005, 0x00080006, 0x00000000, // 72 H 3051 0x00000000, 0x00040002, 0x00050003, 0x00060504, 0x00070005, 0x00080006, 0x00000000, // 72 H
3052 0x00000000, 0x00000300, 0x00000400, 0x00000500, 0x00000600, 0x00000700, 0x00000000, // 73 I 3052 0x00000000, 0x00000300, 0x00000400, 0x00000500, 0x00000600, 0x00000700, 0x00000000, // 73 I
3053 0x00000000, 0x00040000, 0x00050000, 0x00060000, 0x00070005, 0x00000700, 0x00000000, // 74 J 3053 0x00000000, 0x00040000, 0x00050000, 0x00060000, 0x00070005, 0x00000700, 0x00000000, // 74 J
3054 0x00000000, 0x00040002, 0x00050003, 0x00000504, 0x00070005, 0x00080006, 0x00000000, // 75 K 3054 0x00000000, 0x00040002, 0x00050003, 0x00000504, 0x00070005, 0x00080006, 0x00000000, // 75 K
3055 0x00000000, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00080706, 0x00000000, // 76 l 3055 0x00000000, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00080706, 0x00000000, // 76 l
3056 0x00000000, 0x00040002, 0x00050403, 0x00060004, 0x00070005, 0x00080006, 0x00000000, // 77 M 3056 0x00000000, 0x00040002, 0x00050403, 0x00060004, 0x00070005, 0x00080006, 0x00000000, // 77 M
3057 0x00000000, 0x00000302, 0x00050003, 0x00060004, 0x00070005, 0x00080006, 0x00000000, // 78 N 3057 0x00000000, 0x00000302, 0x00050003, 0x00060004, 0x00070005, 0x00080006, 0x00000000, // 78 N
3058 0x00000000, 0x00040302, 0x00050003, 0x00060004, 0x00070005, 0x00080706, 0x00000000, // 79 O 3058 0x00000000, 0x00040302, 0x00050003, 0x00060004, 0x00070005, 0x00080706, 0x00000000, // 79 O
3059 0x00000000, 0x00000302, 0x00050003, 0x00000504, 0x00000005, 0x00000006, 0x00000000, // 80 P 3059 0x00000000, 0x00000302, 0x00050003, 0x00000504, 0x00000005, 0x00000006, 0x00000000, // 80 P
3060 0x00000000, 0x00040302, 0x00050003, 0x00060004, 0x00070005, 0x00080706, 0x00090000, // 81 Q 3060 0x00000000, 0x00040302, 0x00050003, 0x00060004, 0x00070005, 0x00080706, 0x00090000, // 81 Q
3061 0x00000000, 0x00000302, 0x00050003, 0x00000504, 0x00070005, 0x00080006, 0x00000000, // 82 R 3061 0x00000000, 0x00000302, 0x00050003, 0x00000504, 0x00070005, 0x00080006, 0x00000000, // 82 R
3062 0x00000000, 0x00040300, 0x00000003, 0x00000500, 0x00070000, 0x00000706, 0x00000000, // 83 S 3062 0x00000000, 0x00040300, 0x00000003, 0x00000500, 0x00070000, 0x00000706, 0x00000000, // 83 S
3063 0x00000000, 0x00040302, 0x00000400, 0x00000500, 0x00000600, 0x00000700, 0x00000000, // 84 T 3063 0x00000000, 0x00040302, 0x00000400, 0x00000500, 0x00000600, 0x00000700, 0x00000000, // 84 T
3064 0x00000000, 0x00040002, 0x00050003, 0x00060004, 0x00070005, 0x00080706, 0x00000000, // 85 U 3064 0x00000000, 0x00040002, 0x00050003, 0x00060004, 0x00070005, 0x00080706, 0x00000000, // 85 U
3065 0x00000000, 0x00040002, 0x00050003, 0x00060004, 0x00000600, 0x00000700, 0x00000000, // 86 V 3065 0x00000000, 0x00040002, 0x00050003, 0x00060004, 0x00000600, 0x00000700, 0x00000000, // 86 V
3066 0x00000000, 0x00040002, 0x00050003, 0x00060004, 0x00070605, 0x00080006, 0x00000000, // 87 W 3066 0x00000000, 0x00040002, 0x00050003, 0x00060004, 0x00070605, 0x00080006, 0x00000000, // 87 W
3067 0x00000000, 0x00040002, 0x00050003, 0x00000500, 0x00070005, 0x00080006, 0x00000000, // 88 X 3067 0x00000000, 0x00040002, 0x00050003, 0x00000500, 0x00070005, 0x00080006, 0x00000000, // 88 X
3068 0x00000000, 0x00040002, 0x00050003, 0x00000500, 0x00000600, 0x00000700, 0x00000000, // 89 Y 3068 0x00000000, 0x00040002, 0x00050003, 0x00000500, 0x00000600, 0x00000700, 0x00000000, // 89 Y
3069 0x00000000, 0x00040302, 0x00050000, 0x00000500, 0x00000005, 0x00080706, 0x00000000, // 90 Z 3069 0x00000000, 0x00040302, 0x00050000, 0x00000500, 0x00000005, 0x00080706, 0x00000000, // 90 Z
3070 0x00000000, 0x00040300, 0x00000400, 0x00000500, 0x00000600, 0x00080700, 0x00000000, // 91 [ 3070 0x00000000, 0x00040300, 0x00000400, 0x00000500, 0x00000600, 0x00080700, 0x00000000, // 91 [
3071 0x00000000, 0x00000002, 0x00000400, 0x00000500, 0x00070000, 0x00080000, 0x00000000, // 92 '\' 3071 0x00000000, 0x00000002, 0x00000400, 0x00000500, 0x00070000, 0x00080000, 0x00000000, // 92 '\'
3072 0x00000000, 0x00000302, 0x00000400, 0x00000500, 0x00000600, 0x00000706, 0x00000000, // 93 ] 3072 0x00000000, 0x00000302, 0x00000400, 0x00000500, 0x00000600, 0x00000706, 0x00000000, // 93 ]
3073 0x00000000, 0x00000300, 0x00050003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // 94 ^ 3073 0x00000000, 0x00000300, 0x00050003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // 94 ^
3074 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00080706, 0x00000000, // 95 _ 3074 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00080706, 0x00000000, // 95 _
3075 0x00000000, 0x00000002, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // 96 ` 3075 0x00000000, 0x00000002, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // 96 `
3076 0x00000000, 0x00000000, 0x00050400, 0x00060004, 0x00070005, 0x00080700, 0x00000000, // 97 a 3076 0x00000000, 0x00000000, 0x00050400, 0x00060004, 0x00070005, 0x00080700, 0x00000000, // 97 a
3077 0x00000000, 0x00000002, 0x00000003, 0x00000504, 0x00070005, 0x00000706, 0x00000000, // 98 b 3077 0x00000000, 0x00000002, 0x00000003, 0x00000504, 0x00070005, 0x00000706, 0x00000000, // 98 b
3078 0x00000000, 0x00000000, 0x00050400, 0x00000004, 0x00000005, 0x00080700, 0x00000000, // 99 c 3078 0x00000000, 0x00000000, 0x00050400, 0x00000004, 0x00000005, 0x00080700, 0x00000000, // 99 c
3079 0x00000000, 0x00040000, 0x00050000, 0x00060500, 0x00070005, 0x00080700, 0x00000000, // 100 d 3079 0x00000000, 0x00040000, 0x00050000, 0x00060500, 0x00070005, 0x00080700, 0x00000000, // 100 d
3080 0x00000000, 0x00000000, 0x00050400, 0x00060504, 0x00000005, 0x00080700, 0x00000000, // 101 e 3080 0x00000000, 0x00000000, 0x00050400, 0x00060504, 0x00000005, 0x00080700, 0x00000000, // 101 e
3081 0x00000000, 0x00040300, 0x00000003, 0x00000504, 0x00000005, 0x00000006, 0x00000000, // 102 f 3081 0x00000000, 0x00040300, 0x00000003, 0x00000504, 0x00000005, 0x00000006, 0x00000000, // 102 f
3082 0x00000000, 0x00000000, 0x00050400, 0x00060004, 0x00070600, 0x00080000, 0x00000807, // 103 g 3082 0x00000000, 0x00000000, 0x00050400, 0x00060004, 0x00070600, 0x00080000, 0x00000807, // 103 g
3083 0x00000000, 0x00000002, 0x00000003, 0x00000504, 0x00070005, 0x00080006, 0x00000000, // 104 h 3083 0x00000000, 0x00000002, 0x00000003, 0x00000504, 0x00070005, 0x00080006, 0x00000000, // 104 h
3084 0x00000000, 0x00000300, 0x00000000, 0x00000500, 0x00000600, 0x00000700, 0x00000000, // 105 i 3084 0x00000000, 0x00000300, 0x00000000, 0x00000500, 0x00000600, 0x00000700, 0x00000000, // 105 i
3085 0x00000000, 0x00000300, 0x00000000, 0x00000500, 0x00000600, 0x00000700, 0x00000007, // 106 j 3085 0x00000000, 0x00000300, 0x00000000, 0x00000500, 0x00000600, 0x00000700, 0x00000007, // 106 j
3086 0x00000000, 0x00000002, 0x00000003, 0x00060004, 0x00000605, 0x00080006, 0x00000000, // 107 k 3086 0x00000000, 0x00000002, 0x00000003, 0x00060004, 0x00000605, 0x00080006, 0x00000000, // 107 k
3087 0x00000000, 0x00000300, 0x00000400, 0x00000500, 0x00000600, 0x00080000, 0x00000000, // 108 l 3087 0x00000000, 0x00000300, 0x00000400, 0x00000500, 0x00000600, 0x00080000, 0x00000000, // 108 l
3088 0x00000000, 0x00000000, 0x00050003, 0x00060504, 0x00070005, 0x00080006, 0x00000000, // 109 m 3088 0x00000000, 0x00000000, 0x00050003, 0x00060504, 0x00070005, 0x00080006, 0x00000000, // 109 m
3089 0x00000000, 0x00000000, 0x00000403, 0x00060004, 0x00070005, 0x00080006, 0x00000000, // 110 n 3089 0x00000000, 0x00000000, 0x00000403, 0x00060004, 0x00070005, 0x00080006, 0x00000000, // 110 n
3090 0x00000000, 0x00000000, 0x00000400, 0x00060004, 0x00070005, 0x00000700, 0x00000000, // 111 o 3090 0x00000000, 0x00000000, 0x00000400, 0x00060004, 0x00070005, 0x00000700, 0x00000000, // 111 o
3091 0x00000000, 0x00000000, 0x00000400, 0x00060004, 0x00000605, 0x00000006, 0x00000007, // 112 p 3091 0x00000000, 0x00000000, 0x00000400, 0x00060004, 0x00000605, 0x00000006, 0x00000007, // 112 p
3092 0x00000000, 0x00000000, 0x00000400, 0x00060004, 0x00070600, 0x00080000, 0x00090000, // 113 q 3092 0x00000000, 0x00000000, 0x00000400, 0x00060004, 0x00070600, 0x00080000, 0x00090000, // 113 q
3093 0x00000000, 0x00000000, 0x00050003, 0x00000504, 0x00000005, 0x00000006, 0x00000000, // 114 r 3093 0x00000000, 0x00000000, 0x00050003, 0x00000504, 0x00000005, 0x00000006, 0x00000000, // 114 r
3094 0x00000000, 0x00000000, 0x00050400, 0x00000004, 0x00070600, 0x00000706, 0x00000000, // 115 s 3094 0x00000000, 0x00000000, 0x00050400, 0x00000004, 0x00070600, 0x00000706, 0x00000000, // 115 s
3095 0x00000000, 0x00000300, 0x00050403, 0x00000500, 0x00000600, 0x00080000, 0x00000000, // 116 t 3095 0x00000000, 0x00000300, 0x00050403, 0x00000500, 0x00000600, 0x00080000, 0x00000000, // 116 t
3096 0x00000000, 0x00000000, 0x00050003, 0x00060004, 0x00070005, 0x00080700, 0x00000000, // 117 u 3096 0x00000000, 0x00000000, 0x00050003, 0x00060004, 0x00070005, 0x00080700, 0x00000000, // 117 u
3097 0x00000000, 0x00000000, 0x00050003, 0x00060004, 0x00070005, 0x00000700, 0x00000000, // 118 v 3097 0x00000000, 0x00000000, 0x00050003, 0x00060004, 0x00070005, 0x00000700, 0x00000000, // 118 v
3098 0x00000000, 0x00000000, 0x00050003, 0x00060004, 0x00070605, 0x00080006, 0x00000000, // 119 w 3098 0x00000000, 0x00000000, 0x00050003, 0x00060004, 0x00070605, 0x00080006, 0x00000000, // 119 w
3099 0x00000000, 0x00000000, 0x00050003, 0x00000500, 0x00070005, 0x00080006, 0x00000000, // 120 x 3099 0x00000000, 0x00000000, 0x00050003, 0x00000500, 0x00070005, 0x00080006, 0x00000000, // 120 x
3100 0x00000000, 0x00000000, 0x00050003, 0x00060004, 0x00000600, 0x00000700, 0x00000007, // 121 y 3100 0x00000000, 0x00000000, 0x00050003, 0x00060004, 0x00000600, 0x00000700, 0x00000007, // 121 y
3101 0x00000000, 0x00000000, 0x00050403, 0x00000500, 0x00000005, 0x00080706, 0x00000000, // 122 z 3101 0x00000000, 0x00000000, 0x00050403, 0x00000500, 0x00000005, 0x00080706, 0x00000000, // 122 z
3102 0x00000000, 0x00040300, 0x00000400, 0x00000504, 0x00000600, 0x00080700, 0x00000000, // 123 { 3102 0x00000000, 0x00040300, 0x00000400, 0x00000504, 0x00000600, 0x00080700, 0x00000000, // 123 {
3103 0x00000000, 0x00000300, 0x00000400, 0x00000000, 0x00000600, 0x00000700, 0x00000000, // 124 | 3103 0x00000000, 0x00000300, 0x00000400, 0x00000000, 0x00000600, 0x00000700, 0x00000000, // 124 |
3104 0x00000000, 0x00000302, 0x00000400, 0x00060500, 0x00000600, 0x00000706, 0x00000000, // 125 } 3104 0x00000000, 0x00000302, 0x00000400, 0x00060500, 0x00000600, 0x00000706, 0x00000000, // 125 }
3105 0x00000000, 0x00000302, 0x00050000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // 126 ~ 3105 0x00000000, 0x00000302, 0x00050000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // 126 ~
3106 0x00000000, 0x00000000, 0x00000400, 0x00060004, 0x00070605, 0x00000000, 0x00000000, // 127  3106 0x00000000, 0x00000000, 0x00000400, 0x00060004, 0x00070605, 0x00000000, 0x00000000, // 127 
3107 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 3107 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
3108 }; 3108 };
3109 3109
3110 static void PutTextInternal(const char *str, int len, short x, short y, int color, int backcolor) 3110 static void PutTextInternal(const char *str, int len, short x, short y, int color, int backcolor)
3111 { 3111 {
3112 int Opac = (color >> 24) & 0xFF; 3112 int Opac = (color >> 24) & 0xFF;
3113 int backOpac = (backcolor >> 24) & 0xFF; 3113 int backOpac = (backcolor >> 24) & 0xFF;
3114 int origX = x; 3114 int origX = x;
3115 3115
3116 if (!Opac && !backOpac) 3116 if (!Opac && !backOpac)
3117 return; 3117 return;
3118 3118
3119 while (*str && len && y < LUA_SCREEN_HEIGHT) 3119 while (*str && len && y < LUA_SCREEN_HEIGHT)
3120 { 3120 {
3121 int c = *str++; 3121 int c = *str++;
3122 while (x > LUA_SCREEN_WIDTH && c != '\n') 3122 while (x > LUA_SCREEN_WIDTH && c != '\n')
3123 { 3123 {
3124 c = *str; 3124 c = *str;
3125 if (c == '\0') 3125 if (c == '\0')
3126 break; 3126 break;
3127 str++; 3127 str++;
3128 } 3128 }
3129 3129
3130 if (c == '\n') 3130 if (c == '\n')
3131 { 3131 {
3132 x = origX; 3132 x = origX;
3133 y += 8; 3133 y += 8;
3134 continue; 3134 continue;
3135 } 3135 }
3136 else if (c == '\t') // just in case 3136 else if (c == '\t') // just in case
3137 { 3137 {
3138 const int tabSpace = 8; 3138 const int tabSpace = 8;
3139 x += (tabSpace - (((x - origX) / 4) % tabSpace)) * 4; 3139 x += (tabSpace - (((x - origX) / 4) % tabSpace)) * 4;
3140 continue; 3140 continue;
3141 } 3141 }
3142 3142
3143 if ((unsigned int)(c - 32) >= 96) 3143 if ((unsigned int)(c - 32) >= 96)
3144 continue; 3144 continue;
3145 3145
3146 const unsigned char *Cur_Glyph = (const unsigned char *) &Small_Font_Data + (c - 32) * 7 * 4; 3146 const unsigned char *Cur_Glyph = (const unsigned char *) &Small_Font_Data + (c - 32) * 7 * 4;
3147 3147
3148 for (int y2 = 0; y2 < 8; y2++) 3148 for (int y2 = 0; y2 < 8; y2++)
3149 { 3149 {
3150 unsigned int glyphLine = *((unsigned int *)Cur_Glyph + y2); 3150 unsigned int glyphLine = *((unsigned int *)Cur_Glyph + y2);
3151 for (int x2 = -1; x2 < 4; x2++) 3151 for (int x2 = -1; x2 < 4; x2++)
3152 { 3152 {
3153 int shift = x2 << 3; 3153 int shift = x2 << 3;
3154 int mask = 0xFF << shift; 3154 int mask = 0xFF << shift;
3155 int intensity = (glyphLine & mask) >> shift; 3155 int intensity = (glyphLine & mask) >> shift;
3156 3156
3157 if (intensity && x2 >= 0 && y2 < 7) 3157 if (intensity && x2 >= 0 && y2 < 7)
3158 { 3158 {
3159 //int xdraw = max(0,min(LUA_SCREEN_WIDTH - 1,x+x2)); 3159 //int xdraw = max(0,min(LUA_SCREEN_WIDTH - 1,x+x2));
3160 //int ydraw = max(0,min(LUA_SCREEN_HEIGHT - 1,y+y2)); 3160 //int ydraw = max(0,min(LUA_SCREEN_HEIGHT - 1,y+y2));
3161 //gui_drawpixel_fast(xdraw, ydraw, color); 3161 //gui_drawpixel_fast(xdraw, ydraw, color);
3162 gui_drawpixel_internal(x + x2, y + y2, color); 3162 gui_drawpixel_internal(x + x2, y + y2, color);
3163 } 3163 }
3164 else if (backOpac) 3164 else if (backOpac)
3165 { 3165 {
3166 for (int y3 = max(0, y2 - 1); y3 <= min(6, y2 + 1); y3++) 3166 for (int y3 = max(0, y2 - 1); y3 <= min(6, y2 + 1); y3++)
3167 { 3167 {
3168 unsigned int glyphLine = *((unsigned int *)Cur_Glyph + y3); 3168 unsigned int glyphLine = *((unsigned int *)Cur_Glyph + y3);
3169 for (int x3 = max(0, x2 - 1); x3 <= min(3, x2 + 1); x3++) 3169 for (int x3 = max(0, x2 - 1); x3 <= min(3, x2 + 1); x3++)
3170 { 3170 {
3171 int shift = x3 << 3; 3171 int shift = x3 << 3;
3172 int mask = 0xFF << shift; 3172 int mask = 0xFF << shift;
3173 intensity |= (glyphLine & mask) >> shift; 3173 intensity |= (glyphLine & mask) >> shift;
3174 if (intensity) 3174 if (intensity)
3175 goto draw_outline; // speedup? 3175 goto draw_outline; // speedup?
3176 } 3176 }
3177 } 3177 }
3178 3178
3179 draw_outline: 3179 draw_outline:
3180 if (intensity) 3180 if (intensity)
3181 { 3181 {
3182 //int xdraw = max(0,min(LUA_SCREEN_WIDTH - 1,x+x2)); 3182 //int xdraw = max(0,min(LUA_SCREEN_WIDTH - 1,x+x2));
3183 //int ydraw = max(0,min(LUA_SCREEN_HEIGHT - 1,y+y2)); 3183 //int ydraw = max(0,min(LUA_SCREEN_HEIGHT - 1,y+y2));
3184 //gui_drawpixel_fast(xdraw, ydraw, backcolor); 3184 //gui_drawpixel_fast(xdraw, ydraw, backcolor);
3185 gui_drawpixel_internal(x + x2, y + y2, backcolor); 3185 gui_drawpixel_internal(x + x2, y + y2, backcolor);
3186 } 3186 }
3187 } 3187 }
3188 } 3188 }
3189 } 3189 }
3190 3190
3191 x += 4; 3191 x += 4;
3192 len--; 3192 len--;
3193 } 3193 }
3194 } 3194 }
3195 3195
3196 static int strlinelen(const char *string) 3196 static int strlinelen(const char *string)
3197 { 3197 {
3198 const char *s = string; 3198 const char *s = string;
3199 while (*s && *s != '\n') 3199 while (*s && *s != '\n')
3200 s++; 3200 s++;
3201 if (*s) 3201 if (*s)
3202 s++; 3202 s++;
3203 return s - string; 3203 return s - string;
3204 } 3204 }
3205 3205
3206 static void LuaDisplayString(const char *string, int y, int x, uint32 color, uint32 outlineColor) 3206 static void LuaDisplayString(const char *string, int y, int x, uint32 color, uint32 outlineColor)
3207 { 3207 {
3208 if (!string) 3208 if (!string)
3209 return; 3209 return;
3210 3210
3211 gui_prepare(); 3211 gui_prepare();
3212 3212
3213 PutTextInternal(string, strlen(string), x, y, color, outlineColor); 3213 PutTextInternal(string, strlen(string), x, y, color, outlineColor);
3214 3214
3215 /* 3215 /*
3216 const char* ptr = string; 3216 const char* ptr = string;
3217 while(*ptr && y < LUA_SCREEN_HEIGHT) 3217 while(*ptr && y < LUA_SCREEN_HEIGHT)
3218 { 3218 {
3219 int len = strlinelen(ptr); 3219 int len = strlinelen(ptr);
3220 int skip = 0; 3220 int skip = 0;
3221 if(len < 1) len = 1; 3221 if(len < 1) len = 1;
3222 3222
3223 // break up the line if it's too long to display otherwise 3223 // break up the line if it's too long to display otherwise
3224 if(len > 63) 3224 if(len > 63)
3225 { 3225 {
3226 len = 63; 3226 len = 63;
3227 const char* ptr2 = ptr + len-1; 3227 const char* ptr2 = ptr + len-1;
3228 for(int j = len-1; j; j--, ptr2--) 3228 for(int j = len-1; j; j--, ptr2--)
3229 { 3229 {
3230 if(*ptr2 == ' ' || *ptr2 == '\t') 3230 if(*ptr2 == ' ' || *ptr2 == '\t')
3231 { 3231 {
3232 len = j; 3232 len = j;
3233 skip = 1; 3233 skip = 1;
3234 break; 3234 break;
3235 } 3235 }
3236 } 3236 }
3237 } 3237 }
3238 3238
3239 int xl = 0; 3239 int xl = 0;
3240 int yl = 0; 3240 int yl = 0;
3241 int xh = (LUA_SCREEN_WIDTH - 1 - 1) - 4*len; 3241 int xh = (LUA_SCREEN_WIDTH - 1 - 1) - 4*len;
3242 int yh = LUA_SCREEN_HEIGHT - 1; 3242 int yh = LUA_SCREEN_HEIGHT - 1;
3243 int x2 = min(max(x,xl),xh); 3243 int x2 = min(max(x,xl),xh);
3244 int y2 = min(max(y,yl),yh); 3244 int y2 = min(max(y,yl),yh);
3245 3245
3246 PutTextInternal(ptr,len,x2,y2,color,outlineColor); 3246 PutTextInternal(ptr,len,x2,y2,color,outlineColor);
3247 3247
3248 ptr += len + skip; 3248 ptr += len + skip;
3249 y += 8; 3249 y += 8;
3250 } 3250 }
3251 */ 3251 */
3252 } 3252 }
3253 3253
3254 // gui.text(int x, int y, string msg) 3254 // gui.text(int x, int y, string msg)
3255 // 3255 //
3256 // Displays the given text on the screen, using the same font and techniques as the 3256 // Displays the given text on the screen, using the same font and techniques as the
3257 3257
3258 // main HUD. 3258 // main HUD.
3259 static int gui_text(lua_State *L) 3259 static int gui_text(lua_State *L)
3260 { 3260 {
3261 //extern int font_height; 3261 //extern int font_height;
3262 const char *msg; 3262 const char *msg;
3263 int x, y; 3263 int x, y;
3264 uint32 colour, borderColour; 3264 uint32 colour, borderColour;
3265 3265
3266 x = luaL_checkinteger(L, 1); 3266 x = luaL_checkinteger(L, 1);
3267 y = luaL_checkinteger(L, 2); 3267 y = luaL_checkinteger(L, 2);
3268 //msg = luaL_checkstring(L, 3); 3268 //msg = luaL_checkstring(L, 3);
3269 msg = toCString(L, 3); 3269 msg = toCString(L, 3);
3270 3270
3271 // if (x < 0 || x >= LUA_SCREEN_WIDTH || y < 0 || y >= (LUA_SCREEN_HEIGHT - font_height)) 3271 // if (x < 0 || x >= LUA_SCREEN_WIDTH || y < 0 || y >= (LUA_SCREEN_HEIGHT - font_height))
3272 // luaL_error(L,"bad coordinates"); 3272 // luaL_error(L,"bad coordinates");
3273 colour = gui_optcolour(L, 4, LUA_BUILD_PIXEL(255, 255, 255, 255)); 3273 colour = gui_optcolour(L, 4, LUA_BUILD_PIXEL(255, 255, 255, 255));
3274 borderColour = gui_optcolour(L, 5, LUA_BUILD_PIXEL(255, 0, 0, 0)); 3274 borderColour = gui_optcolour(L, 5, LUA_BUILD_PIXEL(255, 0, 0, 0));
3275 3275
3276 gui_prepare(); 3276 gui_prepare();
3277 3277
3278 LuaDisplayString(msg, y, x, colour, borderColour); 3278 LuaDisplayString(msg, y, x, colour, borderColour);
3279 3279
3280 return 0; 3280 return 0;
3281 } 3281 }
3282 3282
3283 // gui.gdoverlay([int dx=0, int dy=0,] string str [, sx=0, sy=0, sw, sh] [, float alphamul=1.0]) 3283 // gui.gdoverlay([int dx=0, int dy=0,] string str [, sx=0, sy=0, sw, sh] [, float alphamul=1.0])
3284 // 3284 //
3285 // Overlays the given image on the screen. 3285 // Overlays the given image on the screen.
3286 3286
3287 // example: gui.gdoverlay(gd.createFromPng("myimage.png"):gdStr()) 3287 // example: gui.gdoverlay(gd.createFromPng("myimage.png"):gdStr())
3288 static int gui_gdoverlay(lua_State *L) 3288 static int gui_gdoverlay(lua_State *L)
3289 { 3289 {
3290 int argCount = lua_gettop(L); 3290 int argCount = lua_gettop(L);
3291 3291
3292 int xStartDst = 0; 3292 int xStartDst = 0;
3293 int yStartDst = 0; 3293 int yStartDst = 0;
3294 int xStartSrc = 0; 3294 int xStartSrc = 0;
3295 int yStartSrc = 0; 3295 int yStartSrc = 0;
3296 3296
3297 int index = 1; 3297 int index = 1;
3298 if (lua_type(L, index) == LUA_TNUMBER) 3298 if (lua_type(L, index) == LUA_TNUMBER)
3299 { 3299 {
3300 xStartDst = lua_tointeger(L, index++); 3300 xStartDst = lua_tointeger(L, index++);
3301 if (lua_type(L, index) == LUA_TNUMBER) 3301 if (lua_type(L, index) == LUA_TNUMBER)
3302 yStartDst = lua_tointeger(L, index++); 3302 yStartDst = lua_tointeger(L, index++);
3303 } 3303 }
3304 3304
3305 luaL_checktype(L, index, LUA_TSTRING); 3305 luaL_checktype(L, index, LUA_TSTRING);
3306 3306
3307 const unsigned char *ptr = (const unsigned char *)lua_tostring(L, index++); 3307 const unsigned char *ptr = (const unsigned char *)lua_tostring(L, index++);
3308 3308
3309 if (ptr[0] != 255 || (ptr[1] != 254 && ptr[1] != 255)) 3309 if (ptr[0] != 255 || (ptr[1] != 254 && ptr[1] != 255))
3310 luaL_error(L, "bad image data"); 3310 luaL_error(L, "bad image data");
3311 3311
3312 bool trueColor = (ptr[1] == 254); 3312 bool trueColor = (ptr[1] == 254);
3313 ptr += 2; 3313 ptr += 2;
3314 3314
3315 int imgwidth = *ptr++ << 8; 3315 int imgwidth = *ptr++ << 8;
3316 imgwidth |= *ptr++; 3316 imgwidth |= *ptr++;
3317 3317
3318 int width = imgwidth; 3318 int width = imgwidth;
3319 int imgheight = *ptr++ << 8; 3319 int imgheight = *ptr++ << 8;
3320 imgheight |= *ptr++; 3320 imgheight |= *ptr++;
3321 3321
3322 int height = imgheight; 3322 int height = imgheight;
3323 if ((!trueColor && *ptr) || (trueColor && !*ptr)) 3323 if ((!trueColor && *ptr) || (trueColor && !*ptr))
3324 luaL_error(L, "bad image data"); 3324 luaL_error(L, "bad image data");
3325 ptr++; 3325 ptr++;
3326 3326
3327 int pitch = imgwidth * (trueColor ? 4 : 1); 3327 int pitch = imgwidth * (trueColor ? 4 : 1);
3328 3328
3329 if ((argCount - index + 1) >= 4) 3329 if ((argCount - index + 1) >= 4)
3330 { 3330 {
3331 xStartSrc = luaL_checkinteger(L, index++); 3331 xStartSrc = luaL_checkinteger(L, index++);
3332 yStartSrc = luaL_checkinteger(L, index++); 3332 yStartSrc = luaL_checkinteger(L, index++);
3333 width = luaL_checkinteger(L, index++); 3333 width = luaL_checkinteger(L, index++);
3334 height = luaL_checkinteger(L, index++); 3334 height = luaL_checkinteger(L, index++);
3335 } 3335 }
3336 3336
3337 int alphaMul = transparencyModifier; 3337 int alphaMul = transparencyModifier;
3338 if (lua_isnumber(L, index)) 3338 if (lua_isnumber(L, index))
3339 alphaMul = (int)(alphaMul * lua_tonumber(L, index++)); 3339 alphaMul = (int)(alphaMul * lua_tonumber(L, index++));
3340 if (alphaMul <= 0) 3340 if (alphaMul <= 0)
3341 return 0; 3341 return 0;
3342 3342
3343 // since there aren't that many possible opacity levels, 3343 // since there aren't that many possible opacity levels,
3344 // do the opacity modification calculations beforehand instead of per pixel 3344 // do the opacity modification calculations beforehand instead of per pixel
3345 int opacMap[256]; 3345 int opacMap[256];
3346 for (int i = 0; i < 128; i++) 3346 for (int i = 0; i < 128; i++)
3347 { 3347 {
3348 int opac = 255 - ((i << 1) | (i & 1)); // gdAlphaMax = 127, not 255 3348 int opac = 255 - ((i << 1) | (i & 1)); // gdAlphaMax = 127, not 255
3349 opac = (opac * alphaMul) / 255; 3349 opac = (opac * alphaMul) / 255;
3350 if (opac < 0) 3350 if (opac < 0)
3351 opac = 0; 3351 opac = 0;
3352 if (opac > 255) 3352 if (opac > 255)
3353 opac = 255; 3353 opac = 255;
3354 opacMap[i] = opac; 3354 opacMap[i] = opac;
3355 } 3355 }
3356 3356
3357 for (int i = 128; i < 256; i++) 3357 for (int i = 128; i < 256; i++)
3358 opacMap[i] = 0; // what should we do for them, actually? 3358 opacMap[i] = 0; // what should we do for them, actually?
3359 int colorsTotal = 0; 3359 int colorsTotal = 0;
3360 if (!trueColor) 3360 if (!trueColor)
3361 { 3361 {
3362 colorsTotal = *ptr++ << 8; 3362 colorsTotal = *ptr++ << 8;
3363 colorsTotal |= *ptr++; 3363 colorsTotal |= *ptr++;
3364 } 3364 }
3365 3365
3366 int transparent = *ptr++ << 24; 3366 int transparent = *ptr++ << 24;
3367 transparent |= *ptr++ << 16; 3367 transparent |= *ptr++ << 16;
3368 transparent |= *ptr++ << 8; 3368 transparent |= *ptr++ << 8;
3369 transparent |= *ptr++; 3369 transparent |= *ptr++;
3370 struct 3370 struct
3371 { 3371 {
3372 uint8 r, g, b, a; 3372 uint8 r, g, b, a;
3373 } pal[256]; 3373 } pal[256];
3374 if (!trueColor) 3374 if (!trueColor)
3375 for (int i = 0; i < 256; i++) 3375 for (int i = 0; i < 256; i++)
3376 { 3376 {
3377 pal[i].r = *ptr++; 3377 pal[i].r = *ptr++;
3378 pal[i].g = *ptr++; 3378 pal[i].g = *ptr++;
3379 pal[i].b = *ptr++; 3379 pal[i].b = *ptr++;
3380 pal[i].a = opacMap[*ptr++]; 3380 pal[i].a = opacMap[*ptr++];
3381 } 3381 }
3382 3382
3383 // some of clippings 3383 // some of clippings
3384 if (xStartSrc < 0) 3384 if (xStartSrc < 0)
3385 { 3385 {
3386 width += xStartSrc; 3386 width += xStartSrc;
3387 xStartDst -= xStartSrc; 3387 xStartDst -= xStartSrc;
3388 xStartSrc = 0; 3388 xStartSrc = 0;
3389 } 3389 }
3390 3390
3391 if (yStartSrc < 0) 3391 if (yStartSrc < 0)
3392 { 3392 {
3393 height += yStartSrc; 3393 height += yStartSrc;
3394 yStartDst -= yStartSrc; 3394 yStartDst -= yStartSrc;
3395 yStartSrc = 0; 3395 yStartSrc = 0;
3396 } 3396 }
3397 3397
3398 if (xStartSrc + width >= imgwidth) 3398 if (xStartSrc + width >= imgwidth)
3399 width = imgwidth - xStartSrc; 3399 width = imgwidth - xStartSrc;
3400 if (yStartSrc + height >= imgheight) 3400 if (yStartSrc + height >= imgheight)
3401 height = imgheight - yStartSrc; 3401 height = imgheight - yStartSrc;
3402 if (xStartDst < 0) 3402 if (xStartDst < 0)
3403 { 3403 {
3404 width += xStartDst; 3404 width += xStartDst;
3405 if (width <= 0) 3405 if (width <= 0)
3406 return 0; 3406 return 0;
3407 xStartSrc = -xStartDst; 3407 xStartSrc = -xStartDst;
3408 xStartDst = 0; 3408 xStartDst = 0;
3409 } 3409 }
3410 3410
3411 if (yStartDst < 0) 3411 if (yStartDst < 0)
3412 { 3412 {
3413 height += yStartDst; 3413 height += yStartDst;
3414 if (height <= 0) 3414 if (height <= 0)
3415 return 0; 3415 return 0;
3416 yStartSrc = -yStartDst; 3416 yStartSrc = -yStartDst;
3417 yStartDst = 0; 3417 yStartDst = 0;
3418 } 3418 }
3419 3419
3420 if (xStartDst + width >= LUA_SCREEN_WIDTH) 3420 if (xStartDst + width >= LUA_SCREEN_WIDTH)
3421 width = LUA_SCREEN_WIDTH - xStartDst; 3421 width = LUA_SCREEN_WIDTH - xStartDst;
3422 if (yStartDst + height >= LUA_SCREEN_HEIGHT) 3422 if (yStartDst + height >= LUA_SCREEN_HEIGHT)
3423 height = LUA_SCREEN_HEIGHT - yStartDst; 3423 height = LUA_SCREEN_HEIGHT - yStartDst;
3424 if (width <= 0 || height <= 0) 3424 if (width <= 0 || height <= 0)
3425 return 0; // out of screen or invalid size 3425 return 0; // out of screen or invalid size
3426 gui_prepare(); 3426 gui_prepare();
3427 3427
3428 const uint8 *pix = (const uint8 *)(&ptr[yStartSrc * pitch + (xStartSrc * (trueColor ? 4 : 1))]); 3428 const uint8 *pix = (const uint8 *)(&ptr[yStartSrc * pitch + (xStartSrc * (trueColor ? 4 : 1))]);
3429 int bytesToNextLine = pitch - (width * (trueColor ? 4 : 1)); 3429 int bytesToNextLine = pitch - (width * (trueColor ? 4 : 1));
3430 if (trueColor) 3430 if (trueColor)
3431 { 3431 {
3432 for (int y = yStartDst; y < height + yStartDst && y < LUA_SCREEN_HEIGHT; y++, pix += bytesToNextLine) 3432 for (int y = yStartDst; y < height + yStartDst && y < LUA_SCREEN_HEIGHT; y++, pix += bytesToNextLine)
3433 { 3433 {
3434 for (int x = xStartDst; x < width + xStartDst && x < LUA_SCREEN_WIDTH; x++, pix += 4) 3434 for (int x = xStartDst; x < width + xStartDst && x < LUA_SCREEN_WIDTH; x++, pix += 4)
3435 { 3435 {
3436 gui_drawpixel_fast(x, y, LUA_BUILD_PIXEL(opacMap[pix[0]], pix[1], pix[2], pix[3])); 3436 gui_drawpixel_fast(x, y, LUA_BUILD_PIXEL(opacMap[pix[0]], pix[1], pix[2], pix[3]));
3437 } 3437 }
3438 } 3438 }
3439 } 3439 }
3440 else 3440 else
3441 { 3441 {
3442 for (int y = yStartDst; y < height + yStartDst && y < LUA_SCREEN_HEIGHT; y++, pix += bytesToNextLine) 3442 for (int y = yStartDst; y < height + yStartDst && y < LUA_SCREEN_HEIGHT; y++, pix += bytesToNextLine)
3443 { 3443 {
3444 for (int x = xStartDst; x < width + xStartDst && x < LUA_SCREEN_WIDTH; x++, pix++) 3444 for (int x = xStartDst; x < width + xStartDst && x < LUA_SCREEN_WIDTH; x++, pix++)
3445 { 3445 {
3446 gui_drawpixel_fast(x, y, LUA_BUILD_PIXEL(pal[*pix].a, pal[*pix].r, pal[*pix].g, pal[*pix].b)); 3446 gui_drawpixel_fast(x, y, LUA_BUILD_PIXEL(pal[*pix].a, pal[*pix].r, pal[*pix].g, pal[*pix].b));
3447 } 3447 }
3448 } 3448 }
3449 } 3449 }
3450 3450
3451 return 0; 3451 return 0;
3452 } 3452 }
3453 3453
3454 // function gui.register(function f) 3454 // function gui.register(function f)
3455 // 3455 //
3456 // This function will be called just before a graphical update. 3456 // This function will be called just before a graphical update.
3457 // More complicated, but doesn't suffer any frame delays. 3457 // More complicated, but doesn't suffer any frame delays.
3458 // Nil will be accepted in place of a function to erase 3458 // Nil will be accepted in place of a function to erase
3459 // a previously registered function, and the previous function 3459 // a previously registered function, and the previous function
3460 3460
3461 // (if any) is returned, or nil if none. 3461 // (if any) is returned, or nil if none.
3462 static int gui_register(lua_State *L) 3462 static int gui_register(lua_State *L)
3463 { 3463 {
3464 // We'll do this straight up. 3464 // We'll do this straight up.
3465 // First set up the stack. 3465 // First set up the stack.
3466 lua_settop(L, 1); 3466 lua_settop(L, 1);
3467 3467
3468 // Verify the validity of the entry 3468 // Verify the validity of the entry
3469 if (!lua_isnil(L, 1)) 3469 if (!lua_isnil(L, 1))
3470 luaL_checktype(L, 1, LUA_TFUNCTION); 3470 luaL_checktype(L, 1, LUA_TFUNCTION);
3471 3471
3472 // Get the old value 3472 // Get the old value
3473 lua_getfield(L, LUA_REGISTRYINDEX, guiCallbackTable); 3473 lua_getfield(L, LUA_REGISTRYINDEX, guiCallbackTable);
3474 3474
3475 // Save the new value 3475 // Save the new value
3476 lua_pushvalue(L, 1); 3476 lua_pushvalue(L, 1);
3477 lua_setfield(L, LUA_REGISTRYINDEX, guiCallbackTable); 3477 lua_setfield(L, LUA_REGISTRYINDEX, guiCallbackTable);
3478 3478
3479 // The old value is on top of the stack. Return it. 3479 // The old value is on top of the stack. Return it.
3480 return 1; 3480 return 1;
3481 } 3481 }
3482 3482
3483 // string gui.popup(string message, [string type = "ok"]) 3483 // string gui.popup(string message, [string type = "ok"])
3484 // 3484 //
3485 3485
3486 // Popup dialog! 3486 // Popup dialog!
3487 int gui_popup(lua_State *L) 3487 int gui_popup(lua_State *L)
3488 { 3488 {
3489 const char *message = luaL_checkstring(L, 1); 3489 const char *message = luaL_checkstring(L, 1);
3490 const char *type = luaL_optstring(L, 2, "ok"); 3490 const char *type = luaL_optstring(L, 2, "ok");
3491 3491
3492 #if (defined(WIN32) && !defined(SDL)) 3492 #if (defined(WIN32) && !defined(SDL))
3493 int t; 3493 int t;
3494 if (strcmp(type, "ok") == 0) 3494 if (strcmp(type, "ok") == 0)
3495 t = MB_OK; 3495 t = MB_OK;
3496 else if (strcmp(type, "yesno") == 0) 3496 else if (strcmp(type, "yesno") == 0)
3497 t = MB_YESNO; 3497 t = MB_YESNO;
3498 else if (strcmp(type, "yesnocancel") == 0) 3498 else if (strcmp(type, "yesnocancel") == 0)
3499 t = MB_YESNOCANCEL; 3499 t = MB_YESNOCANCEL;
3500 else 3500 else
3501 return luaL_error(L, "invalid popup type \"%s\"", type); 3501 return luaL_error(L, "invalid popup type \"%s\"", type);
3502 3502
3503 theApp.winCheckFullscreen(); 3503 theApp.winCheckFullscreen();
3504 systemSoundClearBuffer(); 3504 systemSoundClearBuffer();
3505 int result = AfxGetApp()->m_pMainWnd->MessageBox(message, "Lua Script Pop-up", t); 3505 int result = AfxGetApp()->m_pMainWnd->MessageBox(message, "Lua Script Pop-up", t);
3506 3506
3507 lua_settop(L, 1); 3507 lua_settop(L, 1);
3508 3508
3509 if (t != MB_OK) 3509 if (t != MB_OK)
3510 { 3510 {
3511 if (result == IDYES) 3511 if (result == IDYES)
3512 lua_pushstring(L, "yes"); 3512 lua_pushstring(L, "yes");
3513 else if (result == IDNO) 3513 else if (result == IDNO)
3514 lua_pushstring(L, "no"); 3514 lua_pushstring(L, "no");
3515 else if (result == IDCANCEL) 3515 else if (result == IDCANCEL)
3516 lua_pushstring(L, "cancel"); 3516 lua_pushstring(L, "cancel");
3517 else 3517 else
3518 luaL_error(L, "win32 unrecognized return value %d", result); 3518 luaL_error(L, "win32 unrecognized return value %d", result);
3519 return 1; 3519 return 1;
3520 } 3520 }
3521 3521
3522 // else, we don't care. 3522 // else, we don't care.
3523 return 0; 3523 return 0;
3524 #else 3524 #else
3525 char *t; 3525 char *t;
3526 #ifdef __linux 3526 #ifdef __linux
3527 // The Linux backend has a "FromPause" variable. 3527 // The Linux backend has a "FromPause" variable.
3528 // If set to 1, assume some known external event has screwed with the flow of time. 3528 // If set to 1, assume some known external event has screwed with the flow of time.
3529 // Since this pauses the emulator waiting for a response, we set it to 1. 3529 // Since this pauses the emulator waiting for a response, we set it to 1.
3530 // FIXME: Well, actually it doesn't 3530 // FIXME: Well, actually it doesn't
3531 // extern int FromPause; 3531 // extern int FromPause;
3532 // FromPause = 1; 3532 // FromPause = 1;
3533 3533
3534 int pid; // appease compiler 3534 int pid; // appease compiler
3535 3535
3536 // Before doing any work, verify the correctness of the parameters. 3536 // Before doing any work, verify the correctness of the parameters.
3537 if (strcmp(type, "ok") == 0) 3537 if (strcmp(type, "ok") == 0)
3538 t = "OK:100"; 3538 t = "OK:100";
3539 else if (strcmp(type, "yesno") == 0) 3539 else if (strcmp(type, "yesno") == 0)
3540 t = "Yes:100,No:101"; 3540 t = "Yes:100,No:101";
3541 else if (strcmp(type, "yesnocancel") == 0) 3541 else if (strcmp(type, "yesnocancel") == 0)
3542 t = "Yes:100,No:101,Cancel:102"; 3542 t = "Yes:100,No:101,Cancel:102";
3543 else 3543 else
3544 return luaL_error(L, "invalid popup type \"%s\"", type); 3544 return luaL_error(L, "invalid popup type \"%s\"", type);
3545 3545
3546 // Can we find a copy of xmessage? Search the path. 3546 // Can we find a copy of xmessage? Search the path.
3547 char *path = strdup(getenv("PATH")); 3547 char *path = strdup(getenv("PATH"));
3548 3548
3549 char *current = path; 3549 char *current = path;
3550 3550
3551 char *colon; 3551 char *colon;
3552 3552
3553 int found = 0; 3553 int found = 0;
3554 3554
3555 while (current) 3555 while (current)
3556 { 3556 {
3557 colon = strchr(current, ':'); 3557 colon = strchr(current, ':');
3558 3558
3559 // Clip off the colon. 3559 // Clip off the colon.
3560 *colon++ = 0; 3560 *colon++ = 0;
3561 3561
3562 int len = strlen(current); 3562 int len = strlen(current);
3563 char *filename = (char *)malloc(len + 12); // always give excess 3563 char *filename = (char *)malloc(len + 12); // always give excess
3564 snprintf(filename, len + 12, "%s/xmessage", current); 3564 snprintf(filename, len + 12, "%s/xmessage", current);
3565 3565
3566 if (access(filename, X_OK) == 0) 3566 if (access(filename, X_OK) == 0)
3567 { 3567 {
3568 free(filename); 3568 free(filename);
3569 found = 1; 3569 found = 1;
3570 break; 3570 break;
3571 } 3571 }
3572 3572
3573 // Failed, move on. 3573 // Failed, move on.
3574 current = colon; 3574 current = colon;
3575 free(filename); 3575 free(filename);
3576 } 3576 }
3577 3577
3578 free(path); 3578 free(path);
3579 3579
3580 // We've found it? 3580 // We've found it?
3581 if (!found) 3581 if (!found)
3582 goto use_console; 3582 goto use_console;
3583 3583
3584 pid = fork(); 3584 pid = fork();
3585 if (pid == 0) 3585 if (pid == 0)
3586 { // I'm the virgin sacrifice 3586 { // I'm the virgin sacrifice
3587 // I'm gonna be dead in a matter of microseconds anyways, so wasted memory doesn't matter to me. 3587 // I'm gonna be dead in a matter of microseconds anyways, so wasted memory doesn't matter to me.
3588 // Go ahead and abuse strdup. 3588 // Go ahead and abuse strdup.
3589 char *parameters[] = { "xmessage", "-buttons", t, strdup(message), NULL }; 3589 char *parameters[] = { "xmessage", "-buttons", t, strdup(message), NULL };
3590 3590
3591 execvp("xmessage", parameters); 3591 execvp("xmessage", parameters);
3592 3592
3593 // Aw shitty 3593 // Aw shitty
3594 perror("exec xmessage"); 3594 perror("exec xmessage");
3595 exit(1); 3595 exit(1);
3596 } 3596 }
3597 else if (pid < 0) // something went wrong!!! Oh hell... use the console 3597 else if (pid < 0) // something went wrong!!! Oh hell... use the console
3598 goto use_console; 3598 goto use_console;
3599 else 3599 else
3600 { 3600 {
3601 // We're the parent. Watch for the child. 3601 // We're the parent. Watch for the child.
3602 int r; 3602 int r;
3603 int res = waitpid(pid, &r, 0); 3603 int res = waitpid(pid, &r, 0);
3604 if (res < 0) // wtf? 3604 if (res < 0) // wtf?
3605 goto use_console; 3605 goto use_console;
3606 3606
3607 // The return value gets copmlicated... 3607 // The return value gets copmlicated...
3608 if (!WIFEXITED(r)) 3608 if (!WIFEXITED(r))
3609 { 3609 {
3610 luaL_error(L, "don't screw with my xmessage process!"); 3610 luaL_error(L, "don't screw with my xmessage process!");
3611 } 3611 }
3612 3612
3613 r = WEXITSTATUS(r); 3613 r = WEXITSTATUS(r);
3614 3614
3615 // We assume it's worked. 3615 // We assume it's worked.
3616 if (r == 0) 3616 if (r == 0)
3617 { 3617 {
3618 return 0; // no parameters for an OK 3618 return 0; // no parameters for an OK
3619 } 3619 }
3620 3620
3621 if (r == 100) 3621 if (r == 100)
3622 { 3622 {
3623 lua_pushstring(L, "yes"); 3623 lua_pushstring(L, "yes");
3624 return 1; 3624 return 1;
3625 } 3625 }
3626 3626
3627 if (r == 101) 3627 if (r == 101)
3628 { 3628 {
3629 lua_pushstring(L, "no"); 3629 lua_pushstring(L, "no");
3630 return 1; 3630 return 1;
3631 } 3631 }
3632 3632
3633 if (r == 102) 3633 if (r == 102)
3634 { 3634 {
3635 lua_pushstring(L, "cancel"); 3635 lua_pushstring(L, "cancel");
3636 return 1; 3636 return 1;
3637 } 3637 }
3638 3638
3639 // Wtf? 3639 // Wtf?
3640 return luaL_error(L, "popup failed due to unknown results involving xmessage (%d)", r); 3640 return luaL_error(L, "popup failed due to unknown results involving xmessage (%d)", r);
3641 } 3641 }
3642 3642
3643 use_console: 3643 use_console:
3644 #endif
3645
3646 // All else has failed
3647 if (strcmp(type, "ok") == 0)
3648 t = "";
3649 else if (strcmp(type, "yesno") == 0)
3650 t = "yn";
3651 else if (strcmp(type, "yesnocancel") == 0)
3652 t = "ync";
3653 else
3654 return luaL_error(L, "invalid popup type \"%s\"", type);
3655
3656 fprintf(stderr, "Lua Message: %s\n", message);
3657
3658 while (true)
3659 {
3660 char buffer[64];
3661
3662 // We don't want parameters
3663 if (!t[0])
3664 {
3665 fprintf(stderr, "[Press Enter]");
3666 fgets(buffer, sizeof(buffer), stdin);
3667
3668 // We're done
3669 return 0;
3670 }
3671
3672 fprintf(stderr, "(%s): ", t);
3673 fgets(buffer, sizeof(buffer), stdin);
3674
3675 // Check if the option is in the list
3676 if (strchr(t, tolower(buffer[0])))
3677 {
3678 switch (tolower(buffer[0]))
3679 {
3680 case 'y':
3681 lua_pushstring(L, "yes");
3682 return 1;
3683 case 'n':
3684 lua_pushstring(L, "no");
3685 return 1;
3686 case 'c':
3687 lua_pushstring(L, "cancel");
3688 return 1;
3689 default:
3690 luaL_error(L, "internal logic error in console based prompts for gui.popup");
3691 }
3692 }
3693
3694 // We fell through, so we assume the user answered wrong and prompt again.
3695 }
3696
3697 // Nothing here, since the only way out is in the loop.
3698 #endif 3644 #endif
3699 } 3645
3646 // All else has failed
3647 if (strcmp(type, "ok") == 0)
3648 t = "";
3649 else if (strcmp(type, "yesno") == 0)
3650 t = "yn";
3651 else if (strcmp(type, "yesnocancel") == 0)
3652 t = "ync";
3653 else
3654 return luaL_error(L, "invalid popup type \"%s\"", type);
3655
3656 fprintf(stderr, "Lua Message: %s\n", message);
3657
3658 while (true)
3659 {
3660 char buffer[64];
3661
3662 // We don't want parameters
3663 if (!t[0])
3664 {
3665 fprintf(stderr, "[Press Enter]");
3666 fgets(buffer, sizeof(buffer), stdin);
3667
3668 // We're done
3669 return 0;
3670 }
3671
3672 fprintf(stderr, "(%s): ", t);
3673 fgets(buffer, sizeof(buffer), stdin);
3674
3675 // Check if the option is in the list
3676 if (strchr(t, tolower(buffer[0])))
3677 {
3678 switch (tolower(buffer[0]))
3679 {
3680 case 'y':
3681 lua_pushstring(L, "yes");
3682 return 1;
3683 case 'n':
3684 lua_pushstring(L, "no");
3685 return 1;
3686 case 'c':
3687 lua_pushstring(L, "cancel");
3688 return 1;
3689 default:
3690 luaL_error(L, "internal logic error in console based prompts for gui.popup");
3691 }
3692 }
3693
3694 // We fell through, so we assume the user answered wrong and prompt again.
3695 }
3696
3697 // Nothing here, since the only way out is in the loop.
3698 #endif
3699 }
3700 3700
3701 #if (defined(WIN32) && !defined(SDL)) 3701 #if (defined(WIN32) && !defined(SDL))
3702 const char *s_keyToName[256] = 3702 const char *s_keyToName[256] =
3703 { 3703 {
3704 NULL, 3704 NULL,
3705 "leftclick", 3705 "leftclick",
3706 "rightclick", 3706 "rightclick",
3707 NULL, 3707 NULL,
3708 "middleclick", 3708 "middleclick",
3709 NULL, 3709 NULL,
3710 NULL, 3710 NULL,
3711 NULL, 3711 NULL,
3712 "backspace", 3712 "backspace",
3713 "tab", 3713 "tab",
3714 NULL, 3714 NULL,
3715 NULL, 3715 NULL,
3716 NULL, 3716 NULL,
3717 "enter", 3717 "enter",
3718 NULL, 3718 NULL,
3719 NULL, 3719 NULL,
3720 "shift", // 0x10 3720 "shift", // 0x10
3721 "control", 3721 "control",
3722 "alt", 3722 "alt",
3723 "pause", 3723 "pause",
3724 "capslock", 3724 "capslock",
3725 NULL, 3725 NULL,
3726 NULL, 3726 NULL,
3727 NULL, 3727 NULL,
3728 NULL, 3728 NULL,
3729 NULL, 3729 NULL,
3730 NULL, 3730 NULL,
3731 "escape", 3731 "escape",
3732 NULL, 3732 NULL,
3733 NULL, 3733 NULL,
3734 NULL, 3734 NULL,
3735 NULL, 3735 NULL,
3736 "space", // 0x20 3736 "space", // 0x20
3737 "pageup", 3737 "pageup",
3738 "pagedown", 3738 "pagedown",
3739 "end", 3739 "end",
3740 "home", 3740 "home",
3741 "left", 3741 "left",
3742 "up", 3742 "up",
3743 "right", 3743 "right",
3744 "down", 3744 "down",
3745 NULL, 3745 NULL,
3746 NULL, 3746 NULL,
3747 NULL, 3747 NULL,
3748 NULL, 3748 NULL,
3749 "insert", 3749 "insert",
3750 "delete", 3750 "delete",
3751 NULL, 3751 NULL,
3752 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 3752 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
3753 NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3753 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3754 "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", 3754 "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
3755 "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", 3755 "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
3756 "U", "V", "W", "X", "Y", "Z", 3756 "U", "V", "W", "X", "Y", "Z",
3757 NULL, 3757 NULL,
3758 NULL, 3758 NULL,
3759 NULL, 3759 NULL,
3760 NULL, 3760 NULL,
3761 NULL, 3761 NULL,
3762 "numpad0", "numpad1", "numpad2", "numpad3", "numpad4", "numpad5", "numpad6", "numpad7", "numpad8", "numpad9", 3762 "numpad0", "numpad1", "numpad2", "numpad3", "numpad4", "numpad5", "numpad6", "numpad7", "numpad8", "numpad9",
3763 "numpad*", "numpad+", 3763 "numpad*", "numpad+",
3764 NULL, 3764 NULL,
3765 "numpad-", "numpad.", "numpad/", 3765 "numpad-", "numpad.", "numpad/",
3766 "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", 3766 "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11",
3767 "F12", 3767 "F12",
3768 "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", 3768 "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23",
3769 "F24", 3769 "F24",
3770 NULL, 3770 NULL,
3771 NULL, 3771 NULL,
3772 NULL, 3772 NULL,
3773 NULL, 3773 NULL,
3774 NULL, 3774 NULL,
3775 NULL, 3775 NULL,
3776 NULL, 3776 NULL,
3777 NULL, 3777 NULL,
3778 "numlock", 3778 "numlock",
3779 "scrolllock", 3779 "scrolllock",
3780 NULL, // 0x92 3780 NULL, // 0x92
3781 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3781 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3782 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3782 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3783 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3783 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3784 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3784 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3785 NULL, // 0xB9 3785 NULL, // 0xB9
3786 "semicolon", 3786 "semicolon",
3787 "plus", 3787 "plus",
3788 "comma", 3788 "comma",
3789 "minus", 3789 "minus",
3790 "period", 3790 "period",
3791 "slash", 3791 "slash",
3792 "tilde", 3792 "tilde",
3793 NULL, // 0xC1 3793 NULL, // 0xC1
3794 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3794 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3795 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3795 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3796 NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3796 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3797 NULL, // 0xDA 3797 NULL, // 0xDA
3798 "leftbracket", 3798 "leftbracket",
3799 "backslash", 3799 "backslash",
3800 "rightbracket", 3800 "rightbracket",
3801 "quote", 3801 "quote",
3802 }; 3802 };
3803 #endif 3803 #endif
3804 3804
3805 // input.get() 3805 // input.get()
3806 // takes no input, returns a lua table of entries representing the current input state, 3806 // takes no input, returns a lua table of entries representing the current input state,
3807 // independent of the joypad buttons the emulated game thinks are pressed 3807 // independent of the joypad buttons the emulated game thinks are pressed
3808 // for example: 3808 // for example:
3809 // if the user is holding the W key and the left mouse button 3809 // if the user is holding the W key and the left mouse button
3810 // and has the mouse at the bottom-right corner of the game screen, 3810 // and has the mouse at the bottom-right corner of the game screen,
3811 3811
3812 // then this would return {W=true, leftclick=true, xmouse=255, ymouse=223} 3812 // then this would return {W=true, leftclick=true, xmouse=255, ymouse=223}
3813 static int input_getcurrentinputstatus(lua_State *L) 3813 static int input_getcurrentinputstatus(lua_State *L)
3814 { 3814 {
3815 lua_newtable(L); 3815 lua_newtable(L);
3816 3816
3817 #if (defined(WIN32) && !defined(SDL)) 3817 #if (defined(WIN32) && !defined(SDL))
3818 // keyboard and mouse button status 3818 // keyboard and mouse button status
3819 { 3819 {
3820 unsigned char keys[256]; 3820 unsigned char keys[256];
3821 if (true /*!GUI.BackgroundInput*/) // TODO: background input 3821 if (true /*!GUI.BackgroundInput*/) // TODO: background input
3822 { 3822 {
3823 if (GetKeyboardState(keys)) 3823 if (GetKeyboardState(keys))
3824 { 3824 {
3825 for (int i = 1; i < 255; i++) 3825 for (int i = 1; i < 255; i++)
3826 { 3826 {
3827 int mask = (i == VK_CAPITAL || i == VK_NUMLOCK || i == VK_SCROLL) ? 0x01 : 0x80; 3827 int mask = (i == VK_CAPITAL || i == VK_NUMLOCK || i == VK_SCROLL) ? 0x01 : 0x80;
3828 if (keys[i] & mask) 3828 if (keys[i] & mask)
3829 { 3829 {
3830 const char *name = s_keyToName[i]; 3830 const char *name = s_keyToName[i];
3831 if (name) 3831 if (name)
3832 { 3832 {
3833 lua_pushboolean(L, true); 3833 lua_pushboolean(L, true);
3834 lua_setfield(L, -2, name); 3834 lua_setfield(L, -2, name);
3835 } 3835 }
3836 } 3836 }
3837 } 3837 }
3838 } 3838 }
3839 } 3839 }
3840 else // use a slightly different method that will detect background input: 3840 else // use a slightly different method that will detect background input:
3841 { 3841 {
3842 for (int i = 1; i < 255; i++) 3842 for (int i = 1; i < 255; i++)
3843 { 3843 {
3844 const char *name = s_keyToName[i]; 3844 const char *name = s_keyToName[i];
3845 if (name) 3845 if (name)
3846 { 3846 {
3847 int active; 3847 int active;
3848 if (i == VK_CAPITAL || i == VK_NUMLOCK || i == VK_SCROLL) 3848 if (i == VK_CAPITAL || i == VK_NUMLOCK || i == VK_SCROLL)
3849 active = GetKeyState(i) & 0x01; 3849 active = GetKeyState(i) & 0x01;
3850 else 3850 else
3851 active = GetAsyncKeyState(i) & 0x8000; 3851 active = GetAsyncKeyState(i) & 0x8000;
3852 if (active) 3852 if (active)
3853 { 3853 {
3854 lua_pushboolean(L, true); 3854 lua_pushboolean(L, true);
3855 lua_setfield(L, -2, name); 3855 lua_setfield(L, -2, name);
3856 } 3856 }
3857 } 3857 }
3858 } 3858 }
3859 } 3859 }
3860 } 3860 }
3861 3861
3862 // mouse position in game screen pixel coordinates 3862 // mouse position in game screen pixel coordinates
3863 { 3863 {
3864 POINT mouse; 3864 POINT mouse;
3865 3865
3866 int xofs = 0, yofs = 0, width = 240, height = 160; 3866 int xofs = 0, yofs = 0, width = 240, height = 160;
3867 if (!systemIsRunningGBA()) 3867 if (!systemIsRunningGBA())
3868 { 3868 {
3869 if (gbBorderOn) 3869 if (gbBorderOn)
3870 width = 256, height = 224, xofs = 48, yofs = 40; 3870 width = 256, height = 224, xofs = 48, yofs = 40;
3871 else 3871 else
3872 width = 160, height = 144; 3872 width = 160, height = 144;
3873 } 3873 }
3874 3874
3875 GetCursorPos(&mouse); 3875 GetCursorPos(&mouse);
3876 AfxGetApp()->m_pMainWnd->ScreenToClient(&mouse); 3876 AfxGetApp()->m_pMainWnd->ScreenToClient(&mouse);
3877 3877
3878 // game screen is always fully stretched to window size, 3878 // game screen is always fully stretched to window size,
3879 // with no aspect rate correction, or something like that. 3879 // with no aspect rate correction, or something like that.
3880 RECT clientRect; 3880 RECT clientRect;
3881 AfxGetApp()->m_pMainWnd->GetClientRect(&clientRect); 3881 AfxGetApp()->m_pMainWnd->GetClientRect(&clientRect);
3882 3882
3883 int wndWidth = clientRect.right - clientRect.left; 3883 int wndWidth = clientRect.right - clientRect.left;
3884 int wndHeight = clientRect.bottom - clientRect.top; 3884 int wndHeight = clientRect.bottom - clientRect.top;
3885 mouse.x = (LONG) (mouse.x * ((float)width / wndWidth)) - xofs; 3885 mouse.x = (LONG) (mouse.x * ((float)width / wndWidth)) - xofs;
3886 mouse.y = (LONG) (mouse.y * ((float)height / wndHeight)) - yofs; 3886 mouse.y = (LONG) (mouse.y * ((float)height / wndHeight)) - yofs;
3887 3887
3888 lua_pushinteger(L, mouse.x); 3888 lua_pushinteger(L, mouse.x);
3889 lua_setfield(L, -2, "xmouse"); 3889 lua_setfield(L, -2, "xmouse");
3890 lua_pushinteger(L, mouse.y); 3890 lua_pushinteger(L, mouse.y);
3891 lua_setfield(L, -2, "ymouse"); 3891 lua_setfield(L, -2, "ymouse");
3892 } 3892 }
3893 3893
3894 #else 3894 #else
3895 // NYI (well, return an empty table) 3895 // NYI (well, return an empty table)
3896 #endif 3896 #endif
3897 return 1; 3897 return 1;
3898 } 3898 }
3899 3899
3900 static int avi_framecount(lua_State *L) 3900 static int avi_framecount(lua_State *L)
3901 { 3901 {
3902 #ifdef WIN32 3902 #ifdef WIN32
3903 if (theApp.aviRecorder != NULL) 3903 if (theApp.aviRecorder != NULL)
3904 { 3904 {
3905 lua_pushinteger(L, theApp.aviRecorder->videoFrames()); 3905 lua_pushinteger(L, theApp.aviRecorder->videoFrames());
3906 } 3906 }
3907 else 3907 else
3908 #endif 3908 #endif
3909 { 3909 {
3910 lua_pushinteger(L, 0); 3910 lua_pushinteger(L, 0);
3911 } 3911 }
3912 return 1; 3912 return 1;
3913 } 3913 }
3914 3914
3915 static int avi_pause(lua_State *L) 3915 static int avi_pause(lua_State *L)
3916 { 3916 {
3917 #ifdef WIN32 3917 #ifdef WIN32
3918 if (theApp.aviRecorder != NULL) 3918 if (theApp.aviRecorder != NULL)
3919 theApp.aviRecorder->Pause(true); 3919 theApp.aviRecorder->Pause(true);
3920 #endif 3920 #endif
3921 return 1; 3921 return 1;
3922 } 3922 }
3923 3923
3924 static int avi_resume(lua_State *L) 3924 static int avi_resume(lua_State *L)
3925 { 3925 {
3926 #ifdef WIN32 3926 #ifdef WIN32
3927 if (theApp.aviRecorder != NULL) 3927 if (theApp.aviRecorder != NULL)
3928 theApp.aviRecorder->Pause(false); 3928 theApp.aviRecorder->Pause(false);
3929 #endif 3929 #endif
3930 return 1; 3930 return 1;
3931 } 3931 }
3932 3932
3933 static int sound_get(lua_State *L) 3933 static int sound_get(lua_State *L)
3934 { 3934 {
3935 extern int32 soundLevel1; 3935 extern int32 soundLevel1;
3936 extern int32 soundLevel2; 3936 extern int32 soundLevel2;
3937 extern int32 soundBalance; 3937 extern int32 soundBalance;
3938 extern int32 soundMasterOn; 3938 extern int32 soundMasterOn;
3939 extern int32 soundVIN; 3939 extern int32 soundVIN;
3940 extern int32 sound1On; 3940 extern int32 sound1On;
3941 extern int32 sound1EnvelopeVolume; 3941 extern int32 sound1EnvelopeVolume;
3942 extern int32 sound2On; 3942 extern int32 sound2On;
3943 extern int32 sound2EnvelopeVolume; 3943 extern int32 sound2EnvelopeVolume;
3944 extern int32 sound3On; 3944 extern int32 sound3On;
3945 extern int32 sound3OutputLevel; 3945 extern int32 sound3OutputLevel;
3946 extern int32 sound3Bank; 3946 extern int32 sound3Bank;
3947 extern int32 sound3DataSize; 3947 extern int32 sound3DataSize;
3948 extern int32 sound3ForcedOutput; 3948 extern int32 sound3ForcedOutput;
3949 extern int32 sound4On; 3949 extern int32 sound4On;
3950 extern int32 sound4EnvelopeVolume; 3950 extern int32 sound4EnvelopeVolume;
3951 extern u8 sound3WaveRam[0x20]; 3951 extern u8 sound3WaveRam[0x20];
3952 3952
3953 int freqReg; 3953 int freqReg;
3954 double freq; 3954 double freq;
3955 double leftvolscale; 3955 double leftvolscale;
3956 double rightvolscale; 3956 double rightvolscale;
3957 double panpot; 3957 double panpot;
3958 bool gba = systemIsRunningGBA(); 3958 bool gba = systemIsRunningGBA();
3959 u8* gbMem = gba ? ioMem : gbMemory; 3959 u8* gbMem = gba ? ioMem : gbMemory;
3960 const int rNR10 = gba ? 0x60 : 0xff10; 3960 const int rNR10 = gba ? 0x60 : 0xff10;
3961 const int rNR11 = gba ? 0x62 : 0xff11; 3961 const int rNR11 = gba ? 0x62 : 0xff11;
3962 const int rNR12 = gba ? 0x63 : 0xff12; 3962 const int rNR12 = gba ? 0x63 : 0xff12;
3963 const int rNR13 = gba ? 0x64 : 0xff13; 3963 const int rNR13 = gba ? 0x64 : 0xff13;
3964 const int rNR14 = gba ? 0x65 : 0xff14; 3964 const int rNR14 = gba ? 0x65 : 0xff14;
3965 const int rNR21 = gba ? 0x68 : 0xff16; 3965 const int rNR21 = gba ? 0x68 : 0xff16;
3966 const int rNR22 = gba ? 0x69 : 0xff17; 3966 const int rNR22 = gba ? 0x69 : 0xff17;
3967 const int rNR23 = gba ? 0x6c : 0xff18; 3967 const int rNR23 = gba ? 0x6c : 0xff18;
3968 const int rNR24 = gba ? 0x6d : 0xff19; 3968 const int rNR24 = gba ? 0x6d : 0xff19;
3969 const int rNR30 = gba ? 0x70 : 0xff1a; 3969 const int rNR30 = gba ? 0x70 : 0xff1a;
3970 const int rNR31 = gba ? 0x72 : 0xff1b; 3970 const int rNR31 = gba ? 0x72 : 0xff1b;
3971 const int rNR32 = gba ? 0x73 : 0xff1c; 3971 const int rNR32 = gba ? 0x73 : 0xff1c;
3972 const int rNR33 = gba ? 0x74 : 0xff1d; 3972 const int rNR33 = gba ? 0x74 : 0xff1d;
3973 const int rNR34 = gba ? 0x75 : 0xff1e; 3973 const int rNR34 = gba ? 0x75 : 0xff1e;
3974 const int rNR41 = gba ? 0x78 : 0xff20; 3974 const int rNR41 = gba ? 0x78 : 0xff20;
3975 const int rNR42 = gba ? 0x79 : 0xff21; 3975 const int rNR42 = gba ? 0x79 : 0xff21;
3976 const int rNR43 = gba ? 0x7c : 0xff22; 3976 const int rNR43 = gba ? 0x7c : 0xff22;
3977 const int rNR44 = gba ? 0x7d : 0xff23; 3977 const int rNR44 = gba ? 0x7d : 0xff23;
3978 const int rNR50 = gba ? 0x80 : 0xff24; 3978 const int rNR50 = gba ? 0x80 : 0xff24;
3979 const int rNR51 = gba ? 0x81 : 0xff25; 3979 const int rNR51 = gba ? 0x81 : 0xff25;
3980 const int rNR52 = gba ? 0x84 : 0xff26; 3980 const int rNR52 = gba ? 0x84 : 0xff26;
3981 const int rWAVE_RAM = gba ? 0x90 : 0xff30; 3981 const int rWAVE_RAM = gba ? 0x90 : 0xff30;
3982 3982
3983 const int32 _soundVIN = 0x88; // gba ? 0x88 : soundVIN; 3983 const int32 _soundVIN = 0x88; // gba ? 0x88 : soundVIN;
3984 const bool soundVINLeft = ((_soundVIN & 0x80) != 0); 3984 const bool soundVINLeft = ((_soundVIN & 0x80) != 0);
3985 const bool soundVINRight = ((_soundVIN & 0x08) != 0); 3985 const bool soundVINRight = ((_soundVIN & 0x08) != 0);
3986 3986
3987 lua_newtable(L); 3987 lua_newtable(L);
3988 3988
3989 // square1 3989 // square1
3990 lua_newtable(L); 3990 lua_newtable(L);
3991 if(sound1On == 0 || soundMasterOn == 0) 3991 if(sound1On == 0 || soundMasterOn == 0)
3992 { 3992 {
3993 lua_pushnumber(L, 0.0); 3993 lua_pushnumber(L, 0.0);
3994 panpot = 0.5; 3994 panpot = 0.5;
3995 } 3995 }
3996 else 3996 else
3997 { 3997 {
3998 double envVolume = sound1EnvelopeVolume / 15.0; 3998 double envVolume = sound1EnvelopeVolume / 15.0;
3999 if (soundVINLeft && (soundBalance & 0x10) != 0) 3999 if (soundVINLeft && (soundBalance & 0x10) != 0)
4000 leftvolscale = ((soundLevel2 / 7.0) * envVolume); 4000 leftvolscale = ((soundLevel2 / 7.0) * envVolume);
4001 else 4001 else
4002 leftvolscale = 0.0; 4002 leftvolscale = 0.0;
4003 if (soundVINRight && (soundBalance & 0x01) != 0) 4003 if (soundVINRight && (soundBalance & 0x01) != 0)
4004 rightvolscale = ((soundLevel1 / 7.0) * envVolume); 4004 rightvolscale = ((soundLevel1 / 7.0) * envVolume);
4005 else 4005 else
4006 rightvolscale = 0.0; 4006 rightvolscale = 0.0;
4007 if ((leftvolscale + rightvolscale) != 0) 4007 if ((leftvolscale + rightvolscale) != 0)
4008 panpot = rightvolscale / (leftvolscale + rightvolscale); 4008 panpot = rightvolscale / (leftvolscale + rightvolscale);
4009 else 4009 else
4010 panpot = 0.5; 4010 panpot = 0.5;
4011 lua_pushnumber(L, (leftvolscale + rightvolscale) / 2.0); 4011 lua_pushnumber(L, (leftvolscale + rightvolscale) / 2.0);
4012 } 4012 }
4013 lua_setfield(L, -2, "volume"); 4013 lua_setfield(L, -2, "volume");
4014 lua_pushnumber(L, panpot); 4014 lua_pushnumber(L, panpot);
4015 lua_setfield(L, -2, "panpot"); 4015 lua_setfield(L, -2, "panpot");
4016 freqReg = (((int)(gbMem[rNR14] & 7) << 8) | gbMem[rNR13]); 4016 freqReg = (((int)(gbMem[rNR14] & 7) << 8) | gbMem[rNR13]);
4017 freq = 131072.0 / (2048 - freqReg); 4017 freq = 131072.0 / (2048 - freqReg);
4018 lua_pushnumber(L, freq); 4018 lua_pushnumber(L, freq);
4019 lua_setfield(L, -2, "frequency"); 4019 lua_setfield(L, -2, "frequency");
4020 lua_pushnumber(L, (log(freq / 440.0) * 12 / log(2.0)) + 69); 4020 lua_pushnumber(L, (log(freq / 440.0) * 12 / log(2.0)) + 69);
4021 lua_setfield(L, -2, "midikey"); 4021 lua_setfield(L, -2, "midikey");
4022 lua_pushinteger(L, (gbMem[rNR11] & 0xC0) >> 6); 4022 lua_pushinteger(L, (gbMem[rNR11] & 0xC0) >> 6);
4023 lua_setfield(L, -2, "duty"); 4023 lua_setfield(L, -2, "duty");
4024 lua_newtable(L); 4024 lua_newtable(L);
4025 lua_pushinteger(L, freqReg); 4025 lua_pushinteger(L, freqReg);
4026 lua_setfield(L, -2, "frequency"); 4026 lua_setfield(L, -2, "frequency");
4027 lua_setfield(L, -2, "regs"); 4027 lua_setfield(L, -2, "regs");
4028 lua_setfield(L, -2, "square1"); 4028 lua_setfield(L, -2, "square1");
4029 // square2 4029 // square2
4030 lua_newtable(L); 4030 lua_newtable(L);
4031 if(sound2On == 0 || soundMasterOn == 0) 4031 if(sound2On == 0 || soundMasterOn == 0)
4032 { 4032 {
4033 lua_pushnumber(L, 0.0); 4033 lua_pushnumber(L, 0.0);
4034 panpot = 0.5; 4034 panpot = 0.5;
4035 } 4035 }
4036 else 4036 else
4037 { 4037 {
4038 double envVolume = sound2EnvelopeVolume / 15.0; 4038 double envVolume = sound2EnvelopeVolume / 15.0;
4039 if (soundVINLeft && (soundBalance & 0x20) != 0) 4039 if (soundVINLeft && (soundBalance & 0x20) != 0)
4040 leftvolscale = ((soundLevel2 / 7.0) * envVolume); 4040 leftvolscale = ((soundLevel2 / 7.0) * envVolume);
4041 else 4041 else
4042 leftvolscale = 0.0; 4042 leftvolscale = 0.0;
4043 if (soundVINRight && (soundBalance & 0x02) != 0) 4043 if (soundVINRight && (soundBalance & 0x02) != 0)
4044 rightvolscale = ((soundLevel1 / 7.0) * envVolume); 4044 rightvolscale = ((soundLevel1 / 7.0) * envVolume);
4045 else 4045 else
4046 rightvolscale = 0.0; 4046 rightvolscale = 0.0;
4047 if ((leftvolscale + rightvolscale) != 0) 4047 if ((leftvolscale + rightvolscale) != 0)
4048 panpot = rightvolscale / (leftvolscale + rightvolscale); 4048 panpot = rightvolscale / (leftvolscale + rightvolscale);
4049 else 4049 else
4050 panpot = 0.5; 4050 panpot = 0.5;
4051 lua_pushnumber(L, (leftvolscale + rightvolscale) / 2.0); 4051 lua_pushnumber(L, (leftvolscale + rightvolscale) / 2.0);
4052 } 4052 }
4053 lua_setfield(L, -2, "volume"); 4053 lua_setfield(L, -2, "volume");
4054 lua_pushnumber(L, panpot); 4054 lua_pushnumber(L, panpot);
4055 lua_setfield(L, -2, "panpot"); 4055 lua_setfield(L, -2, "panpot");
4056 freqReg = (((int)(gbMem[rNR24] & 7) << 8) | gbMem[rNR23]); 4056 freqReg = (((int)(gbMem[rNR24] & 7) << 8) | gbMem[rNR23]);
4057 freq = 131072.0 / (2048 - freqReg); 4057 freq = 131072.0 / (2048 - freqReg);
4058 lua_pushnumber(L, freq); 4058 lua_pushnumber(L, freq);
4059 lua_setfield(L, -2, "frequency"); 4059 lua_setfield(L, -2, "frequency");
4060 lua_pushnumber(L, (log(freq / 440.0) * 12 / log(2.0)) + 69); 4060 lua_pushnumber(L, (log(freq / 440.0) * 12 / log(2.0)) + 69);
4061 lua_setfield(L, -2, "midikey"); 4061 lua_setfield(L, -2, "midikey");
4062 lua_pushinteger(L, (gbMem[rNR21] & 0xC0) >> 6); 4062 lua_pushinteger(L, (gbMem[rNR21] & 0xC0) >> 6);
4063 lua_setfield(L, -2, "duty"); 4063 lua_setfield(L, -2, "duty");
4064 lua_newtable(L); 4064 lua_newtable(L);
4065 lua_pushinteger(L, freqReg); 4065 lua_pushinteger(L, freqReg);
4066 lua_setfield(L, -2, "frequency"); 4066 lua_setfield(L, -2, "frequency");
4067 lua_setfield(L, -2, "regs"); 4067 lua_setfield(L, -2, "regs");
4068 lua_setfield(L, -2, "square2"); 4068 lua_setfield(L, -2, "square2");
4069 // wavememory 4069 // wavememory
4070 lua_newtable(L); 4070 lua_newtable(L);
4071 if(sound3On == 0 || soundMasterOn == 0) 4071 if(sound3On == 0 || soundMasterOn == 0)
4072 { 4072 {
4073 lua_pushnumber(L, 0.0); 4073 lua_pushnumber(L, 0.0);
4074 panpot = 0.5; 4074 panpot = 0.5;
4075 } 4075 }
4076 else 4076 else
4077 { 4077 {
4078 double envVolume; 4078 double envVolume;
4079 if (gba && sound3ForcedOutput != 0) 4079 if (gba && sound3ForcedOutput != 0)
4080 envVolume = 0.75; 4080 envVolume = 0.75;
4081 else 4081 else
4082 { 4082 {
4083 double volTable[4] = { 0.0, 1.0, 0.5, 0.25 }; 4083 double volTable[4] = { 0.0, 1.0, 0.5, 0.25 };
4084 envVolume = volTable[sound3OutputLevel & 3]; 4084 envVolume = volTable[sound3OutputLevel & 3];
4085 } 4085 }
4086 4086
4087 if (soundVINLeft && (soundBalance & 0x40) != 0) 4087 if (soundVINLeft && (soundBalance & 0x40) != 0)
4088 leftvolscale = ((soundLevel2 / 7.0) * envVolume); 4088 leftvolscale = ((soundLevel2 / 7.0) * envVolume);
4089 else 4089 else
4090 leftvolscale = 0.0; 4090 leftvolscale = 0.0;
4091 if (soundVINRight && (soundBalance & 0x04) != 0) 4091 if (soundVINRight && (soundBalance & 0x04) != 0)
4092 rightvolscale = ((soundLevel1 / 7.0) * envVolume); 4092 rightvolscale = ((soundLevel1 / 7.0) * envVolume);
4093 else 4093 else
4094 rightvolscale = 0.0; 4094 rightvolscale = 0.0;
4095 if ((leftvolscale + rightvolscale) != 0) 4095 if ((leftvolscale + rightvolscale) != 0)
4096 panpot = rightvolscale / (leftvolscale + rightvolscale); 4096 panpot = rightvolscale / (leftvolscale + rightvolscale);
4097 else 4097 else
4098 panpot = 0.5; 4098 panpot = 0.5;
4099 lua_pushnumber(L, (leftvolscale + rightvolscale) / 2.0); 4099 lua_pushnumber(L, (leftvolscale + rightvolscale) / 2.0);
4100 } 4100 }
4101 lua_setfield(L, -2, "volume"); 4101 lua_setfield(L, -2, "volume");
4102 lua_pushnumber(L, panpot); 4102 lua_pushnumber(L, panpot);
4103 lua_setfield(L, -2, "panpot"); 4103 lua_setfield(L, -2, "panpot");
4104 int waveMemSamples = 32; 4104 int waveMemSamples = 32;
4105 if (gba) 4105 if (gba)
4106 { 4106 {
4107 lua_pushlstring(L, (const char *) &sound3WaveRam[sound3Bank * 0x10], sound3DataSize ? 0x20 : 0x10); 4107 lua_pushlstring(L, (const char *) &sound3WaveRam[sound3Bank * 0x10], sound3DataSize ? 0x20 : 0x10);
4108 waveMemSamples = sound3DataSize ? 64 : 32; 4108 waveMemSamples = sound3DataSize ? 64 : 32;
4109 } 4109 }
4110 else 4110 else
4111 { 4111 {
4112 lua_pushlstring(L, (const char *) &gbMem[rWAVE_RAM], 0x10); 4112 lua_pushlstring(L, (const char *) &gbMem[rWAVE_RAM], 0x10);
4113 } 4113 }
4114 lua_setfield(L, -2, "waveform"); 4114 lua_setfield(L, -2, "waveform");
4115 freqReg = (((int)(gbMem[rNR34] & 7) << 8) | gbMem[rNR33]); 4115 freqReg = (((int)(gbMem[rNR34] & 7) << 8) | gbMem[rNR33]);
4116 freq = 2097152.0 / (waveMemSamples * (2048 - freqReg)); 4116 freq = 2097152.0 / (waveMemSamples * (2048 - freqReg));
4117 lua_pushnumber(L, freq); 4117 lua_pushnumber(L, freq);
4118 lua_setfield(L, -2, "frequency"); 4118 lua_setfield(L, -2, "frequency");
4119 lua_pushnumber(L, (log(freq / 440.0) * 12 / log(2.0)) + 69); 4119 lua_pushnumber(L, (log(freq / 440.0) * 12 / log(2.0)) + 69);
4120 lua_setfield(L, -2, "midikey"); 4120 lua_setfield(L, -2, "midikey");
4121 lua_newtable(L); 4121 lua_newtable(L);
4122 lua_pushinteger(L, freqReg); 4122 lua_pushinteger(L, freqReg);
4123 lua_setfield(L, -2, "frequency"); 4123 lua_setfield(L, -2, "frequency");
4124 lua_setfield(L, -2, "regs"); 4124 lua_setfield(L, -2, "regs");
4125 lua_setfield(L, -2, "wavememory"); 4125 lua_setfield(L, -2, "wavememory");
4126 // noise 4126 // noise
4127 lua_newtable(L); 4127 lua_newtable(L);
4128 if(sound4On == 0 || soundMasterOn == 0) 4128 if(sound4On == 0 || soundMasterOn == 0)
4129 { 4129 {
4130 lua_pushnumber(L, 0.0); 4130 lua_pushnumber(L, 0.0);
4131 panpot = 0.5; 4131 panpot = 0.5;
4132 } 4132 }
4133 else 4133 else
4134 { 4134 {
4135 double envVolume = sound4EnvelopeVolume / 15.0; 4135 double envVolume = sound4EnvelopeVolume / 15.0;
4136 if (soundVINLeft && (soundBalance & 0x80) != 0) 4136 if (soundVINLeft && (soundBalance & 0x80) != 0)
4137 leftvolscale = ((soundLevel2 / 7.0) * envVolume); 4137 leftvolscale = ((soundLevel2 / 7.0) * envVolume);
4138 else 4138 else
4139 leftvolscale = 0.0; 4139 leftvolscale = 0.0;
4140 if (soundVINRight && (soundBalance & 0x08) != 0) 4140 if (soundVINRight && (soundBalance & 0x08) != 0)
4141 rightvolscale = ((soundLevel1 / 7.0) * envVolume); 4141 rightvolscale = ((soundLevel1 / 7.0) * envVolume);
4142 else 4142 else
4143 rightvolscale = 0.0; 4143 rightvolscale = 0.0;
4144 if ((leftvolscale + rightvolscale) != 0) 4144 if ((leftvolscale + rightvolscale) != 0)
4145 panpot = rightvolscale / (leftvolscale + rightvolscale); 4145 panpot = rightvolscale / (leftvolscale + rightvolscale);
4146 else 4146 else
4147 panpot = 0.5; 4147 panpot = 0.5;
4148 lua_pushnumber(L, (leftvolscale + rightvolscale) / 2.0); 4148 lua_pushnumber(L, (leftvolscale + rightvolscale) / 2.0);
4149 } 4149 }
4150 lua_setfield(L, -2, "volume"); 4150 lua_setfield(L, -2, "volume");
4151 lua_pushnumber(L, panpot); 4151 lua_pushnumber(L, panpot);
4152 lua_setfield(L, -2, "panpot"); 4152 lua_setfield(L, -2, "panpot");
4153 const int gbNoiseFreqTable[8] = { 1, 2, 4, 6, 8, 10, 12, 14 }; 4153 const int gbNoiseFreqTable[8] = { 1, 2, 4, 6, 8, 10, 12, 14 };
4154 freqReg = gbNoiseFreqTable[gbMem[rNR43] & 7] << (1 + (gbMem[rNR43] >> 4)); 4154 freqReg = gbNoiseFreqTable[gbMem[rNR43] & 7] << (1 + (gbMem[rNR43] >> 4));
4155 lua_pushboolean(L, (gbMem[rNR43] & 8) != 0); 4155 lua_pushboolean(L, (gbMem[rNR43] & 8) != 0);
4156 lua_setfield(L, -2, "short"); 4156 lua_setfield(L, -2, "short");
4157 freq = 1048576.0 / freqReg; 4157 freq = 1048576.0 / freqReg;
4158 lua_pushnumber(L, freq); 4158 lua_pushnumber(L, freq);
4159 lua_setfield(L, -2, "frequency"); 4159 lua_setfield(L, -2, "frequency");
4160 lua_pushnumber(L, (log(freq / 440.0) * 12 / log(2.0)) + 69); 4160 lua_pushnumber(L, (log(freq / 440.0) * 12 / log(2.0)) + 69);
4161 lua_setfield(L, -2, "midikey"); 4161 lua_setfield(L, -2, "midikey");
4162 lua_newtable(L); 4162 lua_newtable(L);
4163 lua_pushinteger(L, freqReg); 4163 lua_pushinteger(L, freqReg);
4164 lua_setfield(L, -2, "frequency"); 4164 lua_setfield(L, -2, "frequency");
4165 lua_setfield(L, -2, "regs"); 4165 lua_setfield(L, -2, "regs");
4166 lua_setfield(L, -2, "noise"); 4166 lua_setfield(L, -2, "noise");
4167 4167
4168 return 1; 4168 return 1;
4169 } 4169 }
4170 4170
4171 // same as math.random, but uses SFMT instead of C rand() 4171 // same as math.random, but uses SFMT instead of C rand()
4172 // FIXME: this function doesn't care multi-instance, 4172 // FIXME: this function doesn't care multi-instance,
4173 4173
4174 // original math.random either though (Lua 5.1) 4174 // original math.random either though (Lua 5.1)
4175 static int sfmt_random(lua_State *L) 4175 static int sfmt_random(lua_State *L)
4176 { 4176 {
4177 lua_Number r = (lua_Number) genrand_real2(); 4177 lua_Number r = (lua_Number) genrand_real2();
4178 switch (lua_gettop(L)) 4178 switch (lua_gettop(L))
4179 { // check number of arguments 4179 { // check number of arguments
4180 case 0: 4180 case 0:
4181 { // no arguments 4181 { // no arguments
4182 lua_pushnumber(L, r); // Number between 0 and 1 4182 lua_pushnumber(L, r); // Number between 0 and 1
4183 break; 4183 break;
4184 } 4184 }
4185 4185
4186 case 1: 4186 case 1:
4187 { // only upper limit 4187 { // only upper limit
4188 int u = luaL_checkint(L, 1); 4188 int u = luaL_checkint(L, 1);
4189 luaL_argcheck(L, 1 <= u, 1, "interval is empty"); 4189 luaL_argcheck(L, 1 <= u, 1, "interval is empty");
4190 lua_pushnumber(L, floor(r * u) + 1); // int between 1 and `u' 4190 lua_pushnumber(L, floor(r * u) + 1); // int between 1 and `u'
4191 break; 4191 break;
4192 } 4192 }
4193 4193
4194 case 2: 4194 case 2:
4195 { // lower and upper limits 4195 { // lower and upper limits
4196 int l = luaL_checkint(L, 1); 4196 int l = luaL_checkint(L, 1);
4197 int u = luaL_checkint(L, 2); 4197 int u = luaL_checkint(L, 2);
4198 luaL_argcheck(L, l <= u, 2, "interval is empty"); 4198 luaL_argcheck(L, l <= u, 2, "interval is empty");
4199 lua_pushnumber(L, floor(r * (u - l + 1)) + l); // int between `l' and `u' 4199 lua_pushnumber(L, floor(r * (u - l + 1)) + l); // int between `l' and `u'
4200 break; 4200 break;
4201 } 4201 }
4202 4202
4203 default: 4203 default:
4204 return luaL_error(L, "wrong number of arguments"); 4204 return luaL_error(L, "wrong number of arguments");
4205 } 4205 }
4206 4206
4207 return 1; 4207 return 1;
4208 } 4208 }
4209 4209
4210 // same as math.randomseed, but uses SFMT instead of C srand() 4210 // same as math.randomseed, but uses SFMT instead of C srand()
4211 // FIXME: this function doesn't care multi-instance, 4211 // FIXME: this function doesn't care multi-instance,
4212 4212
4213 // original math.randomseed either though (Lua 5.1) 4213 // original math.randomseed either though (Lua 5.1)
4214 static int sfmt_randomseed(lua_State *L) 4214 static int sfmt_randomseed(lua_State *L)
4215 { 4215 {
4216 init_gen_rand(luaL_checkint(L, 1)); 4216 init_gen_rand(luaL_checkint(L, 1));
4217 return 0; 4217 return 0;
4218 } 4218 }
4219 4219
4220 // the following bit operations are ported from LuaBitOp 1.0.1, 4220 // the following bit operations are ported from LuaBitOp 1.0.1,
4221 // because it can handle the sign bit (bit 31) correctly. 4221 // because it can handle the sign bit (bit 31) correctly.
4222 4222
4223 /* 4223 /*
4248 ** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] 4248 ** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
4249 */ 4249 */
4250 4250
4251 #ifdef _MSC_VER 4251 #ifdef _MSC_VER
4252 /* MSVC is stuck in the last century and doesn't have C99's stdint.h. */ 4252 /* MSVC is stuck in the last century and doesn't have C99's stdint.h. */
4253 typedef __int32 int32_t; 4253 typedef __int32 int32_t;
4254 typedef unsigned __int32 uint32_t; 4254 typedef unsigned __int32 uint32_t;
4255 typedef unsigned __int64 uint64_t; 4255 typedef unsigned __int64 uint64_t;
4256 #else 4256 #else
4257 #include <stdint.h> 4257 #include <stdint.h>
4258 #endif 4258 #endif
4259 4259
4260 typedef int32_t SBits; 4260 typedef int32_t SBits;
4261 typedef uint32_t UBits; 4261 typedef uint32_t UBits;
4262 4262
4263 typedef union 4263 typedef union
4264 { 4264 {
4265 lua_Number n; 4265 lua_Number n;
4266 #ifdef LUA_NUMBER_DOUBLE 4266 #ifdef LUA_NUMBER_DOUBLE
4267 uint64_t b; 4267 uint64_t b;
4268 #else 4268 #else
4269 UBits b; 4269 UBits b;
4270 #endif 4270 #endif
4271 } BitNum; 4271 } BitNum;
4272 4272
4273 /* Convert argument to bit type. */ 4273 /* Convert argument to bit type. */
4274 static UBits barg(lua_State *L, int idx) 4274 static UBits barg(lua_State *L, int idx)
4275 { 4275 {
4276 BitNum bn; 4276 BitNum bn;
4277 UBits b; 4277 UBits b;
4278 bn.n = lua_tonumber(L, idx); 4278 bn.n = lua_tonumber(L, idx);
4279 #if defined(LUA_NUMBER_DOUBLE) 4279 #if defined(LUA_NUMBER_DOUBLE)
4280 bn.n += 6755399441055744.0; /* 2^52+2^51 */ 4280 bn.n += 6755399441055744.0; /* 2^52+2^51 */
4281 #ifdef SWAPPED_DOUBLE 4281 #ifdef SWAPPED_DOUBLE
4282 b = (UBits)(bn.b >> 32); 4282 b = (UBits)(bn.b >> 32);
4283 #else 4283 #else
4284 b = (UBits)(bn.b & 0xffffffff); 4284 b = (UBits)(bn.b & 0xffffffff);
4285 #endif 4285 #endif
4286 #elif defined(LUA_NUMBER_INT) || defined(LUA_NUMBER_LONG) || \ 4286 #elif defined(LUA_NUMBER_INT) || defined(LUA_NUMBER_LONG) || \
4287 defined(LUA_NUMBER_LONGLONG) || defined(LUA_NUMBER_LONG_LONG) || \ 4287 defined(LUA_NUMBER_LONGLONG) || defined(LUA_NUMBER_LONG_LONG) || \
4288 defined(LUA_NUMBER_LLONG) 4288 defined(LUA_NUMBER_LLONG)
4289 if (sizeof(UBits) == sizeof(lua_Number)) 4289 if (sizeof(UBits) == sizeof(lua_Number))
4290 b = bn.b; 4290 b = bn.b;
4291 else 4291 else
4292 b = (UBits)(SBits)bn.n; 4292 b = (UBits)(SBits)bn.n;
4293 #elif defined(LUA_NUMBER_FLOAT) 4293 #elif defined(LUA_NUMBER_FLOAT)
4294 #error "A 'float' lua_Number type is incompatible with this library" 4294 #error "A 'float' lua_Number type is incompatible with this library"
4295 #else 4295 #else
4296 #error "Unknown number type, check LUA_NUMBER_* in luaconf.h" 4296 #error "Unknown number type, check LUA_NUMBER_* in luaconf.h"
4297 #endif 4297 #endif
4298 if (b == 0 && !lua_isnumber(L, idx)) 4298 if (b == 0 && !lua_isnumber(L, idx))
4299 luaL_typerror(L, idx, "number"); 4299 luaL_typerror(L, idx, "number");
4300 return b; 4300 return b;
4301 } 4301 }
4302 4302
4303 /* Return bit type. */ 4303 /* Return bit type. */
4304 #define BRET(b) lua_pushnumber(L, (lua_Number)(SBits)(b)); return 1; 4304 #define BRET(b) lua_pushnumber(L, (lua_Number)(SBits)(b)); return 1;
4305 4305
4306 static int bit_tobit(lua_State *L) { BRET(barg(L, 1)) } 4306 static int bit_tobit(lua_State *L) { BRET(barg(L, 1)) }
4307 static int bit_bnot(lua_State *L) { BRET(~barg(L, 1)) } 4307 static int bit_bnot(lua_State *L) { BRET(~barg(L, 1)) }
4308 4308
4309 #define BIT_OP(func, opr) \ 4309 #define BIT_OP(func, opr) \
4310 static int func(lua_State * L) { int i; UBits b = barg(L, 1); \ 4310 static int func(lua_State * L) { int i; UBits b = barg(L, 1); \
4311 for (i = lua_gettop(L); i > 1; i--) \ 4311 for (i = lua_gettop(L); i > 1; i--) \
4312 b opr barg(L, i); BRET(b) } 4312 b opr barg(L, i); BRET(b) }
4313 BIT_OP(bit_band, &= ) 4313 BIT_OP(bit_band, &= )
4314 BIT_OP(bit_bor, |= ) 4314 BIT_OP(bit_bor, |= )
4315 BIT_OP(bit_bxor, ^= ) 4315 BIT_OP(bit_bxor, ^= )
4316 4316
4317 #define bshl(b, n) (b << n) 4317 #define bshl(b, n) (b << n)
4318 #define bshr(b, n) (b >> n) 4318 #define bshr(b, n) (b >> n)
4319 #define bsar(b, n) ((SBits)b >> n) 4319 #define bsar(b, n) ((SBits)b >> n)
4320 #define brol(b, n) ((b << n) | (b >> (32 - n))) 4320 #define brol(b, n) ((b << n) | (b >> (32 - n)))
4321 #define bror(b, n) ((b << (32 - n)) | (b >> n)) 4321 #define bror(b, n) ((b << (32 - n)) | (b >> n))
4322 #define BIT_SH(func, fn) \ 4322 #define BIT_SH(func, fn) \
4323 static int func(lua_State * L) { \ 4323 static int func(lua_State * L) { \
4324 UBits b = barg(L, 1); UBits n = barg(L, 2) & 31; BRET(fn(b, n)) } 4324 UBits b = barg(L, 1); UBits n = barg(L, 2) & 31; BRET(fn(b, n)) }
4325 BIT_SH(bit_lshift, bshl) 4325 BIT_SH(bit_lshift, bshl)
4326 BIT_SH(bit_rshift, bshr) 4326 BIT_SH(bit_rshift, bshr)
4327 BIT_SH(bit_arshift, bsar) 4327 BIT_SH(bit_arshift, bsar)
4328 BIT_SH(bit_rol, brol) 4328 BIT_SH(bit_rol, brol)
4329 BIT_SH(bit_ror, bror) 4329 BIT_SH(bit_ror, bror)
4330 4330
4331 static int bit_bswap(lua_State *L) 4331 static int bit_bswap(lua_State *L)
4332 { 4332 {
4333 UBits b = barg(L, 1); 4333 UBits b = barg(L, 1);
4334 b = (b >> 24) | ((b >> 8) & 0xff00) | ((b & 0xff00) << 8) | (b << 24); 4334 b = (b >> 24) | ((b >> 8) & 0xff00) | ((b & 0xff00) << 8) | (b << 24);
4335 BRET(b) 4335 BRET(b)
4336 } 4336 }
4337 4337
4338 static int bit_tohex(lua_State *L) 4338 static int bit_tohex(lua_State *L)
4339 { 4339 {
4340 UBits b = barg(L, 1); 4340 UBits b = barg(L, 1);
4341 SBits n = lua_isnone(L, 2) ? 8 : (SBits)barg(L, 2); 4341 SBits n = lua_isnone(L, 2) ? 8 : (SBits)barg(L, 2);
4342 const char *hexdigits = "0123456789abcdef"; 4342 const char *hexdigits = "0123456789abcdef";
4343 char buf[8]; 4343 char buf[8];
4344 int i; 4344 int i;
4345 if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; } 4345 if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; }
4346 if (n > 8) n = 8; 4346 if (n > 8) n = 8;
4347 for (i = (int)n; --i >= 0; ) 4347 for (i = (int)n; --i >= 0; )
4348 { 4348 {
4349 buf[i] = hexdigits[b & 15]; b >>= 4; 4349 buf[i] = hexdigits[b & 15]; b >>= 4;
4350 } 4350 }
4351 lua_pushlstring(L, buf, (size_t)n); 4351 lua_pushlstring(L, buf, (size_t)n);
4352 return 1; 4352 return 1;
4353 } 4353 }
4354 4354
4355 static const struct luaL_Reg bit_funcs[] = { 4355 static const struct luaL_Reg bit_funcs[] = {
4356 { "tobit", bit_tobit }, 4356 { "tobit", bit_tobit },
4357 { "bnot", bit_bnot }, 4357 { "bnot", bit_bnot },
4358 { "band", bit_band }, 4358 { "band", bit_band },
4359 { "bor", bit_bor }, 4359 { "bor", bit_bor },
4360 { "bxor", bit_bxor }, 4360 { "bxor", bit_bxor },
4361 { "lshift", bit_lshift }, 4361 { "lshift", bit_lshift },
4362 { "rshift", bit_rshift }, 4362 { "rshift", bit_rshift },
4363 { "arshift", bit_arshift }, 4363 { "arshift", bit_arshift },
4364 { "rol", bit_rol }, 4364 { "rol", bit_rol },
4365 { "ror", bit_ror }, 4365 { "ror", bit_ror },
4366 { "bswap", bit_bswap }, 4366 { "bswap", bit_bswap },
4367 { "tohex", bit_tohex }, 4367 { "tohex", bit_tohex },
4368 { NULL, NULL } 4368 { NULL, NULL }
4369 }; 4369 };
4370 4370
4371 /* Signed right-shifts are implementation-defined per C89/C99. 4371 /* Signed right-shifts are implementation-defined per C89/C99.
4372 ** But the de facto standard are arithmetic right-shifts on two's 4372 ** But the de facto standard are arithmetic right-shifts on two's
4373 ** complement CPUs. This behaviour is required here, so test for it. 4373 ** complement CPUs. This behaviour is required here, so test for it.
4374 */ 4374 */
4375 #define BAD_SAR (bsar(-8, 2) != (SBits) - 2) 4375 #define BAD_SAR (bsar(-8, 2) != (SBits) - 2)
4376 4376
4377 bool luabitop_validate(lua_State *L) // originally named as luaopen_bit 4377 bool luabitop_validate(lua_State *L) // originally named as luaopen_bit
4378 { 4378 {
4379 UBits b; 4379 UBits b;
4380 lua_pushnumber(L, (lua_Number)1437217655L); 4380 lua_pushnumber(L, (lua_Number)1437217655L);
4381 b = barg(L, -1); 4381 b = barg(L, -1);
4382 if (b != (UBits)1437217655L || BAD_SAR) /* Perform a simple self-test. */ 4382 if (b != (UBits)1437217655L || BAD_SAR) /* Perform a simple self-test. */
4383 { 4383 {
4384 const char *msg = "compiled with incompatible luaconf.h"; 4384 const char *msg = "compiled with incompatible luaconf.h";
4385 #ifdef LUA_NUMBER_DOUBLE 4385 #ifdef LUA_NUMBER_DOUBLE
4386 #ifdef WIN32 4386 #ifdef WIN32
4387 if (b == (UBits)1610612736L) 4387 if (b == (UBits)1610612736L)
4388 msg = "use D3DCREATE_FPU_PRESERVE with DirectX"; 4388 msg = "use D3DCREATE_FPU_PRESERVE with DirectX";
4389 #endif 4389 #endif
4390 if (b == (UBits)1127743488L) 4390 if (b == (UBits)1127743488L)
4391 msg = "not compiled with SWAPPED_DOUBLE"; 4391 msg = "not compiled with SWAPPED_DOUBLE";
4392 #endif 4392 #endif
4393 if (BAD_SAR) 4393 if (BAD_SAR)
4394 msg = "arithmetic right-shift broken"; 4394 msg = "arithmetic right-shift broken";
4395 luaL_error(L, "bit library self-test failed (%s)", msg); 4395 luaL_error(L, "bit library self-test failed (%s)", msg);
4396 return false; 4396 return false;
4397 } 4397 }
4398 return true; 4398 return true;
4399 } 4399 }
4400 4400
4401 // LuaBitOp ends here 4401 // LuaBitOp ends here
4402 4402
4403 static int bit_bshift_emulua(lua_State *L) 4403 static int bit_bshift_emulua(lua_State *L)
4404 { 4404 {
4405 int shift = luaL_checkinteger(L, 2); 4405 int shift = luaL_checkinteger(L, 2);
4406 if (shift < 0) 4406 if (shift < 0)
4407 { 4407 {
4408 lua_pushinteger(L, -shift); 4408 lua_pushinteger(L, -shift);
4409 lua_replace(L, 2); 4409 lua_replace(L, 2);
4410 return bit_lshift(L); 4410 return bit_lshift(L);
4411 } 4411 }
4412 else 4412 else
4413 return bit_rshift(L); 4413 return bit_rshift(L);
4414 } 4414 }
4415 4415
4416 static int bitbit(lua_State *L) 4416 static int bitbit(lua_State *L)
4417 { 4417 {
4418 int rv = 0; 4418 int rv = 0;
4419 int numArgs = lua_gettop(L); 4419 int numArgs = lua_gettop(L);
4420 for (int i = 1; i <= numArgs; i++) 4420 for (int i = 1; i <= numArgs; i++)
4421 { 4421 {
4422 int where = luaL_checkinteger(L, i); 4422 int where = luaL_checkinteger(L, i);
4423 if (where >= 0 && where < 32) 4423 if (where >= 0 && where < 32)
4424 rv |= (1 << where); 4424 rv |= (1 << where);
4425 } 4425 }
4426 lua_settop(L, 0); 4426 lua_settop(L, 0);
4427 BRET(rv); 4427 BRET(rv);
4428 } 4428 }
4429 4429
4430 // The function called periodically to ensure Lua doesn't run amok. 4430 // The function called periodically to ensure Lua doesn't run amok.
4431 static void VBALuaHookFunction(lua_State *L, lua_Debug *dbg) 4431 static void VBALuaHookFunction(lua_State *L, lua_Debug *dbg)
4432 { 4432 {
4433 if (numTries-- == 0) 4433 if (numTries-- == 0)
4434 { 4434 {
4435 int kill = 0; 4435 int kill = 0;
4436 4436
4437 #if (defined(WIN32) && !defined(SDL)) 4437 #if (defined(WIN32) && !defined(SDL))
4438 // Uh oh 4438 // Uh oh
4439 theApp.winCheckFullscreen(); 4439 theApp.winCheckFullscreen();
4440 systemSoundClearBuffer(); 4440 systemSoundClearBuffer();
4441 int ret = AfxGetApp()->m_pMainWnd->MessageBox( 4441 int ret = AfxGetApp()->m_pMainWnd->MessageBox(
4442 "The Lua script running has been running a long time. It may have gone crazy. Kill it?\n\n(No = don't check anymore either)", 4442 "The Lua script running has been running a long time. It may have gone crazy. Kill it?\n\n(No = don't check anymore either)",
4443 "Lua Script Gone Nuts?", 4443 "Lua Script Gone Nuts?",
4444 MB_YESNO); 4444 MB_YESNO);
4445 4445
4446 if (ret == IDYES) 4446 if (ret == IDYES)
4447 { 4447 {
4448 kill = 1; 4448 kill = 1;
4449 } 4449 }
4450 4450
4451 #else 4451 #else
4452 fprintf( 4452 fprintf(
4453 stderr, 4453 stderr,
4454 "The Lua script running has been running a long time.\nIt may have gone crazy. Kill it? (I won't ask again if you say No)\n"); 4454 "The Lua script running has been running a long time.\nIt may have gone crazy. Kill it? (I won't ask again if you say No)\n");
4455 4455
4456 char buffer[64]; 4456 char buffer[64];
4457 while (true) 4457 while (true)
4458 { 4458 {
4459 fprintf(stderr, "(y/n): "); 4459 fprintf(stderr, "(y/n): ");
4460 fgets(buffer, sizeof(buffer), stdin); 4460 fgets(buffer, sizeof(buffer), stdin);
4461 if (buffer[0] == 'y' || buffer[0] == 'Y') 4461 if (buffer[0] == 'y' || buffer[0] == 'Y')
4462 { 4462 {
4463 kill = 1; 4463 kill = 1;
4464 break; 4464 break;
4465 } 4465 }
4466 4466
4467 if (buffer[0] == 'n' || buffer[0] == 'N') 4467 if (buffer[0] == 'n' || buffer[0] == 'N')
4468 break; 4468 break;
4469 } 4469 }
4470 #endif 4470 #endif
4471 if (kill) 4471 if (kill)
4472 { 4472 {
4473 luaL_error(L, "Killed by user request."); 4473 luaL_error(L, "Killed by user request.");
4474 VBALuaOnStop(); 4474 VBALuaOnStop();
4475 } 4475 }
4476 4476
4477 // else, kill the debug hook. 4477 // else, kill the debug hook.
4478 lua_sethook(L, NULL, 0, 0); 4478 lua_sethook(L, NULL, 0, 0);
4479 } 4479 }
4480 } 4480 }
4481 4481
4482 static const struct luaL_reg vbalib[] = { 4482 static const struct luaL_reg vbalib[] = {
4483 // {"speedmode", vba_speedmode}, // TODO: NYI 4483 // {"speedmode", vba_speedmode}, // TODO: NYI
4484 { "frameadvance", vba_frameadvance }, 4484 { "frameadvance", vba_frameadvance },
4485 { "pause", vba_pause }, 4485 { "pause", vba_pause },
4486 { "framecount", vba_framecount }, 4486 { "framecount", vba_framecount },
4487 { "lagcount", vba_getlagcount }, 4487 { "lagcount", vba_getlagcount },
4488 { "lagged", vba_lagged }, 4488 { "lagged", vba_lagged },
4489 { "emulating", vba_emulating }, 4489 { "emulating", vba_emulating },
4490 { "registerbefore", vba_registerbefore }, 4490 { "registerbefore", vba_registerbefore },
4491 { "registerafter", vba_registerafter }, 4491 { "registerafter", vba_registerafter },
4492 { "registerexit", vba_registerexit }, 4492 { "registerexit", vba_registerexit },
4493 { "message", vba_message }, 4493 { "message", vba_message },
4494 { "print", print }, // sure, why not 4494 { "print", print }, // sure, why not
4495 { NULL, NULL } 4495 { NULL, NULL }
4496 }; 4496 };
4497 4497
4498 static const struct luaL_reg memorylib[] = { 4498 static const struct luaL_reg memorylib[] = {
4499 { "readbyte", memory_readbyte }, 4499 { "readbyte", memory_readbyte },
4500 { "readbytesigned", memory_readbytesigned }, 4500 { "readbytesigned", memory_readbytesigned },
4501 { "readword", memory_readword }, 4501 { "readword", memory_readword },
4502 { "readwordsigned", memory_readwordsigned }, 4502 { "readwordsigned", memory_readwordsigned },
4503 { "readdword", memory_readdword }, 4503 { "readdword", memory_readdword },
4504 { "readdwordsigned", memory_readdwordsigned }, 4504 { "readdwordsigned", memory_readdwordsigned },
4505 { "readbyterange", memory_readbyterange }, 4505 { "readbyterange", memory_readbyterange },
4506 { "writebyte", memory_writebyte }, 4506 { "writebyte", memory_writebyte },
4507 { "writeword", memory_writeword }, 4507 { "writeword", memory_writeword },
4508 { "writedword", memory_writedword }, 4508 { "writedword", memory_writedword },
4509 { "getregister", memory_getregister }, 4509 { "getregister", memory_getregister },
4510 { "setregister", memory_setregister }, 4510 { "setregister", memory_setregister },
4511 { "gbromreadbyte", memory_gbromreadbyte }, 4511 { "gbromreadbyte", memory_gbromreadbyte },
4512 { "gbromreadbytesigned", memory_gbromreadbytesigned }, 4512 { "gbromreadbytesigned", memory_gbromreadbytesigned },
4513 { "gbromreadword", memory_gbromreadword }, 4513 { "gbromreadword", memory_gbromreadword },
4514 { "gbromreadwordsigned", memory_gbromreadwordsigned }, 4514 { "gbromreadwordsigned", memory_gbromreadwordsigned },
4515 { "gbromreaddword", memory_gbromreaddword }, 4515 { "gbromreaddword", memory_gbromreaddword },
4516 { "gbromreaddwordsigned", memory_gbromreaddwordsigned }, 4516 { "gbromreaddwordsigned", memory_gbromreaddwordsigned },
4517 { "gbromreadbyterange", memory_gbromreadbyterange }, 4517 { "gbromreadbyterange", memory_gbromreadbyterange },
4518 4518
4519 // alternate naming scheme for word and double-word and unsigned 4519 // alternate naming scheme for word and double-word and unsigned
4520 { "readbyteunsigned", memory_readbyte }, 4520 { "readbyteunsigned", memory_readbyte },
4521 { "readwordunsigned", memory_readword }, 4521 { "readwordunsigned", memory_readword },
4522 { "readdwordunsigned", memory_readdword }, 4522 { "readdwordunsigned", memory_readdword },
4523 { "readshort", memory_readword }, 4523 { "readshort", memory_readword },
4524 { "readshortunsigned", memory_readword }, 4524 { "readshortunsigned", memory_readword },
4525 { "readshortsigned", memory_readwordsigned }, 4525 { "readshortsigned", memory_readwordsigned },
4526 { "readlong", memory_readdword }, 4526 { "readlong", memory_readdword },
4527 { "readlongunsigned", memory_readdword }, 4527 { "readlongunsigned", memory_readdword },
4528 { "readlongsigned", memory_readdwordsigned }, 4528 { "readlongsigned", memory_readdwordsigned },
4529 { "writeshort", memory_writeword }, 4529 { "writeshort", memory_writeword },
4530 { "writelong", memory_writedword }, 4530 { "writelong", memory_writedword },
4531 { "gbromreadbyteunsigned", memory_gbromreadbyte }, 4531 { "gbromreadbyteunsigned", memory_gbromreadbyte },
4532 { "gbromreadwordunsigned", memory_gbromreadword }, 4532 { "gbromreadwordunsigned", memory_gbromreadword },
4533 { "gbromreaddwordunsigned", memory_gbromreaddword }, 4533 { "gbromreaddwordunsigned", memory_gbromreaddword },
4534 { "gbromreadshort", memory_gbromreadword }, 4534 { "gbromreadshort", memory_gbromreadword },
4535 { "gbromreadshortunsigned", memory_gbromreadword }, 4535 { "gbromreadshortunsigned", memory_gbromreadword },
4536 { "gbromreadshortsigned", memory_gbromreadwordsigned }, 4536 { "gbromreadshortsigned", memory_gbromreadwordsigned },
4537 { "gbromreadlong", memory_gbromreaddword }, 4537 { "gbromreadlong", memory_gbromreaddword },
4538 { "gbromreadlongunsigned", memory_gbromreaddword }, 4538 { "gbromreadlongunsigned", memory_gbromreaddword },
4539 { "gbromreadlongsigned", memory_gbromreaddwordsigned }, 4539 { "gbromreadlongsigned", memory_gbromreaddwordsigned },
4540 4540
4541 // memory hooks 4541 // memory hooks
4542 { "registerwrite", memory_registerwrite }, 4542 { "registerwrite", memory_registerwrite },
4543 //{"registerread", memory_registerread}, 4543 //{"registerread", memory_registerread},
4544 { "registerexec", memory_registerexec }, 4544 { "registerexec", memory_registerexec },
4545 // alternate names 4545 // alternate names
4546 { "register", memory_registerwrite }, 4546 { "register", memory_registerwrite },
4547 { "registerrun", memory_registerexec }, 4547 { "registerrun", memory_registerexec },
4548 { "registerexecute", memory_registerexec }, 4548 { "registerexecute", memory_registerexec },
4549 4549
4550 { NULL, NULL } 4550 { NULL, NULL }
4551 }; 4551 };
4552 4552
4553 static const struct luaL_reg joypadlib[] = { 4553 static const struct luaL_reg joypadlib[] = {
4554 { "get", joypad_get }, 4554 { "get", joypad_get },
4555 { "getdown", joypad_getdown }, 4555 { "getdown", joypad_getdown },
4556 { "getup", joypad_getup }, 4556 { "getup", joypad_getup },
4557 { "set", joypad_set }, 4557 { "set", joypad_set },
4558 4558
4559 // alternative names 4559 // alternative names
4560 { "read", joypad_get }, 4560 { "read", joypad_get },
4561 { "write", joypad_set }, 4561 { "write", joypad_set },
4562 { "readdown", joypad_getdown }, 4562 { "readdown", joypad_getdown },
4563 { "readup", joypad_getup }, 4563 { "readup", joypad_getup },
4564 { NULL, NULL } 4564 { NULL, NULL }
4565 }; 4565 };
4566 4566
4567 static const struct luaL_reg savestatelib[] = { 4567 static const struct luaL_reg savestatelib[] = {
4568 { "create", savestate_create }, 4568 { "create", savestate_create },
4569 { "save", savestate_save }, 4569 { "save", savestate_save },
4570 { "load", savestate_load }, 4570 { "load", savestate_load },
4571 4571
4572 { NULL, NULL } 4572 { NULL, NULL }
4573 }; 4573 };
4574 4574
4575 static const struct luaL_reg movielib[] = { 4575 static const struct luaL_reg movielib[] = {
4576 { "active", movie_isactive }, 4576 { "active", movie_isactive },
4577 { "recording", movie_isrecording }, 4577 { "recording", movie_isrecording },
4578 { "playing", movie_isplaying }, 4578 { "playing", movie_isplaying },
4579 { "mode", movie_getmode }, 4579 { "mode", movie_getmode },
4580 4580
4581 { "length", movie_getlength }, 4581 { "length", movie_getlength },
4582 { "author", movie_getauthor }, 4582 { "author", movie_getauthor },
4583 { "name", movie_getfilename }, 4583 { "name", movie_getfilename },
4584 { "rerecordcount", movie_rerecordcount }, 4584 { "rerecordcount", movie_rerecordcount },
4585 { "setrerecordcount", movie_setrerecordcount }, 4585 { "setrerecordcount", movie_setrerecordcount },
4586 4586
4587 { "rerecordcounting", movie_rerecordcounting }, 4587 { "rerecordcounting", movie_rerecordcounting },
4588 { "framecount", vba_framecount }, // for those familiar with 4588 { "framecount", vba_framecount }, // for those familiar with
4589 // other emulators that have 4589 // other emulators that have
4590 // movie.framecount() 4590 // movie.framecount()
4591 // instead of 4591 // instead of
4592 // emulatorname.framecount() 4592 // emulatorname.framecount()
4593 4593
4594 { "stop", movie_stop }, 4594 { "stop", movie_stop },
4595 4595
4596 // alternative names 4596 // alternative names
4597 { "close", movie_stop }, 4597 { "close", movie_stop },
4598 { "getauthor", movie_getauthor }, 4598 { "getauthor", movie_getauthor },
4599 { "getname", movie_getfilename }, 4599 { "getname", movie_getfilename },
4600 { NULL, NULL } 4600 { NULL, NULL }
4601 }; 4601 };
4602 4602
4603 static const struct luaL_reg guilib[] = { 4603 static const struct luaL_reg guilib[] = {
4604 { "register", gui_register }, 4604 { "register", gui_register },
4605 { "text", gui_text }, 4605 { "text", gui_text },
4606 { "box", gui_drawbox }, 4606 { "box", gui_drawbox },
4607 { "line", gui_drawline }, 4607 { "line", gui_drawline },
4608 { "pixel", gui_drawpixel }, 4608 { "pixel", gui_drawpixel },
4609 { "opacity", gui_setopacity }, 4609 { "opacity", gui_setopacity },
4610 { "transparency", gui_transparency }, 4610 { "transparency", gui_transparency },
4611 { "popup", gui_popup }, 4611 { "popup", gui_popup },
4612 { "parsecolor", gui_parsecolor }, 4612 { "parsecolor", gui_parsecolor },
4613 { "gdscreenshot", gui_gdscreenshot }, 4613 { "gdscreenshot", gui_gdscreenshot },
4614 { "gdoverlay", gui_gdoverlay }, 4614 { "gdoverlay", gui_gdoverlay },
4615 { "getpixel", gui_getpixel }, 4615 { "getpixel", gui_getpixel },
4616 4616
4617 // alternative names 4617 // alternative names
4618 { "drawtext", gui_text }, 4618 { "drawtext", gui_text },
4619 { "drawbox", gui_drawbox }, 4619 { "drawbox", gui_drawbox },
4620 { "drawline", gui_drawline }, 4620 { "drawline", gui_drawline },
4621 { "drawpixel", gui_drawpixel }, 4621 { "drawpixel", gui_drawpixel },
4622 { "setpixel", gui_drawpixel }, 4622 { "setpixel", gui_drawpixel },
4623 { "writepixel", gui_drawpixel }, 4623 { "writepixel", gui_drawpixel },
4624 { "rect", gui_drawbox }, 4624 { "rect", gui_drawbox },
4625 { "drawrect", gui_drawbox }, 4625 { "drawrect", gui_drawbox },
4626 { "drawimage", gui_gdoverlay }, 4626 { "drawimage", gui_gdoverlay },
4627 { "image", gui_gdoverlay }, 4627 { "image", gui_gdoverlay },
4628 { "readpixel", gui_getpixel }, 4628 { "readpixel", gui_getpixel },
4629 { NULL, NULL } 4629 { NULL, NULL }
4630 }; 4630 };
4631 4631
4632 static const struct luaL_reg inputlib[] = { 4632 static const struct luaL_reg inputlib[] = {
4633 { "get", input_getcurrentinputstatus }, 4633 { "get", input_getcurrentinputstatus },
4634 4634
4635 // alternative names 4635 // alternative names
4636 { "read", input_getcurrentinputstatus }, 4636 { "read", input_getcurrentinputstatus },
4637 { NULL, NULL } 4637 { NULL, NULL }
4638 }; 4638 };
4639 4639
4640 static const struct luaL_reg soundlib[] = { 4640 static const struct luaL_reg soundlib[] = {
4641 { "get", sound_get }, 4641 { "get", sound_get },
4642 4642
4643 // alternative names 4643 // alternative names
4644 { NULL, NULL } 4644 { NULL, NULL }
4645 }; 4645 };
4646 4646
4647 // gocha: since vba dumps avi so badly, 4647 // gocha: since vba dumps avi so badly,
4648 // I add avilib as a workaround for enhanced video encoding. 4648 // I add avilib as a workaround for enhanced video encoding.
4649 static const struct luaL_reg avilib[] = { 4649 static const struct luaL_reg avilib[] = {
4650 { "framecount", avi_framecount }, 4650 { "framecount", avi_framecount },
4651 { "pause", avi_pause }, 4651 { "pause", avi_pause },
4652 { "resume", avi_resume }, 4652 { "resume", avi_resume },
4653 { NULL, NULL } 4653 { NULL, NULL }
4654 }; 4654 };
4655 4655
4656 void CallExitFunction(void) 4656 void CallExitFunction(void)
4657 { 4657 {
4658 if (!LUA) 4658 if (!LUA)
4659 return; 4659 return;
4660 4660
4661 lua_settop(LUA, 0); 4661 lua_settop(LUA, 0);
4662 lua_getfield(LUA, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFOREEXIT]); 4662 lua_getfield(LUA, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFOREEXIT]);
4663 4663
4664 int errorcode = 0; 4664 int errorcode = 0;
4665 if (lua_isfunction(LUA, -1)) 4665 if (lua_isfunction(LUA, -1))
4666 { 4666 {
4667 errorcode = lua_pcall(LUA, 0, 0, 0); 4667 errorcode = lua_pcall(LUA, 0, 0, 0);
4668 } 4668 }
4669 4669
4670 if (errorcode) 4670 if (errorcode)
4671 HandleCallbackError(LUA); 4671 HandleCallbackError(LUA);
4672 } 4672 }
4673 4673
4674 void VBALuaFrameBoundary(void) 4674 void VBALuaFrameBoundary(void)
4675 { 4675 {
4676 // printf("Lua Frame\n"); 4676 // printf("Lua Frame\n");
4677 4677
4678 lua_joypads_used = 0; 4678 lua_joypads_used = 0;
4679 4679
4680 // HA! 4680 // HA!
4681 if (!LUA || !luaRunning) 4681 if (!LUA || !luaRunning)
4682 return; 4682 return;
4683 4683
4684 // Our function needs calling 4684 // Our function needs calling
4685 lua_settop(LUA, 0); 4685 lua_settop(LUA, 0);
4686 lua_getfield(LUA, LUA_REGISTRYINDEX, frameAdvanceThread); 4686 lua_getfield(LUA, LUA_REGISTRYINDEX, frameAdvanceThread);
4687 4687
4688 lua_State *thread = lua_tothread(LUA, 1); 4688 lua_State *thread = lua_tothread(LUA, 1);
4689 4689
4690 // Lua calling C must know that we're busy inside a frame boundary 4690 // Lua calling C must know that we're busy inside a frame boundary
4691 frameBoundary = true; 4691 frameBoundary = true;
4692 frameAdvanceWaiting = false; 4692 frameAdvanceWaiting = false;
4693 4693
4694 numTries = 1000; 4694 numTries = 1000;
4695 4695
4696 int result = lua_resume(thread, 0); 4696 int result = lua_resume(thread, 0);
4697 4697
4698 if (result == LUA_YIELD) 4698 if (result == LUA_YIELD)
4699 { 4699 {
4700 // Okay, we're fine with that. 4700 // Okay, we're fine with that.
4701 } 4701 }
4702 else if (result != 0) 4702 else if (result != 0)
4703 { 4703 {
4704 // Done execution by bad causes 4704 // Done execution by bad causes
4705 VBALuaOnStop(); 4705 VBALuaOnStop();
4706 lua_pushnil(LUA); 4706 lua_pushnil(LUA);
4707 lua_setfield(LUA, LUA_REGISTRYINDEX, frameAdvanceThread); 4707 lua_setfield(LUA, LUA_REGISTRYINDEX, frameAdvanceThread);
4708 lua_pushnil(LUA); 4708 lua_pushnil(LUA);
4709 lua_setfield(LUA, LUA_REGISTRYINDEX, guiCallbackTable); 4709 lua_setfield(LUA, LUA_REGISTRYINDEX, guiCallbackTable);
4710 4710
4711 // Error? 4711 // Error?
4712 //#if (defined(WIN32) && !defined(SDL)) 4712 //#if (defined(WIN32) && !defined(SDL))
4713 // info_print(info_uid, lua_tostring(thread, -1)); //Clear_Sound_Buffer(); 4713 // info_print(info_uid, lua_tostring(thread, -1)); //Clear_Sound_Buffer();
4714 // AfxGetApp()->m_pMainWnd->MessageBox(lua_tostring(thread, -1), "Lua run error", MB_OK | MB_ICONSTOP); 4714 // AfxGetApp()->m_pMainWnd->MessageBox(lua_tostring(thread, -1), "Lua run error", MB_OK | MB_ICONSTOP);
4715 //#else 4715 //#else
4716 // fprintf(stderr, "Lua thread bombed out: %s\n", lua_tostring(thread, -1)); 4716 // fprintf(stderr, "Lua thread bombed out: %s\n", lua_tostring(thread, -1));
4717 //#endif 4717 //#endif
4718 printerror(thread, -1); 4718 printerror(thread, -1);
4719 } 4719 }
4720 else 4720 else
4721 { 4721 {
4722 VBALuaOnStop(); 4722 VBALuaOnStop();
4723 printf("Script died of natural causes.\n"); 4723 printf("Script died of natural causes.\n");
4724 } 4724 }
4725 4725
4726 // Past here, VBA actually runs, so any Lua code is called mid-frame. We must 4726 // Past here, VBA actually runs, so any Lua code is called mid-frame. We must
4727 // not do anything too stupid, so let ourselves know. 4727 // not do anything too stupid, so let ourselves know.
4728 frameBoundary = false; 4728 frameBoundary = false;
4729 4729
4730 if (!frameAdvanceWaiting) 4730 if (!frameAdvanceWaiting)
4731 { 4731 {
4732 VBALuaOnStop(); 4732 VBALuaOnStop();
4733 } 4733 }
4734 } 4734 }
4735 4735
4736 /** 4736 /**
4737 * Loads and runs the given Lua script. 4737 * Loads and runs the given Lua script.
4738 * The emulator MUST be paused for this function to be 4738 * The emulator MUST be paused for this function to be
4739 * called. Otherwise, all frame boundary assumptions go out the window. 4739 * called. Otherwise, all frame boundary assumptions go out the window.
4740 * 4740 *
4741 * Returns true on success, false on failure. 4741 * Returns true on success, false on failure.
4742 */ 4742 */
4743 int VBALoadLuaCode(const char *filename) 4743 int VBALoadLuaCode(const char *filename)
4744 { 4744 {
4745 static bool sfmtInitialized = false; 4745 static bool sfmtInitialized = false;
4746 if (!sfmtInitialized) 4746 if (!sfmtInitialized)
4747 { 4747 {
4748 init_gen_rand((unsigned)time(NULL)); 4748 init_gen_rand((unsigned)time(NULL));
4749 sfmtInitialized = true; 4749 sfmtInitialized = true;
4750 } 4750 }
4751 4751
4752 if (filename != luaScriptName) 4752 if (filename != luaScriptName)
4753 { 4753 {
4754 if (luaScriptName) 4754 if (luaScriptName)
4755 free(luaScriptName); 4755 free(luaScriptName);
4756 luaScriptName = strdup(filename); 4756 luaScriptName = strdup(filename);
4757 } 4757 }
4758 4758
4759 //stop any lua we might already have had running 4759 //stop any lua we might already have had running
4760 VBALuaStop(); 4760 VBALuaStop();
4761 4761
4762 // Set current directory from filename (for dofile) 4762 // Set current directory from filename (for dofile)
4763 char dir[_MAX_PATH]; 4763 char dir[_MAX_PATH];
4764 char *slash, *backslash; 4764 char *slash, *backslash;
4765 strcpy(dir, filename); 4765 strcpy(dir, filename);
4766 slash = strrchr(dir, '/'); 4766 slash = strrchr(dir, '/');
4767 backslash = strrchr(dir, '\\'); 4767 backslash = strrchr(dir, '\\');
4768 if (!slash || (backslash && backslash < slash)) 4768 if (!slash || (backslash && backslash < slash))
4769 slash = backslash; 4769 slash = backslash;
4770 if (slash) 4770 if (slash)
4771 { 4771 {
4772 slash[1] = '\0'; // keep slash itself for some reasons 4772 slash[1] = '\0'; // keep slash itself for some reasons
4773 chdir(dir); 4773 chdir(dir);
4774 } 4774 }
4775 4775
4776 if (!LUA) 4776 if (!LUA)
4777 { 4777 {
4778 LUA = lua_open(); 4778 LUA = lua_open();
4779 luaL_openlibs(LUA); 4779 luaL_openlibs(LUA);
4780 4780
4781 luaL_register(LUA, "emu", vbalib); // added for better cross-emulator compatibility 4781 luaL_register(LUA, "emu", vbalib); // added for better cross-emulator compatibility
4782 luaL_register(LUA, "vba", vbalib); // kept for backward compatibility 4782 luaL_register(LUA, "vba", vbalib); // kept for backward compatibility
4783 luaL_register(LUA, "memory", memorylib); 4783 luaL_register(LUA, "memory", memorylib);
4784 luaL_register(LUA, "joypad", joypadlib); 4784 luaL_register(LUA, "joypad", joypadlib);
4785 luaL_register(LUA, "savestate", savestatelib); 4785 luaL_register(LUA, "savestate", savestatelib);
4786 luaL_register(LUA, "movie", movielib); 4786 luaL_register(LUA, "movie", movielib);
4787 luaL_register(LUA, "gui", guilib); 4787 luaL_register(LUA, "gui", guilib);
4788 luaL_register(LUA, "input", inputlib); 4788 luaL_register(LUA, "input", inputlib);
4789 luaL_register(LUA, "sound", soundlib); 4789 luaL_register(LUA, "sound", soundlib);
4790 luaL_register(LUA, "bit", bit_funcs); // LuaBitOp library 4790 luaL_register(LUA, "bit", bit_funcs); // LuaBitOp library
4791 luaL_register(LUA, "avi", avilib); // workaround for enhanced video encoding 4791 luaL_register(LUA, "avi", avilib); // workaround for enhanced video encoding
4792 lua_settop(LUA, 0); // clean the stack, because each call to luaL_register leaves a table on top 4792 lua_settop(LUA, 0); // clean the stack, because each call to luaL_register leaves a table on top
4793 4793
4794 // register a few utility functions outside of libraries (in the global namespace) 4794 // register a few utility functions outside of libraries (in the global namespace)
4795 lua_register(LUA, "print", print); 4795 lua_register(LUA, "print", print);
4796 lua_register(LUA, "tostring", tostring); 4796 lua_register(LUA, "tostring", tostring);
4797 lua_register(LUA, "addressof", addressof); 4797 lua_register(LUA, "addressof", addressof);
4798 lua_register(LUA, "copytable", copytable); 4798 lua_register(LUA, "copytable", copytable);
4799 4799
4800 // old bit operation functions 4800 // old bit operation functions
4801 lua_register(LUA, "AND", bit_band); 4801 lua_register(LUA, "AND", bit_band);
4802 lua_register(LUA, "OR", bit_bor); 4802 lua_register(LUA, "OR", bit_bor);
4803 lua_register(LUA, "XOR", bit_bxor); 4803 lua_register(LUA, "XOR", bit_bxor);
4804 lua_register(LUA, "SHIFT", bit_bshift_emulua); 4804 lua_register(LUA, "SHIFT", bit_bshift_emulua);
4805 lua_register(LUA, "BIT", bitbit); 4805 lua_register(LUA, "BIT", bitbit);
4806 4806
4807 luabitop_validate(LUA); 4807 luabitop_validate(LUA);
4808 4808
4809 lua_pushstring(LUA, "math"); 4809 lua_pushstring(LUA, "math");
4810 lua_gettable(LUA, LUA_GLOBALSINDEX); 4810 lua_gettable(LUA, LUA_GLOBALSINDEX);
4811 lua_pushcfunction(LUA, sfmt_random); 4811 lua_pushcfunction(LUA, sfmt_random);
4812 lua_setfield(LUA, -2, "random"); 4812 lua_setfield(LUA, -2, "random");
4813 lua_pushcfunction(LUA, sfmt_randomseed); 4813 lua_pushcfunction(LUA, sfmt_randomseed);
4814 lua_setfield(LUA, -2, "randomseed"); 4814 lua_setfield(LUA, -2, "randomseed");
4815 lua_settop(LUA, 0); 4815 lua_settop(LUA, 0);
4816 4816
4817 // push arrays for storing hook functions in 4817 // push arrays for storing hook functions in
4818 for (int i = 0; i < LUAMEMHOOK_COUNT; i++) 4818 for (int i = 0; i < LUAMEMHOOK_COUNT; i++)
4819 { 4819 {
4820 lua_newtable(LUA); 4820 lua_newtable(LUA);
4821 lua_setfield(LUA, LUA_REGISTRYINDEX, luaMemHookTypeStrings[i]); 4821 lua_setfield(LUA, LUA_REGISTRYINDEX, luaMemHookTypeStrings[i]);
4822 } 4822 }
4823 } 4823 }
4824 4824
4825 // We make our thread NOW because we want it at the bottom of the stack. 4825 // We make our thread NOW because we want it at the bottom of the stack.
4826 // If all goes wrong, we let the garbage collector remove it. 4826 // If all goes wrong, we let the garbage collector remove it.
4827 lua_State *thread = lua_newthread(LUA); 4827 lua_State *thread = lua_newthread(LUA);
4828 4828
4829 // Load the data 4829 // Load the data
4830 int result = luaL_loadfile(LUA, filename); 4830 int result = luaL_loadfile(LUA, filename);
4831 4831
4832 if (result) 4832 if (result)
4833 { 4833 {
4834 //#if (defined(WIN32) && !defined(SDL)) 4834 //#if (defined(WIN32) && !defined(SDL))
4835 // info_print(info_uid, lua_tostring(LUA, -1)); //Clear_Sound_Buffer(); 4835 // info_print(info_uid, lua_tostring(LUA, -1)); //Clear_Sound_Buffer();
4836 // AfxGetApp()->m_pMainWnd->MessageBox(lua_tostring(LUA, -1), "Lua load error", MB_OK | MB_ICONSTOP); 4836 // AfxGetApp()->m_pMainWnd->MessageBox(lua_tostring(LUA, -1), "Lua load error", MB_OK | MB_ICONSTOP);
4837 //#else 4837 //#else
4838 // fprintf(stderr, "Failed to compile file: %s\n", lua_tostring(LUA, -1)); 4838 // fprintf(stderr, "Failed to compile file: %s\n", lua_tostring(LUA, -1));
4839 //#endif 4839 //#endif
4840 printerror(LUA, -1); 4840 printerror(LUA, -1);
4841 4841
4842 // Wipe the stack. Our thread 4842 // Wipe the stack. Our thread
4843 lua_settop(LUA, 0); 4843 lua_settop(LUA, 0);
4844 return 0; // Oh shit. 4844 return 0; // Oh shit.
4845 } 4845 }
4846 4846
4847 // Get our function into it 4847 // Get our function into it
4848 lua_xmove(LUA, thread, 1); 4848 lua_xmove(LUA, thread, 1);
4849 4849
4850 // Save the thread to the registry. This is why I make the thread FIRST. 4850 // Save the thread to the registry. This is why I make the thread FIRST.
4851 lua_setfield(LUA, LUA_REGISTRYINDEX, frameAdvanceThread); 4851 lua_setfield(LUA, LUA_REGISTRYINDEX, frameAdvanceThread);
4852 4852
4853 // Initialize settings 4853 // Initialize settings
4854 luaRunning = true; 4854 luaRunning = true;
4855 skipRerecords = false; 4855 skipRerecords = false;
4856 numMemHooks = 0; 4856 numMemHooks = 0;
4857 transparencyModifier = 255; // opaque 4857 transparencyModifier = 255; // opaque
4858 lua_joypads_used = 0; // not used 4858 lua_joypads_used = 0; // not used
4859 //wasPaused = systemIsPaused(); 4859 //wasPaused = systemIsPaused();
4860 //systemSetPause(false); 4860 //systemSetPause(false);
4861 4861
4862 // Set up our protection hook to be executed once every 10,000 bytecode instructions. 4862 // Set up our protection hook to be executed once every 10,000 bytecode instructions.
4863 lua_sethook(thread, VBALuaHookFunction, LUA_MASKCOUNT, 10000); 4863 lua_sethook(thread, VBALuaHookFunction, LUA_MASKCOUNT, 10000);
4864 4864
4865 #ifdef WIN32 4865 #ifdef WIN32
4866 info_print = PrintToWindowConsole; 4866 info_print = PrintToWindowConsole;
4867 info_onstart = WinLuaOnStart; 4867 info_onstart = WinLuaOnStart;
4868 info_onstop = WinLuaOnStop; 4868 info_onstop = WinLuaOnStop;
4869 if (!LuaConsoleHWnd) 4869 if (!LuaConsoleHWnd)
4870 LuaConsoleHWnd = CreateDialog(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDD_LUA), 4870 LuaConsoleHWnd = CreateDialog(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDD_LUA),
4871 AfxGetMainWnd()->GetSafeHwnd(), (DLGPROC) DlgLuaScriptDialog); 4871 AfxGetMainWnd()->GetSafeHwnd(), (DLGPROC) DlgLuaScriptDialog);
4872 info_uid = (int)LuaConsoleHWnd; 4872 info_uid = (int)LuaConsoleHWnd;
4873 #else 4873 #else
4874 info_print = NULL; 4874 info_print = NULL;
4875 info_onstart = NULL; 4875 info_onstart = NULL;
4876 info_onstop = NULL; 4876 info_onstop = NULL;
4877 #endif 4877 #endif
4878 if (info_onstart) 4878 if (info_onstart)
4879 info_onstart(info_uid); 4879 info_onstart(info_uid);
4880 4880
4881 // And run it right now. :) 4881 // And run it right now. :)
4882 VBALuaFrameBoundary(); 4882 VBALuaFrameBoundary();
4883 systemRenderFrame(); 4883 systemRenderFrame();
4884 4884
4885 // We're done. 4885 // We're done.
4886 return 1; 4886 return 1;
4887 } 4887 }
4888 4888
4889 /** 4889 /**
4890 * Equivalent to repeating the last VBALoadLuaCode() call. 4890 * Equivalent to repeating the last VBALoadLuaCode() call.
4891 */ 4891 */
4892 int VBAReloadLuaCode(void) 4892 int VBAReloadLuaCode(void)
4893 { 4893 {
4894 if (!luaScriptName) 4894 if (!luaScriptName)
4895 { 4895 {
4896 systemScreenMessage("There's no script to reload."); 4896 systemScreenMessage("There's no script to reload.");
4897 return 0; 4897 return 0;
4898 } 4898 }
4899 else 4899 else
4900 return VBALoadLuaCode(luaScriptName); 4900 return VBALoadLuaCode(luaScriptName);
4901 } 4901 }
4902 4902
4903 /** 4903 /**
4904 * Terminates a running Lua script by killing the whole Lua engine. 4904 * Terminates a running Lua script by killing the whole Lua engine.
4905 * 4905 *
4906 * Always safe to call, except from within a lua call itself (duh). 4906 * Always safe to call, except from within a lua call itself (duh).
4907 * 4907 *
4908 */ 4908 */
4909 void VBALuaStop(void) 4909 void VBALuaStop(void)
4910 { 4910 {
4911 //already killed 4911 //already killed
4912 if (!LUA) 4912 if (!LUA)
4913 return; 4913 return;
4914 4914
4915 //execute the user's shutdown callbacks 4915 //execute the user's shutdown callbacks
4916 CallExitFunction(); 4916 CallExitFunction();
4917 4917
4918 /*info.*/ numMemHooks = 0; 4918 /*info.*/ numMemHooks = 0;
4919 for (int i = 0; i < LUAMEMHOOK_COUNT; i++) 4919 for (int i = 0; i < LUAMEMHOOK_COUNT; i++)
4920 CalculateMemHookRegions((LuaMemHookType)i); 4920 CalculateMemHookRegions((LuaMemHookType)i);
4921 4921
4922 //sometimes iup uninitializes com 4922 //sometimes iup uninitializes com
4923 //MBG TODO - test whether this is really necessary. i dont think it is 4923 //MBG TODO - test whether this is really necessary. i dont think it is
4924 #if (defined(WIN32) && !defined(SDL)) 4924 #if (defined(WIN32) && !defined(SDL))
4925 CoInitialize(0); 4925 CoInitialize(0);
4926 #endif 4926 #endif
4927 4927
4928 if (info_onstop) 4928 if (info_onstop)
4929 info_onstop(info_uid); 4929 info_onstop(info_uid);
4930 4930
4931 //lua_gc(LUA,LUA_GCCOLLECT,0); 4931 //lua_gc(LUA,LUA_GCCOLLECT,0);
4932 lua_close(LUA); // this invokes our garbage collectors for us 4932 lua_close(LUA); // this invokes our garbage collectors for us
4933 LUA = NULL; 4933 LUA = NULL;
4934 VBALuaOnStop(); 4934 VBALuaOnStop();
4935 } 4935 }
4936 4936
4937 /** 4937 /**
4938 * Returns true if there is a Lua script running. 4938 * Returns true if there is a Lua script running.
4939 * 4939 *
4940 */ 4940 */
4941 int VBALuaRunning(void) 4941 int VBALuaRunning(void)
4942 { 4942 {
4943 // FIXME: return false when no callback functions are registered. 4943 // FIXME: return false when no callback functions are registered.
4944 return (int) (LUA != NULL); // should return true if callback functions are active. 4944 return (int) (LUA != NULL); // should return true if callback functions are active.
4945 } 4945 }
4946 4946
4947 /** 4947 /**
4948 * Returns true if Lua would like to steal the given joypad control. 4948 * Returns true if Lua would like to steal the given joypad control.
4949 * 4949 *
4950 * Range is 0 through 3 4950 * Range is 0 through 3
4951 */ 4951 */
4952 int VBALuaUsingJoypad(int which) 4952 int VBALuaUsingJoypad(int which)
4953 { 4953 {
4954 if (which < 0 || which > 3) 4954 if (which < 0 || which > 3)
4955 which = systemGetDefaultJoypad(); 4955 which = systemGetDefaultJoypad();
4956 return lua_joypads_used & (1 << which); 4956 return lua_joypads_used & (1 << which);
4957 } 4957 }
4958 4958
4959 /** 4959 /**
4960 * Reads the buttons Lua is feeding for the given joypad, in the same 4960 * Reads the buttons Lua is feeding for the given joypad, in the same
4961 * format as the OS-specific code. 4961 * format as the OS-specific code.
4962 * 4962 *
4963 * <del>This function must not be called more than once per frame. </del>Ideally exactly once 4963 * <del>This function must not be called more than once per frame. </del>Ideally exactly once
4964 * per frame (if VBALuaUsingJoypad says it's safe to do so) 4964 * per frame (if VBALuaUsingJoypad says it's safe to do so)
4965 */ 4965 */
4966 int VBALuaReadJoypad(int which) 4966 int VBALuaReadJoypad(int which)
4967 { 4967 {
4968 if (which < 0 || which > 3) 4968 if (which < 0 || which > 3)
4969 which = systemGetDefaultJoypad(); 4969 which = systemGetDefaultJoypad();
4970 4970
4971 //lua_joypads_used &= ~(1 << which); 4971 //lua_joypads_used &= ~(1 << which);
4972 return lua_joypads[which]; 4972 return lua_joypads[which];
4973 } 4973 }
4974 4974
4975 /** 4975 /**
4976 * If this function returns true, the movie code should NOT increment 4976 * If this function returns true, the movie code should NOT increment
4977 * the rerecord count for a load-state. 4977 * the rerecord count for a load-state.
4978 * 4978 *
4979 * This function will not return true if a script is not running. 4979 * This function will not return true if a script is not running.
4980 */ 4980 */
4981 bool8 VBALuaRerecordCountSkip(void) 4981 bool8 VBALuaRerecordCountSkip(void)
4982 { 4982 {
4983 // FIXME: return true if (there are any active callback functions && skipRerecords) 4983 // FIXME: return true if (there are any active callback functions && skipRerecords)
4984 return LUA && luaRunning && skipRerecords; 4984 return LUA && luaRunning && skipRerecords;
4985 } 4985 }
4986 4986
4987 /** 4987 /**
4988 * Given a screen with the indicated resolution, 4988 * Given a screen with the indicated resolution,
4989 * draw the current GUI onto it. 4989 * draw the current GUI onto it.
4990 */ 4990 */
4991 void VBALuaGui(uint8 *screen, int ppl, int width, int height) 4991 void VBALuaGui(uint8 *screen, int ppl, int width, int height)
4992 { 4992 {
4993 if (!LUA /* || !luaRunning*/) 4993 if (!LUA /* || !luaRunning*/)
4994 return; 4994 return;
4995 4995
4996 // First, check if we're being called by anybody 4996 // First, check if we're being called by anybody
4997 lua_getfield(LUA, LUA_REGISTRYINDEX, guiCallbackTable); 4997 lua_getfield(LUA, LUA_REGISTRYINDEX, guiCallbackTable);
4998 4998
4999 if (lua_isfunction(LUA, -1)) 4999 if (lua_isfunction(LUA, -1))
5000 { 5000 {
5001 // We call it now 5001 // We call it now
5002 numTries = 1000; 5002 numTries = 1000;
5003 5003
5004 int ret = lua_pcall(LUA, 0, 0, 0); 5004 int ret = lua_pcall(LUA, 0, 0, 0);
5005 if (ret != 0) 5005 if (ret != 0)
5006 { 5006 {
5007 // This is grounds for trashing the function 5007 // This is grounds for trashing the function
5008 // Note: This must be done before the messagebox pops up, 5008 // Note: This must be done before the messagebox pops up,
5009 // otherwise the messagebox will cause a paint event which causes a weird 5009 // otherwise the messagebox will cause a paint event which causes a weird
5010 // infinite call sequence that makes Snes9x silently exit with error code 3, 5010 // infinite call sequence that makes Snes9x silently exit with error code 3,
5011 // if a Lua GUI function crashes. (nitsuja) 5011 // if a Lua GUI function crashes. (nitsuja)
5012 lua_pushnil(LUA); 5012 lua_pushnil(LUA);
5013 lua_setfield(LUA, LUA_REGISTRYINDEX, guiCallbackTable); 5013 lua_setfield(LUA, LUA_REGISTRYINDEX, guiCallbackTable);
5014 5014
5015 //#if (defined(WIN32) && !defined(SDL)) 5015 //#if (defined(WIN32) && !defined(SDL))
5016 // info_print(info_uid, lua_tostring(LUA, -1)); //AfxGetApp()->m_pMainWnd->MessageBox(lua_tostring(LUA, -1), "Lua Error 5016 // info_print(info_uid, lua_tostring(LUA, -1)); //AfxGetApp()->m_pMainWnd->MessageBox(lua_tostring(LUA, -1), "Lua Error
5017 // in GUI function", MB_OK); 5017 // in GUI function", MB_OK);
5018 //#else 5018 //#else
5019 // fprintf(stderr, "Lua error in gui.register function: %s\n", lua_tostring(LUA, -1)); 5019 // fprintf(stderr, "Lua error in gui.register function: %s\n", lua_tostring(LUA, -1));
5020 //#endif 5020 //#endif
5021 printerror(LUA, -1); 5021 printerror(LUA, -1);
5022 } 5022 }
5023 } 5023 }
5024 5024
5025 // And wreak the stack 5025 // And wreak the stack
5026 lua_settop(LUA, 0); 5026 lua_settop(LUA, 0);
5027 5027
5028 if (!gui_used) 5028 if (!gui_used)
5029 return; 5029 return;
5030 5030
5031 gui_used = false; 5031 gui_used = false;
5032 5032
5033 int x, y; 5033 int x, y;
5034 5034
5035 //int pitch = (((ppl * systemColorDepth + 7)>>3)+3)&~3; 5035 //int pitch = (((ppl * systemColorDepth + 7)>>3)+3)&~3;
5036 int pitch = ppl * (systemColorDepth / 8) + (systemColorDepth == 24 ? 0 : 4); 5036 int pitch = ppl * (systemColorDepth / 8) + (systemColorDepth == 24 ? 0 : 4);
5037 5037
5038 if (width > LUA_SCREEN_WIDTH) 5038 if (width > LUA_SCREEN_WIDTH)
5039 width = LUA_SCREEN_WIDTH; 5039 width = LUA_SCREEN_WIDTH;
5040 if (height > LUA_SCREEN_HEIGHT) 5040 if (height > LUA_SCREEN_HEIGHT)
5041 height = LUA_SCREEN_HEIGHT; 5041 height = LUA_SCREEN_HEIGHT;
5042 5042
5043 GetColorFunc getColor; 5043 GetColorFunc getColor;
5044 SetColorFunc setColor; 5044 SetColorFunc setColor;
5045 getColorIOFunc(systemColorDepth, &getColor, &setColor); 5045 getColorIOFunc(systemColorDepth, &getColor, &setColor);
5046 5046
5047 for (y = 0; y < height; y++) 5047 for (y = 0; y < height; y++)
5048 { 5048 {
5049 uint8 *scr = &screen[y * pitch]; 5049 uint8 *scr = &screen[y * pitch];
5050 for (x = 0; x < width; x++, scr += systemColorDepth / 8) 5050 for (x = 0; x < width; x++, scr += systemColorDepth / 8)
5051 { 5051 {
5052 const uint8 gui_alpha = gui_data[(y * LUA_SCREEN_WIDTH + x) * 4 + 3]; 5052 const uint8 gui_alpha = gui_data[(y * LUA_SCREEN_WIDTH + x) * 4 + 3];
5053 if (gui_alpha == 0) 5053 if (gui_alpha == 0)
5054 { 5054 {
5055 // do nothing 5055 // do nothing
5056 continue; 5056 continue;
5057 } 5057 }
5058 5058
5059 const uint8 gui_red = gui_data[(y * LUA_SCREEN_WIDTH + x) * 4 + 2]; 5059 const uint8 gui_red = gui_data[(y * LUA_SCREEN_WIDTH + x) * 4 + 2];
5060 const uint8 gui_green = gui_data[(y * LUA_SCREEN_WIDTH + x) * 4 + 1]; 5060 const uint8 gui_green = gui_data[(y * LUA_SCREEN_WIDTH + x) * 4 + 1];
5061 const uint8 gui_blue = gui_data[(y * LUA_SCREEN_WIDTH + x) * 4]; 5061 const uint8 gui_blue = gui_data[(y * LUA_SCREEN_WIDTH + x) * 4];
5062 int red, green, blue; 5062 int red, green, blue;
5063 5063
5064 if (gui_alpha == 255) 5064 if (gui_alpha == 255)
5065 { 5065 {
5066 // direct copy 5066 // direct copy
5067 red = gui_red; 5067 red = gui_red;
5068 green = gui_green; 5068 green = gui_green;
5069 blue = gui_blue; 5069 blue = gui_blue;
5070 } 5070 }
5071 else 5071 else
5072 { 5072 {
5073 // alpha-blending 5073 // alpha-blending
5074 uint8 scr_red, scr_green, scr_blue; 5074 uint8 scr_red, scr_green, scr_blue;
5075 getColor(scr, &scr_red, &scr_green, &scr_blue); 5075 getColor(scr, &scr_red, &scr_green, &scr_blue);
5076 red = (((int)gui_red - scr_red) * gui_alpha / 255 + scr_red) & 255; 5076 red = (((int)gui_red - scr_red) * gui_alpha / 255 + scr_red) & 255;
5077 green = (((int)gui_green - scr_green) * gui_alpha / 255 + scr_green) & 255; 5077 green = (((int)gui_green - scr_green) * gui_alpha / 255 + scr_green) & 255;
5078 blue = (((int)gui_blue - scr_blue) * gui_alpha / 255 + scr_blue) & 255; 5078 blue = (((int)gui_blue - scr_blue) * gui_alpha / 255 + scr_blue) & 255;
5079 } 5079 }
5080 5080
5081 setColor(scr, (uint8) red, (uint8) green, (uint8) blue); 5081 setColor(scr, (uint8) red, (uint8) green, (uint8) blue);
5082 } 5082 }
5083 } 5083 }
5084 5084
5085 return; 5085 return;
5086 } 5086 }
5087 5087
5088 void VBALuaClearGui(void) 5088 void VBALuaClearGui(void)
5089 { 5089 {
5090 gui_used = false; 5090 gui_used = false;
5091 } 5091 }
5092 5092
5093 lua_State *VBAGetLuaState() 5093 lua_State *VBAGetLuaState()
5094 { 5094 {
5095 return LUA; 5095 return LUA;
5096 } 5096 }
5097 5097
5098 char *VBAGetLuaScriptName() 5098 char *VBAGetLuaScriptName()
5099 { 5099 {
5100 return luaScriptName; 5100 return luaScriptName;
5101 } 5101 }
5102 5102