├── .gitignore ├── .itch.toml ├── .vscode └── settings.json ├── COMPILING.md ├── LICENSE ├── README.md ├── build_api_doc.sh ├── dlls ├── x86 │ ├── FreeImage.dll │ ├── SDL2.dll │ ├── libcurl.dll │ └── lua53.dll └── x86_64 │ ├── FreeImage.dll │ ├── SDL2.dll │ ├── libcurl.dll │ ├── lua53.dll │ └── vcomp140.dll ├── dub.json ├── dub.selections.json ├── homegirl.bmp ├── homegirl.ico ├── homegirl.res ├── homegirl.sh ├── images ├── download.gif ├── homegirl.png ├── homegirl_screentitles.gif └── itch.png ├── install_dependencies.sh ├── source ├── app.d ├── bindbc-lua │ └── bindbc-lua │ │ ├── .gitignore │ │ ├── LICENSE_1_0.txt │ │ ├── README.md │ │ ├── dub.json │ │ └── source │ │ └── bindbc │ │ └── lua │ │ ├── config.d │ │ ├── package.d │ │ ├── v51 │ │ ├── binddynamic.d │ │ ├── bindstatic.d │ │ ├── package.d │ │ └── types.d │ │ ├── v52 │ │ ├── binddynamic.d │ │ ├── bindstatic.d │ │ ├── package.d │ │ └── types.d │ │ └── v53 │ │ ├── binddynamic.d │ │ ├── bindstatic.d │ │ ├── package.d │ │ └── types.d ├── image_loader.d ├── lua_api │ ├── _basic_.d │ ├── audio.d │ ├── fs.d │ ├── gfx.d │ ├── image.d │ ├── input.d │ ├── sys.d │ ├── text.d │ └── view.d ├── machine.d ├── network.d ├── pixmap.d ├── program.d ├── sample.d ├── screen.d ├── soundchip.d ├── texteditor.d └── viewport.d └── system_drive ├── cmd ├── bg.lua ├── copy.lua ├── date.lua ├── delete.lua ├── dir.lua ├── drives.lua ├── echo.lua ├── edit.lua ├── env.lua ├── fileinfo.lua ├── makedir.lua ├── mem.lua ├── more.lua ├── mount.lua ├── perm.lua ├── play.lua ├── record.lua ├── reimage.lua ├── rename.lua ├── resample.lua ├── sfont2gif.lua ├── shell.lua ├── show.lua ├── type.lua └── unmount.lua ├── docs ├── console.md └── core │ ├── audio.md │ ├── fs.md │ ├── gfx.md │ ├── http-api.md │ ├── image.md │ ├── index.md │ ├── input.md │ ├── overview.md │ ├── sys.md │ ├── text.md │ └── view.md ├── fonts └── victoria.8b.gif ├── libs ├── filerequester.lua ├── menu.lua ├── object.lua ├── path.lua ├── screen.lua └── widget.lua └── startup.lua /.gitignore: -------------------------------------------------------------------------------- 1 | .dub 2 | /homegirl 3 | homegirl.so 4 | homegirl.dylib 5 | homegirl.dll 6 | homegirl.a 7 | homegirl.lib 8 | homegirl-test-* 9 | *.exe 10 | *.o 11 | *.obj 12 | *.lst 13 | config.json 14 | /*.dll 15 | -------------------------------------------------------------------------------- /.itch.toml: -------------------------------------------------------------------------------- 1 | [[actions]] 2 | platform = "windows" 3 | name = "play" 4 | path = "homegirl_windows.exe" 5 | 6 | [[actions]] 7 | platform = "linux" 8 | name = "play" 9 | path = "homegirl.sh" 10 | 11 | [[actions]] 12 | platform = "osx" 13 | name = "play" 14 | path = "homegirl.sh" 15 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "lua.targetVersion": "5.3" 3 | } -------------------------------------------------------------------------------- /COMPILING.md: -------------------------------------------------------------------------------- 1 | How to compile Homegirl 2 | ======================= 3 | 4 | 1. Make sure to install the latest version of the D compiler from https://dlang.org/ 5 | 2. From the project folder, run `dub build` from command line. 6 | 3. To run Homegirl, make sure to install the required libraries. (Windows DLLs are included.) 7 | - [SDL2 2.0.8](https://www.libsdl.org/) 8 | - [Lua 5.3](https://www.lua.org/) 9 | - [FreeImage 3.18](http://freeimage.sourceforge.net/) 10 | - libcurl ([Windows](http://downloads.dlang.org/other/index.html) | [other](https://curl.haxx.se/libcurl/)) 11 | 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 poeticAndroid 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Icon](./images/homegirl.png) Homegirl 2 | ======== 3 | It's a fantasy console (like pico-8 or tic-80) inspired by the Commodore Amiga! 4 | 5 | ![Amigaaah!](./images/homegirl_screentitles.gif) 6 | 7 | 👇 [Get the FULL version of Homegirl on itch.io](https://poeticandroid.itch.io/homegirl) 8 | 9 | [![Download!](./images/itch.png) ![Icon](./images/homegirl.png)](https://poeticandroid.itch.io/homegirl) 10 | 11 | It has graphic resolutions similar to the OCS Amigas, multitasking, multiple screens and windows etc.. It has 4 channel 8-bit stereo sound and ability to mount web-servers as drives.. 12 | 13 | The software for it, is based on Lua, which is a pretty simple and fast scripting language.. 14 | 15 | [Follow #HomegirlFC on Twitter!](https://twitter.com/hashtag/HomegirlFC) 16 | 17 | [**Join the community on Discord!**](https://discord.gg/ND4FErK) 18 | 19 | Specs 20 | ----- 21 | - **Programming language:** Lua ([See API documentation](https://github.com/poeticAndroid/homegirl/tree/master/system_drive/docs/core/)) 22 | - **Screen resolutions:** Multiple screen modes ranging from 80x45 to 640x480 pixels 23 | - **Number of colors:** Up to 256 colors from a palette of 4096 colors 24 | - **Audio:** Four 8-bit PCM channels in stereo, playback up to 32 kHz 25 | - **Input:** Text, mouse, game and audio input.. 26 | - **Filesystem:** Named drives which can be mapped to local folders or websites 27 | - **Native filetypes:** GIF for images and animations, WAV for sound samples 28 | 29 | Installation 30 | ------------ 31 | Download and extract [latest release](https://github.com/poeticAndroid/homegirl/releases/latest) for your OS and run the `homegirl` executable from the same folder.. If it doesn't work, make sure you have the following libraries installed (a setup script may be provided): 32 | 33 | - [SDL2 2.0.8](https://www.libsdl.org/) 34 | - [Lua 5.3](https://www.lua.org/) 35 | - [FreeImage 3.18](http://freeimage.sourceforge.net/) 36 | - libcurl ([Windows](http://downloads.dlang.org/other/index.html) | [other](https://curl.haxx.se/libcurl/)) 37 | -------------------------------------------------------------------------------- /build_api_doc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | apidoc="system_drive/docs/core/overview.md" 3 | echo '# Lua API overview' > $apidoc 4 | echo '[See docs for details.](./)' >> $apidoc 5 | 6 | for pack in ./source/lua_api/*.d; do 7 | echo "## " $(basename $pack .d) >> $apidoc 8 | cat $pack | grep /// | while read _ line; do 9 | echo " " $line >> $apidoc 10 | done 11 | done -------------------------------------------------------------------------------- /dlls/x86/FreeImage.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/dlls/x86/FreeImage.dll -------------------------------------------------------------------------------- /dlls/x86/SDL2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/dlls/x86/SDL2.dll -------------------------------------------------------------------------------- /dlls/x86/libcurl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/dlls/x86/libcurl.dll -------------------------------------------------------------------------------- /dlls/x86/lua53.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/dlls/x86/lua53.dll -------------------------------------------------------------------------------- /dlls/x86_64/FreeImage.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/dlls/x86_64/FreeImage.dll -------------------------------------------------------------------------------- /dlls/x86_64/SDL2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/dlls/x86_64/SDL2.dll -------------------------------------------------------------------------------- /dlls/x86_64/libcurl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/dlls/x86_64/libcurl.dll -------------------------------------------------------------------------------- /dlls/x86_64/lua53.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/dlls/x86_64/lua53.dll -------------------------------------------------------------------------------- /dlls/x86_64/vcomp140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/dlls/x86_64/vcomp140.dll -------------------------------------------------------------------------------- /dub.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "poeticAndroid" 4 | ], 5 | "buildTypes": { 6 | "release": { 7 | "lflags-windows": [ 8 | "/SUBSYSTEM:WINDOWS", 9 | "/ENTRY:mainCRTStartup" 10 | ] 11 | } 12 | }, 13 | "copyFiles-windows-x86": [ 14 | "dlls/x86/*.dll" 15 | ], 16 | "copyFiles-windows-x86_64": [ 17 | "dlls/x86_64/*.dll" 18 | ], 19 | "copyright": "Copyright © 2019, poeticAndroid", 20 | "dependencies": { 21 | "bindbc-freeimage": "~>0.3.1", 22 | "bindbc-sdl": "~>0.13.0", 23 | "htmld": "~>0.3.7" 24 | }, 25 | "description": "A fantasy console inspired by the Amiga.", 26 | "license": "MIT", 27 | "name": "homegirl", 28 | "preBuildCommands": [ 29 | "sh build_api_doc.sh" 30 | ], 31 | "sourceFiles-windows": [ 32 | "./homegirl.res" 33 | ], 34 | "subConfigurations": { 35 | "riverd-lua": "dynamic" 36 | }, 37 | "versions": [ 38 | "SDL_208", 39 | "FI_318", 40 | "LUA_53" 41 | ] 42 | } -------------------------------------------------------------------------------- /dub.selections.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileVersion": 1, 3 | "versions": { 4 | "bindbc-freeimage": "0.3.2", 5 | "bindbc-loader": "0.2.1", 6 | "bindbc-sdl": "0.13.0", 7 | "htmld": "0.3.7" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /homegirl.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/homegirl.bmp -------------------------------------------------------------------------------- /homegirl.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/homegirl.ico -------------------------------------------------------------------------------- /homegirl.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/homegirl.res -------------------------------------------------------------------------------- /homegirl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "$(dirname "$0")" 3 | 4 | if [ "$(uname)" == "Darwin" ]; then 5 | ./homegirl_macos || open -a Terminal ./install_dependencies.sh 6 | else 7 | ./homegirl_linux || (test -f ./install_dependencies.sh && (x-terminal-emulator -e ./install_dependencies.sh || gnome-terminal -e ./install_dependencies.sh || xterm -e ./install_dependencies.sh)) 8 | fi 9 | -------------------------------------------------------------------------------- /images/download.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/images/download.gif -------------------------------------------------------------------------------- /images/homegirl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/images/homegirl.png -------------------------------------------------------------------------------- /images/homegirl_screentitles.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/images/homegirl_screentitles.gif -------------------------------------------------------------------------------- /images/itch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/images/itch.png -------------------------------------------------------------------------------- /install_dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ "$(uname)" == "Darwin" ]; then 3 | echo "This script will install dependencies for Homegirl on MacOS using Homebrew." 4 | echo "Press [Enter] to continue or [Ctrl+C] to cancel." 5 | read enter 6 | 7 | /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 8 | 9 | brew install sdl2 freeimage lua && rm "$0" 10 | else 11 | echo "This script will install dependencies for Homegirl on Ubuntu and Fedora based Linux distros." 12 | echo "Press [Enter] to continue or [Ctrl+C] to cancel." 13 | read enter 14 | 15 | ( 16 | sudo apt-get install libsdl2-2.0-0 libfreeimage3 liblua5.3-dev curl || 17 | sudo dnf install SDL2 freeimage lua curl 18 | ) && rm "$0" 19 | fi 20 | -------------------------------------------------------------------------------- /source/bindbc-lua/bindbc-lua/.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | dub.selections.json 3 | .dub -------------------------------------------------------------------------------- /source/bindbc-lua/bindbc-lua/LICENSE_1_0.txt: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /source/bindbc-lua/bindbc-lua/dub.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "Mike Parker" 4 | ], 5 | "configurations": [ 6 | { 7 | "dependencies": { 8 | "bindbc-loader": "~>0.2.1" 9 | }, 10 | "name": "dynamic", 11 | "targetType": "staticLibrary", 12 | "versions": [ 13 | "BindLua_Dynamic" 14 | ] 15 | }, 16 | { 17 | "dependencies": { 18 | "bindbc-loader": "~>0.2.1" 19 | }, 20 | "dflags": [ 21 | "-betterC" 22 | ], 23 | "name": "dynamicBC", 24 | "subConfigurations": { 25 | "bindbc-loader": "yesBC" 26 | }, 27 | "targetType": "staticLibrary", 28 | "versions": [ 29 | "BindLua_Dynamic" 30 | ] 31 | }, 32 | { 33 | "excludedSourceFiles": [ 34 | "source/bindbc/lua/v51/binddynamic.d", 35 | "source/bindbc/lua/v52/binddynamic.d", 36 | "source/bindbc/lua/v53/binddynamic.d" 37 | ], 38 | "name": "static", 39 | "targetType": "staticLibrary", 40 | "versions": [ 41 | "BindLua_Static" 42 | ] 43 | }, 44 | { 45 | "dflags": [ 46 | "-betterC" 47 | ], 48 | "excludedSourceFiles": [ 49 | "source/bindbc/lua/v51/binddynamic.d", 50 | "source/bindbc/lua/v52/binddynamic.d", 51 | "source/bindbc/lua/v53/binddynamic.d" 52 | ], 53 | "name": "staticBC", 54 | "targetType": "staticLibrary", 55 | "versions": [ 56 | "BindLua_Static" 57 | ] 58 | } 59 | ], 60 | "description": "Dynamic and static bindings to Lua 5.1 and later, compatible with -betterC, @nogc, and nothrow.", 61 | "importPaths": [ 62 | "source/" 63 | ], 64 | "license": "Boost", 65 | "name": "bindbc-lua", 66 | "sourcePaths": [ 67 | "source/" 68 | ], 69 | "targetName": "BindBC_Lua", 70 | "targetPath": "lib", 71 | "targetType": "staticLibrary", 72 | "version": "0.1.2" 73 | } -------------------------------------------------------------------------------- /source/bindbc-lua/bindbc-lua/source/bindbc/lua/config.d: -------------------------------------------------------------------------------- 1 | 2 | // Copyright Michael D. Parker 2018. 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at 5 | // http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | module bindbc.lua.config; 8 | 9 | enum LuaSupport { 10 | noLibrary, 11 | badLibrary, 12 | lua51 = 51, 13 | lua52 = 52, 14 | lua53 = 53, 15 | } 16 | 17 | version(LUA_51) { 18 | enum luaSupport = LuaSupport.lua51; 19 | } -------------------------------------------------------------------------------- /source/bindbc-lua/bindbc-lua/source/bindbc/lua/package.d: -------------------------------------------------------------------------------- 1 | 2 | // Copyright Michael D. Parker 2018. 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at 5 | // http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | module bindbc.lua; 8 | public import bindbc.lua.config; 9 | 10 | version(LUA_51) public import bindbc.lua.v51; 11 | else version(LUA_52) public import bindbc.lua.v52; 12 | else version(LUA_53) public import bindbc.lua.v53; 13 | else static assert(0, "Please specify a Lua version on the commandline (e.g. -version=LUA_52) or in your dub.json/sdl configuration"); -------------------------------------------------------------------------------- /source/bindbc-lua/bindbc-lua/source/bindbc/lua/v51/bindstatic.d: -------------------------------------------------------------------------------- 1 | 2 | // Copyright Michael D. Parker 2018. 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at 5 | // http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | module bindbc.lua.v51.bindstatic; 8 | 9 | version(BindBC_Static) version = BindLua_Static; 10 | version(BindLua_Static) { 11 | version(LUA_51) version = LUA_51_STATIC; 12 | } 13 | 14 | version(LUA_51_STATIC): 15 | 16 | import core.stdc.stdarg : va_list; 17 | import bindbc.lua.v51.types; 18 | 19 | extern(C) @nogc nothrow: 20 | // lauxlib.h 21 | void luaI_openlib(lua_State*,const(char)*,const(luaL_Reg)*,int); 22 | void luaL_register(lua_State*,const(char)*,const(luaL_Reg)*); 23 | int luaL_getmetafield(lua_State*,int,const(char)*); 24 | int luaL_callmeta(lua_State*, int,const(char)*); 25 | int luaL_typerror(lua_State*,int,const(char)*); 26 | int luaL_argerror(lua_State*,int,const(char)*); 27 | const(char)* luaL_checklstring(lua_State*,int,size_t*); 28 | const(char)* luaL_optlstring(lua_State*,int,const(char)*,size_t*); 29 | lua_Number luaL_checknumber(lua_State*,int); 30 | lua_Number luaL_optnumber(lua_State*,int,lua_Number); 31 | lua_Integer luaL_checkinteger(lua_State*,int); 32 | lua_Integer luaL_optinteger(lua_State*,int,lua_Integer); 33 | void luaL_checkstack(lua_State*,int,const(char)*); 34 | void luaL_checktype(lua_State*,int,int); 35 | void luaL_checkany(lua_State*,int); 36 | int luaL_newmetatable(lua_State*,const(char)*); 37 | void* luaL_checkudata(lua_State*,int,const(char)*); 38 | void luaL_where(lua_State*,int); 39 | int luaL_error(lua_State*,const(char)*,...); 40 | int luaL_checkoption(lua_State*,int,const(char)*); 41 | int luaL_ref(lua_State*,int); 42 | void luaL_unref(lua_State*,int,int); 43 | int luaL_loadfile(lua_State*,const(char)*); 44 | int luaL_loadbuffer(lua_State*,const(char)*,size_t,const(char)*); 45 | int luaL_loadstring(lua_State*,const(char)*); 46 | lua_State* luaL_newstate(); 47 | const(char)* luaL_gsub(lua_State*,const(char)*,const(char)*,const(char)*); 48 | const(char)* luaL_findtable(lua_State*,int,const(char)*,int); 49 | void luaL_buffinit(lua_State*,luaL_Buffer*); 50 | char* luaL_prepbuffer(luaL_Buffer*); 51 | void luaL_addlstring(luaL_Buffer*,const(char)*,size_t); 52 | void luaL_addstring(luaL_Buffer*, const(char)*); 53 | void luaL_addvalue(luaL_Buffer*); 54 | void luaL_pushresult(luaL_Buffer*); 55 | 56 | // lua.h 57 | lua_State* lua_newstate(lua_Alloc,void*); 58 | lua_State* lua_close(lua_State*); 59 | lua_State* lua_newthread(lua_State*); 60 | lua_CFunction lua_atpanic(lua_State*,lua_CFunction); 61 | int lua_gettop(lua_State*); 62 | void lua_settop(lua_State*,int); 63 | void lua_pushvalue(lua_State*,int); 64 | void lua_remove(lua_State*,int); 65 | void lua_insert(lua_State*,int); 66 | void lua_replace(lua_State*,int); 67 | int lua_checkstack(lua_State*,int); 68 | void lua_xmove(lua_State*,lua_State*,int); 69 | int lua_isnumber(lua_State*,int); 70 | int lua_isstring(lua_State*,int); 71 | int lua_iscfunction(lua_State*,int); 72 | int lua_isuserdata(lua_State*,int); 73 | int lua_type(lua_State*,int); 74 | const(char)* lua_typename(lua_State*,int); 75 | int lua_equal(lua_State*,int,int); 76 | int lua_rawequal(lua_State*,int,int); 77 | int lua_lessthan(lua_State*,int,int); 78 | lua_Number lua_tonumber(lua_State*,int); 79 | lua_Integer lua_tointeger(lua_State*,int); 80 | int lua_toboolean(lua_State*,int); 81 | const(char)* lua_tolstring(lua_State*,int,size_t*); 82 | size_t lua_objlen(lua_State*,int); 83 | lua_CFunction lua_tocfunction(lua_State*,int); 84 | void* lua_touserdata(lua_State*,int); 85 | lua_State* lua_tothread(lua_State*,int); 86 | const(void)* lua_topointer(lua_State*,int); 87 | void lua_pushnil(lua_State*); 88 | void lua_pushnumber(lua_State*,lua_Number); 89 | void lua_pushinteger(lua_State*,lua_Integer); 90 | void lua_pushlstring(lua_State*,const(char)*,size_t); 91 | void lua_pushstring(lua_State*,const(char)*); 92 | const(char)* lua_pushvfstring(lua_State*,const(char)*,va_list); 93 | const(char)* lua_pushfstring(lua_State*,const(char)*,...); 94 | void lua_pushcclosure(lua_State*,lua_CFunction,int); 95 | void lua_pushboolean(lua_State*,int); 96 | void lua_pushlightuserdata(lua_State*,void*); 97 | int lua_pushthread(lua_State*); 98 | void lua_gettable(lua_State*,int); 99 | void lua_getfield(lua_State*,int,const(char)*); 100 | void lua_rawget(lua_State*,int); 101 | void lua_rawgeti(lua_State*,int,int); 102 | void lua_createtable(lua_State*,int,int); 103 | void* lua_newuserdata(lua_State*,size_t); 104 | int lua_getmetatable(lua_State*,int); 105 | void lua_getfenv(lua_State*,int); 106 | void lua_settable(lua_State*,int); 107 | void lua_setfield(lua_State*,int,const(char)*); 108 | void lua_rawset(lua_State*,int); 109 | void lua_rawseti(lua_State*,int,int); 110 | int lua_setmetatable(lua_State*,int); 111 | int lua_setfenv(lua_State*,int); 112 | void lua_call(lua_State*,int,int); 113 | int lua_pcall(lua_State*,int,int,int); 114 | int lua_cpcall(lua_State*,lua_CFunction,void*); 115 | int lua_load(lua_State*,lua_Reader,void*,const(char)*); 116 | int lua_dump(lua_State*,lua_Writer,void*); 117 | int lua_yield(lua_State*,int); 118 | int lua_resume(lua_State*,int); 119 | int lua_status(lua_State*); 120 | int lua_gc(lua_State*,int,int); 121 | int lua_error(lua_State*); 122 | int lua_next(lua_State*,int); 123 | void lua_concat(lua_State*,int); 124 | lua_Alloc lua_getallocf(lua_State*,void**); 125 | void lua_setallocf(lua_State*,lua_Alloc,void*); 126 | void lua_setlevel(lua_State*, lua_State*); 127 | int lua_getstack(lua_State*,lua_Debug*); 128 | int lua_getinfo(lua_State*,const(char)*,lua_Debug*); 129 | const(char)* lua_getlocal(lua_State*,const(lua_Debug)*,int); 130 | const(char)* lua_setlocal(lua_State*,const(lua_Debug)*,int); 131 | const(char)* lua_getupvalue(lua_State*,int,int); 132 | const(char)* lua_setupvalue(lua_State*,int,int); 133 | int lua_sethook(lua_State*,lua_Hook,int,int); 134 | lua_Hook lua_gethook(lua_State*); 135 | int lua_gethookmask(lua_State*); 136 | int lua_gethookcount(lua_State*); 137 | 138 | // lualib.h 139 | int luaopen_base(lua_State*); 140 | int luaopen_table(lua_State*); 141 | int luaopen_io(lua_State*); 142 | int luaopen_os(lua_State*); 143 | int luaopen_string(lua_State*); 144 | int luaopen_math(lua_State*); 145 | int luaopen_debug(lua_State*); 146 | int luaopen_package(lua_State*); 147 | void luaL_openlibs(lua_State*); -------------------------------------------------------------------------------- /source/bindbc-lua/bindbc-lua/source/bindbc/lua/v51/package.d: -------------------------------------------------------------------------------- 1 | 2 | // Copyright Michael D. Parker 2018. 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at 5 | // http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | module bindbc.lua.v51; 8 | 9 | version(LUA_51): 10 | 11 | public import bindbc.lua.v51.types; 12 | 13 | version(BindBC_Static) version = BindLua_Static; 14 | version(BindLua_Static) { 15 | public import bindbc.lua.v51.bindstatic; 16 | } 17 | else public import bindbc.lua.v51.binddynamic; 18 | 19 | import core.stdc.config : c_long; 20 | 21 | // compatibility function aliases 22 | // lua.h 23 | alias lua_strlen = lua_objlen; 24 | alias lua_open = lua_newstate; 25 | 26 | // Macros 27 | @nogc nothrow { 28 | // lauxlib.h 29 | void luaL_argcheck(lua_State* L, bool cond, int arg, const(char)* extramsg) { 30 | pragma(inline, true) 31 | if(!cond) luaL_argerror(L, arg, extramsg); 32 | } 33 | 34 | const(char)* luaL_checkstring(lua_State* L, int arg) { 35 | pragma(inline, true) 36 | return luaL_checklstring(L, arg, null); 37 | } 38 | 39 | const(char)* luaL_optstring(lua_State* L, int arg, const(char)* d) { 40 | pragma(inline, true) 41 | return luaL_optlstring(L, arg, d, null); 42 | } 43 | 44 | int luaL_checkint(lua_State* L, int arg) { 45 | pragma(inline, true) 46 | return cast(int)luaL_checkinteger(L, arg); 47 | } 48 | 49 | int luaL_optint(lua_State* L, int arg, int d) { 50 | pragma(inline, true) 51 | return cast(int)luaL_optinteger(L, arg, d); 52 | } 53 | 54 | c_long luaL_checklong(lua_State* L, int arg) { 55 | pragma(inline, true) 56 | return cast(c_long)luaL_checkinteger(L, arg); 57 | } 58 | 59 | c_long luaL_optlong(lua_State* L, int arg, int d) { 60 | pragma(inline, true) 61 | return cast(c_long)luaL_optinteger(L, arg, d); 62 | } 63 | 64 | const(char)* luaL_typename(lua_State* L, int i) { 65 | pragma(inline, true) 66 | return lua_typename(L, lua_type(L, i)); 67 | } 68 | 69 | bool luaL_dofile(lua_State* L, const(char)* filename) { 70 | pragma(inline, true) 71 | return luaL_loadfile(L, filename) != 0 || lua_pcall(L, 0, LUA_MULTRET, 0) != 0; 72 | } 73 | 74 | bool luaL_dostring(lua_State* L, const(char)* str) { 75 | pragma(inline, true) 76 | return luaL_loadstring(L, str) != 0 || lua_pcall(L, 0, LUA_MULTRET, 0) != 0; 77 | } 78 | 79 | void luaL_getmetatable(lua_State* L, const(char)* tname) { 80 | pragma(inline, true) 81 | lua_getfield(L, LUA_REGISTRYINDEX, tname); 82 | } 83 | 84 | // TODO: figure out what luaL_opt is supposed to do 85 | 86 | void luaL_addchar(luaL_Buffer* B, char c) { 87 | pragma(inline, true) 88 | if(B.p < (B.buffer.ptr + LUAL_BUFFERSIZE) || luaL_prepbuffer(B)) { 89 | *B.p++ = c; 90 | } 91 | } 92 | 93 | void luaL_addsize(luaL_Buffer* B, size_t n) { 94 | pragma(inline, true) 95 | B.p += n; 96 | } 97 | 98 | // lua.h 99 | int lua_upvalueindex(int i) { 100 | pragma(inline, true) 101 | return LUA_GLOBALSINDEX - i; 102 | } 103 | 104 | void lua_pop(lua_State* L, int n) { 105 | pragma(inline, true) 106 | lua_settop(L, -n - 1); 107 | } 108 | 109 | void lua_newtable(lua_State* L) { 110 | pragma(inline, true) 111 | lua_createtable(L, 0, 0); 112 | } 113 | 114 | void lua_register(lua_State* L, const(char)* n, lua_CFunction f) { 115 | pragma(inline, true) 116 | lua_pushcfunction(L, f); 117 | lua_setglobal(L, n); 118 | } 119 | 120 | void lua_pushcfunction(lua_State* L, lua_CFunction f) { 121 | pragma(inline, true) 122 | lua_pushcclosure(L, f, 0); 123 | } 124 | 125 | bool lua_isfunction(lua_State* L, int n) { 126 | pragma(inline, true) 127 | return lua_type(L, n) == LUA_TFUNCTION; 128 | } 129 | 130 | bool lua_istable(lua_State* L, int n) { 131 | pragma(inline, true) 132 | return lua_type(L, n) == LUA_TTABLE; 133 | } 134 | 135 | bool lua_islightuserdata(lua_State* L, int n) { 136 | pragma(inline, true) 137 | return lua_type(L, n) == LUA_TLIGHTUSERDATA; 138 | } 139 | 140 | bool lua_isnil(lua_State* L, int n) { 141 | pragma(inline, true) 142 | return lua_type(L, n) == LUA_TNIL; 143 | } 144 | 145 | bool lua_isboolean(lua_State* L, int n) { 146 | pragma(inline, true) 147 | return lua_type(L, n) == LUA_TBOOLEAN; 148 | } 149 | 150 | bool lua_isthread(lua_State* L, int n) { 151 | pragma(inline, true) 152 | return lua_type(L, n) == LUA_TTHREAD; 153 | } 154 | 155 | bool lua_isnone(lua_State* L, int n) { 156 | pragma(inline, true) 157 | return lua_type(L, n) == LUA_TNONE; 158 | } 159 | 160 | bool lua_isnoneornil(lua_State* L, int n) { 161 | pragma(inline, true) 162 | return lua_type(L, n) <= 0; 163 | } 164 | 165 | void lua_pushliteral(lua_State* L, const(char)[] s) { 166 | pragma(inline, true) 167 | lua_pushlstring(L, s.ptr, s.length); 168 | } 169 | 170 | void lua_setglobal(lua_State* L, const(char)* s) { 171 | pragma(inline, true) 172 | lua_setfield(L, LUA_GLOBALSINDEX, s); 173 | } 174 | 175 | void lua_getglobal(lua_State* L, const(char)* s) { 176 | pragma(inline, true) 177 | lua_getfield(L, LUA_GLOBALSINDEX, s); 178 | } 179 | 180 | const(char)* lua_tostring(lua_State* L, int i) { 181 | pragma(inline, true) 182 | return lua_tolstring(L, i, null); 183 | } 184 | 185 | void lua_getregistry(lua_State* L) { 186 | pragma(inline, true) 187 | lua_pushvalue(L, LUA_REGISTRYINDEX); 188 | } 189 | 190 | int lua_getgccount(lua_State* L) { 191 | pragma(inline, true) 192 | return lua_gc(L, LUA_GCCOUNT, 0); 193 | } 194 | } -------------------------------------------------------------------------------- /source/bindbc-lua/bindbc-lua/source/bindbc/lua/v51/types.d: -------------------------------------------------------------------------------- 1 | 2 | // Copyright Michael D. Parker 2018. 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at 5 | // http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | module bindbc.lua.v51.types; 8 | 9 | version(LUA_51): 10 | 11 | import core.stdc.stdio : BUFSIZ; 12 | 13 | // luaconf.h 14 | enum LUA_IDSIZE = 60; 15 | alias LUAI_UINT32 = uint; 16 | alias LUAI_INT32 = int; 17 | enum LUAI_MAXINT32 = int.max; 18 | alias LUAI_UMEM = size_t; 19 | alias LUAI_MEM = ptrdiff_t; 20 | alias LUA_NUMBER = double; 21 | alias LUA_INTEGER = ptrdiff_t; 22 | 23 | enum LUAL_BUFFERSIZE = BUFSIZ; 24 | 25 | enum LUAI_MAXSTACK = 1000000; 26 | 27 | // lauxlib.h 28 | enum LUA_ERRFILE = LUA_ERRERR+1; 29 | 30 | struct luaL_Reg { 31 | const(char)* name; 32 | lua_CFunction func; 33 | } 34 | 35 | enum LUA_NOREF = -2; 36 | enum LUA_REFNIL = -1; 37 | 38 | struct luaL_Buffer { 39 | char* p; 40 | int lvl; 41 | lua_State* L; 42 | char[LUAL_BUFFERSIZE] buffer; 43 | } 44 | 45 | // lua.h 46 | // The 5.1 header does not define LUA_VERSION_MAJOR/MINOR/NUM/RELEASE, but we will 47 | // for consistency with the other versions. 48 | enum LUA_VERSION_MAJOR = "5"; 49 | enum LUA_VERSION_MINOR = "1"; 50 | enum LUA_VERSION_NUM = 501; 51 | enum LUA_VERSION_RELEASE = 5; 52 | 53 | enum LUA_VERSION = "Lua " ~ LUA_VERSION_MAJOR ~ "." ~ LUA_VERSION_MINOR; 54 | enum LUA_RELEASE = LUA_VERSION ~ "." ~ LUA_VERSION_RELEASE; 55 | 56 | enum LUA_SIGNATURE = "\033Lua"; 57 | enum LUA_MULTRET = -1; 58 | 59 | enum LUA_REGISTRYINDEX = -10_000; 60 | enum LUA_ENVIRONINDEX = -10_001; 61 | enum LUA_GLOBALSINDEX = -10_002; 62 | 63 | enum LUA_YIELD = 1; 64 | enum LUA_ERRRUN = 2; 65 | enum LUA_ERRSYNTAX = 3; 66 | enum LUA_ERRMEM = 4; 67 | enum LUA_ERRERR = 5; 68 | 69 | struct lua_State; 70 | 71 | nothrow { 72 | alias lua_CFunction = int function(lua_State*); 73 | alias lua_Reader = const(char)* function(lua_State*,void*,size_t); 74 | alias lua_Writer = int function(lua_State*,const(void)*,size_t,void*); 75 | alias lua_Alloc = void* function(void*,void*,size_t,size_t); 76 | } 77 | 78 | enum LUA_TNONE = -1; 79 | enum LUA_TNIL = 0; 80 | enum LUA_TBOOLEAN = 1; 81 | enum LUA_TLIGHTUSERDATA = 2; 82 | enum LUA_TNUMBER = 3; 83 | enum LUA_TSTRING = 4; 84 | enum LUA_TTABLE = 5; 85 | enum LUA_TFUNCTION = 6; 86 | enum LUA_TUSERDATA = 7; 87 | enum LUA_TTHREAD = 8; 88 | 89 | enum LUA_MINSTACK = 20; 90 | 91 | alias lua_Number = LUA_NUMBER; 92 | alias lua_Integer = LUA_INTEGER; 93 | 94 | enum LUA_GCSTOP = 0; 95 | enum LUA_GCRESTART = 1; 96 | enum LUA_GCCOLLECT = 2; 97 | enum LUA_GCCOUNT = 3; 98 | enum LUA_GCCOUNTB = 4; 99 | enum LUA_GCSTEP = 5; 100 | enum LUA_GCSETPAUSE = 6; 101 | enum LUA_GCSETSTEPMUL = 7; 102 | 103 | enum LUA_HOOKCALL = 0; 104 | enum LUA_HOOKRET = 1; 105 | enum LUA_HOOKLINE = 2; 106 | enum LUA_HOOKCOUNT = 3; 107 | enum LUA_HOOKTAILRET = 4; 108 | 109 | enum LUA_MASKCALL = 1 << LUA_HOOKCALL; 110 | enum LUA_MASKRET = 1 << LUA_HOOKRET; 111 | enum LUA_MASKLINE = 1 << LUA_HOOKLINE; 112 | enum LUA_MASKCOUNT = 1 << LUA_HOOKCOUNT; 113 | 114 | struct lua_Debug { 115 | int event; 116 | const(char)* name; 117 | const(char)* namewhat; 118 | const(char)* what; 119 | const(char)* source; 120 | int currentline; 121 | int nups; 122 | int linedefined; 123 | int lastlinedefined; 124 | char[LUA_IDSIZE] short_src; 125 | private int i_ci; 126 | } 127 | 128 | alias lua_Hook = void function(lua_State*,lua_Debug*) nothrow; 129 | 130 | // lualib.h 131 | enum LUA_FILEHANDLE = "FILE*"; 132 | enum LUA_COLIBNAME = "coroutine"; 133 | enum LUA_TABLIBNAME = "table"; 134 | enum LUA_IOLIBNAME = "io"; 135 | enum LUA_OSLIBNAME = "os"; 136 | enum LUA_STRLIBNAME = "string"; 137 | enum LUA_MATHLIBNAME = "math"; 138 | enum LUA_DBLIBNAME = "debug"; 139 | enum LUA_LOADLIBNAME = "package"; -------------------------------------------------------------------------------- /source/bindbc-lua/bindbc-lua/source/bindbc/lua/v52/bindstatic.d: -------------------------------------------------------------------------------- 1 | 2 | // Copyright Michael D. Parker 2018. 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at 5 | // http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | module bindbc.lua.v52.bindstatic; 8 | 9 | 10 | version(BindBC_Static) version = BindLua_Static; 11 | version(BindLua_Static) { 12 | version(LUA_52) version = LUA_52_STATIC; 13 | } 14 | 15 | version(LUA_52_STATIC): 16 | 17 | import core.stdc.stdarg : va_list; 18 | import bindbc.lua.v52.types; 19 | 20 | extern(C) @nogc nothrow: 21 | // lauxlib.h 22 | void luaL_checkversion_(lua_State*,lua_Number); 23 | int luaL_getmetafield(lua_State*,int,const(char)*); 24 | int luaL_callmeta(lua_State*, int,const(char)*); 25 | const(char)* luaL_tolstring(lua_State*,int,size_t*); 26 | int luaL_argerror(lua_State*,int,const(char)*); 27 | const(char)* luaL_checklstring(lua_State*,int,size_t*); 28 | const(char)* luaL_optlstring(lua_State*,int,const(char)*,size_t*); 29 | lua_Number luaL_checknumber(lua_State*,int); 30 | lua_Number luaL_optnumber(lua_State*,int,lua_Number); 31 | lua_Integer luaL_checkinteger(lua_State*,int); 32 | lua_Integer luaL_optinteger(lua_State*,int,lua_Integer); 33 | lua_Unsigned luaL_checkunsigned(lua_State*,int); 34 | lua_Unsigned luaL_optunsigned(lua_State*,int,lua_Unsigned); 35 | void luaL_checkstack(lua_State*,int,const(char)*); 36 | void luaL_checktype(lua_State*,int,int); 37 | void luaL_checkany(lua_State*,int); 38 | int luaL_newmetatable(lua_State*,const(char)*); 39 | void luaL_setmetatable(lua_State*,const(char)*); 40 | void* luaL_testudata(lua_State*,int,const(char)*); 41 | void* luaL_checkudata(lua_State*,int,const(char)*); 42 | void luaL_where(lua_State*,int); 43 | int luaL_error(lua_State*,const(char)*,...); 44 | int luaL_checkoption(lua_State*,int,const(char)*); 45 | int luaL_fileresult(lua_State*,int,const(char)*); 46 | int luaL_execresult(lua_State*,int); 47 | int luaL_ref(lua_State*,int); 48 | void luaL_unref(lua_State*,int,int); 49 | int luaL_loadfilex(lua_State*,const(char)*,const(char)*); 50 | int luaL_loadbufferx(lua_State*,const(char)*,size_t,const(char)*,const(char)*); 51 | int luaL_loadstring(lua_State*,const(char)*); 52 | lua_State* luaL_newstate(); 53 | int luaL_len(lua_State*,int); 54 | const(char)* luaL_gsub(lua_State*,const(char)*,const(char)*,const(char)*); 55 | void luaL_setfuncs(lua_State*,const(luaL_Reg)*,int); 56 | int luaL_getsubtable(lua_State*,int,const(char)*); 57 | void luaL_traceback(lua_State*,lua_State*,const(char)*,int); 58 | void luaL_requiref(lua_State*,const(char)*,lua_CFunction,int); 59 | void luaL_buffinit(lua_State*,luaL_Buffer*); 60 | char* luaL_prepbuffsize(luaL_Buffer*,size_t); 61 | void luaL_addlstring(luaL_Buffer*,const(char)*,size_t); 62 | void luaL_addstring(luaL_Buffer*, const(char)*); 63 | void luaL_addvalue(luaL_Buffer*); 64 | void luaL_pushresult(luaL_Buffer*); 65 | void luaL_pushresultsize(luaL_Buffer*,size_t); 66 | char* luaL_buffinitsize(lua_State*,luaL_Buffer*,size_t); 67 | 68 | // lua.h 69 | lua_State* lua_newstate(lua_Alloc,void*); 70 | lua_State* lua_close(lua_State*); 71 | lua_State* lua_newthread(lua_State*); 72 | lua_CFunction lua_atpanic(lua_State*,lua_CFunction); 73 | const(lua_Number)* lua_version(lua_State*); 74 | int lua_absindex(lua_State*,int); 75 | int lua_gettop(lua_State*); 76 | void lua_settop(lua_State*,int); 77 | void lua_pushvalue(lua_State*,int); 78 | void lua_remove(lua_State*,int); 79 | void lua_insert(lua_State*,int); 80 | void lua_replace(lua_State*,int); 81 | void lua_copy(lua_State*,int,int); 82 | int lua_checkstack(lua_State*,int); 83 | void lua_xmove(lua_State*,lua_State*,int); 84 | int lua_isnumber(lua_State*,int); 85 | int lua_isstring(lua_State*,int); 86 | int lua_iscfunction(lua_State*,int); 87 | int lua_isuserdata(lua_State*,int); 88 | int lua_type(lua_State*,int); 89 | const(char)* lua_typename(lua_State*,int); 90 | lua_Number lua_tonumberx(lua_State*,int,int*); 91 | lua_Integer lua_tointegerx(lua_State*,int,int*); 92 | lua_Unsigned lua_tounsignedx(lua_State*,int,int*); 93 | int lua_toboolean(lua_State*,int); 94 | const(char)* lua_tolstring(lua_State*,int,size_t*); 95 | size_t lua_rawlen(lua_State*,int); 96 | lua_CFunction lua_tocfunction(lua_State*,int); 97 | void* lua_touserdata(lua_State*,int); 98 | lua_State* lua_tothread(lua_State*,int); 99 | const(void)* lua_topointer(lua_State*,int); 100 | void lua_arith(lua_State*,int); 101 | int lua_rawequal(lua_State*,int,int); 102 | int lua_compare(lua_State*,int,int,int); 103 | void lua_pushnil(lua_State*); 104 | void lua_pushnumber(lua_State*,lua_Number); 105 | void lua_pushinteger(lua_State*,lua_Integer); 106 | void lua_pushunsigned(lua_State*,lua_Unsigned); 107 | void lua_pushlstring(lua_State*,const(char)*,size_t); 108 | void lua_pushstring(lua_State*,const(char)*); 109 | const(char)* lua_pushvfstring(lua_State*,const(char)*,va_list); 110 | const(char)* lua_pushfstring(lua_State*,const(char)*,...); 111 | void lua_pushcclosure(lua_State*,lua_CFunction,int); 112 | void lua_pushboolean(lua_State*,int); 113 | void lua_pushlightuserdata(lua_State*,void*); 114 | int lua_pushthread(lua_State*); 115 | void lua_getglobal(lua_State*,const(char)*); 116 | void lua_gettable(lua_State*,int); 117 | void lua_getfield(lua_State*,int,const(char)*); 118 | void lua_rawget(lua_State*,int); 119 | void lua_rawgeti(lua_State*,int,int); 120 | void lua_rawgetp(lua_State*,int,const(void)*); 121 | void lua_createtable(lua_State*,int,int); 122 | void* lua_newuserdata(lua_State*,size_t); 123 | int lua_getmetatable(lua_State*,int); 124 | void lua_getuservalue(lua_State*,int); 125 | void lua_setglobal(lua_State*,const(char)*); 126 | void lua_settable(lua_State*,int); 127 | void lua_setfield(lua_State*,int,const(char)*); 128 | void lua_rawset(lua_State*,int); 129 | void lua_rawseti(lua_State*,int,int); 130 | void lua_rawsetp(lua_State*,int,const(void)*); 131 | int lua_setmetatable(lua_State*,int); 132 | int lua_setuservalue(lua_State*,int); 133 | void lua_callk(lua_State*,int,int,int,lua_CFunction); 134 | int lua_getctx(lua_State*,int*); 135 | int lua_pcallk(lua_State*,int,int,int,int,lua_CFunction); 136 | int lua_load(lua_State*,lua_Reader,void*,const(char)*); 137 | int lua_dump(lua_State*,lua_Writer,void*); 138 | int lua_yieldk(lua_State*,int,int,lua_CFunction); 139 | int lua_resume(lua_State*,int); 140 | int lua_status(lua_State*); 141 | int lua_gc(lua_State*,int,int); 142 | int lua_error(lua_State*); 143 | int lua_next(lua_State*,int); 144 | void lua_concat(lua_State*,int); 145 | lua_Alloc lua_getallocf(lua_State*,void**); 146 | void lua_setallocf(lua_State*,lua_Alloc,void*); 147 | int lua_getstack(lua_State*,lua_Debug*); 148 | int lua_getinfo(lua_State*,const(char)*,lua_Debug*); 149 | const(char)* lua_getlocal(lua_State*,const(lua_Debug)*,int); 150 | const(char)* lua_setlocal(lua_State*,const(lua_Debug)*,int); 151 | const(char)* lua_getupvalue(lua_State*,int,int); 152 | const(char)* lua_setupvalue(lua_State*,int,int); 153 | void* lua_upvalueid(lua_State*,int,int); 154 | void lua_upvaluejoin(lua_State*,int,int,int,int); 155 | int lua_sethook(lua_State*,lua_Hook,int,int); 156 | lua_Hook lua_gethook(lua_State*); 157 | int lua_gethookmask(lua_State*); 158 | int lua_gethookcount(lua_State*); 159 | 160 | // lualib.h 161 | int luaopen_base(lua_State*); 162 | int luaopen_coroutine(lua_State*); 163 | int luaopen_table(lua_State*); 164 | int luaopen_io(lua_State*); 165 | int luaopen_os(lua_State*); 166 | int luaopen_string(lua_State*); 167 | int luaopen_bit32(lua_State*); 168 | int luaopen_math(lua_State*); 169 | int luaopen_debug(lua_State*); 170 | int luaopen_package(lua_State*); 171 | void luaL_openlibs(lua_State*); -------------------------------------------------------------------------------- /source/bindbc-lua/bindbc-lua/source/bindbc/lua/v52/package.d: -------------------------------------------------------------------------------- 1 | 2 | // Copyright Michael D. Parker 2018. 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at 5 | // http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | module bindbc.lua.v52; 8 | 9 | version(LUA_52): 10 | 11 | public import bindbc.lua.v52.types; 12 | 13 | version(BindBC_Static) version = BindLua_Static; 14 | version(BindLua_Static) { 15 | public import bindbc.lua.v52.bindstatic; 16 | } 17 | else public import bindbc.lua.v52.binddynamic; 18 | 19 | import core.stdc.config : c_long; 20 | 21 | // compatibility function aliases 22 | // luaconf.h 23 | alias lua_strlen = lua_rawlen; 24 | alias lua_objlen = lua_rawlen; 25 | 26 | // Macros 27 | @nogc nothrow { 28 | // luaconf.h 29 | int lua_equal(lua_State* L, int idx1, int idx2) { 30 | pragma(inline, true) 31 | return lua_compare(L, idx1, idx2, LUA_OPEQ); 32 | } 33 | 34 | int lua_lessthan(lua_State* L, int idx1, int idx2) { 35 | pragma(inline, true) 36 | return lua_compare(L, idx1, idx2, LUA_OPLT); 37 | } 38 | 39 | // lauxlib.h 40 | void luaL_checkversion(lua_State* L) { 41 | pragma(inline, true) 42 | luaL_checkversion_(L, LUA_VERSION_NUM); 43 | } 44 | 45 | int luaL_loadfile(lua_State* L, const(char)* filename) { 46 | pragma(inline, true) 47 | return luaL_loadfilex(L, filename, null); 48 | } 49 | 50 | void luaL_newlibtable(lua_State* L, const(luaL_Reg)[] l) { 51 | pragma(inline, true) 52 | lua_createtable(L, 0, cast(int)l.length - 1); 53 | } 54 | 55 | void luaL_newlib(lua_State* L, const(luaL_Reg)[] l) { 56 | pragma(inline, true) 57 | luaL_newlibtable(L, l); 58 | luaL_setfuncs(L, l.ptr, 0); 59 | } 60 | 61 | void luaL_argcheck(lua_State* L, bool cond, int arg, const(char)* extramsg) { 62 | pragma(inline, true) 63 | if(!cond) luaL_argerror(L, arg, extramsg); 64 | } 65 | 66 | const(char)* luaL_checkstring(lua_State* L, int arg) { 67 | pragma(inline, true) 68 | return luaL_checklstring(L, arg, null); 69 | } 70 | 71 | const(char)* luaL_optstring(lua_State* L, int arg, const(char)* d) { 72 | pragma(inline, true) 73 | return luaL_optlstring(L, arg, d, null); 74 | } 75 | 76 | int luaL_checkint(lua_State* L, int arg) { 77 | pragma(inline, true) 78 | return cast(int)luaL_checkinteger(L, arg); 79 | } 80 | 81 | int luaL_optint(lua_State* L, int arg, int d) { 82 | pragma(inline, true) 83 | return cast(int)luaL_optinteger(L, arg, d); 84 | } 85 | 86 | c_long luaL_checklong(lua_State* L, int arg) { 87 | pragma(inline, true) 88 | return cast(c_long)luaL_checkinteger(L, arg); 89 | } 90 | 91 | c_long luaL_optlong(lua_State* L, int arg, int d) { 92 | pragma(inline, true) 93 | return cast(c_long)luaL_optinteger(L, arg, d); 94 | } 95 | 96 | const(char)* luaL_typename(lua_State* L, int i) { 97 | pragma(inline, true) 98 | return lua_typename(L, lua_type(L, i)); 99 | } 100 | 101 | bool luaL_dofile(lua_State* L, const(char)* filename) { 102 | pragma(inline, true) 103 | return luaL_loadfile(L, filename) != 0 || lua_pcall(L, 0, LUA_MULTRET, 0) != 0; 104 | } 105 | 106 | bool luaL_dostring(lua_State* L, const(char)* str) { 107 | pragma(inline, true) 108 | return luaL_loadstring(L, str) != 0 || lua_pcall(L, 0, LUA_MULTRET, 0) != 0; 109 | } 110 | 111 | void luaL_getmetatable(lua_State* L, const(char)* tname) { 112 | pragma(inline, true) 113 | lua_getfield(L, LUA_REGISTRYINDEX, tname); 114 | } 115 | 116 | // TODO: figure out what luaL_opt is supposed to do 117 | 118 | int luaL_loadbuffer(lua_State *L, const(char)* buff, size_t sz, const(char)* name) { 119 | pragma(inline, true) 120 | return luaL_loadbufferx(L, buff, sz, name, null); 121 | } 122 | 123 | void luaL_addchar(luaL_Buffer* B, char c) { 124 | pragma(inline, true) 125 | if(B.n < B.size || luaL_prepbuffsize(B, 1)) { 126 | B.b[B.n++] = c; 127 | } 128 | } 129 | 130 | void luaL_addsize(luaL_Buffer* B, size_t s) { 131 | pragma(inline, true) 132 | B.n += s; 133 | } 134 | 135 | char* luaL_prepbuffer(luaL_Buffer* B) { 136 | pragma(inline, true) 137 | return luaL_prepbuffsize(B, LUAL_BUFFERSIZE); 138 | } 139 | 140 | // lua.h 141 | int lua_upvalueindex(int i) { 142 | pragma(inline, true) 143 | return LUA_REGISTRYINDEX - i; 144 | } 145 | 146 | void lua_call(lua_State* L, int n, int r) { 147 | pragma(inline, true) 148 | lua_callk(L, n, r, 0, null); 149 | } 150 | 151 | int lua_pcall(lua_State* L, int n, int r, int f) { 152 | pragma(inline, true) 153 | return lua_pcallk(L, n, r, f, 0, null); 154 | } 155 | 156 | int lua_yield(lua_State* L, int n) { 157 | pragma(inline, true) 158 | return lua_yieldk(L, n, 0, null); 159 | } 160 | 161 | lua_Number lua_tonumber(lua_State* L, int i) { 162 | pragma(inline, true) 163 | return lua_tonumberx(L, i, null); 164 | } 165 | 166 | lua_Integer lua_tointeger(lua_State* L, int i) { 167 | pragma(inline, true) 168 | return lua_tointegerx(L, i, null); 169 | } 170 | 171 | lua_Unsigned lua_tounsigned(lua_State* L, int i) { 172 | pragma(inline, true) 173 | return lua_tounsignedx(L, i, null); 174 | } 175 | 176 | void lua_pop(lua_State* L, int n) { 177 | pragma(inline, true) 178 | lua_settop(L, -n - 1); 179 | } 180 | 181 | void lua_newtable(lua_State* L) { 182 | pragma(inline, true) 183 | lua_createtable(L, 0, 0); 184 | } 185 | 186 | void lua_register(lua_State* L, const(char)* n, lua_CFunction f) { 187 | pragma(inline, true) 188 | lua_pushcfunction(L, f); 189 | lua_setglobal(L, n); 190 | } 191 | 192 | void lua_pushcfunction(lua_State* L, lua_CFunction f) { 193 | pragma(inline, true) 194 | lua_pushcclosure(L, f, 0); 195 | } 196 | 197 | bool lua_isfunction(lua_State* L, int n) { 198 | pragma(inline, true) 199 | return lua_type(L, n) == LUA_TFUNCTION; 200 | } 201 | 202 | bool lua_istable(lua_State* L, int n) { 203 | pragma(inline, true) 204 | return lua_type(L, n) == LUA_TTABLE; 205 | } 206 | 207 | bool lua_islightuserdata(lua_State* L, int n) { 208 | pragma(inline, true) 209 | return lua_type(L, n) == LUA_TLIGHTUSERDATA; 210 | } 211 | 212 | bool lua_isnil(lua_State* L, int n) { 213 | pragma(inline, true) 214 | return lua_type(L, n) == LUA_TNIL; 215 | } 216 | 217 | bool lua_isboolean(lua_State* L, int n) { 218 | pragma(inline, true) 219 | return lua_type(L, n) == LUA_TBOOLEAN; 220 | } 221 | 222 | bool lua_isthread(lua_State* L, int n) { 223 | pragma(inline, true) 224 | return lua_type(L, n) == LUA_TTHREAD; 225 | } 226 | 227 | bool lua_isnone(lua_State* L, int n) { 228 | pragma(inline, true) 229 | return lua_type(L, n) == LUA_TNONE; 230 | } 231 | 232 | bool lua_isnoneornil(lua_State* L, int n) { 233 | pragma(inline, true) 234 | return lua_type(L, n) <= 0; 235 | } 236 | 237 | void lua_pushliteral(lua_State* L, const(char)[] s) { 238 | pragma(inline, true) 239 | lua_pushlstring(L, s.ptr, s.length); 240 | } 241 | 242 | void lua_pushglobaltable(lua_State* L) { 243 | pragma(inline, true) 244 | lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); 245 | } 246 | 247 | const(char)* lua_tostring(lua_State* L, int i) { 248 | pragma(inline, true) 249 | return lua_tolstring(L, i, null); 250 | } 251 | 252 | void lua_getregistry(lua_State* L) { 253 | pragma(inline, true) 254 | lua_pushvalue(L, LUA_REGISTRYINDEX); 255 | } 256 | 257 | int lua_getgccount(lua_State* L) { 258 | pragma(inline, true) 259 | return lua_gc(L, LUA_GCCOUNT, 0); 260 | } 261 | } -------------------------------------------------------------------------------- /source/bindbc-lua/bindbc-lua/source/bindbc/lua/v52/types.d: -------------------------------------------------------------------------------- 1 | 2 | // Copyright Michael D. Parker 2018. 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at 5 | // http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | module bindbc.lua.v52.types; 8 | 9 | version(LUA_52): 10 | 11 | import core.stdc.stdio : BUFSIZ, FILE; 12 | 13 | // luaconf.h 14 | enum LUA_IDSIZE = 60; 15 | alias LUA_INT32 = int; 16 | alias LUAI_UMEM = size_t; 17 | alias LUAI_MEM = ptrdiff_t; 18 | alias LUA_NUMBER = double; 19 | alias LUA_INTEGER = ptrdiff_t; 20 | alias LUA_UNSIGNED = uint; 21 | 22 | enum LUAL_BUFFERSIZE = BUFSIZ; 23 | 24 | enum LUAI_MAXSTACK = 1000000; 25 | 26 | enum LUAI_FIRSTPSEUDOIDX = (-LUAI_MAXSTACK - 1000); 27 | 28 | // lauxlib.h 29 | enum LUA_ERRFILE = LUA_ERRERR+1; 30 | 31 | struct luaL_Reg { 32 | const(char)* name; 33 | lua_CFunction func; 34 | } 35 | 36 | enum LUA_NOREF = -2; 37 | enum LUA_REFNIL = -1; 38 | 39 | struct luaL_Buffer { 40 | char* b; 41 | size_t size; 42 | size_t n; 43 | lua_State* L; 44 | char[LUAL_BUFFERSIZE] buffer; 45 | } 46 | 47 | alias LUA_FILEHANDLE = FILE*; 48 | 49 | struct luaL_Stream { 50 | FILE* f; 51 | lua_CFunction closef; 52 | } 53 | 54 | // lua.h 55 | enum LUA_VERSION_MAJOR = "5"; 56 | enum LUA_VERSION_MINOR = "2"; 57 | enum LUA_VERSION_NUM = 502; 58 | enum LUA_VERSION_RELEASE = 4; 59 | 60 | enum LUA_VERSION = "Lua " ~ LUA_VERSION_MAJOR ~ "." ~ LUA_VERSION_MINOR; 61 | enum LUA_RELEASE = LUA_VERSION ~ "." ~ LUA_VERSION_RELEASE; 62 | 63 | enum LUA_SIGNATURE = "\033Lua"; 64 | enum LUA_MULTRET = -1; 65 | 66 | enum LUA_REGISTRYINDEX = LUAI_FIRSTPSEUDOIDX; 67 | 68 | enum LUA_OK = 0; 69 | enum LUA_YIELD = 1; 70 | enum LUA_ERRRUN = 2; 71 | enum LUA_ERRSYNTAX = 3; 72 | enum LUA_ERRMEM = 4; 73 | enum LUA_ERRGCMM = 5; 74 | enum LUA_ERRERR = 6; 75 | 76 | struct lua_State; 77 | 78 | nothrow { 79 | alias lua_CFunction = int function(lua_State*); 80 | alias lua_Reader = const(char)* function(lua_State*,void*,size_t); 81 | alias lua_Writer = int function(lua_State*,const(void)*,size_t,void*); 82 | alias lua_Alloc = void* function(void*,void*,size_t,size_t); 83 | } 84 | 85 | enum LUA_TNONE = -1; 86 | enum LUA_TNIL = 0; 87 | enum LUA_TBOOLEAN = 1; 88 | enum LUA_TLIGHTUSERDATA = 2; 89 | enum LUA_TNUMBER = 3; 90 | enum LUA_TSTRING = 4; 91 | enum LUA_TTABLE = 5; 92 | enum LUA_TFUNCTION = 6; 93 | enum LUA_TUSERDATA = 7; 94 | enum LUA_TTHREAD = 8; 95 | enum LUA_NUMTAGS = 9; 96 | 97 | enum LUA_MINSTACK = 20; 98 | 99 | enum LUA_RIDX_MAINTHREAD = 1; 100 | enum LUA_RIDX_GLOBALS = 2; 101 | enum LUA_RIDX_LAST = LUA_RIDX_GLOBALS; 102 | 103 | alias lua_Number = LUA_NUMBER; 104 | alias lua_Integer = LUA_INTEGER; 105 | alias lua_Unsigned = LUA_UNSIGNED; 106 | 107 | enum LUA_OPADD = 0; 108 | enum LUA_OPSUB = 1; 109 | enum LUA_OPMUL = 2; 110 | enum LUA_OPDIV = 3; 111 | enum LUA_OPMOD = 4; 112 | enum LUA_OPPOW = 5; 113 | enum LUA_OPUNM = 6; 114 | 115 | enum LUA_OPEQ = 0; 116 | enum LUA_OPLT = 1; 117 | enum LUA_OPLE = 2; 118 | 119 | enum LUA_GCSTOP = 0; 120 | enum LUA_GCRESTART = 1; 121 | enum LUA_GCCOLLECT = 2; 122 | enum LUA_GCCOUNT = 3; 123 | enum LUA_GCCOUNTB = 4; 124 | enum LUA_GCSTEP = 5; 125 | enum LUA_GCSETPAUSE = 6; 126 | enum LUA_GCSETSTEPMUL = 7; 127 | enum LUA_GCSETMAJORINC = 8; 128 | enum LUA_GCISRUNNING = 9; 129 | enum LUA_GCGEN = 10; 130 | enum LUA_GCINC = 11; 131 | 132 | enum LUA_HOOKCALL = 0; 133 | enum LUA_HOOKRET = 1; 134 | enum LUA_HOOKLINE = 2; 135 | enum LUA_HOOKCOUNT = 3; 136 | enum LUA_HOOKTAILRET = 4; 137 | 138 | enum LUA_MASKCALL = 1 << LUA_HOOKCALL; 139 | enum LUA_MASKRET = 1 << LUA_HOOKRET; 140 | enum LUA_MASKLINE = 1 << LUA_HOOKLINE; 141 | enum LUA_MASKCOUNT = 1 << LUA_HOOKCOUNT; 142 | 143 | struct lua_Debug { 144 | int event; 145 | const(char)* name; 146 | const(char)* namewhat; 147 | const(char)* what; 148 | const(char)* source; 149 | int currentline; 150 | int linedefined; 151 | int lastlinedefined; 152 | ubyte nups; 153 | ubyte nparams; 154 | char isvararg; 155 | char istailcall; 156 | char[LUA_IDSIZE] short_src; 157 | private void* i_ci; 158 | } 159 | 160 | alias lua_Hook = void function(lua_State*,lua_Debug*) nothrow; 161 | 162 | // lualib.h 163 | enum LUA_COLIBNAME = "coroutine"; 164 | enum LUA_TABLIBNAME = "table"; 165 | enum LUA_IOLIBNAME = "io"; 166 | enum LUA_OSLIBNAME = "os"; 167 | enum LUA_STRLIBNAME = "string"; 168 | enum LUA_BITLIBNAME = "bit32"; 169 | enum LUA_MATHLIBNAME = "math"; 170 | enum LUA_DBLIBNAME = "debug"; 171 | enum LUA_LOADLIBNAME = "package"; -------------------------------------------------------------------------------- /source/bindbc-lua/bindbc-lua/source/bindbc/lua/v53/bindstatic.d: -------------------------------------------------------------------------------- 1 | 2 | // Copyright Michael D. Parker 2018. 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at 5 | // http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | module bindbc.lua.v53.bindstatic; 8 | 9 | 10 | version(BindBC_Static) version = BindLua_Static; 11 | version(BindLua_Static) { 12 | version(LUA_53) version = LUA_53_STATIC; 13 | } 14 | 15 | version(LUA_53_STATIC): 16 | 17 | import core.stdc.stdarg : va_list; 18 | import bindbc.lua.v53.types; 19 | 20 | extern(C) @nogc nothrow: 21 | // lauxlib.h 22 | void luaL_checkversion_(lua_State*,lua_Number,size_t); 23 | int luaL_getmetafield(lua_State*,int,const(char)*); 24 | int luaL_callmeta(lua_State*, int,const(char)*); 25 | const(char)* luaL_tolstring(lua_State*,int,size_t*); 26 | int luaL_argerror(lua_State*,int,const(char)*); 27 | const(char)* luaL_checklstring(lua_State*,int,size_t*); 28 | const(char)* luaL_optlstring(lua_State*,int,const(char)*,size_t*); 29 | lua_Number luaL_checknumber(lua_State*,int); 30 | lua_Number luaL_optnumber(lua_State*,int,lua_Number); 31 | lua_Integer luaL_checkinteger(lua_State*,int); 32 | lua_Integer luaL_optinteger(lua_State*,int,lua_Integer); 33 | void luaL_checkstack(lua_State*,int,const(char)*); 34 | void luaL_checktype(lua_State*,int,int); 35 | void luaL_checkany(lua_State*,int); 36 | int luaL_newmetatable(lua_State*,const(char)*); 37 | void luaL_setmetatable(lua_State*,const(char)*); 38 | void* luaL_testudata(lua_State*,int,const(char)*); 39 | void* luaL_checkudata(lua_State*,int,const(char)*); 40 | void luaL_where(lua_State*,int); 41 | int luaL_error(lua_State*,const(char)*,...); 42 | int luaL_checkoption(lua_State*,int,const(char)*); 43 | int luaL_fileresult(lua_State*,int,const(char)*); 44 | int luaL_execresult(lua_State*,int); 45 | int luaL_ref(lua_State*,int); 46 | void luaL_unref(lua_State*,int,int); 47 | int luaL_loadfilex(lua_State*,const(char)*,const(char)*); 48 | int luaL_loadbufferx(lua_State*,const(char)*,size_t,const(char)*,const(char)*); 49 | int luaL_loadstring(lua_State*,const(char)*); 50 | lua_State* luaL_newstate(); 51 | int luaL_len(lua_State*,int); 52 | const(char)* luaL_gsub(lua_State*,const(char)*,const(char)*,const(char)*); 53 | void luaL_setfuncs(lua_State*,const(luaL_Reg)*,int); 54 | int luaL_getsubtable(lua_State*,int,const(char)*); 55 | void luaL_traceback(lua_State*,lua_State*,const(char)*,int); 56 | void luaL_requiref(lua_State*,const(char)*,lua_CFunction,int); 57 | void luaL_buffinit(lua_State*,luaL_Buffer*); 58 | char* luaL_prepbuffsize(luaL_Buffer*,size_t); 59 | void luaL_addlstring(luaL_Buffer*,const(char)*,size_t); 60 | void luaL_addstring(luaL_Buffer*, const(char)*); 61 | void luaL_addvalue(luaL_Buffer*); 62 | void luaL_pushresult(luaL_Buffer*); 63 | void luaL_pushresultsize(luaL_Buffer*,size_t); 64 | char* luaL_buffinitsize(lua_State*,luaL_Buffer*,size_t); 65 | 66 | // lua.h 67 | lua_State* lua_newstate(lua_Alloc,void*); 68 | lua_State* lua_close(lua_State*); 69 | lua_State* lua_newthread(lua_State*); 70 | lua_CFunction lua_atpanic(lua_State*,lua_CFunction); 71 | const(lua_Number)* lua_version(lua_State*); 72 | int lua_absindex(lua_State*,int); 73 | int lua_gettop(lua_State*); 74 | void lua_settop(lua_State*,int); 75 | void lua_pushvalue(lua_State*,int); 76 | void lua_rotate(lua_State*,int,int); 77 | void lua_copy(lua_State*,int,int); 78 | int lua_checkstack(lua_State*,int); 79 | void lua_xmove(lua_State*,lua_State*,int); 80 | int lua_isnumber(lua_State*,int); 81 | int lua_isstring(lua_State*,int); 82 | int lua_iscfunction(lua_State*,int); 83 | int lua_isinteger(lua_State*,int); 84 | int lua_isuserdata(lua_State*,int); 85 | int lua_type(lua_State*,int); 86 | const(char)* lua_typename(lua_State*,int); 87 | lua_Number lua_tonumberx(lua_State*,int,int*); 88 | lua_Integer lua_tointegerx(lua_State*,int,int*); 89 | int lua_toboolean(lua_State*,int); 90 | const(char)* lua_tolstring(lua_State*,int,size_t*); 91 | size_t lua_rawlen(lua_State*,int); 92 | lua_CFunction lua_tocfunction(lua_State*,int); 93 | void* lua_touserdata(lua_State*,int); 94 | lua_State* lua_tothread(lua_State*,int); 95 | const(void)* lua_topointer(lua_State*,int); 96 | void lua_arith(lua_State*,int); 97 | int lua_rawequal(lua_State*,int,int); 98 | int lua_compare(lua_State*,int,int,int); 99 | void lua_pushnil(lua_State*); 100 | void lua_pushnumber(lua_State*,lua_Number); 101 | void lua_pushinteger(lua_State*,lua_Integer); 102 | void lua_pushlstring(lua_State*,const(char)*,size_t); 103 | void lua_pushstring(lua_State*,const(char)*); 104 | const(char)* lua_pushvfstring(lua_State*,const(char)*,va_list); 105 | const(char)* lua_pushfstring(lua_State*,const(char)*,...); 106 | void lua_pushcclosure(lua_State*,lua_CFunction,int); 107 | void lua_pushboolean(lua_State*,int); 108 | void lua_pushlightuserdata(lua_State*,void*); 109 | int lua_pushthread(lua_State*); 110 | void lua_getglobal(lua_State*,const(char)*); 111 | void lua_gettable(lua_State*,int); 112 | void lua_getfield(lua_State*,int,const(char)*); 113 | int lua_geti(lua_State*,int,lua_Integer); 114 | void lua_rawget(lua_State*,int); 115 | void lua_rawgeti(lua_State*,int,int); 116 | void lua_rawgetp(lua_State*,int,const(void)*); 117 | void lua_createtable(lua_State*,int,int); 118 | void* lua_newuserdata(lua_State*,size_t); 119 | int lua_getmetatable(lua_State*,int); 120 | void lua_getuservalue(lua_State*,int); 121 | void lua_setglobal(lua_State*,const(char)*); 122 | void lua_settable(lua_State*,int); 123 | void lua_setfield(lua_State*,int,const(char)*); 124 | void lua_seti(lua_State*,int,lua_Integer); 125 | void lua_rawset(lua_State*,int); 126 | void lua_rawseti(lua_State*,int,int); 127 | void lua_rawsetp(lua_State*,int,const(void)*); 128 | int lua_setmetatable(lua_State*,int); 129 | int lua_setuservalue(lua_State*,int); 130 | void lua_callk(lua_State*,int,int,lua_KContext,lua_CFunction); 131 | int lua_pcallk(lua_State*,int,int,int,lua_KContext,lua_CFunction); 132 | int lua_load(lua_State*,lua_Reader,void*,const(char)*); 133 | int lua_dump(lua_State*,lua_Writer,void*); 134 | int lua_yieldk(lua_State*,int,lua_KContext,lua_CFunction); 135 | int lua_resume(lua_State*,int); 136 | int lua_status(lua_State*); 137 | int lua_isyieldable(lua_State*); 138 | int lua_gc(lua_State*,int,int); 139 | int lua_error(lua_State*); 140 | int lua_next(lua_State*,int); 141 | void lua_concat(lua_State*,int); 142 | void lua_len(lua_State*,int); 143 | size_t plua_stringtonumber(lua_State*,const(char)*); 144 | lua_Alloc lua_getallocf(lua_State*,void**); 145 | void lua_setallocf(lua_State*,lua_Alloc,void*); 146 | int lua_getstack(lua_State*,lua_Debug*); 147 | int lua_getinfo(lua_State*,const(char)*,lua_Debug*); 148 | const(char)* lua_getlocal(lua_State*,const(lua_Debug)*,int); 149 | const(char)* lua_setlocal(lua_State*,const(lua_Debug)*,int); 150 | const(char)* lua_getupvalue(lua_State*,int,int); 151 | const(char)* lua_setupvalue(lua_State*,int,int); 152 | int lua_sethook(lua_State*,lua_Hook,int,int); 153 | lua_Hook lua_gethook(lua_State*); 154 | int lua_gethookmask(lua_State*); 155 | int lua_gethookcount(lua_State*); 156 | 157 | // lualib.h 158 | int luaopen_base(lua_State*); 159 | int luaopen_coroutine(lua_State*); 160 | int luaopen_table(lua_State*); 161 | int luaopen_io(lua_State*); 162 | int luaopen_os(lua_State*); 163 | int luaopen_string(lua_State*); 164 | int luaopen_bit32(lua_State*); 165 | int luaopen_utf8(lua_State*); 166 | int luaopen_math(lua_State*); 167 | int luaopen_debug(lua_State*); 168 | int luaopen_package(lua_State*); 169 | void luaL_openlibs(lua_State*); -------------------------------------------------------------------------------- /source/bindbc-lua/bindbc-lua/source/bindbc/lua/v53/package.d: -------------------------------------------------------------------------------- 1 | 2 | // Copyright Michael D. Parker 2018. 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at 5 | // http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | module bindbc.lua.v53; 8 | 9 | version(LUA_53): 10 | 11 | public import bindbc.lua.v53.types; 12 | 13 | version(BindBC_Static) version = BindLua_Static; 14 | version(BindLua_Static) { 15 | public import bindbc.lua.v53.bindstatic; 16 | } 17 | else public import bindbc.lua.v53.binddynamic; 18 | 19 | import core.stdc.config : c_long; 20 | 21 | // compatibility function aliases 22 | // luaconf.h 23 | alias lua_strlen = lua_rawlen; 24 | alias lua_objlen = lua_rawlen; 25 | 26 | // Macros 27 | @nogc nothrow { 28 | // luaconf.h 29 | int lua_equal(lua_State* L, int idx1, int idx2) { 30 | pragma(inline, true) 31 | return lua_compare(L, idx1, idx2, LUA_OPEQ); 32 | } 33 | 34 | int lua_lessthan(lua_State* L, int idx1, int idx2) { 35 | pragma(inline, true) 36 | return lua_compare(L, idx1, idx2, LUA_OPLT); 37 | } 38 | 39 | // lauxlib.h 40 | void luaL_checkversion(lua_State* L) { 41 | pragma(inline, true) 42 | luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES); 43 | } 44 | 45 | int luaL_loadfile(lua_State* L, const(char)* filename) { 46 | pragma(inline, true) 47 | return luaL_loadfilex(L, filename, null); 48 | } 49 | 50 | void luaL_newlibtable(lua_State* L, const(luaL_Reg)[] l) { 51 | pragma(inline, true) 52 | lua_createtable(L, 0, cast(int)l.length - 1); 53 | } 54 | 55 | void luaL_newlib(lua_State* L, const(luaL_Reg)[] l) { 56 | pragma(inline, true) 57 | luaL_newlibtable(L, l); 58 | luaL_setfuncs(L, l.ptr, 0); 59 | } 60 | 61 | void luaL_argcheck(lua_State* L, bool cond, int arg, const(char)* extramsg) { 62 | pragma(inline, true) 63 | if(!cond) luaL_argerror(L, arg, extramsg); 64 | } 65 | 66 | const(char)* luaL_checkstring(lua_State* L, int arg) { 67 | pragma(inline, true) 68 | return luaL_checklstring(L, arg, null); 69 | } 70 | 71 | const(char)* luaL_optstring(lua_State* L, int arg, const(char)* d) { 72 | pragma(inline, true) 73 | return luaL_optlstring(L, arg, d, null); 74 | } 75 | 76 | const(char)* luaL_typename(lua_State* L, int i) { 77 | pragma(inline, true) 78 | return lua_typename(L, lua_type(L, i)); 79 | } 80 | 81 | bool luaL_dofile(lua_State* L, const(char)* filename) { 82 | pragma(inline, true) 83 | return luaL_loadfile(L, filename) != 0 || lua_pcall(L, 0, LUA_MULTRET, 0) != 0; 84 | } 85 | 86 | bool luaL_dostring(lua_State* L, const(char)* str) { 87 | pragma(inline, true) 88 | return luaL_loadstring(L, str) != 0 || lua_pcall(L, 0, LUA_MULTRET, 0) != 0; 89 | } 90 | 91 | void luaL_getmetatable(lua_State* L, const(char)* tname) { 92 | pragma(inline, true) 93 | lua_getfield(L, LUA_REGISTRYINDEX, tname); 94 | } 95 | 96 | // TODO: figure out what luaL_opt is supposed to do 97 | 98 | int luaL_loadbuffer(lua_State *L, const(char)* buff, size_t sz, const(char)* name) { 99 | pragma(inline, true) 100 | return luaL_loadbufferx(L, buff, sz, name, null); 101 | } 102 | 103 | void luaL_addchar(luaL_Buffer* B, char c) { 104 | pragma(inline, true) 105 | if(B.n < B.size || luaL_prepbuffsize(B, 1)) { 106 | B.b[B.n++] = c; 107 | } 108 | } 109 | 110 | void luaL_addsize(luaL_Buffer* B, size_t s) { 111 | pragma(inline, true) 112 | B.n += s; 113 | } 114 | 115 | char* luaL_prepbuffer(luaL_Buffer* B) { 116 | pragma(inline, true) 117 | return luaL_prepbuffsize(B, LUAL_BUFFERSIZE); 118 | } 119 | 120 | lua_Unsigned luaL_checkunsigned(lua_State* L, int a) { 121 | pragma(inline, true) 122 | return cast(lua_Unsigned)luaL_checkinteger(L, a); 123 | } 124 | 125 | lua_Unsigned luaL_optunsigned(lua_State* L, int a, lua_Unsigned d) { 126 | pragma(inline, true) 127 | return cast(lua_Unsigned)luaL_optinteger(L, a, d); 128 | } 129 | 130 | int luaL_checkint(lua_State* L, int a) { 131 | pragma(inline, true) 132 | return cast(int)luaL_checkinteger(L, a); 133 | } 134 | 135 | int luaL_optint(lua_State* L, int a, int d) { 136 | pragma(inline, true) 137 | return cast(int)luaL_optinteger(L, a, d); 138 | } 139 | 140 | c_long luaL_checklong(lua_State* L, int a, int d) { 141 | pragma(inline, true) 142 | return cast(c_long)luaL_checkinteger(L, a); 143 | } 144 | 145 | /*c_long luaL_checklong(lua_State* L, int a, int d) { 146 | pragma(inline, true) 147 | return cast(c_long)luaL_optinteger(L, a, d); 148 | }*/ 149 | 150 | // lua.h 151 | int lua_upvalueindex(int i) { 152 | pragma(inline, true) 153 | return LUA_REGISTRYINDEX - i; 154 | } 155 | 156 | void lua_call(lua_State* L, int n, int r) { 157 | pragma(inline, true) 158 | lua_callk(L, n, r, 0, null); 159 | } 160 | 161 | int lua_pcall(lua_State* L, int n, int r, int f) { 162 | pragma(inline, true) 163 | return lua_pcallk(L, n, r, f, 0, null); 164 | } 165 | 166 | int lua_yield(lua_State* L, int n) { 167 | pragma(inline, true) 168 | return lua_yieldk(L, n, 0, null); 169 | } 170 | 171 | void* lua_getextraspace(lua_State* L) { 172 | pragma(inline, true) 173 | return cast(void*)((cast(char*)L) - LUA_EXTRASPACE); 174 | } 175 | 176 | lua_Number lua_tonumber(lua_State* L, int i) { 177 | pragma(inline, true) 178 | return lua_tonumberx(L, i, null); 179 | } 180 | 181 | lua_Integer lua_tointeger(lua_State* L, int i) { 182 | pragma(inline, true) 183 | return lua_tointegerx(L, i, null); 184 | } 185 | 186 | void lua_pop(lua_State* L, int n) { 187 | pragma(inline, true) 188 | lua_settop(L, -n - 1); 189 | } 190 | 191 | void lua_newtable(lua_State* L) { 192 | pragma(inline, true) 193 | lua_createtable(L, 0, 0); 194 | } 195 | 196 | void lua_register(lua_State* L, const(char)* n, lua_CFunction f) { 197 | pragma(inline, true) 198 | lua_pushcfunction(L, f); 199 | lua_setglobal(L, n); 200 | } 201 | 202 | void lua_pushcfunction(lua_State* L, lua_CFunction f) { 203 | pragma(inline, true) 204 | lua_pushcclosure(L, f, 0); 205 | } 206 | 207 | bool lua_isfunction(lua_State* L, int n) { 208 | pragma(inline, true) 209 | return lua_type(L, n) == LUA_TFUNCTION; 210 | } 211 | 212 | bool lua_istable(lua_State* L, int n) { 213 | pragma(inline, true) 214 | return lua_type(L, n) == LUA_TTABLE; 215 | } 216 | 217 | bool lua_islightuserdata(lua_State* L, int n) { 218 | pragma(inline, true) 219 | return lua_type(L, n) == LUA_TLIGHTUSERDATA; 220 | } 221 | 222 | bool lua_isnil(lua_State* L, int n) { 223 | pragma(inline, true) 224 | return lua_type(L, n) == LUA_TNIL; 225 | } 226 | 227 | bool lua_isboolean(lua_State* L, int n) { 228 | pragma(inline, true) 229 | return lua_type(L, n) == LUA_TBOOLEAN; 230 | } 231 | 232 | bool lua_isthread(lua_State* L, int n) { 233 | pragma(inline, true) 234 | return lua_type(L, n) == LUA_TTHREAD; 235 | } 236 | 237 | bool lua_isnone(lua_State* L, int n) { 238 | pragma(inline, true) 239 | return lua_type(L, n) == LUA_TNONE; 240 | } 241 | 242 | bool lua_isnoneornil(lua_State* L, int n) { 243 | pragma(inline, true) 244 | return lua_type(L, n) <= 0; 245 | } 246 | 247 | void lua_pushliteral(lua_State* L, const(char)[] s) { 248 | pragma(inline, true) 249 | lua_pushlstring(L, s.ptr, s.length); 250 | } 251 | 252 | void lua_pushglobaltable(lua_State* L) { 253 | pragma(inline, true) 254 | lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); 255 | } 256 | 257 | const(char)* lua_tostring(lua_State* L, int i) { 258 | pragma(inline, true) 259 | return lua_tolstring(L, i, null); 260 | } 261 | 262 | void lua_insert(lua_State* L, int idx) { 263 | pragma(inline, true) 264 | lua_rotate(L, idx, 1); 265 | } 266 | 267 | void lua_remove(lua_State* L, int idx) { 268 | pragma(inline, true) 269 | lua_rotate(L, idx, -1); 270 | lua_pop(L, 1); 271 | } 272 | 273 | void lua_replace(lua_State* L, int idx) { 274 | pragma(inline, true) 275 | lua_copy(L, -1, idx); 276 | lua_pop(L, 1); 277 | } 278 | 279 | void lua_pushunsigned(lua_State* L, lua_Unsigned n) { 280 | pragma(inline, true) 281 | lua_pushinteger(L, cast(lua_Integer)n); 282 | } 283 | 284 | lua_Unsigned lua_tounsignedx(lua_State* L, int i, int* pi) { 285 | pragma(inline, true) 286 | return cast(lua_Unsigned)lua_tointegerx(L, i, pi); 287 | } 288 | 289 | lua_Unsigned lua_tounsigned(lua_State* L, int i) { 290 | pragma(inline, true) 291 | return lua_tounsignedx(L, i, null); 292 | } 293 | 294 | } -------------------------------------------------------------------------------- /source/bindbc-lua/bindbc-lua/source/bindbc/lua/v53/types.d: -------------------------------------------------------------------------------- 1 | 2 | // Copyright Michael D. Parker 2018. 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at 5 | // http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | module bindbc.lua.v53.types; 8 | 9 | version(LUA_53): 10 | 11 | import core.stdc.stdio : BUFSIZ, FILE; 12 | import core.stdc.stdint : intptr_t; 13 | 14 | // luaconf.h 15 | alias LUA_INT32 = int; 16 | alias LUAI_UMEM = size_t; 17 | alias LUAI_MEM = ptrdiff_t; 18 | alias LUA_NUMBER = double; 19 | alias LUA_INTEGER = ptrdiff_t; 20 | alias LUA_UNSIGNED = uint; 21 | 22 | alias LUA_KCONTEXT = intptr_t; 23 | enum LUAI_MAXSTACK = 1000000; 24 | enum LUA_EXTRASPACE = (void*).sizeof; 25 | enum LUA_IDSIZE = 60; 26 | enum LUAL_BUFFERSIZE = cast(int)(0x80 * (void*).sizeof * lua_Integer.sizeof); 27 | 28 | // lauxlib.h 29 | enum LUA_ERRFILE = LUA_ERRERR+1; 30 | enum LUA_LOADED_TABLE = "_LOADED"; 31 | enum LUA_PRELOAD_TABLE = "_PRELOAD"; 32 | 33 | struct luaL_Reg { 34 | const(char)* name; 35 | lua_CFunction func; 36 | } 37 | 38 | enum LUAL_NUMSIZES = lua_Integer.sizeof * 16 + lua_Number.sizeof; 39 | 40 | enum LUA_NOREF = -2; 41 | enum LUA_REFNIL = -1; 42 | 43 | struct luaL_Buffer { 44 | char* b; 45 | size_t size; 46 | size_t n; 47 | lua_State* L; 48 | char[LUAL_BUFFERSIZE] initb; 49 | } 50 | 51 | alias LUA_FILEHANDLE = FILE*; 52 | 53 | struct luaL_Stream { 54 | FILE* f; 55 | lua_CFunction closef; 56 | } 57 | 58 | // lua.h 59 | enum LUA_VERSION_MAJOR = "5"; 60 | enum LUA_VERSION_MINOR = "3"; 61 | enum LUA_VERSION_NUM = 503; 62 | enum LUA_VERSION_RELEASE = 5; 63 | 64 | enum LUA_VERSION = "Lua " ~ LUA_VERSION_MAJOR ~ "." ~ LUA_VERSION_MINOR; 65 | enum LUA_RELEASE = LUA_VERSION ~ "." ~ LUA_VERSION_RELEASE; 66 | 67 | enum LUA_SIGNATURE = "\x1bLua"; 68 | enum LUA_MULTRET = -1; 69 | 70 | enum LUA_REGISTRYINDEX = -LUAI_MAXSTACK - 1000; 71 | 72 | enum LUA_OK = 0; 73 | enum LUA_YIELD = 1; 74 | enum LUA_ERRRUN = 2; 75 | enum LUA_ERRSYNTAX = 3; 76 | enum LUA_ERRMEM = 4; 77 | enum LUA_ERRGCMM = 5; 78 | enum LUA_ERRERR = 6; 79 | 80 | struct lua_State; 81 | 82 | nothrow { 83 | alias lua_CFunction = int function(lua_State*); 84 | alias lua_KFunction = int function(lua_State*,int,lua_KContext); 85 | alias lua_Reader = const(char)* function(lua_State*,void*,size_t); 86 | alias lua_Writer = int function(lua_State*,const(void)*,size_t,void*); 87 | alias lua_Alloc = void* function(void*,void*,size_t,size_t); 88 | } 89 | 90 | enum LUA_TNONE = -1; 91 | enum LUA_TNIL = 0; 92 | enum LUA_TBOOLEAN = 1; 93 | enum LUA_TLIGHTUSERDATA = 2; 94 | enum LUA_TNUMBER = 3; 95 | enum LUA_TSTRING = 4; 96 | enum LUA_TTABLE = 5; 97 | enum LUA_TFUNCTION = 6; 98 | enum LUA_TUSERDATA = 7; 99 | enum LUA_TTHREAD = 8; 100 | enum LUA_NUMTAGS = 9; 101 | 102 | enum LUA_MINSTACK = 20; 103 | 104 | enum LUA_RIDX_MAINTHREAD = 1; 105 | enum LUA_RIDX_GLOBALS = 2; 106 | enum LUA_RIDX_LAST = LUA_RIDX_GLOBALS; 107 | 108 | alias lua_Number = LUA_NUMBER; 109 | alias lua_Integer = LUA_INTEGER; 110 | alias lua_Unsigned = LUA_UNSIGNED; 111 | alias lua_KContext = LUA_KCONTEXT; 112 | 113 | enum LUA_OPADD = 0; 114 | enum LUA_OPSUB = 1; 115 | enum LUA_OPMUL = 2; 116 | enum LUA_OPMOD = 3; 117 | enum LUA_OPPOW = 4; 118 | enum LUA_OPDIV = 5; 119 | enum LUA_OPIDIV = 6; 120 | enum LUA_OPBAND = 7; 121 | enum LUA_OPBOR = 8; 122 | enum LUA_OPBXOR = 9; 123 | enum LUA_OPSHL = 10; 124 | enum LUA_OPSHR = 11; 125 | enum LUA_OPUNM = 12; 126 | enum LUA_OPBNOT = 13; 127 | 128 | enum LUA_OPEQ = 0; 129 | enum LUA_OPLT = 1; 130 | enum LUA_OPLE = 2; 131 | 132 | enum LUA_GCSTOP = 0; 133 | enum LUA_GCRESTART = 1; 134 | enum LUA_GCCOLLECT = 2; 135 | enum LUA_GCCOUNT = 3; 136 | enum LUA_GCCOUNTB = 4; 137 | enum LUA_GCSTEP = 5; 138 | enum LUA_GCSETPAUSE = 6; 139 | enum LUA_GCSETSTEPMUL = 7; 140 | enum LUA_GCISRUNNING = 9; 141 | 142 | enum LUA_HOOKCALL = 0; 143 | enum LUA_HOOKRET = 1; 144 | enum LUA_HOOKLINE = 2; 145 | enum LUA_HOOKCOUNT = 3; 146 | enum LUA_HOOKTAILRET = 4; 147 | 148 | enum LUA_MASKCALL = 1 << LUA_HOOKCALL; 149 | enum LUA_MASKRET = 1 << LUA_HOOKRET; 150 | enum LUA_MASKLINE = 1 << LUA_HOOKLINE; 151 | enum LUA_MASKCOUNT = 1 << LUA_HOOKCOUNT; 152 | 153 | struct lua_Debug { 154 | int event; 155 | const(char)* name; 156 | const(char)* namewhat; 157 | const(char)* what; 158 | const(char)* source; 159 | int currentline; 160 | int linedefined; 161 | int lastlinedefined; 162 | ubyte nups; 163 | ubyte nparams; 164 | char isvararg; 165 | char istailcall; 166 | char[LUA_IDSIZE] short_src; 167 | private void* i_ci; 168 | } 169 | 170 | alias lua_Hook = void function(lua_State*,lua_Debug*) nothrow; 171 | 172 | // lualib.h 173 | enum LUA_VERSUFFIX = "_" ~ LUA_VERSION_MAJOR ~ "_" ~ LUA_VERSION_MINOR; 174 | enum LUA_COLIBNAME = "coroutine"; 175 | enum LUA_TABLIBNAME = "table"; 176 | enum LUA_IOLIBNAME = "io"; 177 | enum LUA_OSLIBNAME = "os"; 178 | enum LUA_STRLIBNAME = "string"; 179 | enum LUA_UTF8LIBNAME = "utf8"; 180 | enum LUA_BITLIBNAME = "bit32"; 181 | enum LUA_MATHLIBNAME = "math"; 182 | enum LUA_DBLIBNAME = "debug"; 183 | enum LUA_LOADLIBNAME = "package"; -------------------------------------------------------------------------------- /source/image_loader.d: -------------------------------------------------------------------------------- 1 | module image_loader; 2 | 3 | import std.string; 4 | import std.file; 5 | import std.stdio; 6 | import bindbc.freeimage; 7 | 8 | import pixmap; 9 | 10 | /** 11 | load image from file and return as pixmap 12 | */ 13 | Pixmap loadImage(string filename) 14 | { 15 | if (!exists(filename) || !isFile(filename)) 16 | throw new Exception("No such file " ~ filename); 17 | FIMEMORY* mem = readfile(filename); 18 | FIBITMAP* img = FreeImage_LoadFromMemory(FIF_GIF, mem); 19 | FreeImage_CloseMemory(mem); 20 | Pixmap pix = fibitmapToPixmap(img, null); 21 | FreeImage_Unload(img); 22 | return pix; 23 | } 24 | 25 | /** 26 | load animation from file and return as array of pixmaps 27 | */ 28 | Pixmap[] loadAnimation(string filename, uint maxframes = -1) 29 | { 30 | Pixmap[] frames; 31 | Pixmap canvas = loadImage(filename); 32 | // FIMULTIBITMAP* anim; 33 | FIMEMORY* mem = readfile(filename); 34 | FIMULTIBITMAP* anim = FreeImage_LoadMultiBitmapFromMemory(FIF_GIF, mem); 35 | uint count = FreeImage_GetPageCount(anim); 36 | if (maxframes < count) 37 | count = maxframes; 38 | for (uint i = 0; i < count; i++) 39 | { 40 | FIBITMAP* img = FreeImage_LockPage(anim, i); 41 | frames ~= fibitmapToPixmap(img, canvas).clone(); 42 | FreeImage_UnlockPage(anim, img, false); 43 | } 44 | FreeImage_CloseMultiBitmap(anim); 45 | FreeImage_CloseMemory(mem); 46 | return frames; 47 | } 48 | 49 | /** 50 | save animation to file 51 | */ 52 | void saveAnimation(string filename, Pixmap[] frames) 53 | { 54 | FIMULTIBITMAP* anim = FreeImage_OpenMultiBitmap(FIF_GIF, toStringz(filename), true, false, true); 55 | const count = frames.length; 56 | for (uint i = 0; i < count; i++) 57 | { 58 | FIBITMAP* img = pixmapToFibitmap(frames[i]); 59 | FreeImage_AppendPage(anim, img); 60 | FreeImage_Unload(img); 61 | } 62 | FreeImage_CloseMultiBitmap(anim); 63 | } 64 | 65 | /** 66 | read file into a FIMEMORY stream 67 | */ 68 | FIMEMORY* readfile(string filename) 69 | { 70 | ubyte[] bin = cast(ubyte[]) read(filename); 71 | FIMEMORY* mem = FreeImage_OpenMemory(cast(ubyte*) bin, cast(uint) bin.length); 72 | return mem; 73 | } 74 | 75 | /** 76 | write a FIMEMORY stream to a file 77 | */ 78 | void writefile(string filename, FIMEMORY* mem) 79 | { 80 | ubyte* bin; 81 | DWORD len; 82 | FreeImage_AcquireMemory(mem, &bin, &len); 83 | auto f = File(filename, "wb"); 84 | for (uint i = 0; i < len; i++) 85 | f.write(bin[i]); 86 | f.close(); 87 | // write(filename, staticArray(bin, len)); 88 | } 89 | 90 | /** 91 | Convert FIBITMAP to Pixmap 92 | */ 93 | Pixmap fibitmapToPixmap(FIBITMAP* img, Pixmap pixmap) 94 | { 95 | const width = FreeImage_GetWidth(img); 96 | const height = FreeImage_GetHeight(img); 97 | 98 | int time = 100; 99 | int left = 0; 100 | int top = 0; 101 | ubyte dispose = 0; 102 | FITAG* tag; 103 | FreeImage_GetMetadata(FIMD_ANIMATION, img, "FrameTime", &tag); 104 | if (tag) 105 | time = cast(uint)(cast(long*) FreeImage_GetTagValue(tag))[0]; 106 | FreeImage_GetMetadata(FIMD_ANIMATION, img, "FrameLeft", &tag); 107 | if (tag) 108 | left = (cast(short*) FreeImage_GetTagValue(tag))[0]; 109 | FreeImage_GetMetadata(FIMD_ANIMATION, img, "FrameTop", &tag); 110 | if (tag) 111 | top = (cast(short*) FreeImage_GetTagValue(tag))[0]; 112 | FreeImage_GetMetadata(FIMD_ANIMATION, img, "DisposalMethod", &tag); 113 | if (tag) 114 | dispose = (cast(ubyte*) FreeImage_GetTagValue(tag))[0]; 115 | 116 | ushort color = 1; 117 | ubyte c; 118 | ubyte maxindex = cast(ubyte)(FreeImage_GetColorsUsed(img) - 1); 119 | if (!pixmap) 120 | { 121 | ubyte colorBits = 0; 122 | while (color < maxindex + 1) 123 | { 124 | color *= 2; 125 | colorBits++; 126 | } 127 | pixmap = new Pixmap(width, height, colorBits); 128 | dispose = 2; 129 | } 130 | 131 | pixmap.duration = time; 132 | pixmap.bgColor = cast(ubyte) FreeImage_GetTransparentIndex(img); 133 | if (dispose == 2) 134 | pixmap.cls(); 135 | 136 | RGBQUAD* palette = FreeImage_GetPalette(img); 137 | if (palette) 138 | for (color = 0; color <= maxindex; color++) 139 | pixmap.setColor(color, palette[color].rgbRed / 16, 140 | palette[color].rgbGreen / 16, palette[color].rgbBlue / 16); 141 | for (uint y = 0; y < height; y++) 142 | { 143 | for (uint x = 0; x < width; x++) 144 | { 145 | FreeImage_GetPixelIndex(img, x, height - y - 1, &c); 146 | if (c != pixmap.bgColor) 147 | pixmap.pset(left + x, top + y, c); 148 | } 149 | } 150 | return pixmap; 151 | } 152 | 153 | /** 154 | Convert Pixmap to FIBITMAP 155 | */ 156 | FIBITMAP* pixmapToFibitmap(Pixmap pixmap) 157 | { 158 | auto bpp = pixmap.colorBits; 159 | if (bpp > 8) 160 | bpp = 8; 161 | while (bpp != 1 && bpp != 4 && bpp != 8) 162 | bpp++; 163 | FIBITMAP* img = FreeImage_Allocate(pixmap.width, pixmap.height, bpp); 164 | FITAG* tag = FreeImage_CreateTag(); 165 | FreeImage_SetTagKey(tag, "FrameTime"); 166 | FreeImage_SetTagType(tag, FIDT_LONG); 167 | FreeImage_SetTagCount(tag, 1); 168 | FreeImage_SetTagLength(tag, 4); 169 | FreeImage_SetTagValue(tag, &pixmap.duration); 170 | FreeImage_SetMetadata(FIMD_ANIMATION, img, "FrameTime", tag); 171 | ubyte dismet = 2; 172 | FreeImage_SetTagKey(tag, "DisposalMethod"); 173 | FreeImage_SetTagType(tag, FIDT_BYTE); 174 | FreeImage_SetTagCount(tag, 1); 175 | FreeImage_SetTagLength(tag, 1); 176 | FreeImage_SetTagValue(tag, &dismet); 177 | FreeImage_SetMetadata(FIMD_ANIMATION, img, "DisposalMethod", tag); 178 | uint colors = cast(uint)(pixmap.palette.length / 3); 179 | RGBQUAD* palette = FreeImage_GetPalette(img); 180 | for (uint c = 0; c < colors; c++) 181 | { 182 | palette[c].rgbRed = cast(ubyte)(pixmap.palette[c * 3 + 0]); 183 | palette[c].rgbGreen = cast(ubyte)(pixmap.palette[c * 3 + 1]); 184 | palette[c].rgbBlue = cast(ubyte)(pixmap.palette[c * 3 + 2]); 185 | } 186 | FreeImage_SetTransparentIndex(img, pixmap.bgColor); 187 | for (uint y = 0; y < pixmap.height; y++) 188 | { 189 | for (uint x = 0; x < pixmap.width; x++) 190 | { 191 | ubyte c = pixmap.pget(x, y); 192 | FreeImage_SetPixelIndex(img, x, pixmap.height - y - 1, &c); 193 | } 194 | } 195 | FreeImage_DeleteTag(tag); 196 | return img; 197 | } 198 | -------------------------------------------------------------------------------- /source/lua_api/_basic_.d: -------------------------------------------------------------------------------- 1 | module lua_api._basic_; 2 | 3 | import std.string; 4 | import std.path; 5 | import std.conv; 6 | import std.file; 7 | import bindbc.lua; 8 | 9 | import machine; 10 | import program; 11 | import viewport; 12 | import pixmap; 13 | 14 | import lua_api.sys; 15 | import lua_api.fs; 16 | import lua_api.view; 17 | import lua_api.input; 18 | import lua_api.audio; 19 | import lua_api.image; 20 | import lua_api.gfx; 21 | import lua_api.text; 22 | 23 | int panic(lua_State* L) nothrow 24 | { 25 | lua_getglobal(L, "__program"); 26 | auto prog = cast(Program*) lua_touserdata(L, -1); 27 | try 28 | { 29 | prog.shutdown(-1); 30 | } 31 | catch (Exception err) 32 | { 33 | } 34 | // writeln("Shit hit the fan!"); 35 | return 0; 36 | } 37 | 38 | /// dofile(filename): result 39 | int dofile(lua_State* L) nothrow 40 | { 41 | const filename = to!string(lua_tostring(L, 1)); 42 | lua_getglobal(L, "__program"); 43 | auto prog = cast(Program*) lua_touserdata(L, -1); 44 | try 45 | { 46 | if (!prog.isOnOriginDrive(filename) && !prog.hasPermission(Permissions.readOtherDrives)) 47 | throw new Exception("no permission to read other drives!"); 48 | prog.machine.showBusy(); 49 | prog.doFile(filename); 50 | return 1; 51 | } 52 | catch (Exception err) 53 | { 54 | luaL_error(L, toStringz(err.msg)); 55 | return 0; 56 | } 57 | } 58 | 59 | /// loadfile(filename): function 60 | int loadfile(lua_State* L) nothrow 61 | { 62 | const filename = to!string(lua_tostring(L, 1)); 63 | lua_getglobal(L, "__program"); 64 | auto prog = cast(Program*) lua_touserdata(L, -1); 65 | try 66 | { 67 | if (!prog.isOnOriginDrive(filename) && !prog.hasPermission(Permissions.readOtherDrives)) 68 | throw new Exception("no permission to read other drives!"); 69 | prog.machine.showBusy(); 70 | auto path = prog.actualFile(filename); 71 | if (luaL_loadstring(L, 72 | toStringz(prog.machine.luaFilepathVars(prog.resolve(filename)) ~ readText(path)))) 73 | throw new Exception("Cannot load file " ~ filename); 74 | return 1; 75 | } 76 | catch (Exception err) 77 | { 78 | luaL_error(L, toStringz(err.msg)); 79 | return 0; 80 | } 81 | } 82 | 83 | /// print(message) 84 | int print(lua_State* L) nothrow 85 | { 86 | const msg = to!string(lua_tostring(L, 1)); 87 | lua_getglobal(L, "__program"); 88 | auto prog = cast(Program*) lua_touserdata(L, -1); 89 | try 90 | { 91 | prog.write(1, msg ~ "\n"); 92 | // writeln(prog.machine.baseName(prog.filename) ~ ": " ~ msg); 93 | return 0; 94 | } 95 | catch (Exception err) 96 | { 97 | luaL_error(L, toStringz(err.msg)); 98 | return 0; 99 | } 100 | } 101 | 102 | /// require(filename): module 103 | int require(lua_State* L) nothrow 104 | { 105 | auto filename = to!string(lua_tostring(L, 1)); 106 | lua_getglobal(L, "__program"); 107 | auto prog = cast(Program*) lua_touserdata(L, -1); 108 | try 109 | { 110 | if (!(prog.resolve(filename).length > 10 111 | && prog.resolve(filename)[0 .. 9] == "sys:libs/") 112 | && !prog.isOnOriginDrive(filename) && !prog.hasPermission(Permissions.readOtherDrives)) 113 | throw new Exception("no permission to read other drives!"); 114 | prog.machine.showBusy(); 115 | filename = prog.resolveResource("libs", filename, ".lua"); 116 | auto path = prog.actualFile(filename); 117 | lua_getglobal(L, "package"); 118 | lua_getfield(L, -1, "loaded"); 119 | lua_getfield(L, -1, toStringz(prog.resolve(path))); 120 | if (lua_isnoneornil(L, -1)) 121 | { 122 | lua_pop(L, 1); 123 | prog.doFile(filename); 124 | lua_setfield(L, -2, toStringz(path)); 125 | lua_getfield(L, -1, toStringz(path)); 126 | } 127 | return 1; 128 | } 129 | catch (Exception err) 130 | { 131 | luaL_error(L, toStringz(err.msg)); 132 | return 0; 133 | } 134 | } 135 | 136 | /** 137 | register some functions for a lua program 138 | */ 139 | void registerFunctions(Program program) 140 | { 141 | auto lua = program.lua; 142 | 143 | //Setup the userdata 144 | auto prog = cast(Program*) lua_newuserdata(lua, Program.sizeof); 145 | *prog = program; 146 | lua_setglobal(lua, "__program"); 147 | luaL_dostring(lua, q"{ 148 | io = NIL 149 | file = NIL 150 | os = NIL 151 | package = { loaded = {} } 152 | 153 | function _init() 154 | end 155 | function _step() 156 | sys.exit(0) 157 | end 158 | function _shutdown() 159 | end 160 | }"); 161 | 162 | lua_atpanic(lua, &panic); 163 | 164 | lua_register(lua, "dofile", &dofile); 165 | 166 | lua_register(lua, "loadfile", &loadfile); 167 | 168 | lua_register(lua, "print", &print); 169 | 170 | lua_register(lua, "require", &require); 171 | 172 | lua_api.sys.registerFunctions(program); 173 | lua_api.fs.registerFunctions(program); 174 | lua_api.view.registerFunctions(program); 175 | lua_api.input.registerFunctions(program); 176 | lua_api.audio.registerFunctions(program); 177 | lua_api.image.registerFunctions(program); 178 | lua_api.gfx.registerFunctions(program); 179 | lua_api.text.registerFunctions(program); 180 | 181 | luaL_dostring(lua, "_ = NIL"); 182 | } 183 | -------------------------------------------------------------------------------- /source/lua_api/gfx.d: -------------------------------------------------------------------------------- 1 | module lua_api.gfx; 2 | 3 | import std.string; 4 | import bindbc.lua; 5 | 6 | import program; 7 | 8 | /// gfx.cls() 9 | int gfx_cls(lua_State* L) nothrow 10 | { 11 | lua_getglobal(L, "__program"); 12 | auto prog = cast(Program*) lua_touserdata(L, -1); 13 | try 14 | { 15 | if (!prog.activeViewport) 16 | throw new Exception("No active viewport!"); 17 | prog.activeViewport.pixmap.cls(); 18 | return 0; 19 | } 20 | catch (Exception err) 21 | { 22 | luaL_error(L, toStringz(err.msg)); 23 | return 0; 24 | } 25 | } 26 | 27 | /// gfx.palette(color[, red, green, blue]): red, green, blue 28 | int gfx_palette(lua_State* L) nothrow 29 | { 30 | const c = lua_tonumber(L, 1); 31 | const r = lua_tonumber(L, 2); 32 | const g = lua_tonumber(L, 3); 33 | const b = lua_tonumber(L, 4); 34 | const set = 1 - lua_isnoneornil(L, 2); 35 | lua_getglobal(L, "__program"); 36 | auto prog = cast(Program*) lua_touserdata(L, -1); 37 | try 38 | { 39 | if (!prog.activeViewport) 40 | throw new Exception("No active viewport!"); 41 | if (set) 42 | prog.activeViewport.pixmap.setColor(cast(uint) c, cast(ubyte) r, cast(ubyte) g, cast(ubyte) b); 43 | uint i = cast(uint)(c * 3) % prog.activeViewport.pixmap.palette.length; 44 | lua_pushinteger(L, cast(int) prog.activeViewport.pixmap.palette[i++] % 16); 45 | lua_pushinteger(L, cast(int) prog.activeViewport.pixmap.palette[i++] % 16); 46 | lua_pushinteger(L, cast(int) prog.activeViewport.pixmap.palette[i++] % 16); 47 | return 3; 48 | } 49 | catch (Exception err) 50 | { 51 | luaL_error(L, toStringz(err.msg)); 52 | return 0; 53 | } 54 | } 55 | 56 | /// gfx.fgcolor([color]): color 57 | int gfx_fgcolor(lua_State* L) nothrow 58 | { 59 | const cindex = lua_tonumber(L, 1); 60 | const set = 1 - lua_isnoneornil(L, 1); 61 | lua_getglobal(L, "__program"); 62 | auto prog = cast(Program*) lua_touserdata(L, -1); 63 | try 64 | { 65 | if (!prog.activeViewport) 66 | throw new Exception("No active viewport!"); 67 | if (set) 68 | prog.activeViewport.pixmap.setFGColor(cast(ubyte) cindex); 69 | lua_pushinteger(L, cast(int) prog.activeViewport.pixmap.fgColor); 70 | return 1; 71 | } 72 | catch (Exception err) 73 | { 74 | luaL_error(L, toStringz(err.msg)); 75 | return 0; 76 | } 77 | } 78 | 79 | /// gfx.bgcolor([color]): color 80 | int gfx_bgcolor(lua_State* L) nothrow 81 | { 82 | const cindex = lua_tonumber(L, 1); 83 | const set = 1 - lua_isnoneornil(L, 1); 84 | lua_getglobal(L, "__program"); 85 | auto prog = cast(Program*) lua_touserdata(L, -1); 86 | try 87 | { 88 | if (!prog.activeViewport) 89 | throw new Exception("No active viewport!"); 90 | if (set) 91 | prog.activeViewport.pixmap.setBGColor(cast(ubyte) cindex); 92 | lua_pushinteger(L, cast(int) prog.activeViewport.pixmap.bgColor); 93 | return 1; 94 | } 95 | catch (Exception err) 96 | { 97 | luaL_error(L, toStringz(err.msg)); 98 | return 0; 99 | } 100 | } 101 | 102 | /// gfx.nearestcolor(r, g, b): color 103 | int gfx_nearestcolor(lua_State* L) nothrow 104 | { 105 | const r = lua_tonumber(L, 1); 106 | const g = lua_tonumber(L, 2); 107 | const b = lua_tonumber(L, 3); 108 | lua_getglobal(L, "__program"); 109 | auto prog = cast(Program*) lua_touserdata(L, -1); 110 | try 111 | { 112 | if (!prog.activeViewport) 113 | throw new Exception("No active viewport!"); 114 | lua_pushinteger(L, 115 | cast(int) prog.activeViewport.pixmap.nearestColor(cast(ubyte)(r * 17), 116 | cast(ubyte)(g * 17), cast(ubyte)(b * 17))); 117 | return 1; 118 | } 119 | catch (Exception err) 120 | { 121 | luaL_error(L, toStringz(err.msg)); 122 | return 0; 123 | } 124 | } 125 | 126 | /// gfx.pixel(x, y[, color]): color 127 | int gfx_pixel(lua_State* L) nothrow 128 | { 129 | const x = lua_tonumber(L, 1); 130 | const y = lua_tonumber(L, 2); 131 | const c = lua_tonumber(L, 3); 132 | const set = 1 - lua_isnoneornil(L, 3); 133 | lua_getglobal(L, "__program"); 134 | auto prog = cast(Program*) lua_touserdata(L, -1); 135 | try 136 | { 137 | if (!prog.activeViewport) 138 | throw new Exception("No active viewport!"); 139 | if (set) 140 | prog.activeViewport.pixmap.pset(cast(uint) x, cast(uint) y, cast(ubyte) c); 141 | lua_pushinteger(L, cast(int) prog.activeViewport.pixmap.pget(cast(uint) x, cast(uint) y)); 142 | return 1; 143 | } 144 | catch (Exception err) 145 | { 146 | luaL_error(L, toStringz(err.msg)); 147 | return 0; 148 | } 149 | } 150 | 151 | /// gfx.plot(x, y) 152 | int gfx_plot(lua_State* L) nothrow 153 | { 154 | const x = lua_tonumber(L, 1); 155 | const y = lua_tonumber(L, 2); 156 | lua_getglobal(L, "__program"); 157 | auto prog = cast(Program*) lua_touserdata(L, -1); 158 | try 159 | { 160 | if (!prog.activeViewport) 161 | throw new Exception("No active viewport!"); 162 | prog.activeViewport.pixmap.plot(cast(uint) x, cast(uint) y); 163 | return 0; 164 | } 165 | catch (Exception err) 166 | { 167 | luaL_error(L, toStringz(err.msg)); 168 | return 0; 169 | } 170 | } 171 | 172 | /// gfx.bar(x, y, width, height) 173 | int gfx_bar(lua_State* L) nothrow 174 | { 175 | const x = lua_tonumber(L, 1); 176 | const y = lua_tonumber(L, 2); 177 | const width = lua_tonumber(L, 3); 178 | const height = lua_tonumber(L, 4); 179 | lua_getglobal(L, "__program"); 180 | auto prog = cast(Program*) lua_touserdata(L, -1); 181 | try 182 | { 183 | if (!prog.activeViewport) 184 | throw new Exception("No active viewport!"); 185 | prog.activeViewport.pixmap.bar(cast(int) x, cast(int) y, cast(int) width, cast(int) height); 186 | return 0; 187 | } 188 | catch (Exception err) 189 | { 190 | luaL_error(L, toStringz(err.msg)); 191 | return 0; 192 | } 193 | } 194 | 195 | /// gfx.line(x1, y1, x2, y2) 196 | int gfx_line(lua_State* L) nothrow 197 | { 198 | const x1 = lua_tonumber(L, 1); 199 | const y1 = lua_tonumber(L, 2); 200 | const x2 = lua_tonumber(L, 3); 201 | const y2 = lua_tonumber(L, 4); 202 | lua_getglobal(L, "__program"); 203 | auto prog = cast(Program*) lua_touserdata(L, -1); 204 | try 205 | { 206 | if (!prog.activeViewport) 207 | throw new Exception("No active viewport!"); 208 | prog.activeViewport.pixmap.line(cast(int) x1, cast(int) y1, cast(int) x2, cast(int) y2); 209 | return 0; 210 | } 211 | catch (Exception err) 212 | { 213 | luaL_error(L, toStringz(err.msg)); 214 | return 0; 215 | } 216 | } 217 | 218 | /// gfx.tri(x1, y1, x2, y2, x3, y3) 219 | int gfx_tri(lua_State* L) nothrow 220 | { 221 | const x1 = lua_tonumber(L, 1); 222 | const y1 = lua_tonumber(L, 2); 223 | const x2 = lua_tonumber(L, 3); 224 | const y2 = lua_tonumber(L, 4); 225 | const x3 = lua_tonumber(L, 5); 226 | const y3 = lua_tonumber(L, 6); 227 | lua_getglobal(L, "__program"); 228 | auto prog = cast(Program*) lua_touserdata(L, -1); 229 | try 230 | { 231 | if (!prog.activeViewport) 232 | throw new Exception("No active viewport!"); 233 | prog.activeViewport.pixmap.triangle(cast(int) x1, cast(int) y1, cast(int) x2, 234 | cast(int) y2, cast(int) x3, cast(int) y3); 235 | return 0; 236 | } 237 | catch (Exception err) 238 | { 239 | luaL_error(L, toStringz(err.msg)); 240 | return 0; 241 | } 242 | } 243 | 244 | /** 245 | register gfx functions for a lua program 246 | */ 247 | void registerFunctions(Program program) 248 | { 249 | auto lua = program.lua; 250 | luaL_dostring(lua, "gfx = {}"); 251 | 252 | lua_register(lua, "_", &gfx_cls); 253 | luaL_dostring(lua, "gfx.cls = _"); 254 | 255 | lua_register(lua, "_", &gfx_palette); 256 | luaL_dostring(lua, "gfx.palette = _"); 257 | 258 | lua_register(lua, "_", &gfx_fgcolor); 259 | luaL_dostring(lua, "gfx.fgcolor = _"); 260 | 261 | lua_register(lua, "_", &gfx_bgcolor); 262 | luaL_dostring(lua, "gfx.bgcolor = _"); 263 | 264 | lua_register(lua, "_", &gfx_nearestcolor); 265 | luaL_dostring(lua, "gfx.nearestcolor = _"); 266 | 267 | lua_register(lua, "_", &gfx_pixel); 268 | luaL_dostring(lua, "gfx.pixel = _"); 269 | 270 | lua_register(lua, "_", &gfx_plot); 271 | luaL_dostring(lua, "gfx.plot = _"); 272 | 273 | lua_register(lua, "_", &gfx_bar); 274 | luaL_dostring(lua, "gfx.bar = _"); 275 | 276 | lua_register(lua, "_", &gfx_line); 277 | luaL_dostring(lua, "gfx.line = _"); 278 | 279 | lua_register(lua, "_", &gfx_tri); 280 | luaL_dostring(lua, "gfx.tri = _"); 281 | } 282 | -------------------------------------------------------------------------------- /source/lua_api/input.d: -------------------------------------------------------------------------------- 1 | module lua_api.input; 2 | 3 | import std.string; 4 | import std.conv; 5 | import bindbc.lua; 6 | 7 | import program; 8 | 9 | /// input.text([text]): text 10 | int input_text(lua_State* L) nothrow 11 | { 12 | const text = to!string(lua_tostring(L, 1)); 13 | const set = 1 - lua_isnoneornil(L, 1); 14 | lua_getglobal(L, "__program"); 15 | auto prog = cast(Program*) lua_touserdata(L, -1); 16 | try 17 | { 18 | if (!prog.activeViewport) 19 | throw new Exception("No active viewport!"); 20 | if (set) 21 | prog.activeViewport.getTextinput(true).setText(text); 22 | lua_pushstring(L, toStringz(prog.activeViewport.getTextinput(true).getText())); 23 | return 1; 24 | } 25 | catch (Exception err) 26 | { 27 | luaL_error(L, toStringz(err.msg)); 28 | return 0; 29 | } 30 | } 31 | 32 | /// input.selected([text]): text 33 | int input_selected(lua_State* L) nothrow 34 | { 35 | const text = to!string(lua_tostring(L, 1)); 36 | const set = 1 - lua_isnoneornil(L, 1); 37 | lua_getglobal(L, "__program"); 38 | auto prog = cast(Program*) lua_touserdata(L, -1); 39 | try 40 | { 41 | if (!prog.activeViewport) 42 | throw new Exception("No active viewport!"); 43 | if (set) 44 | prog.activeViewport.getTextinput(true).insertText(text); 45 | lua_pushstring(L, toStringz(prog.activeViewport.getTextinput(true).getSelectedText())); 46 | return 1; 47 | } 48 | catch (Exception err) 49 | { 50 | luaL_error(L, toStringz(err.msg)); 51 | return 0; 52 | } 53 | } 54 | 55 | /// input.cursor([pos, selected]): pos, selected 56 | int input_cursor(lua_State* L) nothrow 57 | { 58 | const pos = lua_tonumber(L, 1); 59 | const sel = lua_tonumber(L, 2); 60 | const set = 1 - lua_isnoneornil(L, 1); 61 | lua_getglobal(L, "__program"); 62 | auto prog = cast(Program*) lua_touserdata(L, -1); 63 | try 64 | { 65 | if (!prog.activeViewport) 66 | throw new Exception("No active viewport!"); 67 | if (set) 68 | { 69 | prog.activeViewport.getTextinput(true).setPosBytes(cast(uint) pos); 70 | prog.activeViewport.getTextinput(true).setSelectedBytes(cast(uint) sel); 71 | } 72 | lua_pushinteger(L, cast(int) prog.activeViewport.getTextinput(true).posBytes); 73 | lua_pushinteger(L, cast(int) prog.activeViewport.getTextinput(true).selectedBytes); 74 | return 2; 75 | } 76 | catch (Exception err) 77 | { 78 | luaL_error(L, toStringz(err.msg)); 79 | return 0; 80 | } 81 | } 82 | 83 | /// input.linesperpage([linesperpage]): linesperpage 84 | int input_linesperpage(lua_State* L) nothrow 85 | { 86 | const lines = lua_tonumber(L, 1); 87 | const set = 1 - lua_isnoneornil(L, 1); 88 | lua_getglobal(L, "__program"); 89 | auto prog = cast(Program*) lua_touserdata(L, -1); 90 | try 91 | { 92 | if (!prog.activeViewport) 93 | throw new Exception("No active viewport!"); 94 | if (set) 95 | prog.activeViewport.getTextinput(true).linesPerPage = cast(uint) lines; 96 | lua_pushinteger(L, cast(int) prog.activeViewport.getTextinput(true).linesPerPage); 97 | return 1; 98 | } 99 | catch (Exception err) 100 | { 101 | luaL_error(L, toStringz(err.msg)); 102 | return 0; 103 | } 104 | } 105 | 106 | /// input.clearhistory() 107 | int input_clearhistory(lua_State* L) nothrow 108 | { 109 | lua_getglobal(L, "__program"); 110 | auto prog = cast(Program*) lua_touserdata(L, -1); 111 | try 112 | { 113 | if (!prog.activeViewport) 114 | throw new Exception("No active viewport!"); 115 | prog.activeViewport.getTextinput(true).clearHistory(); 116 | return 0; 117 | } 118 | catch (Exception err) 119 | { 120 | luaL_error(L, toStringz(err.msg)); 121 | return 0; 122 | } 123 | } 124 | 125 | /// input.hotkey(): hotkey 126 | int input_hotkey(lua_State* L) nothrow 127 | { 128 | lua_getglobal(L, "__program"); 129 | auto prog = cast(Program*) lua_touserdata(L, -1); 130 | try 131 | { 132 | if (!prog.activeViewport) 133 | throw new Exception("No active viewport!"); 134 | lua_pushstring(L, toStringz("" ~ prog.activeViewport.hotkey)); 135 | return 1; 136 | } 137 | catch (Exception err) 138 | { 139 | luaL_error(L, toStringz(err.msg)); 140 | return 0; 141 | } 142 | } 143 | 144 | /// input.mouse(): x, y, btn 145 | int input_mouse(lua_State* L) nothrow 146 | { 147 | lua_getglobal(L, "__program"); 148 | auto prog = cast(Program*) lua_touserdata(L, -1); 149 | try 150 | { 151 | if (!prog.activeViewport) 152 | throw new Exception("No active viewport!"); 153 | lua_pushinteger(L, cast(int) prog.activeViewport.mouseX); 154 | lua_pushinteger(L, cast(int) prog.activeViewport.mouseY); 155 | lua_pushinteger(L, cast(int) prog.activeViewport.mouseBtn); 156 | return 3; 157 | } 158 | catch (Exception err) 159 | { 160 | luaL_error(L, toStringz(err.msg)); 161 | return 0; 162 | } 163 | } 164 | 165 | /// input.gamepad([player]): btn 166 | int input_gamepad(lua_State* L) nothrow 167 | { 168 | const player = lua_tointeger(L, 1); 169 | lua_getglobal(L, "__program"); 170 | auto prog = cast(Program*) lua_touserdata(L, -1); 171 | try 172 | { 173 | if (!prog.activeViewport) 174 | throw new Exception("No active viewport!"); 175 | lua_pushinteger(L, cast(int) prog.activeViewport.getGameBtn(cast(ubyte) player)); 176 | return 1; 177 | } 178 | catch (Exception err) 179 | { 180 | luaL_error(L, toStringz(err.msg)); 181 | return 0; 182 | } 183 | } 184 | 185 | /// input.drag(drop, icon) 186 | int input_drag(lua_State* L) nothrow 187 | { 188 | const drop = to!string(lua_tostring(L, 1)); 189 | const icon = lua_tointeger(L, 2); 190 | lua_getglobal(L, "__program"); 191 | auto prog = cast(Program*) lua_touserdata(L, -1); 192 | try 193 | { 194 | if (icon >= prog.pixmaps.length || !prog.pixmaps[cast(uint) icon]) 195 | throw new Exception("Invalid image!"); 196 | if (!prog.activeViewport) 197 | throw new Exception("No active viewport!"); 198 | if (!prog.activeViewport.containsViewport(prog.machine.focusedViewport)) 199 | throw new Exception("viewport is not focused!"); 200 | if (prog.activeViewport.mouseBtn == 0) 201 | throw new Exception("no mouse buttons pressed!"); 202 | // if (prog.activeViewport.mouseX < 0 || prog.activeViewport.mouseY < 0 203 | // || prog.activeViewport.mouseX >= prog.activeViewport.pixmap.width 204 | // || prog.activeViewport.mouseY >= prog.activeViewport.pixmap.height) 205 | // throw new Exception("mouse is outside viewport!"); 206 | prog.machine.dragObject(drop, prog.pixmaps[cast(uint) icon]); 207 | return 0; 208 | } 209 | catch (Exception err) 210 | { 211 | luaL_error(L, toStringz(err.msg)); 212 | return 0; 213 | } 214 | } 215 | 216 | /// input.drop(): drop 217 | int input_drop(lua_State* L) nothrow 218 | { 219 | lua_getglobal(L, "__program"); 220 | auto prog = cast(Program*) lua_touserdata(L, -1); 221 | try 222 | { 223 | if (!prog.activeViewport) 224 | throw new Exception("No active viewport!"); 225 | auto drop = prog.activeViewport.getBasket(true).dispense(); 226 | if (drop) 227 | lua_pushstring(L, toStringz(drop)); 228 | else 229 | lua_pushnil(L); 230 | return 1; 231 | } 232 | 233 | catch (Exception err) 234 | { 235 | luaL_error(L, toStringz(err.msg)); 236 | return 0; 237 | } 238 | } 239 | 240 | /// input.midi(): byte 241 | int input_midi(lua_State* L) nothrow 242 | { 243 | lua_getglobal(L, "__program"); 244 | auto prog = cast(Program*) lua_touserdata(L, -1); 245 | try 246 | { 247 | if (prog.machine.hasMidi()) 248 | lua_pushinteger(L, cast(int) prog.machine.getMidi()); 249 | else 250 | lua_pushnil(L); 251 | return 1; 252 | } 253 | catch (Exception err) 254 | { 255 | luaL_error(L, toStringz(err.msg)); 256 | return 0; 257 | } 258 | } 259 | 260 | /** 261 | register input functions for a lua program 262 | */ 263 | void registerFunctions(Program program) 264 | { 265 | auto lua = program.lua; 266 | luaL_dostring(lua, "input = {}"); 267 | 268 | lua_register(lua, "_", &input_text); 269 | luaL_dostring(lua, "input.text = _"); 270 | 271 | lua_register(lua, "_", &input_selected); 272 | luaL_dostring(lua, "input.selected = _"); 273 | 274 | lua_register(lua, "_", &input_cursor); 275 | luaL_dostring(lua, "input.cursor = _"); 276 | 277 | lua_register(lua, "_", &input_linesperpage); 278 | luaL_dostring(lua, "input.linesperpage = _"); 279 | 280 | lua_register(lua, "_", &input_clearhistory); 281 | luaL_dostring(lua, "input.clearhistory = _"); 282 | 283 | lua_register(lua, "_", &input_hotkey); 284 | luaL_dostring(lua, "input.hotkey = _"); 285 | 286 | lua_register(lua, "_", &input_mouse); 287 | luaL_dostring(lua, "input.mouse = _"); 288 | 289 | lua_register(lua, "_", &input_gamepad); 290 | luaL_dostring(lua, "input.gamepad = _"); 291 | 292 | lua_register(lua, "_", &input_drag); 293 | luaL_dostring(lua, "input.drag = _"); 294 | 295 | lua_register(lua, "_", &input_drop); 296 | luaL_dostring(lua, "input.drop = _"); 297 | 298 | lua_register(lua, "_", &input_midi); 299 | luaL_dostring(lua, "input.midi = _"); 300 | } 301 | -------------------------------------------------------------------------------- /source/lua_api/text.d: -------------------------------------------------------------------------------- 1 | module lua_api.text; 2 | 3 | import std.string; 4 | import std.conv; 5 | import bindbc.lua; 6 | 7 | import program; 8 | import pixmap; 9 | import machine; 10 | 11 | /// text.loadfont(filename): font 12 | int text_loadfont(lua_State* L) nothrow 13 | { 14 | auto filename = to!string(lua_tostring(L, 1)); 15 | lua_getglobal(L, "__program"); 16 | auto prog = cast(Program*) lua_touserdata(L, -1); 17 | try 18 | { 19 | if (!prog.isOnOriginDrive(filename) && !prog.hasPermission(Permissions.readOtherDrives)) 20 | throw new Exception("no permission to read other drives!"); 21 | filename = prog.resolveResource("fonts", filename, ".gif"); 22 | lua_pushinteger(L, cast(int) prog.loadFont(prog.actualFile(filename))); 23 | return 1; 24 | } 25 | catch (Exception err) 26 | { 27 | lua_pushnil(L); 28 | return 1; 29 | } 30 | } 31 | 32 | /// text.copymode([mode, masked]): mode, masked 33 | int text_copymode(lua_State* L) nothrow 34 | { 35 | const mode = lua_tointeger(L, 1); 36 | const masked = lua_toboolean(L, 2); 37 | const set = 1 - lua_isnoneornil(L, 1); 38 | lua_getglobal(L, "__program"); 39 | auto prog = cast(Program*) lua_touserdata(L, -1); 40 | try 41 | { 42 | if (!prog.activeViewport) 43 | throw new Exception("No active viewport!"); 44 | if (set) 45 | { 46 | prog.activeViewport.pixmap.textCopymode = cast(CopyMode) mode; 47 | prog.activeViewport.pixmap.textCopyMasked = cast(bool) masked; 48 | } 49 | lua_pushinteger(L, cast(int) prog.activeViewport.pixmap.textCopymode); 50 | lua_pushboolean(L, cast(int) prog.activeViewport.pixmap.textCopyMasked); 51 | return 2; 52 | } 53 | catch (Exception err) 54 | { 55 | luaL_error(L, toStringz(err.msg)); 56 | return 0; 57 | } 58 | } 59 | 60 | /// text.draw(text, font, x, y): width, height 61 | int text_draw(lua_State* L) nothrow 62 | { 63 | const text = to!string(lua_tostring(L, 1)); 64 | const font = lua_tointeger(L, 2); 65 | const x = lua_tonumber(L, 3); 66 | const y = lua_tonumber(L, 4); 67 | lua_getglobal(L, "__program"); 68 | auto prog = cast(Program*) lua_touserdata(L, -1); 69 | try 70 | { 71 | if (!prog.activeViewport) 72 | throw new Exception("No active viewport!"); 73 | if (font >= prog.fonts.length || !prog.fonts[cast(uint) font]) 74 | throw new Exception("Invalid font!"); 75 | auto o = prog.activeViewport.pixmap.text(text, prog.fonts[cast(uint) font], 76 | cast(int) x, cast(int) y); 77 | for (uint i = 0; i < o.length; i++) 78 | lua_pushinteger(L, cast(int) o[i]); 79 | return o.length; 80 | } 81 | catch (Exception err) 82 | { 83 | luaL_error(L, toStringz(err.msg)); 84 | return 0; 85 | } 86 | } 87 | 88 | /// text.forgetfont(font) 89 | int text_forgetfont(lua_State* L) nothrow 90 | { 91 | const font = lua_tointeger(L, 1); 92 | lua_getglobal(L, "__program"); 93 | auto prog = cast(Program*) lua_touserdata(L, -1); 94 | try 95 | { 96 | if (font >= prog.fonts.length || !prog.fonts[cast(uint) font]) 97 | throw new Exception("Invalid font!"); 98 | prog.removeFont(cast(uint) font); 99 | return 0; 100 | } 101 | catch (Exception err) 102 | { 103 | luaL_error(L, toStringz(err.msg)); 104 | return 0; 105 | } 106 | } 107 | 108 | /** 109 | register text functions for a lua program 110 | */ 111 | void registerFunctions(Program program) 112 | { 113 | auto lua = program.lua; 114 | luaL_dostring(lua, "text = {}"); 115 | 116 | lua_register(lua, "_", &text_loadfont); 117 | luaL_dostring(lua, "text.loadfont = _"); 118 | 119 | lua_register(lua, "_", &text_copymode); 120 | luaL_dostring(lua, "text.copymode = _"); 121 | 122 | lua_register(lua, "_", &text_draw); 123 | luaL_dostring(lua, "text.draw = _"); 124 | 125 | lua_register(lua, "_", &text_forgetfont); 126 | luaL_dostring(lua, "text.forgetfont = _"); 127 | } 128 | -------------------------------------------------------------------------------- /source/sample.d: -------------------------------------------------------------------------------- 1 | module sample; 2 | 3 | import std.stdio; 4 | import std.string; 5 | import std.file; 6 | import core.stdc.stdlib; 7 | 8 | /** 9 | Sound sample 10 | */ 11 | class Sample 12 | { 13 | byte[] data; /// sample data 14 | int freq = 11_025; /// samplerate 15 | uint loopStart = 0; /// start of loop 16 | uint loopEnd = 0; /// end of loop 17 | 18 | /** 19 | create sound sample 20 | */ 21 | this(string filename) 22 | { 23 | if (filename) 24 | this.loadWav(filename); 25 | } 26 | 27 | /** 28 | calculate memory usage of this sample 29 | */ 30 | uint memoryUsed() 31 | { 32 | return cast(uint) this.data.length; 33 | } 34 | 35 | /** 36 | load sample from wav file 37 | */ 38 | void loadWav(string filename) 39 | { 40 | char[4] tag; 41 | ubyte[1] b; 42 | ushort[1] s; 43 | uint[1] i; 44 | auto f = File(filename, "rb"); 45 | if (this.nextChunk(f) != "RIFF") 46 | throw new Exception("Unsupported format!"); 47 | if (f.rawRead(tag) != "WAVE") 48 | throw new Exception("Unsupported format!"); 49 | while (f.eof() == false && this.nextChunk(f) != "fmt ") 50 | this.skipChunk(f); 51 | ushort audioFormat = f.rawRead(s)[0]; 52 | ushort numChannels = f.rawRead(s)[0]; 53 | uint sampleRate = f.rawRead(i)[0]; 54 | uint byteRate = f.rawRead(i)[0]; 55 | ushort blockAlign = f.rawRead(s)[0]; 56 | ushort bitsPerSample = f.rawRead(s)[0]; 57 | if (audioFormat != 1) 58 | throw new Exception("Unsupported format!"); 59 | while (sampleRate > 32_000) 60 | { 61 | numChannels *= 2; 62 | sampleRate /= 2; 63 | } 64 | this.freq = sampleRate; 65 | this.skipChunk(f); 66 | while (!f.eof() && this.nextChunk(f) != "data") 67 | this.skipChunk(f); 68 | uint p = cast(uint)(this.nextChuckOffset - f.tell()); 69 | p /= numChannels * (bitsPerSample / 8); 70 | this.data.length = p; 71 | p = 0; 72 | uint skip = numChannels * (bitsPerSample / 8) - 1; 73 | for (uint n = 1; n < (bitsPerSample / 8); n++) 74 | f.rawRead(b); 75 | while (!f.eof() && p < this.data.length) 76 | { 77 | f.rawRead(b); 78 | if ((bitsPerSample / 8) > 1) 79 | this.data[p++] = b[0]; 80 | else 81 | this.data[p++] = b[0] - 128; 82 | for (uint n = 0; !f.eof() && n < skip; n++) 83 | f.rawRead(b); 84 | } 85 | this.data.length = p; 86 | f.close(); 87 | // this._loadWav(filename); 88 | } 89 | 90 | /** 91 | save sample to wav file 92 | */ 93 | void saveWav(string filename) 94 | { 95 | ubyte[] b; 96 | ushort[] s; 97 | uint[] i; 98 | auto f = File(filename, "wb"); 99 | f.rawWrite("RIFF"); 100 | i = [36 + cast(uint) this.data.length]; 101 | f.rawWrite(i); 102 | f.rawWrite("WAVE"); 103 | f.rawWrite("fmt "); 104 | i = [16]; 105 | f.rawWrite(i); 106 | s = [1, 1]; 107 | f.rawWrite(s); 108 | i = [this.freq, this.freq]; 109 | f.rawWrite(i); 110 | s = [1, 8]; 111 | f.rawWrite(s); 112 | f.rawWrite("data"); 113 | i = [cast(uint) this.data.length]; 114 | f.rawWrite(i); 115 | b.length = this.data.length; 116 | for (uint n = 0; n < b.length; n++) 117 | b[n] = this.data[n] + 128; 118 | f.rawWrite(b); 119 | f.close(); 120 | } 121 | 122 | // --- _privates --- // 123 | private long nextChuckOffset; 124 | 125 | private char[4] nextChunk(File f) 126 | { 127 | char[4] tag; 128 | uint[1] i; 129 | f.rawRead(tag); 130 | f.rawRead(i); 131 | this.nextChuckOffset = f.tell() + i[0]; 132 | return tag; 133 | } 134 | 135 | private void skipChunk(File f) 136 | { 137 | f.seek(this.nextChuckOffset); 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /source/screen.d: -------------------------------------------------------------------------------- 1 | module screen; 2 | 3 | import viewport; 4 | import pixmap; 5 | 6 | /** 7 | Class representing a screen 8 | */ 9 | class Screen : Viewport 10 | { 11 | static bool widescreen; /// whether to do 16:9 or 4:3 aspect ratio 12 | ubyte pixelWidth; /// width of each pixel 13 | ubyte pixelHeight; /// height of each pixel 14 | 15 | /** 16 | create a new screen 17 | */ 18 | this(ubyte mode, ubyte colorBits) 19 | { 20 | super(null, 0, 0, 0, 0, 0); 21 | this.changeMode(mode, colorBits); 22 | // this.defaultPointer(); 23 | } 24 | 25 | override 26 | { 27 | /** 28 | change screen mode 29 | */ 30 | void changeMode(ubyte mode, ubyte colorBits) 31 | { 32 | this.pixmap.destroyTexture(); 33 | if (mode > 31) 34 | throw new Exception("Unsupported screen mode!"); 35 | if (colorBits > 8) 36 | throw new Exception("Unsupported number of colorBits!"); 37 | mode = mode % 16; 38 | this.mode = mode; 39 | this.pixelWidth = 8; 40 | this.pixelHeight = 8; 41 | for (uint i = 0; i < (mode % 4); i++) 42 | this.pixelWidth /= 2; 43 | mode /= 4; 44 | for (uint i = 0; i < (mode % 4); i++) 45 | this.pixelHeight /= 2; 46 | mode /= 4; 47 | uint height = 360; 48 | if (!Screen.widescreen) 49 | height = 480; 50 | if (this.program) 51 | this.program.freeMemory(this.memoryUsed()); 52 | this.pixmap.destroyTexture(); 53 | Pixmap oldpix = this.pixmap; 54 | this.pixmap = new Pixmap(640 / this.pixelWidth, height / this.pixelHeight, colorBits); 55 | this.pixmap.viewport = this; 56 | this.pixmap.copyRectFrom(oldpix, 0, 0, 0, 0, oldpix.width, oldpix.height); 57 | this.pixmap.setFGColor(oldpix.fgColor); 58 | this.pixmap.setBGColor(oldpix.bgColor); 59 | this.pixmap.copymode = oldpix.copymode; 60 | this.pixmap.copyMasked = oldpix.copyMasked; 61 | this.pixmap.textCopymode = oldpix.textCopymode; 62 | this.pixmap.textCopyMasked = oldpix.textCopyMasked; 63 | this.pixmap.errorDiffusion = oldpix.errorDiffusion; 64 | if (oldpix.palette.length == this.pixmap.palette.length) 65 | this.pixmap.palette = oldpix.palette; 66 | this.setDirty(); 67 | if (this.program) 68 | this.program.useMemory(this.memoryUsed()); 69 | } 70 | 71 | /** 72 | screens are not resizable 73 | */ 74 | void resize(uint width, uint height) 75 | { 76 | } 77 | } 78 | 79 | void defaultPointer() 80 | { 81 | this.pointer = new Pixmap(11, 11, 2); 82 | this.pointer.pixels = [ 83 | 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 1, 3, 84 | 3, 3, 3, 2, 1, 0, 0, 0, 0, 1, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 1, 3, 3, 3, 85 | 3, 2, 1, 0, 0, 0, 0, 1, 3, 3, 1, 3, 3, 2, 1, 0, 0, 0, 0, 1, 1, 0, 1, 3, 86 | 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 1, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 1, 3, 87 | 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 88 | ]; 89 | this.pointerX = 0; 90 | this.pointerY = 0; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /source/soundchip.d: -------------------------------------------------------------------------------- 1 | module soundchip; 2 | 3 | import core.stdc.stdlib; 4 | import std.math; 5 | import std.string; 6 | import bindbc.sdl; 7 | 8 | import sample; 9 | 10 | /** 11 | Sound chip simulator 12 | */ 13 | class SoundChip 14 | { 15 | ulong lastTick = 0; /// last time audio was updated 16 | Sample[4] src; /// sample for each channel 17 | double[4] head; /// playhead for each channel 18 | double[4] loopStart; /// loop start for each channel 19 | double[4] loopEnd; /// loop end for each channel 20 | double[4] rate; /// playback rate for each channel 21 | double[4] volume; /// volume for each channel 22 | string recDevName; /// name of recording device 23 | 24 | /** 25 | create a SoundChip 26 | */ 27 | this() 28 | { 29 | this.initDevice(); 30 | this.buflen = this.spec.freq / 10; 31 | this.buffer = cast(float*) malloc(this.buflen * this.spec.channels * float.sizeof); 32 | this.timeToSync = this.spec.freq * 4; 33 | this.timeToIdle = this.spec.freq * 8; 34 | this.clear(); 35 | } 36 | 37 | /** 38 | main loop 39 | */ 40 | void step(ulong t) 41 | { 42 | t *= this.spec.freq / 1000; 43 | if (this.lastTick > t || this.lastTick == 0) 44 | this.lastTick = t; 45 | if (t - this.lastTick > this.buflen) 46 | this.lastTick = t - this.buflen; 47 | uint p = 0; 48 | while (this.lastTick < t) 49 | { 50 | for (uint i = 0; i < this.src.length; i++) 51 | { 52 | this.value[i] = 0; 53 | if (this.rate[i]) 54 | { 55 | this.timeToSync = this.spec.freq * 1; 56 | this.timeToIdle = this.spec.freq * 8; 57 | uint pos = cast(int) trunc(this.head[i]); 58 | if (this.src[i] && pos < this.src[i].data.length) 59 | this.value[i] = 1.0 * this.src[i].data[pos] / 128 * this.volume[i]; 60 | else 61 | this.rate[i] = 0; 62 | this.head[i] += this.rate[i]; 63 | if (this.rate[i] > 0 && this.head[i] >= this.loopEnd[i]) 64 | this.head[i] -= this.loopEnd[i] - this.loopStart[i]; 65 | if (this.rate[i] < 0 && this.head[i] < this.loopStart[i]) 66 | this.head[i] += this.loopEnd[i] - this.loopStart[i]; 67 | } 68 | else 69 | this.rate[i] = 0; 70 | } 71 | if (this.timeToIdle-- > 0) 72 | { 73 | this.buffer[p++] = this.value[0] * .5 + this.value[1] * .5 + this.value[2] * .25; 74 | this.buffer[p++] = this.value[3] * .5 + this.value[2] * .5 + this.value[1] * .25; 75 | } 76 | else 77 | this.lastTick = t; 78 | if (this.timeToSync-- == 0) 79 | SDL_ClearQueuedAudio(this.dev); 80 | this.lastTick++; 81 | } 82 | if (p) 83 | { 84 | SDL_QueueAudio(this.dev, this.buffer, cast(uint)(p * float.sizeof)); 85 | SDL_PauseAudioDevice(this.dev, 0); 86 | } 87 | if (this.recdev && t > this.lastRec + this.spec.freq) 88 | { 89 | SDL_PauseAudioDevice(this.recdev, 1); 90 | SDL_ClearQueuedAudio(this.recdev); 91 | this.recmax /= 2; 92 | } 93 | } 94 | 95 | /** 96 | play sample 97 | */ 98 | void play(uint channel, Sample sample) 99 | { 100 | channel = channel % this.src.length; 101 | this.src[channel] = sample; 102 | this.head[channel] = 0; 103 | this.setLoop(channel, this.src[channel].loopStart, this.src[channel].loopEnd); 104 | this.setFreq(channel, sample.freq); 105 | this.setVolume(channel, 63); 106 | } 107 | 108 | /** 109 | set samplerate on channel 110 | */ 111 | void setFreq(uint channel, int freq) 112 | { 113 | channel = channel % this.src.length; 114 | while (freq > 32_000) 115 | freq /= 2; 116 | 117 | this.rate[channel] = 1.0 * freq / this.spec.freq; 118 | } 119 | 120 | /** 121 | set volume on channel 122 | */ 123 | void setVolume(uint channel, ubyte vol) 124 | { 125 | channel = channel % this.src.length; 126 | if (vol > 63) 127 | vol = 63; 128 | this.volume[channel] = 1.0 * vol / 63; 129 | } 130 | 131 | /** 132 | set loop on channel 133 | */ 134 | void setLoop(uint channel, uint start, uint end) 135 | { 136 | channel = channel % this.src.length; 137 | this.loopStart[channel] = start; 138 | this.loopEnd[channel] = end; 139 | } 140 | 141 | /** 142 | get samplerate on channel 143 | */ 144 | int getFreq(uint channel) 145 | { 146 | channel = channel % this.src.length; 147 | return cast(int)(this.rate[channel] * this.spec.freq); 148 | } 149 | 150 | /** 151 | get volume on channel 152 | */ 153 | ubyte getVolume(uint channel) 154 | { 155 | channel = channel % this.src.length; 156 | return cast(ubyte)(this.volume[channel] * 63); 157 | } 158 | 159 | /** 160 | get loop start on channel 161 | */ 162 | uint getLoopStart(uint channel) 163 | { 164 | channel = channel % this.src.length; 165 | return cast(uint)(this.loopStart[channel]); 166 | } 167 | 168 | /** 169 | get loop end on channel 170 | */ 171 | uint getLoopEnd(uint channel) 172 | { 173 | channel = channel % this.src.length; 174 | return cast(uint)(this.loopEnd[channel]); 175 | } 176 | 177 | /** 178 | reset all channels 179 | */ 180 | void clear() 181 | { 182 | for (uint i = 0; i < this.src.length; i++) 183 | { 184 | this.src[i] = null; 185 | this.head[i] = 0; 186 | this.loopStart[i] = 0; 187 | this.loopEnd[i] = 0; 188 | this.rate[i] = 0; 189 | this.volume[i] = 1; 190 | } 191 | } 192 | 193 | /** 194 | reset audio buffer 195 | */ 196 | void sync() 197 | { 198 | SDL_ClearQueuedAudio(this.dev); 199 | this.lastTick = 0; 200 | 201 | this.recgain *= 2; 202 | this.recmax /= 2; 203 | } 204 | 205 | /** 206 | */ 207 | byte[] record(int freq) 208 | { 209 | byte[] data; 210 | if (this.recdev && this.recspec.freq != freq) 211 | { 212 | SDL_CloseAudioDevice(this.recdev); 213 | this.recdev = 0; 214 | } 215 | if (!this.recdev) 216 | { 217 | this.recspec.freq = freq; 218 | this.recspec.format = AUDIO_F32SYS; 219 | this.recspec.channels = 1; 220 | this.recdev = SDL_OpenAudioDevice(this.recDevName 221 | ? toStringz(this.recDevName) : null, 1, this.recspec, this.recspec, 0); 222 | } 223 | SDL_PauseAudioDevice(this.recdev, 0); 224 | auto len = SDL_DequeueAudio(this.recdev, this.buffer, 225 | cast(uint)(this.buflen * this.spec.channels * float.sizeof)); 226 | len /= this.recspec.channels; 227 | len /= float.sizeof; 228 | data.length = len; 229 | for (uint i = 0; i < len; i++) 230 | { 231 | if (abs(this.buffer[i] * this.recgain) > 1) 232 | this.recgain = 1 / abs(this.buffer[i]); 233 | data[i] = cast(byte)(this.buffer[i] * this.recgain * 127); 234 | if (abs(this.buffer[i]) > this.recmax) 235 | this.recmax = abs(this.buffer[i] * this.recgain); 236 | if (abs(this.buffer[i]) > (this.recmax / 2)) 237 | this.recgain += 1.0 / 256; 238 | } 239 | this.lastRec = SDL_GetTicks() * (this.spec.freq / 1000); 240 | return data; 241 | } 242 | 243 | // --- _privates --- // 244 | private SDL_AudioSpec* spec = new SDL_AudioSpec(); 245 | private SDL_AudioSpec* recspec = new SDL_AudioSpec(); 246 | private SDL_AudioDeviceID dev; 247 | private SDL_AudioDeviceID recdev; 248 | private float recgain = 1; 249 | private float recmax = 0; 250 | private float* buffer; 251 | private uint buflen; 252 | private float[4] value; 253 | private long timeToSync = 10; 254 | private long timeToIdle = 10; 255 | private long lastRec = 10; 256 | 257 | private void initDevice() 258 | { 259 | this.spec.freq = 48_000; 260 | this.spec.format = AUDIO_F32SYS; 261 | this.spec.channels = 2; 262 | this.dev = SDL_OpenAudioDevice(null, 0, this.spec, this.spec, 263 | SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /system_drive/cmd/bg.lua: -------------------------------------------------------------------------------- 1 | function _init(args) 2 | if #args < 1 then 3 | print("Usage: bg [args...]") 4 | return sys.exit(1) 5 | end 6 | sys.exec(table.remove(args, 1), args, fs.cd()) 7 | end 8 | -------------------------------------------------------------------------------- /system_drive/cmd/copy.lua: -------------------------------------------------------------------------------- 1 | local path = require("path") 2 | local queue = {} 3 | local indent = "" 4 | 5 | function _init(args) 6 | if #args < 2 then 7 | print("Usage: copy ") 8 | return sys.exit(1) 9 | end 10 | local src = args[1] 11 | local dest = args[#args] 12 | if fs.isdir(dest) then 13 | dest = path.trailslash(dest) 14 | for i = 1, #args - 1 do 15 | local entry = args[i] 16 | if fs.isdir(entry) then 17 | if not copydir(entry, dest .. path.basename(entry)) then 18 | return sys.exit(1) 19 | end 20 | else 21 | if not copyfile(entry, dest .. path.basename(entry)) then 22 | return sys.exit(1) 23 | end 24 | end 25 | end 26 | elseif fs.isdir(src) then 27 | if not copydir(src, dest) then 28 | return sys.exit(1) 29 | end 30 | else 31 | if not copyfile(src, dest) then 32 | return sys.exit(1) 33 | end 34 | end 35 | sys.stepinterval(0) 36 | end 37 | 38 | function _step() 39 | if #queue == 0 then 40 | return sys.exit() 41 | end 42 | local task = table.remove(queue, 1) 43 | local src = task.src 44 | local dest = task.dest 45 | local indent = task.indent 46 | if fs.isdir(src) then 47 | if not fs.mkdir(dest) then 48 | print("Could not create dir '" .. dest .. "'!") 49 | return sys.exit(1) 50 | end 51 | print(indent .. src .. " -> " .. dest) 52 | else 53 | local data = fs.read(src) 54 | if not data then 55 | print("Could not read '" .. src .. "'!") 56 | return sys.exit(1) 57 | end 58 | if not fs.write(dest, data) then 59 | print("Could not write to '" .. dest .. "'!") 60 | return sys.exit(1) 61 | end 62 | print(indent .. path.basename(src) .. " copied!") 63 | end 64 | end 65 | 66 | function copyfile(src, dest) 67 | local task = { 68 | src = src, 69 | dest = dest, 70 | indent = indent 71 | } 72 | table.insert(queue, task) 73 | return true 74 | end 75 | 76 | function copydir(src, dest) 77 | src = path.trailslash(src) 78 | dest = path.trailslash(dest) 79 | local task = { 80 | src = src, 81 | dest = dest, 82 | indent = indent 83 | } 84 | table.insert(queue, task) 85 | indent = indent .. " " 86 | local entries = fs.list(src) 87 | for i, entry in pairs(entries) do 88 | if fs.isdir(src .. entry) then 89 | if not copydir(src .. entry, dest .. entry) then 90 | return false 91 | end 92 | else 93 | if not copyfile(src .. entry, dest .. entry) then 94 | return false 95 | end 96 | end 97 | end 98 | indent = task.indent 99 | return true 100 | end 101 | -------------------------------------------------------------------------------- /system_drive/cmd/date.lua: -------------------------------------------------------------------------------- 1 | wdays = {"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"} 2 | months = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"} 3 | 4 | function _init() 5 | h, m, s, off = sys.time() 6 | yr, mn, dt, wd = sys.date() 7 | print(string.format("%d-%s-%02d %s %d:%02d:%02d UTC%+gh", yr, months[mn], dt, wdays[wd + 1], h, m, s, off / 60)) 8 | end 9 | -------------------------------------------------------------------------------- /system_drive/cmd/delete.lua: -------------------------------------------------------------------------------- 1 | function _init(args) 2 | if #args < 1 then 3 | print("Usage: delete ") 4 | return sys.exit(1) 5 | end 6 | if not fs.delete(args[1]) then 7 | print("Could not delete '" .. args[1] .. "'!") 8 | return sys.exit(1) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /system_drive/cmd/dir.lua: -------------------------------------------------------------------------------- 1 | function _init(args) 2 | local line = "" 3 | list = fs.list(args[1]) 4 | if not list then 5 | print("Could not list '" .. (args[1] or fs.cd()) .. "'") 6 | return sys.exit(1) 7 | end 8 | table.sort(list) 9 | for i, entry in pairs(list) do 10 | if string.sub(entry, -1) == "/" then 11 | print(" " .. string.sub(entry, 0, -2) .. " (dir)") 12 | end 13 | end 14 | for i, entry in pairs(list) do 15 | if string.sub(entry, -1) ~= "/" then 16 | if line == "" then 17 | line = line .. " " .. entry 18 | else 19 | while #line < 35 do 20 | line = line .. " " 21 | end 22 | print(line .. entry) 23 | line = "" 24 | end 25 | if #line >= 35 then 26 | print(line) 27 | line = "" 28 | end 29 | end 30 | end 31 | if line ~= "" then 32 | print(line) 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /system_drive/cmd/drives.lua: -------------------------------------------------------------------------------- 1 | function _init() 2 | list = fs.drives() 3 | table.sort(list) 4 | print("Available drives:\n") 5 | for i, entry in pairs(list) do 6 | print(" " .. entry .. ":") 7 | end 8 | print("") 9 | end 10 | -------------------------------------------------------------------------------- /system_drive/cmd/echo.lua: -------------------------------------------------------------------------------- 1 | function _init(args) 2 | print(table.concat(args, " ")) 3 | end 4 | -------------------------------------------------------------------------------- /system_drive/cmd/edit.lua: -------------------------------------------------------------------------------- 1 | Screen, Menu, FileRequester = require("screen"), require("menu"), require("filerequester") 2 | 3 | filename = nil 4 | lasttxt = "" 5 | statustxt = "" 6 | statusto = 0 7 | 8 | function _init(args) 9 | scrn = Screen:new("Edit", 11, 2) 10 | menu = 11 | Menu:new( 12 | { 13 | { 14 | label = "File", 15 | menu = { 16 | {label = "Load..", hotkey = "l", action = reqload}, 17 | { 18 | label = "Save", 19 | hotkey = "s", 20 | action = function(self) 21 | save(filename) 22 | end 23 | }, 24 | {label = "Save as..", action = reqsave}, 25 | {label = "Quit", action = quit, hotkey = "q"} 26 | } 27 | } 28 | } 29 | ) 30 | scrn:attach("menu", menu) 31 | font = text.loadfont("Victoria.8b") 32 | scrn:palette(0, 0, 0, 0) 33 | scrn:palette(1, 13, 14, 15) 34 | scrn:palette(2, 0, 3, 8) 35 | scrn:palette(3, 0, 10, 15) 36 | gfx.bgcolor(0) 37 | gfx.fgcolor(1) 38 | input.linesperpage(20) 39 | load(args[1] or "user:new.txt") 40 | end 41 | 42 | function _step(t) 43 | local txt = input.text() 44 | local change = txt ~= lasttxt 45 | local deltalen = #txt - #lasttxt 46 | local pos, sel = input.cursor() 47 | local lines = getlines(txt) 48 | local gutter = "" 49 | local gutterw = 0 50 | line, col = txtpos(txt, pos) 51 | local top = 86 - 8 * line 52 | local left = 500 - 8 * col 53 | if top > 0 then 54 | top = 0 55 | end 56 | if left > 0 then 57 | left = 0 58 | end 59 | if deltalen > 0 then 60 | if string.sub(txt, pos - 1, pos) == "\n\t" or string.sub(txt, pos - 2, pos) == " \t" then 61 | pos = pos - 1 62 | sel = 1 63 | input.cursor(pos, sel) 64 | input.selected(" ") 65 | txt = input.text() 66 | end 67 | pos, sel = input.cursor() 68 | end 69 | if change then 70 | if txt == savedtxt then 71 | scrn:title(filename) 72 | else 73 | scrn:title(filename .. " *") 74 | end 75 | end 76 | lasttxt = txt 77 | 78 | gutterw = string.len("" .. #lines) 79 | for i = 1, #lines do 80 | gutter = gutter .. string.format("%0" .. gutterw .. "d", i) .. "\n" 81 | end 82 | gfx.cls() 83 | gutterw = text.draw(gutter, font, 0, top) + 8 84 | gfx.fgcolor(1) 85 | text.draw(txt, font, gutterw + left, top) 86 | gfx.fgcolor(3) 87 | text.draw(string.sub(txt, 0, pos) .. "\x7f", font, gutterw + left, top) 88 | text.draw(string.sub(txt, 0, pos + sel), font, gutterw + left, top) 89 | if sel == 0 then 90 | gfx.fgcolor(2) 91 | else 92 | gfx.fgcolor(1) 93 | end 94 | text.draw(string.sub(txt, 0, pos + 1), font, gutterw + left, top) 95 | gfx.fgcolor(1) 96 | text.draw(string.sub(txt, 0, pos), font, gutterw + left, top) 97 | gfx.fgcolor(0) 98 | gfx.bar(0, 0, gutterw, 1024) 99 | gfx.fgcolor(3) 100 | text.draw(gutter, font, 0, top) 101 | scrn:step() 102 | end 103 | 104 | function _shutdown() 105 | if input.text() ~= savedtxt then 106 | print("exiting without saving!") 107 | end 108 | end 109 | 110 | function quit() 111 | sys.exit() 112 | end 113 | 114 | function reqload() 115 | if scrn.children["req"] then 116 | return 117 | end 118 | local req = FileRequester:new("Load..", {""}, filename .. "/../") 119 | req.ondone = function(self, filename) 120 | if filename then 121 | load(filename) 122 | end 123 | end 124 | scrn:attachwindow("req", req) 125 | end 126 | function load(_filename) 127 | filename = _filename 128 | savedtxt = fs.read(filename) 129 | lasttxt = savedtxt or "" 130 | view.active(scrn.mainvp) 131 | input.text(lasttxt) 132 | input.clearhistory() 133 | input.cursor(0) 134 | scrn:title(filename) 135 | end 136 | function reqsave() 137 | if scrn.children["req"] then 138 | return 139 | end 140 | local req = FileRequester:new("Save as..", {""}, filename) 141 | req.ondone = function(self, filename) 142 | if filename then 143 | save(filename) 144 | end 145 | end 146 | scrn:attachwindow("req", req) 147 | end 148 | function save(_filename) 149 | filename = _filename 150 | if fs.write(filename, input.text()) then 151 | setstatus("saved!") 152 | savedtxt = input.text() 153 | else 154 | setstatus("could not save!") 155 | end 156 | lasttxt = savedtxt or "" 157 | end 158 | 159 | function txtpos(txt, pos) 160 | local line = 1 161 | local col = 0 162 | for i = 0, pos do 163 | col = col + 1 164 | if string.sub(txt, i, i) == "\n" then 165 | line = line + 1 166 | col = 0 167 | end 168 | end 169 | return line, col 170 | end 171 | 172 | function getlines(txt) 173 | local lines = {} 174 | local line = "" 175 | for i = 1, #txt do 176 | if string.sub(txt, i, i) == "\n" then 177 | table.insert(lines, line) 178 | line = "" 179 | else 180 | line = line .. string.sub(txt, i, i) 181 | end 182 | end 183 | table.insert(lines, line) 184 | return lines 185 | end 186 | 187 | function getindent(line) 188 | local indent = "" 189 | for i = 1, #line do 190 | if string.sub(line, i, i) == " " then 191 | indent = indent .. string.sub(line, i, i) 192 | else 193 | break 194 | end 195 | end 196 | return indent 197 | end 198 | 199 | function setstatus(txt) 200 | scrn:title(filename .. " - " .. txt) 201 | end 202 | -------------------------------------------------------------------------------- /system_drive/cmd/env.lua: -------------------------------------------------------------------------------- 1 | function _init(args) 2 | if #args >= 2 then 3 | sys.env(args[1], args[2]) 4 | end 5 | if #args >= 1 then 6 | if sys.env(args[1]) then 7 | print(args[1] .. " = " .. sys.env(args[1])) 8 | else 9 | print(args[1] .. " has no value!") 10 | end 11 | else 12 | list = sys.listenv() 13 | table.sort(list) 14 | for i, entry in pairs(list) do 15 | print(entry .. " = " .. sys.env(entry)) 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /system_drive/cmd/fileinfo.lua: -------------------------------------------------------------------------------- 1 | wdays = {"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"} 2 | months = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"} 3 | function _init(args) 4 | if #args < 1 then 5 | print("Usage: fileinfo ") 6 | return sys.exit(1) 7 | end 8 | print("Filename: " .. args[1]) 9 | size = fs.size(args[1]) 10 | print("Size: " .. size .. " bytes") 11 | th, tm, ts, tu = fs.time(args[1]) 12 | dy, dm, dd, dw = fs.date(args[1]) 13 | print( 14 | string.format( 15 | "Modified: %d-%s-%02d %s %d:%02d:%02d UTC%+gh", 16 | dy, 17 | months[dm], 18 | dd, 19 | wdays[dw + 1], 20 | th, 21 | tm, 22 | ts, 23 | tu / 60 24 | ) 25 | ) 26 | end 27 | -------------------------------------------------------------------------------- /system_drive/cmd/makedir.lua: -------------------------------------------------------------------------------- 1 | function _init(args) 2 | if #args < 1 then 3 | print("Usage: makedir ") 4 | return sys.exit(1) 5 | end 6 | if not fs.mkdir(args[1]) then 7 | print("Could not make directory '" .. args[1] .. "'!") 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /system_drive/cmd/mem.lua: -------------------------------------------------------------------------------- 1 | function _init() 2 | print("Memory used: " .. friendly(sys.memoryusage())) 3 | end 4 | 5 | function friendly(bytes) 6 | local units = bytes 7 | local measures = {"YiB", "ZiB", "EiB", "PiB", "TiB", "GiB", "MiB", "KiB"} 8 | local measure = "bytes" 9 | while units >= 1024 do 10 | units = units / 1024 11 | measure = table.remove(measures) 12 | end 13 | return string.format("%4.3f", units) .. " " .. measure 14 | end 15 | -------------------------------------------------------------------------------- /system_drive/cmd/more.lua: -------------------------------------------------------------------------------- 1 | function _init(args) 2 | if #args < 1 then 3 | print("Usage: more ") 4 | return sys.exit(1) 5 | end 6 | txt = fs.read(args[1]) 7 | if txt == nil then 8 | print("Couldn't type file " .. args[1]) 9 | return sys.exit(1) 10 | end 11 | pos = 0 12 | print("(press enter to scroll down)") 13 | end 14 | 15 | function _step() 16 | local inp = sys.read() 17 | if inp ~= "\n" then 18 | return 19 | end 20 | local char = "" 21 | while char ~= "\n" and pos < #txt do 22 | sys.write(char) 23 | pos = pos + 1 24 | char = string.sub(txt, pos, pos) 25 | end 26 | if pos >= #txt then 27 | sys.exit() 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /system_drive/cmd/mount.lua: -------------------------------------------------------------------------------- 1 | function _init(args) 2 | if #args < 2 then 3 | print("Usage: mount ") 4 | return sys.exit(1) 5 | end 6 | if not fs.mount(args[1], args[2]) then 7 | print("Could not mount '" .. args[1] .. "' drive") 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /system_drive/cmd/perm.lua: -------------------------------------------------------------------------------- 1 | local SYMS = { 2 | "mpm", 3 | "mld", 4 | "mrd", 5 | "uod", 6 | "mms", 7 | "mop", 8 | "rod", 9 | "wod", 10 | "rev", 11 | "wev", 12 | "rec" 13 | } 14 | local PERM = { 15 | mpm = 1, 16 | mld = 2, 17 | mrd = 4, 18 | uod = 8, 19 | mms = 16, 20 | mop = 32, 21 | rod = 256, 22 | wod = 512, 23 | rev = 1024, 24 | wev = 2048, 25 | rec = 4096 26 | } 27 | local PERMDESC = { 28 | mpm = "Manage permissions", 29 | mld = "Mount local drives", 30 | mrd = "Mount remote drives", 31 | uod = "Unmount other drives", 32 | mms = "Manage main screen", 33 | mop = "Manage other programs", 34 | rod = "Read other drives", 35 | wod = "Write to other drives", 36 | rev = "Read environment variables", 37 | wev = "Set environment variables", 38 | rec = "Record audio" 39 | } 40 | 41 | function _init(args) 42 | if #args < 1 then 43 | print("Usage: perm ") 44 | return sys.exit(1) 45 | end 46 | local perms = sys.permissions(args[1]) 47 | for i = 2, #args do 48 | if tonumber(args[i]) then 49 | perms = args[i] 50 | elseif PERM[string.lower(args[i])] then 51 | perms = perms ~ PERM[string.lower(args[i])] 52 | end 53 | end 54 | if #args > 1 then 55 | perms = sys.permissions(args[1], perms) 56 | end 57 | if perms then 58 | print("Permissions for programs on " .. string.upper(args[1]) .. " drive\n") 59 | for i, sym in pairs(SYMS) do 60 | print(sym .. " = " .. ((perms & PERM[string.lower(sym)] > 0) and "true " or "false ") .. "-- " .. PERMDESC[sym]) 61 | end 62 | print("\nPermission sum: " .. perms) 63 | else 64 | print("Could not access permissions of " .. string.upper(args[1]) .. " drive") 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /system_drive/cmd/play.lua: -------------------------------------------------------------------------------- 1 | Screen = require("screen") 2 | 3 | function _init(args) 4 | if #args < 1 then 5 | print("Usage: play ") 6 | return sys.exit(1) 7 | end 8 | snd = audio.load(args[1]) 9 | if snd == nil then 10 | print("Couldn't play file " .. args[1]) 11 | return sys.exit(1) 12 | end 13 | scrn = Screen:new(args[1], 15, 4) 14 | sndlen = audio.samplelength(snd) 15 | lasthead = 0 16 | audio.play(0, snd) 17 | audio.play(3, snd) 18 | print("Playing " .. args[1] .. " at " .. audio.samplefreq(snd) .. " Hz") 19 | sys.stepinterval(1000 / 60) 20 | for c = 1, 7 do 21 | scrn:palette(c, 15, c * 2, 0) 22 | end 23 | for c = 0, 7 do 24 | scrn:palette(c + 8, 15, 15, c * 2) 25 | end 26 | scrnw, scrnh = scrn:size() 27 | end 28 | 29 | function _step() 30 | local head = audio.channelhead(0) 31 | local speed = head - lasthead 32 | local stp = scrnw / speed 33 | local x = scrnw 34 | local h = head 35 | if h >= sndlen then 36 | h = sndlen - 1 37 | end 38 | lineto(scrnw, scrnh / 2) 39 | gfx.cls() 40 | while x >= 0 and h >= 0 do 41 | lineto(x, scrnh / 2 + audio.samplevalue(snd, h)) 42 | gfx.fgcolor(1 + math.abs(audio.samplevalue(snd, h)) / 9) 43 | x = x - stp 44 | h = h - 1 45 | end 46 | if audio.channelfreq(0) == 0 then 47 | sys.exit(0) 48 | end 49 | lasthead = head 50 | if input.hotkey() == "q" then 51 | sys.exit(0) 52 | end 53 | scrn:step() 54 | end 55 | 56 | function lineto(x, y) 57 | gfx.line(ltx, lty, x, y) 58 | ltx = x 59 | lty = y 60 | end 61 | -------------------------------------------------------------------------------- /system_drive/cmd/record.lua: -------------------------------------------------------------------------------- 1 | function _init(args) 2 | sys.stepinterval(0) 3 | snd = audio.new() 4 | filename = args[1] 5 | if not filename then 6 | print("No filename was given!") 7 | end 8 | print("(press enter to stop recording)") 9 | end 10 | 11 | function _step() 12 | audio.record(snd) 13 | local inp = sys.read() 14 | if inp == "\n" then 15 | if audio.save(filename, snd) then 16 | print("Recording saved to " .. filename) 17 | else 18 | print("Could not save recording to " .. filename) 19 | end 20 | sys.exit() 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /system_drive/cmd/reimage.lua: -------------------------------------------------------------------------------- 1 | function _init(args) 2 | if #args < 1 then 3 | print("Usage: reimage ") 4 | return sys.exit(1) 5 | end 6 | anim = image.load(args[1]) 7 | if anim == nil then 8 | print("Couldn't load file " .. args[1]) 9 | return sys.exit(1) 10 | end 11 | scrn = view.newscreen(0, 8) 12 | w, h = image.size(anim[1]) 13 | view.new(scrn, 0, 0, w, h) 14 | bpp = minbpp(anim) 15 | for i = 1, #anim do 16 | gfx.cls() 17 | image.usepalette(anim[i]) 18 | image.draw(anim[i], 0, 0, 0, 0, w, h) 19 | image.forget(anim[i]) 20 | anim[i] = image.new(w, h, bpp) 21 | image.copypalette(anim[i]) 22 | image.copy(anim[i], 0, 0, 0, 0, w, h) 23 | end 24 | image.save(args[#args], anim) 25 | end 26 | 27 | function minbpp(anim) 28 | local colors, c, bpp = 0, 0, 1 29 | local w, h = image.size(anim[1]) 30 | for i = 1, #anim do 31 | gfx.cls() 32 | image.draw(anim[i], 0, 0, 0, 0, image.size(anim[i])) 33 | for y = 1, h do 34 | for x = 1, w do 35 | c = gfx.pixel(x - 1, y - 1) 36 | if c > colors then 37 | colors = c 38 | end 39 | end 40 | end 41 | end 42 | colors = colors + 1 43 | while math.pow(2, bpp) < colors do 44 | bpp = bpp + 1 45 | end 46 | return bpp 47 | end 48 | -------------------------------------------------------------------------------- /system_drive/cmd/rename.lua: -------------------------------------------------------------------------------- 1 | function _init(args) 2 | if #args < 1 then 3 | print("Usage: rename ") 4 | return sys.exit(1) 5 | end 6 | if not fs.rename(args[1], args[2]) then 7 | print("Could not rename '" .. args[1] .. "'!") 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /system_drive/cmd/resample.lua: -------------------------------------------------------------------------------- 1 | function _init(args) 2 | if #args < 1 then 3 | print("Usage: resample ") 4 | return sys.exit(1) 5 | end 6 | snd = audio.load(args[1]) 7 | if snd == nil then 8 | print("Couldn't load file " .. args[1]) 9 | return sys.exit(1) 10 | end 11 | audio.save(args[#args], snd) 12 | end 13 | -------------------------------------------------------------------------------- /system_drive/cmd/sfont2gif.lua: -------------------------------------------------------------------------------- 1 | local sheet, sheetw, sheeth, font, x, dot, bg, maxw, wsum, dest, bpp, bw 2 | 3 | function _init(args) 4 | dest = args[2] 5 | sheet = image.load(args[1])[1] 6 | sheetw, sheeth = image.size(sheet) 7 | dest = string.gsub(dest, "%.gif", "." .. (sheeth - 1) .. "c.gif") 8 | font = {} 9 | x = 0 10 | maxw = 0 11 | wsum = 0 12 | view.newscreen(15, 8) 13 | image.usepalette(sheet) 14 | image.draw(sheet, 0, 4, 0, 0, sheetw, sheeth) 15 | image.draw(sheet, 0, 0, 0, 0, sheetw, sheeth) 16 | dot = gfx.pixel(0, 0) 17 | bg = gfx.pixel(1, 0) 18 | gfx.fgcolor(dot) 19 | gfx.bgcolor(bg) 20 | sys.stepinterval(16) 21 | 22 | local maxc, c, uni = 0, 0, {} 23 | for y = 1, (sheeth - 1) do 24 | for x = 1, 79 do 25 | c = gfx.pixel(x, y) 26 | if c > maxc then 27 | maxc = c 28 | end 29 | if not contains(uni, c) then 30 | table.insert(uni, c) 31 | end 32 | end 33 | end 34 | bpp = 0 35 | while maxc > 0 do 36 | maxc = math.floor(maxc / 2) 37 | bpp = bpp + 1 38 | end 39 | if #uni <= 2 then 40 | gobw(8) 41 | bw = true 42 | bpp = 1 43 | dest = string.gsub(dest, "c%.gif", ".gif") 44 | end 45 | -- fs.delete(dest .. ".txt", args[1] .. "\t" .. bpp .. "\n") 46 | -- bpp = 4 47 | end 48 | 49 | function _step() 50 | if x >= sheetw then 51 | return sys.exit() 52 | end 53 | gfx.cls() 54 | gfx.bar(0, 0, 640, 1) 55 | image.draw(sheet, -x, 0, 0, 0, sheetw, sheeth) 56 | if gfx.pixel(0, 0) == dot then 57 | local w = 1 58 | while gfx.pixel(w + 1, 0) ~= dot do 59 | w = w + 1 60 | if w > 80 then 61 | return sys.exit() 62 | end 63 | end 64 | if w > maxw then 65 | maxw = w 66 | end 67 | wsum = wsum + w 68 | if bw then 69 | gobw(w) 70 | end 71 | local char = image.new(w, sheeth - 1, bpp) 72 | image.copy(char, 1, 1, 0, 0, w, sheeth - 1) 73 | image.copypalette(char) 74 | image.duration(char, w * 10) 75 | table.insert(font, char) 76 | end 77 | x = x + 1 78 | end 79 | 80 | function _shutdown(code) 81 | if code == 0 then 82 | gfx.cls() 83 | if bw then 84 | bg = 0 85 | gfx.fgcolor(1) 86 | end 87 | local char = image.new(maxw, sheeth - 1, bpp) 88 | image.copy(char, 1, 1, 0, 0, maxw, sheeth - 1) 89 | image.copypalette(char) 90 | image.duration(char, (wsum / #font) * 10) 91 | table.insert(font, 1, char) 92 | 93 | char = image.new(maxw, sheeth - 1, bpp) 94 | image.copy(char, 1, 1, 0, 0, maxw, sheeth - 1) 95 | image.copypalette(char) 96 | image.duration(char, 0) 97 | 98 | while #font < 97 do 99 | table.insert(font, char) 100 | end 101 | 102 | for n = 34, 59 do 103 | if font[91] == char then 104 | font[n + 32] = font[n] 105 | end 106 | end 107 | 108 | gfx.line(1, 1, maxw, 1) 109 | gfx.line(1, 1, maxw, sheeth - 1) 110 | gfx.line(1, 1, 1, sheeth - 1) 111 | gfx.line(1, sheeth - 1, maxw, sheeth - 1) 112 | gfx.line(maxw, 1, maxw, sheeth - 1) 113 | gfx.line(maxw, 1, 1, sheeth - 1) 114 | char = image.new(maxw, sheeth - 1, bpp) 115 | image.copy(char, 1, 1, 0, 0, maxw, sheeth - 1) 116 | image.copypalette(char) 117 | image.duration(char, maxw * 10) 118 | font[97] = char 119 | 120 | gfx.bar(0, 0, maxw, sheeth) 121 | char = image.new(maxw, sheeth - 1, bpp) 122 | image.copy(char, 1, 1, 0, 0, maxw, sheeth - 1) 123 | image.copypalette(char) 124 | image.duration(char, maxw * 10) 125 | font[96] = char 126 | 127 | image.save(dest, font) 128 | end 129 | end 130 | 131 | function contains(tab, srch) 132 | for i, item in pairs(tab) do 133 | if item == srch then 134 | return true 135 | end 136 | end 137 | return false 138 | end 139 | 140 | function gobw(w) 141 | local c 142 | gfx.bgcolor(0) 143 | gfx.palette(0, 0, 0, 0) 144 | gfx.palette(1, 15, 15, 15) 145 | for y = 1, sheeth do 146 | for x = 0, w do 147 | c = gfx.pixel(x, y) 148 | if c == bg then 149 | gfx.pixel(x, y, 0) 150 | else 151 | gfx.pixel(x, y, 1) 152 | end 153 | end 154 | end 155 | end 156 | -------------------------------------------------------------------------------- /system_drive/cmd/shell.lua: -------------------------------------------------------------------------------- 1 | Screen = require("screen") 2 | 3 | fontsize = 8 4 | fontw = 8 5 | termline = "" 6 | termbottom = fontsize 7 | state = 1 8 | task = nil 9 | history = {} 10 | histpos = #history 11 | 12 | function _init() 13 | scrn = Screen:new((sys.env("ENGINE") or "System") .. " Shell", 11, 2) 14 | scrnw, scrnh = view.size(scrn.mainvp) 15 | spare = image.new(scrnw, scrnh, 4) 16 | font = text.loadfont("Victoria.8b") 17 | 18 | scrn:palette(0, 0, 5, 10) 19 | scrn:palette(1, 15, 15, 15) 20 | scrn:palette(2, 0, 0, 2) 21 | scrn:palette(3, 15, 8, 0) 22 | 23 | -- out("Homegirl Shell\n") 24 | if sys.env("ENGINE_VERSION") then 25 | out("System version " .. sys.env("ENGINE_VERSION") .. "\n\n") 26 | out("Thank you for trying out the free version of Homegirl! :-)\n") 27 | out("You can get the full version on\n\t\t\t\tpoeticandroid.itch.io/homegirl\n\n") 28 | end 29 | end 30 | 31 | function _step() 32 | local inp = input.text() 33 | if string.find(inp, "\t") ~= nil then 34 | input.text(tabcomplete(inp, fs.list())) 35 | end 36 | if string.find(inp, "\n") ~= nil then 37 | submit(string.gsub(inp, "\n", "")) 38 | end 39 | if state == 0 then 40 | local btn = input.gamepad() 41 | if lastinp == inp and lastbtn == 0 and btn > 0 then 42 | if btn & 4 > 0 then 43 | histpos = histpos - 1 44 | if histpos < 1 then 45 | histpos = 1 46 | end 47 | input.text(history[histpos]) 48 | end 49 | if btn & 8 > 0 then 50 | histpos = histpos + 1 51 | if histpos > #history then 52 | histpos = #history + 1 53 | input.text("") 54 | end 55 | input.text(history[histpos]) 56 | end 57 | end 58 | lastbtn = btn 59 | out("") 60 | elseif state == 1 then 61 | if task == nil then 62 | out(fs.cd() .. "> ") 63 | state = 0 64 | else 65 | out(sys.readfromchild(task)) 66 | out(sys.errorfromchild(task)) 67 | if sys.childrunning(task) then 68 | if (input.hotkey() == "c") then 69 | sys.killchild(task) 70 | end 71 | else 72 | sys.forgetchild(task) 73 | task = nil 74 | end 75 | end 76 | end 77 | lastinp = inp 78 | scrn:step() 79 | end 80 | 81 | function _shutdown() 82 | print("terminal terminated!") 83 | end 84 | 85 | function submit(line) 86 | local cmd = "" 87 | local args = parsecmd(line) 88 | out(line .. "\n") 89 | input.text("") 90 | input.clearhistory() 91 | if state == 0 then 92 | cmd = table.remove(args, 1) 93 | if cmd then 94 | if searchhistory(line) then 95 | table.remove(history, searchhistory(line)) 96 | end 97 | table.insert(history, line) 98 | end 99 | histpos = #history + 1 100 | 101 | if (cmd == "endcli") then 102 | sys.exit(0) 103 | elseif (cmd == "cd") then 104 | if not fs.cd(args[1]) then 105 | out("Unable to change directory to " .. args[1] .. "\n") 106 | end 107 | elseif (cmd == "clear") then 108 | gfx.cls() 109 | termbottom = 0 110 | out("\n") 111 | elseif (cmd == "help") then 112 | out("Builtin commands: cd, clear, endcli, help\n\nsys:cmd/\n") 113 | task = sys.startchild(_DRIVE .. "cmd/dir.lua", {_DRIVE .. "cmd/"}) 114 | elseif cmd and cmd ~= "" then 115 | if task == nil then 116 | task = sys.startchild(cmd, args) 117 | end 118 | if task == nil then 119 | task = sys.startchild(cmd .. ".lua", args) 120 | end 121 | if task == nil then 122 | task = sys.startchild("user:cmd/" .. cmd, args) 123 | end 124 | if task == nil then 125 | task = sys.startchild("user:cmd/" .. cmd .. ".lua", args) 126 | end 127 | if task == nil then 128 | task = sys.startchild("sys:cmd/" .. cmd, args) 129 | end 130 | if task == nil then 131 | task = sys.startchild("sys:cmd/" .. cmd .. ".lua", args) 132 | end 133 | if task == nil then 134 | out("Unknown command " .. cmd .. "\n") 135 | end 136 | end 137 | state = 1 138 | elseif state == 1 then 139 | if task ~= nil then 140 | sys.writetochild(task, line .. "\n") 141 | end 142 | end 143 | end 144 | 145 | function out(data) 146 | local w, h 147 | local txt = input.text() 148 | local pos, sel = input.cursor() 149 | termline = termline .. wrap(data, scrnw / fontw) 150 | gfx.fgcolor(0) 151 | gfx.bar(0, termbottom - fontsize, scrnw, scrnh) 152 | gfx.fgcolor(1) 153 | -- repeat 154 | w, h = text.draw(termline, font, 0, termbottom - fontsize) 155 | h = termbottom - fontsize + h 156 | if h > scrnh then 157 | scroll(h - scrnh) 158 | text.draw(termline, font, 0, termbottom - fontsize) 159 | end 160 | while string.find(termline, "\n") ~= nil do 161 | termline = string.sub(termline, string.find(termline, "\n") + 1) 162 | termbottom = termbottom + fontsize 163 | end 164 | if state == 1 then 165 | sys.stepinterval(64) 166 | else 167 | sys.stepinterval(-1) 168 | end 169 | -- until string.find(termline, "\n") == nil 170 | text.draw(txt, font, w, termbottom - fontsize) 171 | gfx.fgcolor(3) 172 | text.draw(string.sub(txt, 0, pos) .. "\x7f", font, w, termbottom - fontsize) 173 | text.draw(string.sub(txt, 0, pos + sel), font, w, termbottom - fontsize) 174 | if sel == 0 then 175 | gfx.fgcolor(2) 176 | else 177 | gfx.fgcolor(1) 178 | end 179 | text.draw(string.sub(txt, 0, pos + 1), font, w, termbottom - fontsize) 180 | gfx.fgcolor(1) 181 | text.draw(string.sub(txt, 0, pos), font, w, termbottom - fontsize) 182 | end 183 | 184 | function scroll(amount) 185 | image.copy(spare, 0, 0, 0, 0, scrnw, scrnh) 186 | gfx.cls() 187 | image.draw(spare, 0, -amount, 0, 0, scrnw, scrnh) 188 | termbottom = termbottom - amount 189 | end 190 | 191 | function wrap(txt, width) 192 | local col = 0 193 | local out = "" 194 | for i = 1, #txt do 195 | out = out .. string.sub(txt, i, i) 196 | col = col + 1 197 | if string.sub(txt, i, i) == "\n" then 198 | col = 0 199 | end 200 | if col == width then 201 | out = out .. "\n" 202 | col = 0 203 | end 204 | end 205 | return out 206 | end 207 | 208 | function parsecmd(line) 209 | local args = {} 210 | local arg = nil 211 | local term = " " 212 | local esc = false 213 | for i = 1, #line do 214 | local char = string.sub(line, i, i) 215 | if esc then 216 | arg = arg .. char 217 | esc = false 218 | elseif char == term then 219 | if arg ~= nil then 220 | table.insert(args, arg) 221 | arg = nil 222 | term = " " 223 | end 224 | elseif term == " " and (char == '"' or char == "'") then 225 | term = char 226 | arg = arg or "" 227 | else 228 | arg = arg or "" 229 | if char == "\\" then 230 | esc = true 231 | else 232 | arg = arg .. char 233 | end 234 | end 235 | end 236 | if arg ~= nil then 237 | table.insert(args, arg) 238 | end 239 | return args 240 | end 241 | 242 | function searchhistory(line) 243 | for i = 1, #history do 244 | if history[i] == line then 245 | return i 246 | end 247 | end 248 | return nil 249 | end 250 | 251 | function tabcomplete(line, options) 252 | if not options then 253 | return line 254 | end 255 | local tabpos = string.find(line, "\t") 256 | if not tabpos then 257 | return line 258 | end 259 | local rest = string.sub(line, tabpos + 1) 260 | local args = parsecmd(string.sub(line, 1, tabpos - 1)) 261 | local arg = table.remove(args) 262 | if not arg then 263 | return line 264 | end 265 | for i = 1, #options do 266 | local opt = options[i] 267 | if string.lower(string.sub(opt, 1, #arg)) == string.lower(arg) then 268 | arg = opt 269 | end 270 | end 271 | table.insert(args, arg) 272 | line = "" 273 | for i = 1, #args do 274 | arg = args[i] 275 | line = line .. string.gsub(arg, " ", "\\ ") .. " " 276 | end 277 | line = line .. rest 278 | return line 279 | end 280 | -------------------------------------------------------------------------------- /system_drive/cmd/show.lua: -------------------------------------------------------------------------------- 1 | Screen = require("screen") 2 | 3 | function _init(args) 4 | if #args < 1 then 5 | print("Usage: show ") 6 | return sys.exit(1) 7 | end 8 | mode = 0 9 | anim = image.load(args[1]) 10 | if anim == nil then 11 | print("Couldn't show file " .. args[1]) 12 | return sys.exit(1) 13 | end 14 | scrn = Screen:new(args[1], mode, 8) 15 | view.visible(scrn.mainvp, false) 16 | view.active(scrn.rootvp) 17 | width, height = image.size(anim[1]) 18 | print(args[1] .. ": " .. width .. " x " .. height .. " pixels") 19 | scrnw, scrnh = view.size(scrn.rootvp) 20 | if width > height then 21 | while width > scrnw do 22 | mode = mode + 5 23 | scrnw = scrnw * 2 24 | scrnh = scrnh * 2 25 | end 26 | else 27 | while height > scrnh do 28 | mode = mode + 5 29 | scrnw = scrnw * 2 30 | scrnh = scrnh * 2 31 | end 32 | end 33 | if mode > 15 then 34 | mode = 15 35 | end 36 | zoom(0) 37 | f = 0 38 | _lastbtn = 255 39 | end 40 | 41 | function _step(t) 42 | local mx, my, mbtn = input.mouse() 43 | local btn = input.gamepad() 44 | gfx.cls() 45 | f = f + 1 46 | if f > #anim then 47 | f = 1 48 | end 49 | if mbtn == 1 then 50 | x = mx + rx 51 | y = my + ry 52 | else 53 | rx = x - mx 54 | ry = y - my 55 | view.visible(scrn.titlevp, my <= 10) 56 | end 57 | if btn & 1 > 0 then 58 | x = x - 1 59 | end 60 | if btn & 2 > 0 then 61 | x = x + 1 62 | end 63 | if btn & 4 > 0 then 64 | y = y + 1 65 | end 66 | if btn & 8 > 0 then 67 | y = y - 1 68 | end 69 | if _lastbtn == 0 and btn & 16 > 0 then -- A 70 | zoom(-32) 71 | end 72 | if _lastbtn == 0 and btn & 32 > 0 then -- B 73 | zoom(5) 74 | end 75 | if _lastbtn == 0 and btn & 64 > 0 then -- X 76 | zoom(1) 77 | end 78 | if _lastbtn == 0 and btn & 128 > 0 then -- Y 79 | zoom(4) 80 | end 81 | _lastbtn = btn 82 | scrn:usepalette(anim[f]) 83 | gfx.bgcolor(0) 84 | scrn:autocolor() 85 | image.draw(anim[f], x, y, 0, 0, width, height) 86 | if input.hotkey() == "q" then 87 | sys.exit(0) 88 | end 89 | scrn:step() 90 | sys.stepinterval(image.duration(anim[f])) 91 | end 92 | 93 | function zoom(amount) 94 | mode = mode + amount 95 | if mode < 0 then 96 | mode = 0 97 | end 98 | while mode >= 32 do 99 | mode = mode - 32 100 | end 101 | scrn:mode(mode, 8) 102 | scrnw, scrnh = view.size(scrn.rootvp) 103 | x = scrnw / 2 - width / 2 104 | y = scrnh / 2 - height / 2 105 | end 106 | -------------------------------------------------------------------------------- /system_drive/cmd/type.lua: -------------------------------------------------------------------------------- 1 | function _init(args) 2 | if #args < 1 then 3 | print("Usage: type ") 4 | return sys.exit(1) 5 | end 6 | txt = fs.read(args[1]) 7 | if txt == nil then 8 | print("Couldn't type file " .. args[1]) 9 | return sys.exit(1) 10 | end 11 | print(txt) 12 | end 13 | -------------------------------------------------------------------------------- /system_drive/cmd/unmount.lua: -------------------------------------------------------------------------------- 1 | function _init(args) 2 | if #args < 2 then 3 | print("Usage: unmount [force]") 4 | return sys.exit(1) 5 | end 6 | if not fs.unmount(args[1], args[2] == "force") then 7 | print("Could not unmount '" .. args[1] .. "' drive") 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /system_drive/docs/console.md: -------------------------------------------------------------------------------- 1 | Using the Homegirl console 2 | ========================== 3 | To use Homegirl, download and extract the zip file. If you're on Windows, run `homegirl_windows.exe`, else run `homegirl.sh`. 4 | 5 | Keyboard hotkeys 6 | ---------------- 7 | Key | Action 8 | ----|--------- 9 | Ctrl+F4 | Kill the program of the front-most screen (unless it's the main screen). 10 | F7 | Auto-resize and center window 11 | F8 | Sync audio buffer 12 | F9 | Toggle CRT filter 13 | F11 | Toggle Fullscreen 14 | F12 | Open config folder 15 | 16 | Configuration 17 | ------------- 18 | Homegirl is configured with a config file, discovered in the following order: 19 | 20 | 1. specified as a command line argument. (filename has to end with `.json`) 21 | 2. `homegirl.json` in the current working directory. 22 | 3. `%APPDATA%\Homegirl\config.json` if on Windows. 23 | 4. `~/.config/Homegirl/config.json` or `config.json` in the current working directory if no home directory can be found. 24 | 25 | If a config file can't be found, a default file will be created. 26 | 27 | -------------------------------------------------------------------------------- /system_drive/docs/core/audio.md: -------------------------------------------------------------------------------- 1 | `audio` module 2 | ============== 3 | The audio system of Homegirl consists of 4 digital 8-bit channels (numbered 0 to 3) evenly spread between left and right speaker. 4 | 5 | L[0...1...2...3]R 6 | 7 | Each channel can play up to one sample at a time. Playback frequency (sample values per second), volume and loop markers can be altered during playback for each channel independently. Maximum playbackrate is 32000. 8 | 9 | Creating and managing audio samples 10 | ----------------------------------- 11 | **`audio.new(): sampl`** 12 | Create a new empty audio sample and return it. 13 | 14 | **`audio.load(filename): sampl`** 15 | Load audio sample from `.wav` file and return it. The audio will automatically be converted to 8-bit mono and the samplerate halfed until it is 32 kHz or less. 16 | 17 | **`audio.save(filename, sampl): success`** 18 | Save audio sample to `.wav` file and return `true` on success. 19 | 20 | **`audio.forget(sampl)`** 21 | Erase given audio sample from memory. 22 | 23 | Playing audio samples 24 | --------------------- 25 | **`audio.play(channel, sampl)`** 26 | Play audio sample on given channel. Channel playback frequency and loop markers will automatically be set according to the given sample. The channel volume will be set to maximum. 27 | 28 | **`audio.channelfreq(channel[, freq]): freq`** 29 | Get/set the playback frequency of the given channel. Any frequency above 32 kHz will be halfed until it is 32 kHz or less. Once an audio sample has finished playing, playback frequency will be set to 0; 30 | 31 | **`audio.channelhead(channel[, pos]): pos`** 32 | Get/set the current playback position (in number of sample values) on the given channel. 33 | 34 | **`audio.channelvolume(channel[, volume]): volume`** 35 | Get/set the volume (0 to 63) of the given channel. 36 | 37 | **`audio.channelloop(channel[, start, end]): start, end`** 38 | Get/set the loop markers of the given channel. To disable loop, set both markers to `0`. 39 | 40 | Manipulating audio samples 41 | -------------------------- 42 | **`audio.samplevalue(sampl, pos[, value]): value`** 43 | Get/set value (-128 to 127) of given audio sample at given position. If given position is beyond the length of the sample, an error will occur. 44 | 45 | **`audio.samplelength(sampl[, length]): length`** 46 | Get/set the length of given audio sample in number of sample values. 47 | 48 | **`audio.samplefreq(sampl[, freq]): freq`** 49 | Get/set the inherent playback frequency of the given audio sample. 50 | 51 | **`audio.sampleloop(sampl[, start, end]): start, end`** 52 | Get/set the inherent loop markers of the given audio sample. 53 | 54 | **`audio.record(sampl): bytes`** 55 | Record from the input audio device to the given sample at the given sample's frequency and return number of bytes added to given sample. 56 | 57 | -------------------------------------------------------------------------------- /system_drive/docs/core/fs.md: -------------------------------------------------------------------------------- 1 | `fs` module 2 | =========== 3 | The Homegirl filesystem consists of a number of named drives, each of which is mapped to a folder on the host system (or a webserver). A file path is constructed like this: 4 | 5 | drivename:directory/subdirectory/filename.ext 6 | 7 | **`fs.drives(): drivenames[]`** 8 | Get a list of available drives. 9 | 10 | **`fs.mount(drive, url): success`** 11 | Mount a local or remote drive. 12 | 13 | **`fs.unmount(drive[, force]): success`** 14 | Unmount a drive. If `force` is `true`, all programs originating from that drive will be terminated. 15 | 16 | **`fs.isfile(filename): confirmed`** 17 | Return `true` if given filename refers to an existing file. 18 | 19 | **`fs.isdir(filename): confirmed`** 20 | Return `true` if given filename refers to an existing directory. 21 | 22 | **`fs.size(filename): bytes`** 23 | Return the size of a given file in bytes. 24 | 25 | **`fs.time(filename): hour, minute, second, UTCoffset`** 26 | Return the local time a given file was last modified. 27 | 28 | **`fs.date(filename): year, month, date, weekday`** 29 | Return the local date a given file was last modified. 30 | 31 | **`fs.read(filename): string`** 32 | Read given filename and return its content as a string. 33 | 34 | **`fs.write(filename, string): success`** 35 | Write given string to given filename and return `true` if successful. 36 | 37 | **`fs.post(filename, request, type): response`** 38 | If `filename` is on a webserver, this will perform a `POST` request to it and return the response from it. 39 | 40 | **`fs.rename(filename, newname): success`** 41 | Rename a file or folder and return `true` if successful. 42 | 43 | **`fs.delete(filename): success`** 44 | Delete given filename and return `true` if succesful. 45 | 46 | **`fs.list(dirname): entries[]`** 47 | Read given dirname and return a list of its files and subdirectories (which will end with `/`). 48 | 49 | **`fs.cd([dirname]): dirname`** 50 | Get/set the current working directory. 51 | 52 | **`fs.mkdir(dirname): success`** 53 | Create a directory and return `true` if succesful. 54 | -------------------------------------------------------------------------------- /system_drive/docs/core/gfx.md: -------------------------------------------------------------------------------- 1 | `gfx` module 2 | ============ 3 | These functions require that a [screen or other viewport](view.md) is created and active. 4 | 5 | **`gfx.cls()`** 6 | Fill the entire active viewport with the current background color. 7 | 8 | **`gfx.palette(color[, red, green, blue]): red, green, blue`** 9 | Get/set the RGB values of a given color index. Each value can range from 0 to 15. 10 | 11 | **`gfx.fgcolor([color]): color`** 12 | Get/set the current foreground color of the active viewport. 13 | 14 | **`gfx.bgcolor([color]): color`** 15 | Get/set the current background color of the active viewport. 16 | 17 | **`gfx.nearestcolor(r, g, b): color`** 18 | Get the color nearest the given RGB values from the palette of the active viewport. 19 | 20 | **`gfx.pixel(x, y[, color]): color`** 21 | Get/set the color of a given pixel in the active viewport. 22 | 23 | **`gfx.plot(x, y)`** 24 | Set the given pixel to the current foreground color. 25 | 26 | **`gfx.bar(x, y, width, height)`** 27 | Draw a rectangle filled with the current foreground color. 28 | 29 | **`gfx.line(x1, y1, x2, y2)`** 30 | Draw a line with the current foreground color. 31 | 32 | **`gfx.tri(x1, y1, x2, y2, x3, y3)`** 33 | Draw a filled triangle with the current foreground color. 34 | -------------------------------------------------------------------------------- /system_drive/docs/core/http-api.md: -------------------------------------------------------------------------------- 1 | HTTP API 2 | ======== 3 | Homegirl is able to mount websites as drives, provided the website is at least somewhat crawler friendly. Any static webserver with directory listings enabled can be mounted as a read-only drive. 4 | 5 | Any HTTP request from Homegirl will be provided with a `User-Agent` header with name and version of the console, and a `Referer` header referring to the program causing the request, if that program is from a webserver. 6 | 7 | Getting directory contents 8 | -------------------------- 9 | Whenever Homegirl accesses a HTML resource on a webserver, the contents will be scanned for any tags with either a `src` or `href` attribute, resolve the references and mark them as existing files in the cache. So whenever `fs.list` is called, it returns a modified list of the entries in cache. 10 | 11 | Reading files 12 | ------------- 13 | Reading a file from a webserver is just a simple `GET` request. Homegirl will then cache the result, even errors, for at least 10 minutes. 14 | 15 | Writing files 16 | ------------- 17 | When Homegirl tries to write a file to a webserver, a `PUT` request is issued to the desired URL of the file with the file contents in the request body. If the server replies with an error (HTTP status 400 or above), Homegirl will try and (re)fetch the original file from the server, if it exists. 18 | 19 | Deleting files and directories 20 | ------------------------------ 21 | To delete files or directories, a `DELETE` request is issued to the URL that should be deleted. An error results in Homegirl trying to refetch the file. 22 | 23 | Creating directories 24 | -------------------- 25 | Homegirl expects webservers, that support the `PUT` method, to recursively create any directories needed to write to the desired path. So to create a directory, Homegirl will simply write an empty file inside the directory and then delete it, so that only an empty directory remains. (Provided the directory wasn't already there.) 26 | 27 | Renaming/moving files and directories 28 | ------------------------------------- 29 | To rename files and directories, a `PATCH` request is issued to the URL that needs to be renamed, with a `Location` header that provides the new desired path. An error will result in trying to refetch both the old and new path. 30 | 31 | -------------------------------------------------------------------------------- /system_drive/docs/core/image.md: -------------------------------------------------------------------------------- 1 | `image` module 2 | ============== 3 | Homegirl and load and save frames from GIF animations. Each frame has its own palette (converted from 24 to 12 bit colors) and exposure duration. Since the screen can only show up to 256 colors at once, GIF files that depend on accumulating palettes will not work. 4 | 5 | Creating and managing images 6 | ---------------------------- 7 | **`image.new(width, height, colorbits): img`** 8 | Create a blank image with given width, height and [colorbits](view.md) and return it. 9 | 10 | **`image.load(filename[, maxframes]): img[]`** 11 | Read a GIF file and return a table of its frames. 12 | 13 | **`image.save(filename, img[]): success`** 14 | Write a given table of images to a GIF file and return `true` if succesful. 15 | 16 | **`image.size(img): width, height`** 17 | Get the width and height of a given image. 18 | 19 | **`image.colordepth(img): colorbits`** 20 | Get the number of colorbits per pixel of a given image. 21 | 22 | **`image.forget(img)`** 23 | Erase image from memory. 24 | 25 | 26 | Manipulating images 27 | ------------------- 28 | **`image.duration(img[, milliseconds]): milliseconds`** 29 | Get/set the exposure time of a given image. 30 | 31 | **`image.pixel(img, x, y[, color]): color`** 32 | Get/set the color of a given pixel in a given image. 33 | 34 | **`image.palette(img, color[, red, green, blue]): red, green, blue`** 35 | Get/set the RGB values of a given color index. Each value can range from 0 to 15. 36 | 37 | **`image.bgcolor(img[, color]): color`** 38 | Get/set the current background color of a given image. 39 | 40 | 41 | Drawing images 42 | -------------- 43 | These functions require that a [screen or other viewport](view.md) is created and active. 44 | 45 | **`image.copymode([mode, masked]): mode, masked`** 46 | Get/set the current copy mode of the active viewport. If `masked` is `true` then all background pixels from source will not be copied. 47 | 48 | Mode | Name | Effect 49 | -----|------|------- 50 | 0| zero | always index 0 51 | 1| conNonimpl | dest src 55 | 5| xor | dest xor src 56 | 6| dest | always destination index 57 | 7| or | dest or src 58 | 8| not | inverts destination index 59 | 9| min | lowest index of destination or source 60 | 10| max | highest index of destination or source 61 | 11| average | average index of destination or source 62 | 12| add | sum of destination and source index 63 | 13| subtract | destination index minus source index 64 | 14| multiply | product of destination and source index 65 | 15| divide | destination index divided by source index 66 | 16| bgcolor, | always background index 67 | 17| fgcolor, | always foreground index 68 | 18| srcbgColor, | always background color of source 69 | 20| sourceColor, | always source color 70 | 21| darkerColor, | darkest combination of destination and source colors 71 | 22| lighterColor, | lightest combination of destination and source colors 72 | 23| averageColor, | average of destination and source colors 73 | 24| addColor, | sum of destination and source colors (capped at white) 74 | 25| subtractColor, | destination color minus source color (capped at black) 75 | 26| multiplyColor, | product of destination and source colors 76 | 28| hueColor, | destination color with the hue of source color 77 | 29| saturationColor, | destination color with the saturation of source color 78 | 30| lightnessColor, | destination color with the lightness of source color 79 | 31| graynessColor, | destination color with the saturation and lightness of source color 80 | 81 | 82 | **`image.errordiffusion([enabled]): enabled`** 83 | Get/set whether or not error diffusion is enabled when using copymodes above 17 or the `gfx.nearestcolor` function. 84 | 85 | **`image.tri(img, x1,y1, x2,y2, x3,y3, imgx1,imgy1, imgx2,imgy2, imgx3,imgy3)`** 86 | Draw a given triangular portion of given image to a given triangular spot on the active viewport. 87 | 88 | **`image.draw(img, x, y, imgx, imgy, width, height[, imgwidth, imgheight])`** 89 | Draw a given rectangular portion of given image to a given rectangular spot on the active viewport. 90 | 91 | **`image.copy(img, x, y, imgx, imgy, width, height)`** 92 | Copy a given portion of the active viewport to a given spot on given image. (Copy mode will always be 0 here.) 93 | 94 | **`image.usepalette(img)`** 95 | Copy the palette from a given image to the active screen. This only works if a screen is active. 96 | 97 | **`image.copypalette(img)`** 98 | Copy the palette from the active screen to given image. 99 | 100 | **`image.busypointer(img, Xoffset, Yoffset)`** 101 | Set the given image as busy pointer. Color palette works the same as with `image.pointer`. 102 | 103 | **`image.pointer(img, Xoffset, Yoffset)`** 104 | Set the given image as mouse pointer for the active viewport. Only 4 color images are supported and the colors are automatically assigned to the following: 105 | 106 | Index | Color 107 | ------|------ 108 | 0 | transparent 109 | 1 | darkest color in the palette 110 | 2 | lightest color in the palette 111 | 3 | most saturated color in the palette 112 | -------------------------------------------------------------------------------- /system_drive/docs/core/index.md: -------------------------------------------------------------------------------- 1 | Developing for Homegirl 2 | ======================= 3 | The Homegirl console is based on the [Lua programming language](https://www.lua.org/). All of the Lua standard library is available, except for `io`, `file`, `os` and most of the `package` module. But Homegirl also has its own API, which is documented in the other pages of this wiki. 👉 4 | 5 | Special functions 6 | ----------------- 7 | Each program can define three special functions, which will be called automatically at certain times. 8 | 9 | **`_init(args[])`** 10 | This will be called immediately after the program has been loaded and initialized. The `args` parameter is a table of strings which is passed from the command line or another program. 11 | 12 | **`_step(time)`** 13 | This will be called at regular intervals or (by default) whenever a key/button is pressed/released or mouse is dragged. The `time` parameter is the amount of time in milliseconds the console has been running for. 14 | 15 | **`_shutdown(exitcode)`** 16 | This will only be called if the program exits by itself or another program kills it. It will not be called if there is an error in the program. The `exitcode` parameter is the numeric code that the program exits with. This is usually an error code, if the program didn't succeed at its task, or `0` if it did. If the program was killed, the exit code will be `-1`. 17 | 18 | Special constants 19 | ----------------- 20 | **`_DRIVE`** 21 | This will automatically be set to the drive that contains the current program file, regardless of current working directory. 22 | 23 | **`_DIR`** 24 | This will automatically be set to the directory that contains the current program file, regardless of current working directory. 25 | 26 | **`_FILE`** 27 | This will automatically be set to the name of the current program file. 28 | -------------------------------------------------------------------------------- /system_drive/docs/core/input.md: -------------------------------------------------------------------------------- 1 | `input` module 2 | ============== 3 | These functions require that a [screen or other viewport](view.md) is created and active. 4 | 5 | Text input 6 | ---------- 7 | **`input.text([text]): text`** 8 | Get/set the text currently entered into the active viewport. 9 | 10 | **`input.selected([text]): text`** 11 | Get the text that is currently selected or enter given text at cursor. 12 | 13 | **`input.cursor([pos, selected]): pos, selected`** 14 | Get/set the cursor position and selection length in bytes. 15 | 16 | **`input.linesperpage([linesperpage]): linesperpage`** 17 | Get/set the number of lines to jump on PageUp/Down. 18 | 19 | **`input.clearhistory()`** 20 | Clear undo history in active viewport. 21 | 22 | Other input 23 | ----------- 24 | **`input.hotkey(): hotkey`** 25 | Get the key that was just pressed in conjunction with Ctrl(unless it's Esc or Tab). This will reset each step. 26 | 27 | **`input.mouse(): x, y, btn`** 28 | Get the current mouse coordinates relative to the active viewport and any mouse buttons currently pressed, if the viewport has focus. 29 | 30 | **`input.drag(drop, icon)`** 31 | Add a string for the mouse pointer to drag and an icon to represent it. This only works as long as active viewport has focus and a mouse button is held down. Mouse button input will be suppressed as long as something is being dragged. 32 | 33 | **`input.drop(): drop`** 34 | Catch something currently being dropped into the active viewport or return `nil`. 35 | 36 | **`input.midi(): byte`** 37 | Read a byte of data from MIDI. 38 | 39 | **`input.gamepad([player]): btn`** 40 | Get the gamepad state of given player. Player can be either 0, 1 or 2. If player is 0 then the states of both players will be combined. 41 | 42 | Each button can be tested like this: 43 | 44 | ```lua 45 | right = btn & 1 > 0 46 | left = btn & 2 > 0 47 | up = btn & 4 > 0 48 | down = btn & 8 > 0 49 | A = btn & 16 > 0 50 | B = btn & 32 > 0 51 | X = btn & 64 > 0 52 | Y = btn & 128 > 0 53 | ``` -------------------------------------------------------------------------------- /system_drive/docs/core/overview.md: -------------------------------------------------------------------------------- 1 | # Lua API overview 2 | [See docs for details.](./) 3 | ## _basic_ 4 | dofile(filename): result 5 | loadfile(filename): function 6 | print(message) 7 | require(filename): module 8 | ## audio 9 | audio.new(): sampl 10 | audio.load(filename): sampl 11 | audio.save(filename, sampl): success 12 | audio.play(channel, sampl) 13 | audio.record(sampl): bytes 14 | audio.channelfreq(channel[, freq]): freq 15 | audio.channelhead(channel[, pos]): pos 16 | audio.channelvolume(channel[, volume]): volume 17 | audio.channelloop(channel[, start, end]): start, end 18 | audio.samplevalue(sampl, pos[, value]): value 19 | audio.samplelength(sampl[, length]): length 20 | audio.samplefreq(sampl[, freq]): freq 21 | audio.sampleloop(sampl[, start, end]): start, end 22 | audio.forget(sampl) 23 | ## fs 24 | fs.drives(): drivenames[] 25 | fs.mount(drive, url): success 26 | fs.unmount(drive[, force]): success 27 | fs.isfile(filename): confirmed 28 | fs.isdir(filename): confirmed 29 | fs.size(filename): bytes 30 | fs.time(filename): hour, minute, second, UTCoffset 31 | fs.date(filename): year, month, date, weekday 32 | fs.read(filename): string 33 | fs.write(filename, string): success 34 | fs.post(filename, request, type): response 35 | fs.rename(filename, newname): success 36 | fs.delete(filename): success 37 | fs.list(dirname): entries[] 38 | fs.cd([dirname]): dirname 39 | fs.mkdir(dirname): success 40 | ## gfx 41 | gfx.cls() 42 | gfx.palette(color[, red, green, blue]): red, green, blue 43 | gfx.fgcolor([color]): color 44 | gfx.bgcolor([color]): color 45 | gfx.nearestcolor(r, g, b): color 46 | gfx.pixel(x, y[, color]): color 47 | gfx.plot(x, y) 48 | gfx.bar(x, y, width, height) 49 | gfx.line(x1, y1, x2, y2) 50 | gfx.tri(x1, y1, x2, y2, x3, y3) 51 | ## image 52 | image.new(width, height, colorbits): img 53 | image.load(filename[, maxframes]): img[] 54 | image.save(filename, img[]): success 55 | image.size(img): width, height 56 | image.colordepth(img): colorbits 57 | image.duration(img[, milliseconds]): milliseconds 58 | image.pixel(img, x, y[, color]): color 59 | image.palette(img, color[, red, green, blue]): red, green, blue 60 | image.bgcolor(img[, color]): color 61 | image.copymode([mode, masked]): mode, masked 62 | image.errordiffusion([enabled]): enabled 63 | image.tri(img, x1,y1, x2,y2, x3,y3, imgx1,imgy1, imgx2,imgy2, imgx3,imgy3) 64 | image.draw(img, x, y, imgx, imgy, width, height[, imgwidth, imgheight]) 65 | image.copy(img, x, y, imgx, imgy, width, height) 66 | image.usepalette(img) 67 | image.copypalette(img) 68 | image.pointer(img, Xoffset, Yoffset) 69 | image.busypointer(img, Xoffset, Yoffset) 70 | image.forget(img) 71 | ## input 72 | input.text([text]): text 73 | input.selected([text]): text 74 | input.cursor([pos, selected]): pos, selected 75 | input.linesperpage([linesperpage]): linesperpage 76 | input.clearhistory() 77 | input.hotkey(): hotkey 78 | input.mouse(): x, y, btn 79 | input.gamepad([player]): btn 80 | input.drag(drop, icon) 81 | input.drop(): drop 82 | input.midi(): byte 83 | ## sys 84 | sys.read(): string 85 | sys.write(string) 86 | sys.err(string) 87 | sys.stepinterval([milliseconds]): milliseconds 88 | sys.listenv(): keys[] 89 | sys.env(key[, value]): value 90 | sys.time(): hour, minute, second, UTCoffset 91 | sys.date(): year, month, date, weekday 92 | sys.exit([code]) 93 | sys.permissions(drive[, perms]): perms 94 | sys.requestedpermissions(drive[, perms]): perms 95 | sys.lookbusy() 96 | sys.memoryusage(): bytesinuse 97 | sys.exec(filename[, args[][, cwd]]): success 98 | sys.killall(programname): count 99 | sys.startchild(filename[, args[]]): child 100 | sys.childrunning(child): bool 101 | sys.childexitcode(child): int 102 | sys.writetochild(child, str) 103 | sys.readfromchild(child): str 104 | sys.errorfromchild(child): str 105 | sys.killchild(child) 106 | sys.forgetchild(child) 107 | ## text 108 | text.loadfont(filename): font 109 | text.copymode([mode, masked]): mode, masked 110 | text.draw(text, font, x, y): width, height 111 | text.forgetfont(font) 112 | ## view 113 | view.newscreen(mode, colorbits): view 114 | view.screenmode(view[, mode, colorbits]): mode, colorbits 115 | view.new(parentview, left, top, width, height): view 116 | view.active([view]): view 117 | view.position(view[, left, top]): left, top 118 | view.size(view[, width, height]): width, height 119 | view.visible(view[, isvisible]): isvisible 120 | view.focused(view[, isfocused]): isfocused 121 | view.zindex(view[, index]): index 122 | view.children(view): views[] 123 | view.owner(view): programname 124 | view.attribute(view, name[, value]): value 125 | view.remove(view) 126 | -------------------------------------------------------------------------------- /system_drive/docs/core/sys.md: -------------------------------------------------------------------------------- 1 | `sys` module 2 | ============ 3 | System functions. 4 | 5 | **`sys.read(): string`** 6 | Read text from standard input. 7 | 8 | **`sys.write(string)`** 9 | Write text to standard output. 10 | 11 | **`sys.err(string)`** 12 | Write text to standard error output. 13 | 14 | **`sys.stepinterval([milliseconds]): milliseconds`** 15 | Get/set the minimum amount of time between each stepping of the program. By default this is set to `-1`, which means that the program will only be stepped whenever there is new input. 16 | 17 | **`sys.listenv(): keys[]`** 18 | Get a list of all environment variables on the system. 19 | 20 | **`sys.env(key[, value]): value`** 21 | Get/set a given environment variable on the system. 22 | 23 | **`sys.time(): hour, minute, second, UTCoffset`** 24 | Get the current local time. 25 | 26 | **`sys.date(): year, month, date, weekday`** 27 | Get the current local date. 28 | 29 | **`sys.exit([code])`** 30 | End the program with given exitcode when this step is done. This will call the `_shutdown` function with the given exitcode. 31 | 32 | **`sys.exec(filename[, args[][, cwd]]): success`** 33 | Load and run given program independently of this program. 34 | 35 | **`sys.killall(programname): count`** 36 | Kill all instances of a given program and return the number of instances killed. 37 | 38 | **`sys.lookbusy()`** 39 | Show busy pointer for the rest of the step. 40 | 41 | **`sys.permissions(drive[, perms]): perms`** 42 | Get/set permissions for a given drive. `perms` is the sum of the corresponding values listed below. 43 | 44 | **`sys.requestedpermissions(drive[, perms]): perms`** 45 | Get/set requested permissions for a given drive. `perms` is the sum of the corresponding values listed below. 46 | 47 | Value | Permission 48 | ------|----------- 49 | 1 | Manage permissions 50 | 2 | Mount local drives 51 | 4 | Mount remote drives 52 | 8 | Unmount other drives 53 | 16 | Manage main screen 54 | 32 | Manage programs 55 | 256 | Read other drives 56 | 512 | Write to other drives 57 | 1024 | Read environment variables 58 | 2048 | Set environment variables 59 | 4096 | Record audio 60 | 61 | Child programs 62 | -------------- 63 | **`sys.startchild(filename[, args[]]): child`** 64 | Load and run given program as a child and return it. 65 | 66 | **`sys.childrunning(child): bool`** 67 | Return `true` if given child is still running. 68 | 69 | **`sys.childexitcode(child): int`** 70 | Return exitcode of given child. 71 | 72 | **`sys.writetochild(child, str)`** 73 | Send given str to given child's default input. 74 | 75 | **`sys.readfromchild(child): str`** 76 | Read from given child's default output. 77 | 78 | **`sys.errorfromchild(child): str`** 79 | Read from given child's error output. 80 | 81 | **`sys.killchild(child)`** 82 | Force child to end itself. 83 | 84 | **`sys.forgetchild(child)`** 85 | Forget about that child. 86 | -------------------------------------------------------------------------------- /system_drive/docs/core/text.md: -------------------------------------------------------------------------------- 1 | `text` module 2 | ============= 3 | Homegirl uses GIF files as fonts. Each character is stored as a frame and the character width is stored as the frame's duration in centiseconds. 4 | 5 | [See example](https://raw.githubusercontent.com/poeticAndroid/homegirl/master/system_drive/fonts/Victoria.8b.gif) 6 | 7 | Managing fonts 8 | -------------- 9 | **`text.loadfont(fontname): font`** 10 | Load a font and return it. If `fontname` doesn't refer directly to a filename, it will search the program directory, the `fonts` folder on the root of the origin drive and `sys:` drive, in that order. 11 | 12 | **`text.forgetfont(font)`** 13 | Forget about that font. 14 | 15 | Printing text on the screen 16 | --------------------------- 17 | These functions require that a [screen or other viewport](view.md) is created and active. 18 | 19 | **`text.copymode([mode, masked]): mode, masked`** 20 | Get/set the [copy mode](image.md) regarding text. 21 | 22 | **`text.draw(text, font, x, y): width, height`** 23 | Draw given text with given font at given spot and return the size of the text in pixels. 24 | -------------------------------------------------------------------------------- /system_drive/docs/core/view.md: -------------------------------------------------------------------------------- 1 | `view` module 2 | ============= 3 | The display system of Homegirl consists of a tree of viewports. The top level of viewports are screens which are layered on top of each other. Each screen be configured in different screen modes and color depths and can have their own tree of viewports which inherit the pixel resolution and colors of the screen. 4 | 5 | The first screen created since console startup will become the main screen. Any program can create viewports (to make windows) on the main screen. With the right permission, programs can also manage the main screen by passing `nil` as the `view` parameter in most of these functions. 6 | 7 | Creating and removing viewports 8 | ------------------------------- 9 | **`view.newscreen(mode, colorbits): view`** 10 | Create a new screen in given screen mode and colorbits, make it active and return it. The number of colors will be 2 raised to the power of `colorbits`. 11 | 12 | Mode | Width | Height 16:9 | Height 4:3 | Pixel size (ratio) 13 | -----|-------|-------------|------------|------------------ 14 | 0 | 80 | 45 | 60 | 8x8 (1:1) 15 | 1 | 160 | 45 | 60 | 4x8 (1:2) 16 | 2 | 320 | 45 | 60 | 2x8 (1:4) 17 | 3 | 640 | 45 | 60 | 1x8 (1:8) 18 | 4 | 80 | 90 | 120 | 8x4 (2:1) 19 | 5 | 160 | 90 | 120 | 4x4 (1:1) 20 | 6 | 320 | 90 | 120 | 2x4 (1:2) 21 | 7 | 640 | 90 | 120 | 1x4 (1:4) 22 | 8 | 80 | 180 | 240 | 8x2 (4:1) 23 | 9 | 160 | 180 | 240 | 4x2 (2:1) 24 | 10 | 320 | 180 | 240 | 2x2 (1:1) 25 | 11 | 640 | 180 | 240 | 1x2 (1:2) 26 | 12 | 80 | 360 | 480 | 8x1 (8:1) 27 | 13 | 160 | 360 | 480 | 4x1 (4:1) 28 | 14 | 320 | 360 | 480 | 2x1 (2:1) 29 | 15 | 640 | 360 | 480 | 1x1 (1:1) 30 | 31 | **`view.new(parentview, left, top, width, height): view`** 32 | Create a new subviewport to given parent viewport, make it active and return it. If `parentview` is `nil`, then the viewport will be created on the main screen. 33 | 34 | **`view.remove(view)`** 35 | Remove and forget about given viewport. 36 | 37 | Managing viewports 38 | ------------------ 39 | **`view.screenmode(view[, mode, colorbits]): mode, colorbits`** 40 | If given viewport is a screen, this will get/set its screen mode and colorbits. 41 | 42 | **`view.active([view]): view`** 43 | Get/set the currently active viewport. 44 | 45 | **`view.position(view[, left, top]): left, top`** 46 | Get/set the position of given viewport. 47 | 48 | **`view.size(view[, width, height]): width, height`** 49 | Get/set the size of given viewport. 50 | 51 | **`view.visible(view[, isvisible]): isvisible`** 52 | Get/set whether given viewport is visible. 53 | 54 | **`view.focused(view[, isfocused]): isfocused`** 55 | Get/set whether given viewport has input focus. 56 | 57 | **`view.zindex(view[, index]): index`** 58 | Get/set the z-index of given viewport. `0` sends the viewport to the back of its parent. `-1` brings it to the front. 59 | 60 | **`view.children(view): views[]`** 61 | Get all sub-viewports of given viewport. 62 | 63 | **`view.owner(view): programname`** 64 | Get the programname of the program that created the given viewport. 65 | 66 | **`view.attribute(view, name[, value]): value`** 67 | Get/set a given attribute of a given viewport. 68 | -------------------------------------------------------------------------------- /system_drive/fonts/victoria.8b.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/poeticAndroid/homegirl/2884a11dff3dd38370f2005b87a2105bd7fccc91/system_drive/fonts/victoria.8b.gif -------------------------------------------------------------------------------- /system_drive/libs/filerequester.lua: -------------------------------------------------------------------------------- 1 | local Widget, path = require("widget"), require("path") 2 | 3 | local FileRequester = Widget:extend() 4 | do 5 | function FileRequester:constructor(title, suffixes, default) 6 | self.title = title or "Select a file" 7 | self.suffixes = suffixes or {""} 8 | self.filename = path.resolve(fs.cd(), default) 9 | if fs.isdir(self.filename) then 10 | self.filename = path.trailslash(self.filename) 11 | end 12 | self.list = {} 13 | table.insert(self.suffixes, "/") 14 | end 15 | 16 | function FileRequester:attachto(parent, vp, screen) 17 | Widget.attachto(self, parent, vp, screen) 18 | local sw, sh = view.size(self.screen) 19 | self:position(sw / 4, sh / 4) 20 | self:size(sw / 2, sh / 2) 21 | input.text(self.filename) 22 | input.clearhistory() 23 | self.filename = self.filename .. "/." 24 | self:step(42) 25 | end 26 | 27 | function FileRequester:step(time) 28 | local prevvp = view.active() 29 | view.active(self.container) 30 | 31 | local list = self.list 32 | local delta = #(input.text()) - #(self.filename) 33 | self.filename = input.text() 34 | if self.filename == path.trailslash(self.filename) then 35 | self.dirname = self.filename 36 | self.basename = "" 37 | else 38 | self.dirname = path.dirname(self.filename) 39 | self.basename = path.basename(self.filename) 40 | end 41 | if #(self.dirname) < 2 then 42 | self.dirname = "" 43 | end 44 | if string.find(self.basename, "\t") then 45 | self.basename = self.list[1] or "" 46 | self.filename = input.text(self.dirname .. self.basename) 47 | if self.filename == path.trailslash(self.filename) then 48 | self.dirname = self.filename 49 | self.basename = "" 50 | end 51 | end 52 | if delta < 0 or (delta > 0 and self.filename == path.trailslash(self.filename)) then 53 | list = fs.list(self.dirname) or {} 54 | end 55 | self.list = {} 56 | if #(self.dirname) < 2 then 57 | list = fs.drives() 58 | end 59 | for i, name in ipairs(list) do 60 | if #(self.dirname) < 2 then 61 | name = name .. ":" 62 | end 63 | local good = #(self.dirname) < 2 64 | for i, suff in ipairs(self.suffixes) do 65 | if suff == "" or string.lower(string.sub(name, -(#suff))) == suff then 66 | good = true 67 | end 68 | end 69 | if string.lower(string.sub(name, 1, #(self.basename))) ~= string.lower(self.basename) then 70 | good = false 71 | end 72 | if good then 73 | table.insert(self.list, name) 74 | end 75 | end 76 | 77 | self:redraw(time) 78 | view.active(prevvp) 79 | if input.hotkey() == "\x1b" then 80 | self.parent:destroychild(self) 81 | self:ondone() 82 | end 83 | if string.find(self.filename, "\n") then 84 | self.parent:destroychild(self) 85 | self:ondone(string.gsub(self.filename, "\n", "")) 86 | end 87 | end 88 | 89 | function FileRequester:redraw() 90 | local prevvp = view.active() 91 | local cw, ch = view.size(self.container) 92 | local x, y = 0, 0 93 | view.active(self.container) 94 | gfx.bgcolor(self.darkcolor) 95 | gfx.fgcolor(self.lightcolor) 96 | local tw, th = text.draw(self.title, self.font, 0, 0) 97 | gfx.cls() 98 | gfx.bar(0, 0, cw, th + 2) 99 | gfx.bar(0, 0, 1, ch) 100 | gfx.bar(0, ch - 1, cw, 1) 101 | gfx.bar(cw - 1, 0, 1, ch) 102 | gfx.fgcolor(self.darkcolor) 103 | text.draw(self.title, self.font, 1, 1) 104 | local chwidth = tw / #(self.title) 105 | gfx.fgcolor(self.lightcolor) 106 | 107 | local cpos, csel = input.cursor() 108 | x, y = 2, th + 3 109 | tw, th = text.draw(self:_letterwrap(self.filename, math.floor((cw - 4) / chwidth)), self.font, x, y) 110 | tw, th = 111 | text.draw( 112 | self:_letterwrap(string.sub(self.filename, 1, cpos) .. "\x7f", math.floor((cw - 4) / chwidth)), 113 | self.font, 114 | x, 115 | y 116 | ) 117 | gfx.fgcolor(self.darkcolor) 118 | tw, th = 119 | text.draw( 120 | self:_letterwrap(string.sub(self.filename, 1, cpos + 1), math.floor((cw - 4) / chwidth)), 121 | self.font, 122 | x, 123 | y 124 | ) 125 | gfx.fgcolor(self.lightcolor) 126 | tw, th = 127 | text.draw(self:_letterwrap(string.sub(self.filename, 1, cpos), math.floor((cw - 4) / chwidth)), self.font, x, y) 128 | 129 | y = y + th + 1 130 | gfx.bar(x, y, cw - x * 2, 1) 131 | y = y + 2 132 | local top, maxw = y, 0 133 | for i, name in ipairs(self.list) do 134 | tw, th = text.draw(name, self.font, x, y) 135 | y = y + th 136 | if tw > maxw then 137 | maxw = tw 138 | end 139 | if y + th >= ch then 140 | x, y = x + maxw + chwidth / 2, top 141 | maxw = 0 142 | end 143 | end 144 | 145 | view.active(prevvp) 146 | end 147 | 148 | function FileRequester:_letterwrap(txt, width) 149 | local out, pos = "", 0 150 | for i = 1, #txt do 151 | local ch = string.sub(txt, i, i) 152 | if ch == "\n" then 153 | pos = -1 154 | end 155 | if pos >= width then 156 | out = out .. "\n" 157 | pos = 0 158 | end 159 | out = out .. ch 160 | pos = pos + 1 161 | end 162 | return out 163 | end 164 | end 165 | return FileRequester 166 | -------------------------------------------------------------------------------- /system_drive/libs/menu.lua: -------------------------------------------------------------------------------- 1 | local Widget = require("widget") 2 | 3 | local Menu = Widget:extend() 4 | do 5 | function Menu:constructor(struct) 6 | self.struct = { 7 | onopen = function(...) 8 | if self.onopen then 9 | return self.onopen(...) 10 | end 11 | return true 12 | end, 13 | menu = struct 14 | } 15 | self.active = false 16 | self:_gethotkeys() 17 | end 18 | 19 | function Menu:attachto(parent, parentvp, screen) 20 | self.parent = parent 21 | self.parentvp = parentvp or parent.mainvp or parent.container 22 | self.screen = screen or parent.screen 23 | end 24 | function Menu:destroy() 25 | self:close() 26 | if self._prevstepint and sys.stepinterval() == -2 then 27 | sys.stepinterval(self._prevstepint) 28 | end 29 | end 30 | 31 | function Menu:step(t) 32 | local prevvp = view.active() 33 | view.active(self.parentvp) 34 | local mx, my, mb = input.mouse() 35 | if self.active then 36 | mb = math.min(2, mb * 2) 37 | if not view.focused(self.parentvp) and self._mb == 0 then 38 | mb = 2 39 | end 40 | end 41 | if self._mb == 2 and mb == 0 then 42 | self.active = not self.active 43 | if self.active then 44 | self._prevstepint = nil 45 | if sys.stepinterval() == -1 then 46 | self._prevstepint = sys.stepinterval() 47 | sys.stepinterval(-2) 48 | end 49 | else 50 | self:close() 51 | if self._prevstepint and math.abs(sys.stepinterval()) == 2 then 52 | sys.stepinterval(self._prevstepint) 53 | end 54 | end 55 | end 56 | local hk = input.hotkey() 57 | if self._hotkeys[hk] then 58 | self._selected = self._hotkeys[hk] 59 | end 60 | if self.active then 61 | self:open() 62 | view.focused(self.parentvp, true) 63 | elseif self._selected then 64 | if self._selected.action then 65 | self._selected.action(self._selected) 66 | end 67 | self._selected = nil 68 | end 69 | self._mb = mb 70 | view.active(prevvp) 71 | end 72 | 73 | function Menu:open(struct, ml, mt) 74 | local prevvp = view.active() 75 | local sw, sh = view.size(self.screen) 76 | local topmenu = false 77 | local mw, mh, tw, th = 0, 0, 0, 0 78 | local newvp 79 | if not struct then 80 | topmenu = true 81 | struct = self.struct 82 | end 83 | if not struct.vp then 84 | newvp = true 85 | if struct.onopen and (struct:onopen() == false) then 86 | return 87 | end 88 | struct.vp = view.new(self.screen, math.max(0, ml or 0), math.max(0, mt or 0)) 89 | struct._frozen = false 90 | input.text("\n\n") 91 | input.cursor(1) 92 | end 93 | ml, mt = view.position(struct.vp) 94 | view.active(struct.vp) 95 | local tl = 0 96 | for i, menu in ipairs(struct.menu) do 97 | tw, th = text.draw(self:_label(menu, topmenu), self.font) 98 | if not topmenu then 99 | tl = math.max(tl, #(menu.label)) 100 | end 101 | if topmenu then 102 | mw = mw + tw 103 | else 104 | mh = mh + th 105 | end 106 | if mw < tw then 107 | mw = tw 108 | end 109 | if mh < th then 110 | mh = th 111 | end 112 | end 113 | mw = mw + 2 114 | mh = mh + 2 115 | if topmenu then 116 | mw = math.max(mw, sw) 117 | end 118 | view.size(struct.vp, mw, mh) 119 | if not topmenu then 120 | if ml + mw > sw then 121 | self:_scrollX(ml + mw - sw) 122 | ml, mt = view.position(struct.vp) 123 | end 124 | if newvp and mt + mh > sh then 125 | mt = math.max(0, sh - mh) 126 | view.position(struct.vp, ml, mt) 127 | end 128 | end 129 | gfx.bgcolor(self.lightcolor) 130 | gfx.cls() 131 | local mx, my, mb = input.mouse() 132 | local inside = false 133 | if mx >= 0 and my >= 0 and mx < mw and my < mh then 134 | inside = true 135 | end 136 | if inside then 137 | local mscroll = input.cursor() 138 | input.cursor(1) 139 | if topmenu then 140 | if mscroll < 1 and ml < 0 then 141 | ml = ml + 5 142 | end 143 | if mscroll > 1 and ml + mw > sw then 144 | ml = ml - 5 145 | end 146 | if mx + ml < 8 and ml < 0 then 147 | ml = ml + 1 148 | end 149 | if mx + ml > sw - 8 and ml + mw > sw then 150 | ml = ml - 1 151 | end 152 | else 153 | if mscroll < 1 and mt < 0 then 154 | mt = mt + 5 155 | end 156 | if mscroll > 1 and mt + mh > sh then 157 | mt = mt - 5 158 | end 159 | if my + mt < 8 and mt < 0 then 160 | mt = mt + 1 161 | end 162 | if my + mt > sh - 8 and mt + mh > sh then 163 | mt = mt - 1 164 | end 165 | end 166 | view.position(struct.vp, ml, mt) 167 | end 168 | local x = topmenu and 3 or 0 169 | local y = topmenu and 0 or 1 170 | for i, menu in ipairs(struct.menu) do 171 | if inside then 172 | if struct._parent and not struct._frozen then 173 | struct._parent._frozen = true 174 | end 175 | if not struct._frozen then 176 | if topmenu then 177 | tw, th = text.draw(self:_label(menu, topmenu), self.font, mw, mh) 178 | if mx >= x and mx < x + tw then 179 | menu.active = true 180 | if mb == 1 then 181 | self._selected = menu 182 | end 183 | else 184 | menu.active = false 185 | end 186 | else 187 | if my >= y and my < y + th then 188 | menu.active = true 189 | if mb == 1 then 190 | self._selected = menu 191 | end 192 | else 193 | menu.active = false 194 | end 195 | end 196 | end 197 | else 198 | if struct._parent and not struct._frozen then 199 | struct._parent._frozen = false 200 | end 201 | end 202 | if menu.active and menu.menu then 203 | if struct._parent then 204 | struct._parent._frozen = true 205 | end 206 | menu._parent = struct 207 | if topmenu then 208 | self:open(menu, ml + x, th + 1) 209 | elseif mx > mw - 8 then 210 | self:open(menu, ml + mw - 4, mt + y - 1) 211 | end 212 | else 213 | self:close(menu) 214 | end 215 | while #(menu.label) < tl do 216 | menu.label = menu.label .. " " 217 | end 218 | gfx.fgcolor(menu.active and self.fgcolor or self.lightcolor) 219 | gfx.bar(x, y, mw, mh) 220 | gfx.fgcolor(menu.active and self.fgtextcolor or self.darkcolor) 221 | tw, th = text.draw(self:_label(menu, topmenu), self.font, x, y + (topmenu and 1 or 0)) 222 | if topmenu then 223 | x = x + tw 224 | else 225 | y = y + th 226 | end 227 | end 228 | gfx.fgcolor(self.lightcolor) 229 | gfx.bar(x, y, mw, mh) 230 | if not topmenu then 231 | gfx.fgcolor(self.darkcolor) 232 | gfx.bar(0, 0, mw, 1) 233 | gfx.bar(0, mh - 1, mw, 1) 234 | gfx.bar(0, 0, 1, mh) 235 | gfx.bar(mw - 1, 0, 1, mh) 236 | end 237 | view.active(prevvp) 238 | end 239 | function Menu:close(struct) 240 | if not struct then 241 | struct = self.struct 242 | self.active = false 243 | end 244 | if struct.vp then 245 | for i, menu in ipairs(struct.menu) do 246 | self:close(menu) 247 | end 248 | view.remove(struct.vp) 249 | struct.vp = nil 250 | end 251 | end 252 | 253 | function Menu:_label(struct, top) 254 | if top then 255 | return " " .. struct.label .. " " 256 | else 257 | return (struct.checked and " *" or " ") .. 258 | struct.label .. 259 | (struct.menu and " >" or 260 | (struct.hotkey and 261 | (struct.hotkey == "\x1b" and " Esc" or 262 | (struct.hotkey == "\t" and " Tab" or (" ^" .. string.upper(struct.hotkey)))) or 263 | " ")) 264 | end 265 | end 266 | 267 | function Menu:_gethotkeys(struct) 268 | if not struct then 269 | struct = self.struct 270 | self._hotkeys = {} 271 | end 272 | if struct.hotkey then 273 | self._hotkeys[struct.hotkey] = struct 274 | end 275 | if struct.menu then 276 | for i, menu in ipairs(struct.menu) do 277 | self:_gethotkeys(menu) 278 | end 279 | end 280 | end 281 | 282 | function Menu:_scrollX(amount, struct) 283 | if not struct then 284 | struct = self.struct 285 | end 286 | if struct.vp and struct ~= self.struct then 287 | local ml, mt = view.position(struct.vp) 288 | view.position(struct.vp, ml - amount, mt) 289 | end 290 | if struct.menu then 291 | for i, menu in ipairs(struct.menu) do 292 | self:_scrollX(amount, menu) 293 | end 294 | end 295 | end 296 | end 297 | return Menu 298 | -------------------------------------------------------------------------------- /system_drive/libs/object.lua: -------------------------------------------------------------------------------- 1 | local Object = {} 2 | do 3 | Object.__index = Object 4 | function Object:constructor() 5 | end 6 | function Object:new(...) 7 | local obj = setmetatable({}, self) 8 | obj:constructor(...) 9 | return obj 10 | end 11 | function Object:extend() 12 | local class = setmetatable({}, self) 13 | class.__index = class 14 | return class 15 | end 16 | end 17 | return Object 18 | -------------------------------------------------------------------------------- /system_drive/libs/path.lua: -------------------------------------------------------------------------------- 1 | local path = {} 2 | 3 | function path.split(pathname) 4 | pathname = path.notrailslash(pathname) 5 | local segs = {} 6 | local i = string.find(pathname, ":") 7 | if i then 8 | table.insert(segs, string.sub(pathname, 1, i)) 9 | pathname = string.sub(pathname, i + 1) 10 | end 11 | i = string.find(pathname, "/") 12 | while i do 13 | table.insert(segs, string.sub(pathname, 1, i - 1)) 14 | pathname = string.sub(pathname, i + 1) 15 | i = string.find(pathname, "/") 16 | end 17 | if #pathname > 0 then 18 | table.insert(segs, pathname) 19 | end 20 | return segs 21 | end 22 | 23 | function path.resolve(...) 24 | local segs = {} 25 | local rels = {...} 26 | for i, rel in ipairs(rels) do 27 | local _segs = path.split(rel) 28 | for i, seg in ipairs(_segs) do 29 | if string.sub(seg, -1) == ":" then 30 | segs = {seg} 31 | elseif seg == "" then 32 | segs = {segs[1]} 33 | elseif seg == "." then 34 | elseif seg == ".." then 35 | table.remove(segs) 36 | else 37 | table.insert(segs, seg) 38 | end 39 | end 40 | end 41 | local abspath = "" 42 | for i, seg in ipairs(segs) do 43 | if i > 2 then 44 | abspath = abspath .. "/" 45 | end 46 | abspath = abspath .. seg 47 | end 48 | return abspath 49 | end 50 | 51 | function path.basename(pathname) 52 | pathname = path.notrailslash(pathname) 53 | local i = string.find(string.reverse(pathname), "/") or string.find(string.reverse(pathname), ":") 54 | if i then 55 | return string.sub(pathname, -i + 1) 56 | else 57 | return pathname 58 | end 59 | end 60 | 61 | function path.dirname(pathname) 62 | return path.trailslash(path.resolve(pathname, "..")) 63 | end 64 | 65 | function path.trailslash(pathname) 66 | if string.sub(pathname, -1) == "/" then 67 | return pathname 68 | elseif string.sub(pathname, -1) == ":" then 69 | return pathname 70 | else 71 | return pathname .. "/" 72 | end 73 | end 74 | 75 | function path.notrailslash(pathname) 76 | if string.sub(pathname, -1) == "/" then 77 | return string.sub(pathname, 1, -2) 78 | else 79 | return pathname 80 | end 81 | end 82 | 83 | return path 84 | -------------------------------------------------------------------------------- /system_drive/libs/screen.lua: -------------------------------------------------------------------------------- 1 | local Widget = require("widget") 2 | 3 | local defaultfont = text.loadfont("Victoria.8b") 4 | 5 | local Screen = Widget:extend() 6 | do 7 | function Screen:constructor(title, mode, colorbits) 8 | self.children = {} 9 | self._mode = mode 10 | self._colorbits = colorbits 11 | self.rootvp = view.newscreen(self._mode, self._colorbits) 12 | self.titlevp = view.new(self.rootvp, 0, 0, 8, 8) 13 | self.mainvp = view.new(self.rootvp, 0, 8, 8, 8) 14 | self:colors(1, 0) 15 | self:font(defaultfont) 16 | self:title(title) 17 | end 18 | 19 | function Screen:attach(name, child) 20 | if name then 21 | if self.children[name] then 22 | self:destroychild(name) 23 | end 24 | self.children[name] = child 25 | else 26 | table.insert(self.children, child) 27 | end 28 | child:attachto(self, self.mainvp, self.rootvp) 29 | return child 30 | end 31 | function Screen:attachwindow(name, child) 32 | if name then 33 | if self.children[name] then 34 | self:destroychild(name) 35 | end 36 | self.children[name] = child 37 | else 38 | table.insert(self.children, child) 39 | end 40 | child:attachto(self, self.rootvp, self.rootvp) 41 | return child 42 | end 43 | 44 | function Screen:font(font) 45 | if font then 46 | self._font = font 47 | local prevvp = view.active() 48 | view.active(self.titlevp) 49 | local sw, sh = view.size(self.rootvp) 50 | local tw, th = text.draw(self._title, self._font, 0, 0) 51 | view.size(self.titlevp, sw, th + 3) 52 | view.position(self.mainvp, 0, th + 3) 53 | view.size(self.mainvp, sw, sh - th - 3) 54 | self:title(self._title) 55 | view.active(prevvp) 56 | end 57 | return self._font 58 | end 59 | 60 | function Screen:title(title) 61 | if title then 62 | self._title = view.attribute(self.rootvp, "title", title) 63 | local prevvp = view.active() 64 | view.active(self.titlevp) 65 | gfx.bgcolor(self.lightcolor) 66 | gfx.fgcolor(self.darkcolor) 67 | local vw, vh = view.size(self.titlevp) 68 | local btnx = vw - vh * 2 - 2 69 | gfx.cls() 70 | local tw, th = text.draw(self._title, self._font, 1, 1) 71 | if tw >= btnx then 72 | gfx.cls() 73 | tw, th = text.draw(self._title, self._font, btnx - tw, 1) 74 | end 75 | gfx.bar(0, vh - 1, vw, 1) 76 | self:_drawbtn() 77 | view.active(prevvp) 78 | end 79 | return self._title 80 | end 81 | 82 | function Screen:redraw() 83 | self:title(self._title) 84 | end 85 | 86 | function Screen:step(time) 87 | local prevvp = view.active() 88 | view.active(self.titlevp) 89 | local vw, vh = view.size(self.titlevp) 90 | local btnx = vw - vh * 2 91 | local x, y, btn = input.mouse() 92 | if btn == 1 then 93 | if x < btnx then 94 | local top = self:top(self:top() + y - 5) 95 | else 96 | self:_drawbtn(true) 97 | end 98 | elseif view.focused(self.titlevp) then 99 | self:title(self._title) 100 | if self._lastmbtn == 1 and x >= btnx then 101 | view.zindex(self.rootvp, 0) 102 | view.focused(self.rootvp, false) 103 | else 104 | view.focused(self.mainvp, true) 105 | end 106 | end 107 | self._lastmbtn = btn 108 | view.active(self.rootvp) 109 | if input.hotkey() == "." then 110 | view.zindex(self.rootvp, 0) 111 | view.focused(self.rootvp, false) 112 | end 113 | for name, child in pairs(self.children) do 114 | child:step(time) 115 | end 116 | view.active(prevvp) 117 | end 118 | 119 | function Screen:palette(c, r, g, b) 120 | local prevvp = view.active() 121 | view.active(self.rootvp) 122 | local r, g, b = gfx.palette(c, r, g, b) 123 | view.active(prevvp) 124 | return r, g, b 125 | end 126 | 127 | function Screen:usepalette(img) 128 | local prevvp = view.active() 129 | view.active(self.rootvp) 130 | image.usepalette(img) 131 | view.active(prevvp) 132 | end 133 | 134 | function Screen:copypalette(img) 135 | local prevvp = view.active() 136 | view.active(self.rootvp) 137 | image.copypalette(img) 138 | view.active(prevvp) 139 | end 140 | 141 | function Screen:top(top) 142 | if top then 143 | view.position(self.rootvp, 0, top) 144 | end 145 | local left, top = view.position(self.rootvp) 146 | return top 147 | end 148 | 149 | function Screen:size() 150 | return view.size(self.mainvp) 151 | end 152 | 153 | function Screen:mode(mode, colorbits) 154 | if mode then 155 | self._mode = mode 156 | self._colorbits = colorbits 157 | view.screenmode(self.rootvp, self._mode, self._colorbits) 158 | self:font(self._font) 159 | end 160 | return self._mode, self._colorbits 161 | end 162 | 163 | function Screen:colors(bg, fg) 164 | self.darkcolor = fg 165 | self.lightcolor = bg 166 | self:title(self._title) 167 | end 168 | 169 | function Screen:_drawbtn(pressed) 170 | local vw, vh = view.size(self.titlevp) 171 | local btnx = vw - vh * 2 172 | local s = vh * .55 173 | local bg, fg = self.lightcolor, self.darkcolor 174 | gfx.fgcolor(fg) 175 | gfx.bar(btnx - 2, 0, 2, vh) 176 | if pressed then 177 | gfx.bar(btnx, 0, vh * 3, vh) 178 | bg, fg = fg, bg 179 | end 180 | gfx.fgcolor(fg) 181 | gfx.bar(btnx + 2, 1, s * 2, s) 182 | gfx.fgcolor(bg) 183 | s = s - 2 184 | gfx.bar(btnx + 4, 2, s * 2, s) 185 | gfx.fgcolor(fg) 186 | s = s + 2 187 | gfx.bar(vw - s * 2 - 1, vh - s - 1, s * 2, s) 188 | end 189 | end 190 | return Screen 191 | -------------------------------------------------------------------------------- /system_drive/libs/widget.lua: -------------------------------------------------------------------------------- 1 | local Object = require("object") 2 | 3 | local Widget = Object:extend() 4 | do 5 | Widget.darkcolor = 1 6 | Widget.lightcolor = 2 7 | Widget.fgcolor = 3 8 | Widget.bgcolor = 0 9 | Widget.fgtextcolor = 2 10 | Widget.bgtextcolor = 1 11 | Widget.parent = false 12 | Widget.font = text.loadfont("Victoria.8b") 13 | 14 | function Widget:constructor(label) 15 | self.label = label 16 | end 17 | 18 | function Widget:attach(name, child) 19 | if name then 20 | if self.children[name] then 21 | self:destroychild(name) 22 | end 23 | self.children[name] = child 24 | else 25 | table.insert(self.children, child) 26 | end 27 | child:attachto(self) 28 | child:redraw() 29 | return child 30 | end 31 | function Widget:attachto(parent, vp, screen) 32 | if parent then 33 | if vp == nil then 34 | vp = parent.mainvp or parent.container 35 | end 36 | if screen == nil then 37 | screen = parent.screen 38 | end 39 | self.darkcolor = parent.darkcolor 40 | self.lightcolor = parent.lightcolor 41 | self.fgcolor = parent.fgcolor 42 | self.bgcolor = parent.bgcolor 43 | self.fgtextcolor = parent.fgtextcolor 44 | self.bgtextcolor = parent.bgtextcolor 45 | end 46 | if self.parent ~= parent then 47 | self.parent = parent 48 | local l, t, w, h = 0, 0, 8, 8 49 | if self.container then 50 | l, t = view.position(self.container) 51 | w, h = view.size(self.container) 52 | view.remove(self.container) 53 | end 54 | self.parentvp = vp 55 | if screen then 56 | Widget.screen = screen 57 | end 58 | self.screen = Widget.screen 59 | self.container = view.new(self.parentvp, l, t, w, h) 60 | end 61 | end 62 | 63 | function Widget:destroy() 64 | if self.children then 65 | for name, child in pairs(self.children) do 66 | child:destroy() 67 | end 68 | end 69 | self.children = nil 70 | if self.container then 71 | view.remove(self.container) 72 | end 73 | self.container = nil 74 | self.parentvp = nil 75 | self.screen = nil 76 | end 77 | function Widget:destroychild(name) 78 | local child = self.children[name] 79 | if child then 80 | child:destroy() 81 | self.children[name] = nil 82 | else 83 | for n, child in pairs(self.children) do 84 | if child == name then 85 | child:destroy() 86 | self.children[n] = nil 87 | end 88 | end 89 | end 90 | end 91 | 92 | function Widget:position(left, top) 93 | return view.position(self.container, left, top) 94 | end 95 | function Widget:size(width, height) 96 | local w, h = view.size(self.container, width, height) 97 | self:redraw() 98 | return w, h 99 | end 100 | function Widget:autosize() 101 | return self:size(16, 9) 102 | end 103 | function Widget:focus() 104 | view.focused(self.mainvp or self.container, true) 105 | self:redraw() 106 | end 107 | 108 | function Widget:step(t) 109 | if self.children then 110 | for name, child in pairs(self.children) do 111 | child:step(t) 112 | end 113 | end 114 | end 115 | function Widget:redraw() 116 | end 117 | 118 | function Widget:autocolor() 119 | self.darkcolor = gfx.nearestcolor(0, 0, 0) 120 | self.lightcolor = gfx.nearestcolor(15, 15, 15) 121 | self.fgcolor = gfx.nearestcolor(0, 7, 15) 122 | self.bgcolor = gfx.nearestcolor(8, 8, 8) 123 | local r, g, b = gfx.palette(self.fgcolor) 124 | local l = r + g + b 125 | self.fgtextcolor = l > 22 and self.darkcolor or self.lightcolor 126 | r, g, b = gfx.palette(self.bgcolor) 127 | l = r + g + b 128 | self.bgtextcolor = l > 22 and self.darkcolor or self.lightcolor 129 | if self.children then 130 | for name, child in pairs(self.children) do 131 | child:autocolor() 132 | end 133 | end 134 | self:redraw() 135 | end 136 | 137 | function Widget:outset(x, y, w, h) 138 | gfx.fgcolor(self.lightcolor) 139 | gfx.bar(x, y, w, 1) 140 | gfx.bar(x, y, 1, h) 141 | gfx.fgcolor(self.darkcolor) 142 | gfx.bar(x + w - 1, y + 1, 1, h - 1) 143 | gfx.bar(x, y + h - 1, w, 1) 144 | end 145 | function Widget:inset(x, y, w, h) 146 | gfx.fgcolor(self.darkcolor) 147 | gfx.bar(x, y, w, 1) 148 | gfx.bar(x, y, 1, h) 149 | gfx.fgcolor(self.lightcolor) 150 | gfx.bar(x + w - 1, y + 1, 1, h - 1) 151 | gfx.bar(x, y + h - 1, w, 1) 152 | end 153 | function Widget:aabb(x1, y1, w1, h1, x2, y2, w2, h2) 154 | if x1 < x2 + w2 and x1 + w1 > x2 and y1 < y2 + h2 and y1 + h1 > y2 then 155 | return true 156 | end 157 | return false 158 | end 159 | 160 | function Widget:gotclicked(vp) 161 | if not vp then 162 | vp = self.container 163 | end 164 | local clicked = false 165 | local prevvp = view.active() 166 | view.active(vp) 167 | local mx, my, mb = input.mouse() 168 | if view.attribute(vp, "pressed") == "true" and mb == 0 then 169 | clicked = true 170 | end 171 | if mb == 0 then 172 | view.attribute(vp, "pressed", "false") 173 | else 174 | local w, h = view.size(vp) 175 | if mx >= 0 and my >= 0 and mx < w and my < h then 176 | view.attribute(vp, "pressed", "true") 177 | else 178 | view.attribute(vp, "pressed", "false") 179 | end 180 | end 181 | view.active(prevvp) 182 | return clicked 183 | end 184 | end 185 | return Widget 186 | -------------------------------------------------------------------------------- /system_drive/startup.lua: -------------------------------------------------------------------------------- 1 | sys.exec("/cmd/shell.lua", {}, "user:") 2 | sys.exec("user:startup.lua", {}, "user:") 3 | --------------------------------------------------------------------------------