love.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /**
  2. * Copyright (c) 2006-2011 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. // LOVE
  21. #include <common/config.h>
  22. #include <common/version.h>
  23. #include <common/runtime.h>
  24. #include <common/MemoryData.h>
  25. #ifdef LOVE_WINDOWS
  26. #include <windows.h>
  27. #endif // LOVE_WINDOWS
  28. #ifdef LOVE_LEGENDARY_CONSOLE_IO_HACK
  29. #include <fcntl.h>
  30. #include <io.h>
  31. #include <iostream>
  32. #include <fstream>
  33. #endif // LOVE_LEGENDARY_CONSOLE_IO_HACK
  34. #ifdef LOVE_BUILD_EXE
  35. // SDL
  36. #include <SDL.h>
  37. // Modules
  38. #include <audio/wrap_Audio.h>
  39. #include <event/sdl/wrap_Event.h>
  40. #include <filesystem/physfs/wrap_Filesystem.h>
  41. #include <font/freetype/wrap_Font.h>
  42. #include <graphics/opengl/wrap_Graphics.h>
  43. #include <image/wrap_Image.h>
  44. #include <joystick/sdl/wrap_Joystick.h>
  45. #include <keyboard/sdl/wrap_Keyboard.h>
  46. #include <mouse/sdl/wrap_Mouse.h>
  47. #include <physics/box2d/wrap_Physics.h>
  48. #include <sound/wrap_Sound.h>
  49. #include <timer/sdl/wrap_Timer.h>
  50. #include <thread/sdl/wrap_Thread.h>
  51. // Libraries.
  52. #include "libraries/luasocket/luasocket.h"
  53. // Scripts
  54. #include "scripts/boot.lua.h"
  55. #endif // LOVE_BUILD_EXE
  56. #ifdef LOVE_BUILD_STANDALONE
  57. static const luaL_Reg modules[] = {
  58. { "love.audio", love::audio::luaopen_love_audio },
  59. { "love.event", love::event::sdl::luaopen_love_event },
  60. { "love.filesystem", love::filesystem::physfs::luaopen_love_filesystem },
  61. { "love.font", love::font::freetype::luaopen_love_font },
  62. { "love.graphics", love::graphics::opengl::luaopen_love_graphics },
  63. { "love.image", love::image::luaopen_love_image },
  64. { "love.joystick", love::joystick::sdl::luaopen_love_joystick },
  65. { "love.keyboard", love::keyboard::sdl::luaopen_love_keyboard },
  66. { "love.mouse", love::mouse::sdl::luaopen_love_mouse },
  67. { "love.physics", love::physics::box2d::luaopen_love_physics },
  68. { "love.sound", love::sound::luaopen_love_sound },
  69. { "love.timer", love::timer::sdl::luaopen_love_timer },
  70. { "love.thread", love::thread::sdl::luaopen_love_thread },
  71. { 0, 0 }
  72. };
  73. #endif // LOVE_BUILD_STANDALONE
  74. #ifdef LOVE_LEGENDARY_CONSOLE_IO_HACK
  75. int w__openConsole(lua_State * L);
  76. #endif // LOVE_LEGENDARY_CONSOLE_IO_HACK
  77. extern "C" LOVE_EXPORT int luaopen_love(lua_State * L)
  78. {
  79. love::luax_insistglobal(L, "love");
  80. // Set version information.
  81. lua_pushinteger(L, love::VERSION);
  82. lua_setfield(L, -2, "_version");
  83. lua_pushstring(L, love::VERSION_STR);
  84. lua_setfield(L, -2, "_version_string");
  85. lua_pushstring(L, love::VERSION_CODENAME);
  86. lua_setfield(L, -2, "_version_codename");
  87. #ifdef LOVE_LEGENDARY_CONSOLE_IO_HACK
  88. lua_pushcfunction(L, w__openConsole);
  89. lua_setfield(L, -2, "_openConsole");
  90. #endif // LOVE_LEGENDARY_CONSOLE_IO_HACK
  91. lua_newtable(L);
  92. for(int i = 0; love::VERSION_COMPATIBILITY[i] != 0; ++i)
  93. {
  94. lua_pushinteger(L, love::VERSION_COMPATIBILITY[i]);
  95. lua_rawseti(L, -2, i+1);
  96. }
  97. lua_setfield(L, -2, "_version_compat");
  98. lua_pop(L, 1); // love
  99. #ifdef LOVE_BUILD_STANDALONE
  100. // Preload module loaders.
  101. for(int i = 0; modules[i].name != 0; i++)
  102. {
  103. love::luax_preload(L, modules[i].func, modules[i].name);
  104. }
  105. love::luasocket::__open(L);
  106. #endif // LOVE_BUILD_STANDALONE
  107. return 0;
  108. }
  109. #ifdef LOVE_LEGENDARY_UTF8_ARGV_HACK
  110. void get_utf8_arguments(int & argc, char **& argv)
  111. {
  112. LPWSTR cmd = GetCommandLineW();
  113. if(!cmd)
  114. return;
  115. LPWSTR * argv_w = CommandLineToArgvW(cmd, &argc);
  116. argv = new char*[argc];
  117. for(int i = 0; i<argc; ++i)
  118. {
  119. // Size of wide char buffer (plus one for trailing '\0').
  120. size_t wide_len = wcslen(argv_w[i])+1;
  121. // Get size in UTF-8.
  122. int utf8_size = WideCharToMultiByte(CP_UTF8, 0, argv_w[i], wide_len, argv[i], 0, 0, 0);
  123. argv[i] = new char[utf8_size];
  124. // Convert to UTF-8.
  125. int ok = WideCharToMultiByte(CP_UTF8, 0, argv_w[i], wide_len, argv[i], utf8_size, 0, 0);
  126. int len = strlen(argv[i]);
  127. if(!ok)
  128. printf("Warning: could not convert to UTF8.\n");
  129. }
  130. LocalFree(argv_w);
  131. }
  132. #endif // LOVE_LEGENDARY_UTF8_ARGV_HACK
  133. #ifdef LOVE_LEGENDARY_CONSOLE_IO_HACK
  134. int w__openConsole(lua_State * L)
  135. {
  136. static bool is_open = false;
  137. if(is_open)
  138. return 0;
  139. static const int MAX_CONSOLE_LINES = 5000;
  140. long std_handle;
  141. int console_handle;
  142. CONSOLE_SCREEN_BUFFER_INFO console_info;
  143. FILE *fp;
  144. AllocConsole();
  145. // Set size.
  146. GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &console_info);
  147. console_info.dwSize.Y = MAX_CONSOLE_LINES;
  148. SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), console_info.dwSize);
  149. SetConsoleTitle(TEXT("LOVE Console"));
  150. // Redirect stdout.
  151. std_handle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
  152. console_handle = _open_osfhandle(std_handle, _O_TEXT);
  153. fp = _fdopen(console_handle, "w");
  154. *stdout = *fp;
  155. setvbuf(stdout, NULL, _IONBF, 0);
  156. // Redirect stdin.
  157. std_handle = (long)GetStdHandle(STD_INPUT_HANDLE);
  158. console_handle = _open_osfhandle(std_handle, _O_TEXT);
  159. fp = _fdopen(console_handle, "r");
  160. *stdin = *fp;
  161. setvbuf(stdin, NULL, _IONBF, 0);
  162. // Redirect stderr.
  163. std_handle = (long)GetStdHandle(STD_ERROR_HANDLE);
  164. console_handle = _open_osfhandle(std_handle, _O_TEXT);
  165. fp = _fdopen(console_handle, "w");
  166. *stderr = *fp;
  167. setvbuf(stderr, NULL, _IONBF, 0);
  168. // Sync std::cout, std::cerr, etc.
  169. std::ios::sync_with_stdio();
  170. is_open = true;
  171. return 0;
  172. }
  173. #endif // LOVE_LEGENDARY_CONSOLE_IO_HACK
  174. #ifdef LOVE_BUILD_EXE
  175. int main(int argc, char ** argv)
  176. {
  177. #ifdef LOVE_LEGENDARY_UTF8_ARGV_HACK
  178. int hack_argc = 0;
  179. char ** hack_argv = 0;
  180. get_utf8_arguments(hack_argc, hack_argv);
  181. argc = hack_argc;
  182. argv = hack_argv;
  183. #endif // LOVE_LEGENDARY_UTF8_ARGV_HACK
  184. // Oh, you just want the version? Okay!
  185. if(argc > 1 && strcmp(argv[1],"--version") == 0) {
  186. printf("LOVE %s (%s)\n", love::VERSION_STR, love::VERSION_CODENAME);
  187. return 0;
  188. }
  189. // Create the virtual machine.
  190. lua_State * L = lua_open();
  191. luaL_openlibs(L);
  192. love::luax_preload(L, luaopen_love, "love");
  193. luaopen_love(L);
  194. // Add command line arguments to global arg (like stand-alone Lua).
  195. {
  196. lua_newtable(L);
  197. if(argc > 0)
  198. {
  199. lua_pushstring(L, argv[0]);
  200. lua_rawseti(L, -2, -2);
  201. }
  202. lua_pushstring(L, "embedded boot.lua");
  203. lua_rawseti(L, -2, -1);
  204. for(int i = 1; i<argc; i++)
  205. {
  206. lua_pushstring(L, argv[i]);
  207. lua_rawseti(L, -2, i);
  208. }
  209. lua_setglobal(L, "arg");
  210. }
  211. // Add love.__exe = true.
  212. // This indicates that we're running the
  213. // standalone version of love, and not the
  214. // DLL version.
  215. {
  216. lua_getglobal(L, "love");
  217. lua_pushboolean(L, 1);
  218. lua_setfield(L, -2, "_exe");
  219. lua_pop(L, 1);
  220. }
  221. // Boot
  222. if (luaL_loadbuffer(L, (const char *)love::boot_lua, sizeof(love::boot_lua), "boot.lua") == 0)
  223. lua_call(L, 0, 0);
  224. lua_close(L);
  225. #ifdef LOVE_LEGENDARY_UTF8_ARGV_HACK
  226. if(hack_argv)
  227. {
  228. for(int i = 0; i<hack_argc; ++i)
  229. delete [] hack_argv[i];
  230. delete [] hack_argv;
  231. }
  232. #endif // LOVE_LEGENDARY_UTF8_ARGV_HACK
  233. return 0;
  234. }
  235. #endif // LOVE_BUILD_EXE