├── templates ├── rust │ ├── .gitignore │ ├── .cargo │ │ └── config.toml │ ├── Cargo.toml │ ├── src │ │ ├── lib.rs │ │ └── alloc.rs │ └── README.md ├── zig │ ├── wasmdemo.wasm │ ├── README.md │ ├── src │ │ └── main.zig │ ├── build.zig │ └── wasmdemo.wasmp ├── d │ ├── buildwasm.sh │ ├── buildcart.sh │ ├── Makefile │ ├── dub.json │ ├── src │ │ └── main.d │ ├── wasmdemo.wasmp │ └── README.md ├── c │ ├── buildwasm.sh │ ├── buildcart.sh │ ├── src │ │ └── main.c │ ├── README.md │ ├── wasmdemo.wasmp │ └── Makefile └── README.md ├── vendor ├── fennel │ ├── .gitignore │ └── Makefile └── .gitignore ├── demos ├── wasm │ ├── wasmdemo.wasm │ ├── build.zig │ ├── src │ │ └── main.zig │ └── wasmdemo.wasmp ├── bunny │ ├── wasmmark │ │ ├── wasmmark.wasm │ │ ├── README.md │ │ ├── build.zig │ │ ├── wasmmark.wasmp │ │ └── src │ │ │ └── main.zig │ ├── moonmark.moon │ ├── rubymark.rb │ ├── jsmark.js │ ├── wrenmark.wren │ ├── squirrelmark.nut │ └── luamark.lua ├── luademo.lua ├── sfx.lua ├── fenneldemo.fnl ├── rubydemo.rb ├── jsdemo.js ├── moondemo.moon ├── squirreldemo.nut ├── fire.lua ├── wrendemo.wren ├── palette.lua ├── p3d.lua └── music.lua ├── src ├── system │ ├── baremetalpi │ │ ├── gamepads.h │ │ ├── utils.h │ │ ├── kernel.h │ │ ├── customchargenerator.cpp │ │ ├── gamepads.cpp │ │ ├── main.cpp │ │ ├── customchargenerator.h │ │ ├── utils.cpp │ │ └── keycodes.h │ ├── libretro │ │ ├── README.md │ │ └── libretro_core_options_intl.h │ ├── sokol │ │ ├── sokol_impl.m │ │ ├── sokol_impl.c │ │ ├── sokol.h │ │ └── player.c │ ├── n3ds │ │ ├── utils.h │ │ ├── keyboard.h │ │ └── utils.c │ └── sdl │ │ ├── kbdlabels.inl │ │ └── keycodes.inl ├── studio │ ├── demos.h │ ├── project.h │ ├── screens │ │ ├── mainmenu.h │ │ ├── run.h │ │ ├── start.h │ │ ├── menu.h │ │ ├── surf.h │ │ └── console.h │ ├── config.h │ ├── editors │ │ ├── world.h │ │ ├── sfx.h │ │ ├── music.h │ │ ├── sprite.h │ │ ├── map.h │ │ └── code.h │ ├── net.h │ ├── anim.h │ └── fs.h ├── tic_assert.h ├── ext │ ├── fft.h │ ├── kiss_fftr.h │ ├── md5.h │ ├── history.h │ ├── gif.h │ ├── png.h │ └── kiss_fft.h ├── cart.h ├── core │ └── languages.c ├── api │ └── lua_api.h ├── tic.c ├── defines.h ├── tilesheet.h └── tools.h ├── tools └── zig_sync ├── Dockerfile.dapper ├── version.h.in ├── SECURITY.md ├── .github └── workflows │ └── webapp.yml ├── CommunityGuidelines.md ├── tic80.sublime-project ├── LICENSE ├── include ├── tic80_types.h ├── retro_inline.h └── tic80_config.h ├── .gitmodules └── CODE_OF_CONDUCT.md /templates/rust/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /vendor/fennel/.gitignore: -------------------------------------------------------------------------------- 1 | /loadfennel.lua 2 | 3 | -------------------------------------------------------------------------------- /demos/wasm/wasmdemo.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glastonbridge/TIC-80/HEAD/demos/wasm/wasmdemo.wasm -------------------------------------------------------------------------------- /templates/zig/wasmdemo.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glastonbridge/TIC-80/HEAD/templates/zig/wasmdemo.wasm -------------------------------------------------------------------------------- /demos/bunny/wasmmark/wasmmark.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glastonbridge/TIC-80/HEAD/demos/bunny/wasmmark/wasmmark.wasm -------------------------------------------------------------------------------- /templates/d/buildwasm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | make clean 3 | make 4 | tic80 --fs . --cmd 'load wasmdemo.wasmp & import binary cart.wasm & run & exit' 5 | -------------------------------------------------------------------------------- /templates/c/buildwasm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | make clean 3 | make 4 | tic80 --fs . --cmd 'load wasmdemo.wasmp & import binary build/cart.wasm & run & exit' 5 | -------------------------------------------------------------------------------- /templates/d/buildcart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | rm -f game.tic 3 | make clean 4 | make 5 | tic80 --fs . --cmd 'load wasmdemo.wasmp & import binary cart.wasm & save game.tic & exit' 6 | tic80 --fs . --cmd 'load game.tic & run & exit' 7 | -------------------------------------------------------------------------------- /templates/c/buildcart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | rm -f game.tic 3 | make clean 4 | make 5 | tic80 --fs . --cmd 'load wasmdemo.wasmp & import binary build/cart.wasm & save game.tic & exit' 6 | tic80 --fs . --cmd 'load game.tic & run & exit' 7 | -------------------------------------------------------------------------------- /src/system/baremetalpi/gamepads.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | void initGamepads(CDeviceNameService m_DeviceNameService, TGamePadStatusHandler handler); 8 | -------------------------------------------------------------------------------- /vendor/.gitignore: -------------------------------------------------------------------------------- 1 | sdl2/CMakeFiles/ 2 | sdl2/include/SDL_config.h 3 | sdl2/wayland-generated-protocols/ 4 | sdl2/sdl2-config 5 | sdl2/sdl2.pc 6 | sdl2/Makefile 7 | zlib/CMakeFiles/ 8 | zlib/zlib.pc 9 | *.cmake 10 | *.tlog 11 | *.obj 12 | *.filters 13 | -------------------------------------------------------------------------------- /tools/zig_sync: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | FILES=`find ./demos -name tic80.zig` 4 | for FILE in $FILES; do 5 | cp -v templates/zig/src/tic80.zig $FILE 6 | done 7 | 8 | FILES=`find ./demos -name build.zig` 9 | for FILE in $FILES; do 10 | cp -v templates/zig/build.zig $FILE 11 | done 12 | 13 | -------------------------------------------------------------------------------- /templates/d/Makefile: -------------------------------------------------------------------------------- 1 | DUB_FLAGS = --quiet --build release --compiler ldc2 --arch wasm32-unknown-unknown-wasm 2 | ifneq ($(origin WASI_SDK_PATH), undefined) 3 | override DUB_FLAGS += --config wasi 4 | endif 5 | 6 | build: 7 | dub build ${DUB_FLAGS} 8 | 9 | clean: 10 | rm -rf cart.wasm .dub 11 | -------------------------------------------------------------------------------- /Dockerfile.dapper: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | RUN apt-get update && apt-get install -y g++ git cmake libgtk-3-dev \ 3 | libglvnd-dev libglu1-mesa-dev freeglut3-dev libasound2-dev 4 | WORKDIR ${DAPPER_SOURCE:-/source} 5 | ENV DAPPER_OUTPUT build/bin 6 | ENTRYPOINT ["sh", "-c", "cd build; cmake .. && make -j4"] 7 | -------------------------------------------------------------------------------- /templates/rust/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "wasm32-unknown-unknown" 3 | 4 | [target.wasm32-unknown-unknown] 5 | rustflags = [ 6 | "-C", "link-arg=--import-memory", 7 | "-C", "link-arg=--initial-memory=262144", 8 | "-C", "link-arg=--max-memory=262144", 9 | "-C", "link-arg=-zstack-size=106496", 10 | ] 11 | -------------------------------------------------------------------------------- /version.h.in: -------------------------------------------------------------------------------- 1 | #define TIC_VERSION_MAJOR @VERSION_MAJOR@ 2 | #define TIC_VERSION_MINOR @VERSION_MINOR@ 3 | #define TIC_VERSION_REVISION @VERSION_REVISION@ 4 | #define TIC_VERSION_STATUS "@VERSION_STATUS@" 5 | #define TIC_VERSION_BUILD "@VERSION_BUILD@" 6 | #define TIC_VERSION_YEAR "@VERSION_YEAR@" 7 | #define TIC_VERSION_HASH "@VERSION_HASH@" 8 | -------------------------------------------------------------------------------- /src/studio/demos.h: -------------------------------------------------------------------------------- 1 | #include "api.h" 2 | 3 | typedef struct 4 | { 5 | const char* name; 6 | const void* demoRom; 7 | const s32 demoRomSize; 8 | const void* markRom; 9 | const s32 markRomSize; 10 | } tic_script_config_extra; 11 | 12 | 13 | extern tic_script_config_extra* LanguagesExtra[]; 14 | 15 | tic_script_config_extra* getConfigExtra(const tic_script_config* config); 16 | -------------------------------------------------------------------------------- /demos/luademo.lua: -------------------------------------------------------------------------------- 1 | function TIC()t=time()//32 2 | for y=0,136 do for x=0,240 do 3 | pix(x,y,(x+y+t)>>3) 4 | end end end 5 | 6 | -- 7 | -- 000:00000000ffffffff00000000ffffffff 8 | -- 001:0123456789abcdeffedcba9876543210 9 | -- 002:0123456789abcdef0123456789abcdef 10 | -- 11 | 12 | -- 13 | -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 14 | -- 15 | -------------------------------------------------------------------------------- /templates/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cart" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | crate-type = ["cdylib"] 8 | 9 | [dependencies] 10 | buddy-alloc = { version = "0.4.1", optional = true } 11 | 12 | [profile.release] 13 | opt-level = 0 14 | lto = true 15 | strip = true 16 | 17 | [features] 18 | # use `--no-default-features` or comment out next line to disable allocator 19 | default = ["buddy-alloc"] 20 | -------------------------------------------------------------------------------- /src/tic_assert.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #if (defined(DINGUX) || defined(__DJGPP__)) && !defined(static_assert) 4 | #define static_assert _Static_assert 5 | #endif 6 | 7 | #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5 8 | #define static_assert__(x,line) static char stat_ass ## line[(x) ? +1 : -1] 9 | #define static_assert_(x,line) static_assert__(x,line) 10 | #define static_assert(x,y) static_assert_(x, __LINE__) 11 | #endif 12 | -------------------------------------------------------------------------------- /vendor/fennel/Makefile: -------------------------------------------------------------------------------- 1 | fennel.h: loadfennel.lua 2 | xxd -i $^ > $@ 3 | 4 | # A modified copy of Fennel that puts itself into package.loaded rather 5 | # than simply returning module, since it won't be loaded properly with require. 6 | loadfennel.lua: fennel.lua 7 | sed "s/return mod/package.loaded['fennel'] = mod/" $< > $@ 8 | 9 | # Assuming you have a checkout as a sibling dir to this repo. 10 | fennel.lua: ../../../fennel/fennel.lua 11 | cp $< $@ 12 | -------------------------------------------------------------------------------- /demos/bunny/wasmmark/README.md: -------------------------------------------------------------------------------- 1 | # Bunnymark in Zig / WASM 2 | 3 | This is a Zig project. To build it you'll need Zig 0.9 or 0.10. 4 | 5 | ### Building 6 | 7 | ``` 8 | zig build 9 | ``` 10 | 11 | ### Replacing the assets used to build TIC-80 12 | 13 | Copy the build over the canonical WASM file: 14 | 15 | ``` 16 | cp zig-out/lib/cart.wasm wasmmark.wasm 17 | ``` 18 | 19 | During a TIC-80 build the `wasm` and `wasmp` file will be merged into a single demo cartridge and embedded into the TIC-80 binary. -------------------------------------------------------------------------------- /src/system/baremetalpi/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _utils_h 2 | #define _utils_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef EN_DEBUG 15 | #define dbg(...) printf(__VA_ARGS__) 16 | #else 17 | #define dbg(...) 18 | #endif 19 | 20 | 21 | void* loadFile(const char *filename, u32* size); 22 | char *strdup (const char *s); 23 | 24 | #endif 25 | 26 | -------------------------------------------------------------------------------- /templates/zig/README.md: -------------------------------------------------------------------------------- 1 | # ZIG Starter Project Template 2 | 3 | This is a ZIG / TIC-80 starter template. To build it, ensure you have a recent development release of Zig 0.10, then run: 4 | 5 | ``` 6 | zig build 7 | ``` 8 | 9 | To import the resulting WASM to a cartridge: 10 | 11 | ``` 12 | tic80 --fs . --cmd 'load game.tic & import binary zig-out/lib/cart.wasm & save' 13 | ``` 14 | 15 | Or from the TIC-80 console: 16 | 17 | ``` 18 | load game.tic 19 | import binary zig-out/lib/cart.wasm 20 | save 21 | ``` 22 | 23 | This is assuming you've run TIC-80 with `--fs .` inside your project directory. -------------------------------------------------------------------------------- /src/system/libretro/README.md: -------------------------------------------------------------------------------- 1 | # TIC-80 libretro 2 | 3 | Provided is a [TIC-80](https://tic.computer) libretro core to render TIC-80 cartridges through the [libretro](https://www.libretro.com) API and [RetroArch](https://www.retroarch.com). 4 | 5 | ## Build 6 | 7 | To build the core by itself, run the following commands. 8 | 9 | ``` 10 | git clone https://github.com/nesbox/TIC-80.git 11 | cd TIC-80 12 | git submodule update --init --recursive 13 | cd build 14 | cmake .. -DBUILD_PLAYER=OFF -DBUILD_SOKOL=OFF -DBUILD_SDL=OFF -DBUILD_DEMO_CARTS=OFF -DBUILD_LIBRETRO=ON 15 | make 16 | ``` 17 | 18 | ## Usage 19 | 20 | ``` 21 | retroarch -L lib/tic80_libretro.so sfx.tic 22 | ``` 23 | -------------------------------------------------------------------------------- /templates/zig/src/main.zig: -------------------------------------------------------------------------------- 1 | const tic = @import("tic80.zig"); 2 | 3 | const TICGuy = struct { 4 | x: i32 = 96, 5 | y: i32 = 24, 6 | }; 7 | 8 | var t: u16 = 0; 9 | var mascot: TICGuy = .{}; 10 | 11 | export fn BOOT() void {} 12 | 13 | export fn TIC() void { 14 | if (tic.btn(0)) { 15 | mascot.y -= 1; 16 | } 17 | if (tic.btn(1)) { 18 | mascot.y += 1; 19 | } 20 | if (tic.btn(2)) { 21 | mascot.x -= 1; 22 | } 23 | if (tic.btn(3)) { 24 | mascot.x += 1; 25 | } 26 | 27 | tic.cls(13); 28 | tic.spr(@as(i32, 1 + t % 60 / 30 * 2), mascot.x, mascot.y, .{ .w = 2, .h = 2, .transparent = &.{14}, .scale = 3 }); 29 | _ = tic.print("HELLO WORLD!", 84, 84, .{}); 30 | 31 | t += 1; 32 | } 33 | -------------------------------------------------------------------------------- /demos/wasm/build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | pub fn build(b: *std.build.Builder) void { 4 | const mode = b.standardReleaseOptions(); 5 | 6 | const lib = b.addSharedLibrary("cart", "src/main.zig", .unversioned); 7 | lib.setBuildMode(mode); 8 | lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }); 9 | lib.import_memory = true; 10 | lib.initial_memory = 65536 * 4; 11 | lib.max_memory = 65536 * 4; 12 | lib.export_table = true; 13 | // all the memory below 96kb is reserved for TIC and memory mapped I/O 14 | // so our own usage must start above the 96kb mark 15 | lib.global_base = 96 * 1024; 16 | lib.stack_size = 8192; 17 | lib.export_symbol_names = &[_][]const u8{ "TIC", "OVR", "BDR", "SCR", "BOOT" }; 18 | lib.install(); 19 | } 20 | -------------------------------------------------------------------------------- /templates/zig/build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | pub fn build(b: *std.build.Builder) void { 4 | const mode = b.standardReleaseOptions(); 5 | 6 | const lib = b.addSharedLibrary("cart", "src/main.zig", .unversioned); 7 | lib.setBuildMode(mode); 8 | lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }); 9 | lib.import_memory = true; 10 | lib.initial_memory = 65536 * 4; 11 | lib.max_memory = 65536 * 4; 12 | lib.export_table = true; 13 | // all the memory below 96kb is reserved for TIC and memory mapped I/O 14 | // so our own usage must start above the 96kb mark 15 | lib.global_base = 96 * 1024; 16 | lib.stack_size = 8192; 17 | lib.export_symbol_names = &[_][]const u8{ "TIC", "OVR", "BDR", "SCR", "BOOT" }; 18 | lib.install(); 19 | } 20 | -------------------------------------------------------------------------------- /demos/bunny/wasmmark/build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | pub fn build(b: *std.build.Builder) void { 4 | const mode = b.standardReleaseOptions(); 5 | 6 | const lib = b.addSharedLibrary("cart", "src/main.zig", .unversioned); 7 | lib.setBuildMode(mode); 8 | lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }); 9 | lib.import_memory = true; 10 | lib.initial_memory = 65536 * 4; 11 | lib.max_memory = 65536 * 4; 12 | lib.export_table = true; 13 | // all the memory below 96kb is reserved for TIC and memory mapped I/O 14 | // so our own usage must start above the 96kb mark 15 | lib.global_base = 96 * 1024; 16 | lib.stack_size = 8192; 17 | lib.export_symbol_names = &[_][]const u8{ "TIC", "OVR", "BDR", "SCR", "BOOT" }; 18 | lib.install(); 19 | } 20 | -------------------------------------------------------------------------------- /src/ext/fft.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define FFT_SIZE 2048 3 | 4 | typedef int BOOL; 5 | ////////////////////////////////////////////////////////////////////////// 6 | 7 | typedef struct FFT_Settings 8 | { 9 | BOOL bUseRecordingDevice; 10 | void* pDeviceID; 11 | } FFT_Settings; 12 | 13 | typedef void (*FFT_ENUMERATE_FUNC)(const BOOL bIsCaptureDevice, const char* szDeviceName, void* pDeviceID, void* pUserContext); 14 | 15 | extern float fAmplification; 16 | 17 | void FFT_EnumerateDevices(FFT_ENUMERATE_FUNC pEnumerationFunction, void* pUserContext); 18 | 19 | BOOL FFT_Create(); 20 | BOOL FFT_Destroy(); 21 | BOOL FFT_Open(FFT_Settings* pSettings); 22 | BOOL FFT_GetFFT(float* _samples); 23 | void FFT_Close(); 24 | 25 | ////////////////////////////////////////////////////////////////////////// 26 | 27 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Only the latest releases are supported and may receive security updates. 6 | If you aren't using the latest stable version, please upgrade. 7 | 8 | | Version | Status | Supported | 9 | | ---------- | -------- | ------------------ | 10 | | 1.0.x-dev | Alpha | :white_check_mark: | 11 | | 0.90.x | Stable | :white_check_mark: | 12 | | 0.80.x | | :x: | 13 | | 0.70.x | Obsolete | :x: | 14 | | < 0.70 | Obsolete | :x: | 15 | 16 | ## Reporting a Vulnerability 17 | 18 | Please open a [new GitHub issue](https://github.com/nesbox/TIC-80/issues/new) to report a vulnerability. 19 | 20 | If you feel your vulnerability is serious and should not 21 | be publically disclosed you may reach out via email: 22 | 23 | grigoruk@gmail.com 24 | -------------------------------------------------------------------------------- /templates/d/dub.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cart", 3 | "targetType": "executable", 4 | "configurations": [ 5 | { 6 | "name": "raw", 7 | "dflags": [ 8 | "-betterC" 9 | ], 10 | "lflags": [ 11 | "--strip-all", 12 | "--allow-undefined", 13 | "--stack-first", 14 | "--no-entry" 15 | ] 16 | }, 17 | { 18 | "name": "wasi", 19 | "dflags": [ 20 | "-betterC", 21 | "-Xcc", 22 | "$WASI_SDK_PATH/share/wasi-sysroot" 23 | ], 24 | "lflags": [ 25 | "--strip-all", 26 | "--allow-undefined", 27 | "--stack-first", 28 | "--no-entry", 29 | "$WASI_SDK_PATH/share/wasi-sysroot/lib/wasm32-wasi/libc.a" 30 | ] 31 | } 32 | ], 33 | "toolchainRequirements": { 34 | "dmd": "no", 35 | "gdc": "no", 36 | "ldc": ">=1.11.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /.github/workflows/webapp.yml: -------------------------------------------------------------------------------- 1 | name: WebApp 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | env: 8 | BUILD_TYPE: MinSizeRel 9 | 10 | jobs: 11 | webapp: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Setup Emscripten 15 | uses: mymindstorm/setup-emsdk@v7 16 | 17 | - name: Checkout 18 | uses: actions/checkout@v2 19 | with: 20 | submodules: recursive 21 | fetch-depth: 0 22 | 23 | - name: Build 24 | run: | 25 | cd build 26 | emcmake cmake -DBUILD_SDLGPU=On -DCMAKE_BUILD_TYPE=$BUILD_TYPE .. 27 | cmake --build . --config $BUILD_TYPE --parallel 28 | cp bin/tic80.js webapp/tic80.js 29 | cp bin/tic80.wasm webapp/tic80.wasm 30 | 31 | - name: Deploy 32 | uses: JamesIves/github-pages-deploy-action@4.1.3 33 | with: 34 | branch: webapp 35 | folder: build/webapp 36 | -------------------------------------------------------------------------------- /templates/rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod alloc; 2 | mod tic80; 3 | 4 | use tic80::*; 5 | 6 | static mut T: i32 = 0; 7 | static mut X: i32 = 96; 8 | static mut Y: i32 = 24; 9 | 10 | #[export_name = "TIC"] 11 | pub fn tic() { 12 | if btn(0) { 13 | unsafe { Y -= 1 } 14 | } 15 | if btn(1) { 16 | unsafe { Y += 1 } 17 | } 18 | if btn(2) { 19 | unsafe { X -= 1 } 20 | } 21 | if btn(3) { 22 | unsafe { X += 1 } 23 | } 24 | 25 | cls(13); 26 | unsafe { 27 | spr( 28 | 1 + T % 60 / 30 * 2, 29 | X, 30 | Y, 31 | SpriteOptions { 32 | w: 2, 33 | h: 2, 34 | transparent: &[14], 35 | scale: 3, 36 | ..Default::default() 37 | }, 38 | ); 39 | } 40 | print!("HELLO WORLD!", 84, 84, PrintOptions::default()); 41 | 42 | unsafe { 43 | T += 1; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /CommunityGuidelines.md: -------------------------------------------------------------------------------- 1 | ## TIC-80 Community Guidelines 2 | 3 | We welcome everyone on the TIC-80 community, regardless of age and programming level, unless they are not following these guidelines. Help us keep your, our, and other's properties safe by following these Community Guidelines: 4 | ### Be respectful. 5 | We are all different. Try not to distrupt other people's rights. 6 | ### Don't place strong violence in-game. 7 | Do not place adult content, especially strong violence or strong language, in a TIC-80 game. This would be too inappropriate content. **The violence and bad language level should be between none to minimally strong.** 8 | ### Keep personal info private. 9 | Do not share emails, DOBs (dates of births), people's ages, and do not link to chats except on encrypted secure websites. 10 | ### Be friendly. 11 | It is important that all of our user generated content has no content that is only suitable for adults. If anything on TIC-80 you find looks too inappropriate for under 18s, please let us know. 12 | -------------------------------------------------------------------------------- /src/system/baremetalpi/kernel.h: -------------------------------------------------------------------------------- 1 | // 2 | // kernel.h 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | #ifndef _kernel_h 18 | #define _kernel_h 19 | 20 | 21 | enum TShutdownMode 22 | { 23 | ShutdownNone, 24 | ShutdownHalt, 25 | ShutdownReboot 26 | }; 27 | 28 | TShutdownMode Run (void); 29 | 30 | #endif 31 | 32 | -------------------------------------------------------------------------------- /templates/README.md: -------------------------------------------------------------------------------- 1 | # Compiled Language Templates 2 | 3 | This directory contains starter projects (and libs) for the compiled languages we support via `script: wasm`. Currently this list includes: 4 | 5 | - Zig (low-level) 6 | - D (low-level) 7 | 8 | We could easily support these as well, with contributor help: 9 | 10 | - C 11 | - C++ 12 | - Go 13 | - Nelua 14 | - Nim 15 | - Odin 16 | - Rust 17 | - Wat 18 | 19 | What is needed? Pull over the example build/template scripts from the [WASM-4](https://wasm4.org) project [templates](https://github.com/aduros/wasm4/tree/main/cli/assets/templates). These are typically well done and well maintained so they are a great starting point. 20 | 21 | - Remove `wasm4.h`. 22 | - Replace with `tic80.h` 23 | - Implement the core API wrapper for your language 24 | - Implement "nice to haves" to make the API easier to use in your language 25 | 26 | If you're interested in helping start by posting on the overarching GitHub topic: 27 | 28 | https://github.com/nesbox/TIC-80/issues/1784 29 | 30 | 31 | -------------------------------------------------------------------------------- /demos/wasm/src/main.zig: -------------------------------------------------------------------------------- 1 | const tic = @import("tic80.zig"); 2 | 3 | var initDone = false; 4 | 5 | fn INIT() void { 6 | } 7 | 8 | const TICGuy = struct { 9 | x : i32 = 96, 10 | y : i32 = 24, 11 | }; 12 | 13 | var t : u16 = 0; 14 | var mascot : TICGuy = .{}; 15 | 16 | export fn TIC() void { 17 | if (!initDone) { INIT(); } 18 | 19 | tic.sync(.{ 20 | .sections = .{.tiles = true}, 21 | .bank = 1, 22 | .toCartridge = true 23 | }); 24 | 25 | if (tic.btn(0)) { 26 | mascot.y -= 1; 27 | } 28 | if (tic.btn(1)) { 29 | mascot.y +=1; 30 | } 31 | if (tic.btn(2)) { 32 | mascot.x -= 1; 33 | } 34 | if (tic.btn(3)) { 35 | mascot.x += 1; 36 | } 37 | 38 | tic.cls(13); 39 | tic.spr(@as(i32, 1+t%60/30*2),mascot.x,mascot.y,.{ 40 | .transparent = &.{14}, 41 | .scale = 3, 42 | .w = 2, 43 | .h = 2, 44 | }); 45 | _ = tic.print("HELLO WORLD!", 84, 84, .{.fixed = true}); 46 | 47 | t += 1; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /tic80.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "build_systems": 3 | [ 4 | { 5 | "name": "build", 6 | "shell_cmd": "cd ${project_path}/build && cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel .. && ninja", 7 | "file_regex": "/([^/:]+):(\\d+):(\\d+): ", 8 | "variants": [ 9 | { 10 | "name": "run", 11 | "shell_cmd": "cd ${project_path}/build && ninja && ${project_path}/build/bin/tic80 --skip --codeexport 123.lua --battletime 25" 12 | }, 13 | { 14 | "name": "clean", 15 | "shell_cmd": "cd ${project_path}/build && ninja -t clean" 16 | }, 17 | { 18 | "name": "clean rebuild", 19 | "shell_cmd": "cd ${project_path}/build && ninja -t clean && ninja" 20 | } 21 | ] 22 | } 23 | ], 24 | "folders": 25 | [ 26 | { 27 | "path": "." 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /src/system/baremetalpi/customchargenerator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "customfont.h" 4 | 5 | #define FIRSTCHAR 0x00 6 | #define LASTCHAR 0xFF 7 | #define CHARCOUNT (LASTCHAR - FIRSTCHAR + 1) 8 | CCharGenerator::CCharGenerator (void) 9 | : m_nCharWidth (width) 10 | { 11 | } 12 | CCharGenerator::~CCharGenerator (void) { 13 | } 14 | unsigned CCharGenerator::GetCharWidth (void) const { 15 | return m_nCharWidth; 16 | } 17 | unsigned CCharGenerator::GetCharHeight (void) const { 18 | return height + extraheight; 19 | } 20 | unsigned CCharGenerator::GetUnderline (void) const { 21 | return height; 22 | } 23 | boolean CCharGenerator::GetPixel (char chAscii, unsigned nPosX, unsigned nPosY) const { 24 | unsigned nAscii = (u8) chAscii; 25 | if ( nAscii < FIRSTCHAR 26 | || nAscii > LASTCHAR) 27 | { 28 | return FALSE; 29 | } 30 | unsigned nIndex = nAscii - FIRSTCHAR; 31 | assert (nIndex < CHARCOUNT); 32 | assert (nPosX < m_nCharWidth); 33 | if (nPosY >= height) 34 | { 35 | return FALSE; 36 | } 37 | return font_data[nIndex][nPosY] & (0x80 >> nPosX) ? TRUE : FALSE; 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Vadim Grigoruk 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. -------------------------------------------------------------------------------- /templates/d/src/main.d: -------------------------------------------------------------------------------- 1 | import std.algorithm: min, max; 2 | import tic80; 3 | 4 | extern(C): 5 | 6 | // From WASI libc: 7 | int snprintf(scope char* s, size_t n, scope const char* format, scope const ...); 8 | 9 | int t, x, y; 10 | const char* m = "HELLO WORLD FROM D!"; 11 | int r = 0; 12 | MouseData md; 13 | 14 | void BOOT() { 15 | t = 1; 16 | x = 96; 17 | y = 24; 18 | } 19 | 20 | void TIC() { 21 | cls(13); 22 | 23 | // The standard demo. 24 | if (btn(0) > 0) { y--; } 25 | if (btn(1) > 0) { y++; } 26 | if (btn(2) > 0) { x--; } 27 | if (btn(3) > 0) { x++; } 28 | 29 | spr(1+t%60/30*2, x, y, null, 0, 3, 0, 0, 2, 2); 30 | print(m, 60, 84, 15, 1, 1, 0); 31 | t++; 32 | 33 | // Mouse example demonstrating use of libc function. 34 | mouse(&md); 35 | if (md.left) { r = r + 2; } 36 | r--; 37 | r = max(0, min(32, r)); 38 | line(md.x, 0, md.x, 136, 11); 39 | line(0, md.y, 240, md.y, 11); 40 | circ(md.x, md.y, r, 11); 41 | 42 | const BUFSIZ = 10; 43 | char[BUFSIZ] buf; 44 | char* bufptr = cast(char*)buf; 45 | snprintf(bufptr, BUFSIZ, "(%03d,%03d)", md.x, md.y); 46 | print(bufptr, 3, 3, 15, 0, 1, 1); 47 | } 48 | -------------------------------------------------------------------------------- /src/system/baremetalpi/gamepads.cpp: -------------------------------------------------------------------------------- 1 | #include "gamepads.h" 2 | #include "utils.h" 3 | 4 | void initGamepads(CDeviceNameService m_DeviceNameService, TGamePadStatusHandler handler) 5 | { 6 | dbg("Searching gamepads..\n"); 7 | for (unsigned nDevice = 1; nDevice<=4; nDevice++) // max 4 gamepads 8 | { 9 | CString DeviceName; 10 | DeviceName.Format ("upad%u", nDevice); 11 | 12 | CUSBGamePadDevice *pGamePad = 13 | (CUSBGamePadDevice *) m_DeviceNameService.GetDevice (DeviceName, FALSE); 14 | 15 | if (pGamePad == 0) 16 | { 17 | // no more gamepads 18 | break; 19 | } 20 | 21 | const TGamePadState *pState = pGamePad->GetInitialState (); 22 | 23 | assert (pState != 0); 24 | 25 | dbg("Prop %d\n", pGamePad->GetProperties()); 26 | 27 | dbg("Gamepad %u: %d Button(s) %d Hat(s)\n", nDevice, pState->nbuttons, pState->nhats); 28 | 29 | for (int i = 0; i < pState->naxes; i++) 30 | { 31 | dbg("Gamepad %u: Axis %d: Minimum %d Maximum %d\n", nDevice, i+1, pState->axes[i].minimum, pState->axes[i].maximum); 32 | } 33 | 34 | pGamePad->RegisterStatusHandler (handler); 35 | 36 | } 37 | dbg("Finished searching gamepads\n"); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /demos/sfx.lua: -------------------------------------------------------------------------------- 1 | -- title: sfx 2 | -- author: Nesbox 3 | -- desc: how to play SFX demo 4 | -- script: lua 5 | -- input: gamepad 6 | 7 | t=0 8 | id=0 9 | 10 | function TIC() 11 | 12 | if btnp(0) then sfx(id,"E-4") 13 | elseif btnp(1) then sfx(id,"E-6") 14 | elseif btnp(2) then sfx(id,"E-7") 15 | elseif btnp(3) then sfx(id,"E-5") 16 | end 17 | 18 | cls(15) 19 | spr(1+(t%20)/10,102,24,1,4) 20 | print("PRESS ANY ARROW KEY",64,64,0) 21 | 22 | t=t+1 23 | 24 | end 25 | 26 | -- 27 | -- 001:1111111111110111111100111111010111110111100001110000011110001111 28 | -- 002:1111011111110011111101011111011110000111000001111000111111111111 29 | -- 30 | 31 | -- 32 | -- 000:00000000ffffffff00000000ffffffff 33 | -- 001:0123456789abcdeffedcba9876543210 34 | -- 002:0123456789abcdef0123456789abcdef 35 | -- 36 | 37 | -- 38 | -- 000:50003000300020002000200030003000300030004000400050005000600060007000800090009000a000b000b000c000c000d000e000e000f000f000304000000000 39 | -- 40 | 41 | -- 42 | -- 000:140c1c44243430346d4e4a4e854c30346524d04648757161597dced27d2c8595a16daa2cd2aa996dc2cadad45edeeed6 43 | -- 44 | 45 | -------------------------------------------------------------------------------- /src/system/baremetalpi/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // main.cpp 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | // 17 | #include "kernel.h" 18 | #include 19 | #include "utils.h" 20 | int main (void) 21 | { 22 | // cannot return here because some destructors used in CKernel are not implemented 23 | 24 | TShutdownMode s = Run(); 25 | 26 | switch (s) 27 | { 28 | case ShutdownReboot: 29 | reboot (); 30 | return EXIT_REBOOT; 31 | 32 | case ShutdownHalt: 33 | default: 34 | halt (); 35 | return EXIT_HALT; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /templates/c/src/main.c: -------------------------------------------------------------------------------- 1 | #include "tic80.h" 2 | 3 | #define max(a, b) (a > b) ? a : b 4 | #define min(a, b) (a < b) ? a : b 5 | 6 | // From WASI libc: 7 | WASM_IMPORT("snprintf") 8 | int snprintf(char* s, size_t n, const char* format, ...); 9 | 10 | int t, x, y; 11 | const char* m = "HELLO WORLD FROM C!"; 12 | int r = 0; 13 | MouseData md; 14 | uint8_t transcolors = { 14 }; 15 | 16 | WASM_EXPORT("BOOT") 17 | void BOOT() { 18 | t = 1; 19 | x = 96; 20 | y = 24; 21 | } 22 | 23 | WASM_EXPORT("TIC") 24 | void TIC() { 25 | cls(13); 26 | 27 | // The standard demo. 28 | if (btn(0) > 0) { y--; } 29 | if (btn(1) > 0) { y++; } 30 | if (btn(2) > 0) { x--; } 31 | if (btn(3) > 0) { x++; } 32 | 33 | spr(1+t%60/30*2, x, y, &transcolors, 1, 3, 0, 0, 2, 2); 34 | print(m, 60, 84, 15, 1, 1, 0); 35 | t++; 36 | 37 | // Mouse example demonstrating use of libc function. 38 | mouse(&md); 39 | if (md.left) { r = r + 2; } 40 | r--; 41 | r = max(0, min(32, r)); 42 | line(md.x, 0, md.x, 136, 11); 43 | line(0, md.y, 240, md.y, 11); 44 | circ(md.x, md.y, r, 11); 45 | 46 | const int BUFSIZ = 10; 47 | char buf[BUFSIZ]; 48 | snprintf(buf, BUFSIZ, "(%03d,%03d)", md.x, md.y); 49 | print(buf, 3, 3, 15, 0, 1, 1); 50 | } -------------------------------------------------------------------------------- /src/system/sokol/sokol_impl.m: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #define SOKOL_IMPL 24 | 25 | #include "sokol_app.h" 26 | #include "sokol_gfx.h" 27 | #include "sokol_time.h" 28 | #include "sokol_audio.h" 29 | -------------------------------------------------------------------------------- /src/system/baremetalpi/customchargenerator.h: -------------------------------------------------------------------------------- 1 | // 2 | // chargenerator.h 3 | // 4 | // Circle - A C++ bare metal environment for Raspberry Pi 5 | // Copyright (C) 2014 R. Stange 6 | // 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | // 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | // 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program. If not, see . 19 | // 20 | #ifndef _customchargenerator_h 21 | #define _customchargenerator_h 22 | 23 | #include 24 | 25 | class CCharGenerator 26 | { 27 | public: 28 | CCharGenerator (void); 29 | ~CCharGenerator (void); 30 | 31 | unsigned GetCharWidth (void) const; 32 | unsigned GetCharHeight (void) const; 33 | unsigned GetUnderline (void) const; 34 | 35 | boolean GetPixel (char chAscii, unsigned nPosX, unsigned nPosY) const; 36 | 37 | private: 38 | unsigned m_nCharWidth; 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/cart.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2020 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "tic.h" 26 | 27 | void tic_cart_load(tic_cartridge* rom, const u8* buffer, s32 size); 28 | s32 tic_cart_save(const tic_cartridge* rom, u8* buffer); 29 | -------------------------------------------------------------------------------- /src/ext/kiss_fftr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003-2004, Mark Borgerding. All rights reserved. 3 | * This file is part of KISS FFT - https://github.com/mborgerding/kissfft 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | * See COPYING file for more information. 7 | */ 8 | 9 | #ifndef KISS_FTR_H 10 | #define KISS_FTR_H 11 | 12 | #include "kiss_fft.h" 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | 18 | /* 19 | 20 | Real optimized version can save about 45% cpu time vs. complex fft of a real seq. 21 | 22 | 23 | 24 | */ 25 | 26 | typedef struct kiss_fftr_state* kiss_fftr_cfg; 27 | 28 | 29 | kiss_fftr_cfg kiss_fftr_alloc(int nfft, int inverse_fft, void* mem, size_t* lenmem); 30 | /* 31 | nfft must be even 32 | 33 | If you don't care to allocate space, use mem = lenmem = NULL 34 | */ 35 | 36 | 37 | void kiss_fftr(kiss_fftr_cfg cfg, const kiss_fft_scalar* timedata, kiss_fft_cpx* freqdata); 38 | /* 39 | input timedata has nfft scalar points 40 | output freqdata has nfft/2+1 complex points 41 | */ 42 | 43 | void kiss_fftri(kiss_fftr_cfg cfg, const kiss_fft_cpx* freqdata, kiss_fft_scalar* timedata); 44 | /* 45 | input freqdata has nfft/2+1 complex points 46 | output timedata has nfft scalar points 47 | */ 48 | 49 | #define kiss_fftr_free KISS_FFT_FREE 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | #endif 55 | -------------------------------------------------------------------------------- /src/studio/project.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2020 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "cart.h" 26 | 27 | bool tic_project_load(const char* name, const char* data, s32 size, tic_cartridge* dst); 28 | s32 tic_project_save(const char* name, void* data, const tic_cartridge* cart); 29 | -------------------------------------------------------------------------------- /templates/rust/README.md: -------------------------------------------------------------------------------- 1 | # Rust Starter Project Template 2 | 3 | ## Important Note 4 | This template currently produces unoptimised builds. This is required due to TIC-80's memory layout placing data at the address 0, which Rust does not understand. 5 | If you aren't using direct framebuffer access, you should be able to use another level by changing the `Cargo.toml`. 6 | 7 | This is a Rust / TIC-80 starter template. Before using it, make sure you have installed the `wasm32-unknown-unknown` target using rustup: 8 | ``` 9 | rustup target add wasm32-unknown-unknown 10 | ``` 11 | 12 | Then, to build a cart.wasm file, run: 13 | 14 | ``` 15 | cargo build --release 16 | ``` 17 | 18 | To import the resulting WASM to a cartridge: 19 | 20 | ``` 21 | tic80 --fs . --cmd 'load game.tic & import binary target/wasm32-unknown-unknown/release/cart.wasm & save' 22 | ``` 23 | 24 | Or from the TIC-80 console: 25 | 26 | ``` 27 | load game.tic 28 | import binary target/wasm32-unknown-unknown/release/cart.wasm 29 | save 30 | ``` 31 | 32 | This is assuming you've run TIC-80 with `--fs .` inside your project directory. 33 | 34 | 35 | ## wasm-opt 36 | It is highly recommended that you run `wasm-opt` on the output `cart.wasm` file, especially if using the usual unoptimised builds. To do so, make sure `wasm-opt` is installed, then run: 37 | ``` 38 | wasm-opt -Os target/wasm32-unknown-unknown/release/cart.wasm -o cart.wasm 39 | ``` 40 | This will create a new, smaller `cart.wasm` file in the working directory. -------------------------------------------------------------------------------- /src/system/n3ds/utils.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2020 Adrian "asie" Siekierka 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. 22 | 23 | #pragma once 24 | 25 | #include <3ds.h> 26 | #include 27 | #include 28 | 29 | typedef enum { 30 | TEXTURE_TARGET_RAM, 31 | TEXTURE_TARGET_VRAM 32 | } texture_location; 33 | 34 | bool ctr_load_png(C3D_Tex* tex, const char *name, texture_location loc); -------------------------------------------------------------------------------- /src/studio/screens/mainmenu.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | typedef struct StudioMainMenu StudioMainMenu; 26 | 27 | StudioMainMenu* studio_mainmenu_init(Menu *menu, Config *config); 28 | bool studio_mainmenu_keyboard(StudioMainMenu* menu); 29 | void studio_mainmenu_free(StudioMainMenu* menu); 30 | -------------------------------------------------------------------------------- /src/system/sokol/sokol_impl.c: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #define SOKOL_IMPL 24 | 25 | #if defined(WIN32) 26 | 27 | #ifndef WM_MOUSEHWHEEL 28 | #define WM_MOUSEHWHEEL 0x020E 29 | #endif 30 | 31 | #endif 32 | 33 | #include "sokol_app.h" 34 | #include "sokol_gfx.h" 35 | #include "sokol_time.h" 36 | #include "sokol_audio.h" 37 | -------------------------------------------------------------------------------- /include/tic80_types.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include 26 | #include 27 | 28 | typedef uint8_t u8; 29 | typedef uint16_t u16; 30 | typedef uint32_t u32; 31 | typedef uint64_t u64; 32 | typedef int8_t s8; 33 | typedef int16_t s16; 34 | typedef int32_t s32; 35 | typedef int64_t s64; 36 | -------------------------------------------------------------------------------- /src/ext/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. 3 | * MD5 Message-Digest Algorithm (RFC 1321). 4 | * 5 | * Homepage: 6 | * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 7 | * 8 | * Author: 9 | * Alexander Peslyak, better known as Solar Designer 10 | * 11 | * This software was written by Alexander Peslyak in 2001. No copyright is 12 | * claimed, and the software is hereby placed in the public domain. 13 | * In case this attempt to disclaim copyright and place the software in the 14 | * public domain is deemed null and void, then the software is 15 | * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the 16 | * general public under the following terms: 17 | * 18 | * Redistribution and use in source and binary forms, with or without 19 | * modification, are permitted. 20 | * 21 | * There's ABSOLUTELY NO WARRANTY, express or implied. 22 | * 23 | * See md5.c for more information. 24 | */ 25 | 26 | #ifndef _MD5_H 27 | #define _MD5_H 28 | 29 | /* Any 32-bit or wider unsigned integer data type will do */ 30 | typedef unsigned int MD5_u32plus; 31 | 32 | typedef struct { 33 | MD5_u32plus lo, hi; 34 | MD5_u32plus a, b, c, d; 35 | unsigned char buffer[64]; 36 | MD5_u32plus block[16]; 37 | } MD5_CTX; 38 | 39 | extern void MD5_Init(MD5_CTX *ctx); 40 | extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); 41 | extern void MD5_Final(unsigned char *result, MD5_CTX *ctx); 42 | 43 | #endif -------------------------------------------------------------------------------- /src/ext/history.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include 26 | 27 | typedef struct History History; 28 | 29 | History* history_create(void* data, u32 size); 30 | bool history_add(History* history); 31 | void history_undo(History* history); 32 | void history_redo(History* history); 33 | void history_delete(History* history); -------------------------------------------------------------------------------- /demos/fenneldemo.fnl: -------------------------------------------------------------------------------- 1 | ;; title: game title 2 | ;; author: game developer, email, etc. 3 | ;; desc: short description 4 | ;; site: website link 5 | ;; license: MIT License (change this to your license of choice) 6 | ;; version: 0.1 7 | ;; script: fennel 8 | ;; strict: true 9 | 10 | (var t 0) 11 | (var x 96) 12 | (var y 24) 13 | 14 | (fn _G.TIC [] 15 | (when (btn 0) (set y (- y 1))) 16 | (when (btn 1) (set y (+ y 1))) 17 | (when (btn 2) (set x (- x 1))) 18 | (when (btn 3) (set x (+ x 1))) 19 | (cls 0) 20 | (spr (+ 1 (* (// (% t 60) 30) 2)) 21 | x y 14 3 0 0 2 2) 22 | (print "HELLO WORLD!" 84 84) 23 | (set t (+ t 1))) 24 | 25 | ;; 26 | ;; 001:eccccccccc888888caaaaaaaca888888cacccccccacc0ccccacc0ccccacc0ccc 27 | ;; 002:ccccceee8888cceeaaaa0cee888a0ceeccca0ccc0cca0c0c0cca0c0c0cca0c0c 28 | ;; 003:eccccccccc888888caaaaaaaca888888cacccccccacccccccacc0ccccacc0ccc 29 | ;; 004:ccccceee8888cceeaaaa0cee888a0ceeccca0cccccca0c0c0cca0c0c0cca0c0c 30 | ;; 017:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 31 | ;; 018:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 32 | ;; 019:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 33 | ;; 020:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 34 | ;; 35 | 36 | ;; 37 | ;; 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 38 | ;; 39 | 40 | ;; 41 | ;; 000:100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 42 | ;; 43 | -------------------------------------------------------------------------------- /src/core/languages.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "api.h" 3 | 4 | #if defined(TIC_BUILD_WITH_MRUBY) 5 | extern tic_script_config MRubySyntaxConfig; 6 | #endif 7 | 8 | #if defined(TIC_BUILD_WITH_JS) 9 | extern tic_script_config JsSyntaxConfig; 10 | #endif 11 | 12 | #if defined (TIC_BUILD_WITH_LUA) 13 | extern tic_script_config LuaSyntaxConfig; 14 | #endif 15 | 16 | #if defined(TIC_BUILD_WITH_MOON) 17 | extern tic_script_config MoonSyntaxConfig; 18 | #endif 19 | 20 | #if defined(TIC_BUILD_WITH_FENNEL) 21 | extern tic_script_config FennelSyntaxConfig; 22 | #endif 23 | 24 | #if defined(TIC_BUILD_WITH_SQUIRREL) 25 | extern tic_script_config SquirrelSyntaxConfig; 26 | #endif 27 | 28 | #if defined(TIC_BUILD_WITH_WREN) 29 | extern tic_script_config WrenSyntaxConfig; 30 | #endif 31 | 32 | #if defined(TIC_BUILD_WITH_WASM) 33 | extern tic_script_config WasmSyntaxConfig; 34 | #endif 35 | 36 | 37 | tic_script_config* Languages[] = { 38 | 39 | #if defined (TIC_BUILD_WITH_LUA) 40 | &LuaSyntaxConfig, 41 | #endif 42 | 43 | #if defined(TIC_BUILD_WITH_MRUBY) 44 | &MRubySyntaxConfig, 45 | #endif 46 | 47 | #if defined(TIC_BUILD_WITH_JS) 48 | &JsSyntaxConfig, 49 | #endif 50 | 51 | #if defined(TIC_BUILD_WITH_MOON) 52 | &MoonSyntaxConfig, 53 | #endif 54 | 55 | #if defined(TIC_BUILD_WITH_FENNEL) 56 | &FennelSyntaxConfig, 57 | #endif 58 | 59 | #if defined(TIC_BUILD_WITH_SQUIRREL) 60 | &SquirrelSyntaxConfig, 61 | #endif 62 | 63 | #if defined(TIC_BUILD_WITH_WREN) 64 | &WrenSyntaxConfig, 65 | #endif 66 | 67 | #if defined(TIC_BUILD_WITH_WASM) 68 | &WasmSyntaxConfig, 69 | #endif 70 | 71 | NULL}; 72 | 73 | -------------------------------------------------------------------------------- /src/system/sokol/sokol.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "sokol_app.h" 26 | #include "sokol_gfx.h" 27 | #include "sokol_time.h" 28 | #include "sokol_audio.h" 29 | 30 | #include 31 | 32 | void sokol_calc_viewport(int* x, int* y, int* w, int* h); 33 | void sokol_gfx_init(int w, int h, int sx, int sy, bool integer_scale, bool portrait_top_align); 34 | void sokol_gfx_draw(const uint32_t* ptr); 35 | -------------------------------------------------------------------------------- /src/studio/config.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "studio.h" 26 | 27 | typedef struct Config Config; 28 | 29 | struct Config 30 | { 31 | Studio* studio; 32 | tic_mem* tic; 33 | struct tic_fs* fs; 34 | 35 | StudioConfig data; 36 | tic_cartridge* cart; 37 | 38 | void(*save)(Config*); 39 | void(*reset)(Config*); 40 | }; 41 | 42 | void initConfig(Config* config, Studio* studio, struct tic_fs* fs); 43 | void freeConfig(Config* config); 44 | -------------------------------------------------------------------------------- /src/studio/editors/world.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "studio/studio.h" 26 | #include "map.h" 27 | 28 | typedef struct World World; 29 | 30 | struct World 31 | { 32 | Studio* studio; 33 | tic_mem* tic; 34 | Map* map; 35 | 36 | void* preview; 37 | 38 | void (*tick)(World* world); 39 | void (*scanline)(tic_mem* tic, s32 row, void* data); 40 | }; 41 | 42 | void initWorld(World* world, Studio* studio, Map* map); 43 | void freeWorld(World* world); -------------------------------------------------------------------------------- /demos/rubydemo.rb: -------------------------------------------------------------------------------- 1 | # title: game title 2 | # author: game developer, email, etc. 3 | # desc: short description 4 | # site: website link 5 | # license: MIT License (change this to your license of choice) 6 | # version: 0.1 7 | # script: ruby 8 | 9 | $t=0 10 | $x=96 11 | $y=24 12 | 13 | def TIC 14 | $y-=1 if btn 0 15 | $y+=1 if btn 1 16 | $x-=1 if btn 2 17 | $x+=1 if btn 3 18 | 19 | cls 13 20 | spr 1+(($t%60)/30|0)*2,$x,$y,14,3,0,0,2,2 21 | print "HELLO WORLD!",84,84 22 | $t+=1 23 | end 24 | 25 | # 26 | # 001:eccccccccc888888caaaaaaaca888888cacccccccacc0ccccacc0ccccacc0ccc 27 | # 002:ccccceee8888cceeaaaa0cee888a0ceeccca0ccc0cca0c0c0cca0c0c0cca0c0c 28 | # 003:eccccccccc888888caaaaaaaca888888cacccccccacccccccacc0ccccacc0ccc 29 | # 004:ccccceee8888cceeaaaa0cee888a0ceeccca0cccccca0c0c0cca0c0c0cca0c0c 30 | # 017:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 31 | # 018:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 32 | # 019:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 33 | # 020:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 34 | # 35 | 36 | # 37 | # 000:00000000ffffffff00000000ffffffff 38 | # 001:0123456789abcdeffedcba9876543210 39 | # 002:0123456789abcdef0123456789abcdef 40 | # 41 | 42 | # 43 | # 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000 44 | # 45 | 46 | # 47 | # 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 48 | # 49 | 50 | # 51 | # 000:100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 52 | # 53 | -------------------------------------------------------------------------------- /templates/rust/src/alloc.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "buddy-alloc")] 2 | 3 | use std::alloc::{GlobalAlloc, Layout}; 4 | use std::cell::RefCell; 5 | 6 | use buddy_alloc::{BuddyAllocParam, FastAllocParam, NonThreadsafeAlloc}; 7 | 8 | extern "C" { 9 | static __heap_base: u8; 10 | } 11 | 12 | const FAST_HEAP_SIZE: usize = 24 * 1024; 13 | const LEAF_SIZE: usize = 16; 14 | 15 | // This allocator implementation will, on first use, prepare a NonThreadsafeAlloc using all the remaining memory. 16 | // This is done at runtime as a workaround for the fact that __heap_base can't be accessed at compile time. 17 | struct TicAlloc(RefCell>); 18 | 19 | unsafe impl GlobalAlloc for TicAlloc { 20 | unsafe fn alloc(&self, layout: Layout) -> *mut u8 { 21 | let is_none = self.0.borrow().is_none(); 22 | if is_none { 23 | let mut inner = self.0.borrow_mut(); 24 | *inner = { 25 | let fast_heap_ptr = std::ptr::addr_of!(__heap_base); 26 | let heap_ptr = fast_heap_ptr.add(FAST_HEAP_SIZE); 27 | let heap_size = 0x40000 - (heap_ptr as usize); 28 | 29 | let fast_param = FastAllocParam::new(fast_heap_ptr, FAST_HEAP_SIZE); 30 | let buddy_param = BuddyAllocParam::new(heap_ptr, heap_size, LEAF_SIZE); 31 | Some(NonThreadsafeAlloc::new(fast_param, buddy_param)) 32 | }; 33 | } 34 | self.0.borrow().as_ref().unwrap().alloc(layout) 35 | } 36 | 37 | unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { 38 | self.0.borrow().as_ref().unwrap().dealloc(ptr, layout) 39 | } 40 | } 41 | 42 | unsafe impl Sync for TicAlloc {} 43 | 44 | #[global_allocator] 45 | static ALLOC: TicAlloc = TicAlloc(RefCell::new(None)); 46 | -------------------------------------------------------------------------------- /src/studio/screens/run.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "../system.h" 26 | #include "studio/studio.h" 27 | 28 | typedef struct Run Run; 29 | 30 | struct Run 31 | { 32 | Studio* studio; 33 | tic_mem* tic; 34 | struct Console* console; 35 | struct tic_fs* fs; 36 | tic_tick_data tickData; 37 | 38 | bool exit; 39 | 40 | char saveid[TICNAME_MAX]; 41 | tic_persistent pmem; 42 | 43 | void(*tick)(Run*); 44 | }; 45 | 46 | void initRun(Run*, struct Console*, struct tic_fs*, Studio* studio); 47 | void freeRun(Run* run); 48 | -------------------------------------------------------------------------------- /demos/jsdemo.js: -------------------------------------------------------------------------------- 1 | // title: game title 2 | // author: game developer, email, etc. 3 | // desc: short description 4 | // site: website link 5 | // license: MIT License (change this to your license of choice) 6 | // version: 0.1 7 | // script: js 8 | 9 | var t=0 10 | var x=96 11 | var y=24 12 | 13 | function TIC() 14 | { 15 | if(btn(0))y-- 16 | if(btn(1))y++ 17 | if(btn(2))x-- 18 | if(btn(3))x++ 19 | 20 | cls(13) 21 | spr(1+((t%60)/30|0)*2,x,y,14,3,0,0,2,2) 22 | print("HELLO WORLD!",84,84) 23 | t++ 24 | } 25 | 26 | // 27 | // 001:eccccccccc888888caaaaaaaca888888cacccccccacc0ccccacc0ccccacc0ccc 28 | // 002:ccccceee8888cceeaaaa0cee888a0ceeccca0ccc0cca0c0c0cca0c0c0cca0c0c 29 | // 003:eccccccccc888888caaaaaaaca888888cacccccccacccccccacc0ccccacc0ccc 30 | // 004:ccccceee8888cceeaaaa0cee888a0ceeccca0cccccca0c0c0cca0c0c0cca0c0c 31 | // 017:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 32 | // 018:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 33 | // 019:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 34 | // 020:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 35 | // 36 | 37 | // 38 | // 000:00000000ffffffff00000000ffffffff 39 | // 001:0123456789abcdeffedcba9876543210 40 | // 002:0123456789abcdef0123456789abcdef 41 | // 42 | 43 | // 44 | // 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000 45 | // 46 | 47 | // 48 | // 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 49 | // 50 | 51 | // 52 | // 000:100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 53 | // 54 | -------------------------------------------------------------------------------- /src/system/baremetalpi/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | 4 | #define MAXBUFLEN (1024*1024) 5 | 6 | 7 | extern "C" { 8 | 9 | // this functions are absent for circle-stdlib for some reason 10 | // (maybe i can't link properly). Since they shouldn't be used 11 | // too much, i'll put some stub here. Chmod is ok since we're on 12 | // fat anyway, symlink won't work either. ftruncate could break 13 | // something 14 | 15 | int chmod (const char *filename, mode_t mode) 16 | { 17 | dbg("called chmod\n"); 18 | return -1; 19 | } 20 | 21 | int ftruncate(int fd, off_t length) 22 | { 23 | dbg("called ftruncate\n"); 24 | return -1; 25 | } 26 | 27 | int symlink(const char *target, const char *linkpath) 28 | { 29 | dbg("called symlink\n"); 30 | 31 | return -1; 32 | } 33 | } 34 | 35 | char *strdup (const char *s) { 36 | char *d = (char*)malloc (strlen (s) + 1); // Space for length plus nul 37 | if (d == NULL) return NULL; // No memory 38 | strcpy (d,s); // Copy the characters 39 | return d; // Return the new string 40 | } 41 | 42 | 43 | 44 | void* loadFile(const char *filename, u32* size) 45 | { 46 | /* 47 | // slow way to load a file since we don't have fseek 48 | / char source[MAXBUFLEN]; 49 | FILE *fp = fopen(filename, "rb"); 50 | if (fp != NULL) { 51 | size_t newLen = fread(source, sizeof(char), MAXBUFLEN, fp); 52 | if ( ferror( fp ) != 0 ) { 53 | fputs("Error reading file", stderr); 54 | } else { 55 | } 56 | 57 | fclose(fp); 58 | printf("STREAM SIZE is %d\n", newLen); 59 | void* cart = malloc(newLen); 60 | memcpy(cart, source, newLen); 61 | *size = newLen; 62 | return cart; 63 | } 64 | else 65 | { 66 | return NULL; 67 | } 68 | */ 69 | return NULL; 70 | } 71 | 72 | -------------------------------------------------------------------------------- /demos/moondemo.moon: -------------------------------------------------------------------------------- 1 | -- title: game title 2 | -- author: game developer, email, etc. 3 | -- desc: short description 4 | -- site: website link 5 | -- license: MIT License (change this to your license of choice) 6 | -- version: 0.1 7 | -- script: moon 8 | 9 | t=0 10 | x=96 11 | y=24 12 | 13 | export TIC=-> 14 | if btn 0 15 | y-=1 16 | if btn 1 17 | y+=1 18 | if btn 2 19 | x-=1 20 | if btn 3 21 | x+=1 22 | 23 | cls 13 24 | spr 1+(t%60)//30*2,x,y,14,3,0,0,2,2 25 | print "HELLO WORLD!",84,84 26 | t+=1 27 | 28 | -- 29 | -- 001:eccccccccc888888caaaaaaaca888888cacccccccacc0ccccacc0ccccacc0ccc 30 | -- 002:ccccceee8888cceeaaaa0cee888a0ceeccca0ccc0cca0c0c0cca0c0c0cca0c0c 31 | -- 003:eccccccccc888888caaaaaaaca888888cacccccccacccccccacc0ccccacc0ccc 32 | -- 004:ccccceee8888cceeaaaa0cee888a0ceeccca0cccccca0c0c0cca0c0c0cca0c0c 33 | -- 017:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 34 | -- 018:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 35 | -- 019:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 36 | -- 020:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 37 | -- 38 | 39 | -- 40 | -- 000:00000000ffffffff00000000ffffffff 41 | -- 001:0123456789abcdeffedcba9876543210 42 | -- 002:0123456789abcdef0123456789abcdef 43 | -- 44 | 45 | -- 46 | -- 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000 47 | -- 48 | 49 | -- 50 | -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 51 | -- 52 | 53 | -- 54 | -- 000:100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 55 | -- 56 | -------------------------------------------------------------------------------- /src/system/n3ds/keyboard.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2020 Adrian "asie" Siekierka 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. 22 | 23 | #pragma once 24 | 25 | #include "tic.h" 26 | #include "api.h" 27 | 28 | #include <3ds.h> 29 | #include 30 | 31 | typedef struct 32 | { 33 | C3D_Tex tex; 34 | u8 kd[8]; 35 | u32 kd_count; 36 | bool render_dirty; 37 | 38 | u64 scroll_debounce; 39 | } tic_n3ds_keyboard; 40 | 41 | void n3ds_keyboard_init(tic_n3ds_keyboard *kbd); 42 | void n3ds_keyboard_free(tic_n3ds_keyboard *kbd); 43 | void n3ds_keyboard_draw(tic_n3ds_keyboard *kbd); 44 | void n3ds_keyboard_update(tic_n3ds_keyboard *kbd, tic80_input* input); 45 | void n3ds_gamepad_update(tic_n3ds_keyboard *kbd, tic80_input* input); -------------------------------------------------------------------------------- /demos/squirreldemo.nut: -------------------------------------------------------------------------------- 1 | // title: game title 2 | // author: game developer, email, etc. 3 | // desc: short description 4 | // site: website link 5 | // license: MIT License (change this to your license of choice) 6 | // version: 0.1 7 | // script: squirrel 8 | 9 | t<-0 10 | x<-96 11 | y<-24 12 | 13 | function TIC() 14 | { 15 | if (btn(0)) y=y-1; 16 | if (btn(1)) y=y+1; 17 | if (btn(2)) x=x-1; 18 | if (btn(3)) x=x+1; 19 | 20 | cls(13) 21 | spr(1+((t%60)/30)*2,x,y,14,3,0,0,2,2) 22 | print("HELLO WORLD!",84,84) 23 | t=t+1 24 | } 25 | 26 | // 27 | // 001:eccccccccc888888caaaaaaaca888888cacccccccacc0ccccacc0ccccacc0ccc 28 | // 002:ccccceee8888cceeaaaa0cee888a0ceeccca0ccc0cca0c0c0cca0c0c0cca0c0c 29 | // 003:eccccccccc888888caaaaaaaca888888cacccccccacccccccacc0ccccacc0ccc 30 | // 004:ccccceee8888cceeaaaa0cee888a0ceeccca0cccccca0c0c0cca0c0c0cca0c0c 31 | // 017:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 32 | // 018:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 33 | // 019:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 34 | // 020:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 35 | // 36 | 37 | // 38 | // 000:00000000ffffffff00000000ffffffff 39 | // 001:0123456789abcdeffedcba9876543210 40 | // 002:0123456789abcdef0123456789abcdef 41 | // 42 | 43 | // 44 | // 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000 45 | // 46 | 47 | // 48 | // 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 49 | // 50 | 51 | // 52 | // 000:100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 53 | // 54 | -------------------------------------------------------------------------------- /demos/fire.lua: -------------------------------------------------------------------------------- 1 | -- title: fire 2 | -- author: by Filippo 3 | -- desc: fire demo 4 | -- script: lua 5 | -- input: gamepad 6 | 7 | t=0 8 | x=120 9 | y=120 10 | 11 | particle = {} 12 | palete = {14,9,6,3,10,15} 13 | 14 | function addParticle(x,y) 15 | local p = {} 16 | p.x = x 17 | p.y = y 18 | p.dx = math.random(-10.0,10.0)/150.0 19 | p.dy = math.random(-10.0,-2)/50 20 | p.t = 0 21 | table.insert(particle,p) 22 | end 23 | 24 | function ticParticle() 25 | --print("#"..#particle) 26 | local s=0 27 | local s2=0 28 | local c=0 29 | for k,p in pairs(particle) do 30 | p.t = p.t + 1 31 | s = math.log(p.t / 2.0) 32 | s2 = s/2.0 33 | c = palete[math.ceil(p.t/70)] 34 | p.x = p.x + p.dx 35 | p.y = p.y + p.dy 36 | 37 | rect(p.x-s2,p.y-s2,s,s,c) 38 | 39 | --remove old ones 40 | if p.t > 300 then 41 | table.remove(particle,k) 42 | end 43 | end 44 | end 45 | 46 | function TIC() 47 | 48 | if btn(0) then y=y-1 end 49 | if btn(1) then y=y+1 end 50 | if btn(2) then x=x-1 end 51 | if btn(3) then x=x+1 end 52 | 53 | --warp space 54 | x = x % 240 55 | y = y % 136 56 | 57 | --reset 58 | if btn(4) then 59 | x = 120 60 | y = 120 61 | end 62 | 63 | addParticle(x,y) 64 | addParticle(30,130) 65 | addParticle(210,130) 66 | 67 | cls(8) 68 | 69 | --Update & Draw particles 70 | ticParticle() 71 | 72 | --cursor 73 | pix(x,y,7) 74 | 75 | print("! FIRE !",94,64) 76 | t=t+1 77 | end 78 | 79 | -- 80 | -- 001:a000000aa0f00f0aaaaaaaaaaafaaa6aafffaaaaaafaa6aaaaaaaaaa33333333 81 | -- 002:a000000aa060060aaaaaaaaaaafaaa6aafffaaaaaafaa6aaaaaaaaaa33333333 82 | -- 017:e963af00e963af00e963af00e963af00e963af00e963af00e963af00e963af00 83 | -- 84 | 85 | -- 86 | -- 000:140c1c44243430346d4e4a4e854c30346524d04648757161597dced27d2c8595a16daa2cd2aa996dc2cadad45edeeed6 87 | -- 88 | 89 | -------------------------------------------------------------------------------- /include/retro_inline.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2010-2020 The RetroArch team 2 | * 3 | * --------------------------------------------------------------------------------------- 4 | * The following license statement only applies to this file (retro_inline.h). 5 | * --------------------------------------------------------------------------------------- 6 | * 7 | * Permission is hereby granted, free of charge, 8 | * to any person obtaining a copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 11 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 16 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | * 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 SOFTWARE. 21 | */ 22 | 23 | #ifndef __LIBRETRO_SDK_INLINE_H 24 | #define __LIBRETRO_SDK_INLINE_H 25 | 26 | #ifndef INLINE 27 | 28 | #if defined(_WIN32) || defined(__INTEL_COMPILER) 29 | #define INLINE __inline 30 | #elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L 31 | #define INLINE inline 32 | #elif defined(__GNUC__) 33 | #define INLINE __inline__ 34 | #else 35 | #define INLINE 36 | #endif 37 | 38 | #endif 39 | #endif 40 | -------------------------------------------------------------------------------- /demos/bunny/wasmmark/wasmmark.wasmp: -------------------------------------------------------------------------------- 1 | -- title: Bunnymark in Zig 2 | -- author: Josh Goebel 3 | -- desc: Benchmarking tool to see how many bunnies can fly around the screen, using Lua. 4 | -- input: gamepad 5 | -- script: wasm 6 | -- license: MIT 7 | -- version: 0.1 8 | 9 | """"""""""""""""""""""""""""""""""""""" 10 | 11 | This is a WASM binary project, you 12 | won't find the Zig source here. 13 | 14 | For source code see the TIC-80 15 | repository folder: 16 | 17 | /demos/bunny/wasmmark/ 18 | 19 | " 20 | 21 | -- 22 | -- 001:11111100111110dd111110dc111110dc111110dc111110dc111110dd111110dd 23 | -- 002:00011110ddd0110dccd0110dccd0110dccd0110dccd0110dcddd00dddddddddd 24 | -- 003:00001111dddd0111cccd0111cccd0111cccd0111cccd0111dcdd0111dddd0111 25 | -- 004:1111111111111111111111111111111111111111111111111111111111111111 26 | -- 017:111110dd111110dd111110dd111110dd10000ddd1eeeeddd1eeeeedd10000eed 27 | -- 018:d0ddddddd0ddddddddddddddddd0000dddddccddddddccdddddddddddddddddd 28 | -- 019:0ddd01110ddd0111dddd0111dddd0111ddddd000ddddddddddddddddddddd000 29 | -- 020:1111111111111111111111111111111101111111d0111111d011111101111111 30 | -- 033:111110ee111110ee111110ee111110ee111110ee111110ee111110ee111110ee 31 | -- 034:dddcccccddccccccddccccccddccccccddccccccdddcccccdddddddddddddddd 32 | -- 035:dddd0111cddd0111cddd0111cddd0111cddd0111dddd0111dddd0111dddd0111 33 | -- 036:1111111111111111111111111111111111111111111111111111111111111111 34 | -- 049:111110ee111110ee111110ee111110ee111110ee111110ee111110ee11111100 35 | -- 050:dddeeeeeddeeeeeed00000000111111101111111011111110111111111111111 36 | -- 051:eddd0111eedd01110eed011110ee011110ee011110ee011110ee011111001111 37 | -- 052:1111111111111111111111111111111111111111111111111111111111111111 38 | -- 39 | 40 | -- 41 | -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 42 | -- 43 | -------------------------------------------------------------------------------- /src/studio/editors/sfx.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "studio/studio.h" 26 | 27 | typedef struct Sfx Sfx; 28 | 29 | struct Sfx 30 | { 31 | Studio* studio; 32 | tic_mem* tic; 33 | 34 | tic_sfx* src; 35 | 36 | u8 index:SFX_COUNT_BITS; 37 | s32 volwave; 38 | s32 hoverWave; 39 | s32 holdValue; 40 | 41 | struct 42 | { 43 | bool active; 44 | s32 note; 45 | u32 tick; 46 | } play; 47 | 48 | struct History* history; 49 | struct History* waveHistory; 50 | 51 | void(*tick)(Sfx*); 52 | void(*event)(Sfx*, StudioEvent); 53 | }; 54 | 55 | void initSfx(Sfx*, Studio* studio, tic_sfx* src); 56 | void freeSfx(Sfx* sfx); 57 | -------------------------------------------------------------------------------- /src/ext/gif.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include 26 | 27 | typedef struct 28 | { 29 | u8 r; 30 | u8 g; 31 | u8 b; 32 | }gif_color; 33 | 34 | typedef struct 35 | { 36 | u8* buffer; 37 | 38 | gif_color* palette; 39 | 40 | s32 width; 41 | s32 height; 42 | 43 | s32 colors; 44 | } gif_image; 45 | 46 | gif_image* gif_read_data(const void* buffer, s32 size); 47 | bool gif_write_data(const void* buffer, s32* size, s32 width, s32 height, const u8* data, const gif_color* palette, u8 bpp); 48 | bool gif_write_animation(const void* buffer, s32* size, s32 width, s32 height, const u8* data, s32 frames, s32 fps, s32 scale); 49 | void gif_close(gif_image* image); 50 | -------------------------------------------------------------------------------- /templates/c/README.md: -------------------------------------------------------------------------------- 1 | # C Starter Project Template 2 | 3 | ## Pre-requisites 4 | 5 | - [WASI SDK](https://github.com/WebAssembly/wasi-sdk) 6 | 7 | ## Files in this template 8 | 9 | - ```buildcart.sh``` - convenience script to build and run the game cartridge 10 | - ```buildwasm.sh``` - convenience script to build and run the Wasm program 11 | - ```Makefile``` - convenience Makefile that builds the project 12 | - ```wasmdemo.wasmp``` - TIC-80 Wasm 'script' file. Note the embedded game assets data at the end of the file. 13 | 14 | ## Building your game 15 | 16 | Define the environment variable WASI_SDK_PATH; e.g., if you installed WASI 17 | into ```$HOME/wasi-sdk```, then ```export WASI_SDK_PATH=$HOME/wasi-sdk```. 18 | 19 | Edit ```src/main.c``` to implement your game. You are of course free to 20 | organize your code in more than one C source file. 21 | 22 | If you create sprites, map, music, etc., for your game, remember to 23 | replace the game asset data at the end of ```wasmdemo.wasmp``` with 24 | your creations. 25 | 26 | To build the Wasm file, execute ```make```. This generates ```cart.wasm``` 27 | in the build directory. To run: 28 | 29 | ``` 30 | % tic80 --fs . --cmd 'load wasmdemo.wasmp & import binary cart.wasm & run & exit' 31 | ``` 32 | 33 | The script ```buildwasm.sh``` contains above steps as a convenience. 34 | 35 | To build a TIC-80 cartridge, first build the Wasm file, then build the 36 | cartridge file: 37 | 38 | ``` 39 | % tic80 --fs . --cmd 'load wasmdemo.wasmp & import binary cart.wasm & save game.tic & exit' 40 | ``` 41 | 42 | You can then run your cartridge as follows: 43 | 44 | ``` 45 | % tic80 --fs . --cmd 'load game.tic & run & exit' 46 | ``` 47 | 48 | The script ```buildcart.sh``` does the above steps as a convenience. 49 | 50 | ## Additional Notes 51 | TIC-80 API functions that merely duplicate standard library functionality are not imported. Please use the `memcpy` and `memset` functions provided by the C standard library instead. -------------------------------------------------------------------------------- /demos/wrendemo.wren: -------------------------------------------------------------------------------- 1 | // title: game title 2 | // author: game developer, email, etc. 3 | // desc: short description 4 | // site: website link 5 | // license: MIT License (change this to your license of choice) 6 | // version: 0.1 7 | // script: wren 8 | 9 | class Game is TIC{ 10 | 11 | construct new(){ 12 | _t=0 13 | _x=96 14 | _y=24 15 | } 16 | 17 | TIC(){ 18 | if(TIC.btn(0)){ 19 | _y=_y-1 20 | } 21 | if(TIC.btn(1)){ 22 | _y=_y+1 23 | } 24 | if(TIC.btn(2)){ 25 | _x=_x-1 26 | } 27 | if(TIC.btn(3)){ 28 | _x=_x+1 29 | } 30 | 31 | TIC.cls(13) 32 | TIC.spr(1+((_t%60)/30|0)*2,_x,_y,14,3,0,0,2,2) 33 | TIC.print("HELLO WORLD!",84,84) 34 | 35 | _t=_t+1 36 | } 37 | } 38 | 39 | // 40 | // 001:eccccccccc888888caaaaaaaca888888cacccccccacc0ccccacc0ccccacc0ccc 41 | // 002:ccccceee8888cceeaaaa0cee888a0ceeccca0ccc0cca0c0c0cca0c0c0cca0c0c 42 | // 003:eccccccccc888888caaaaaaaca888888cacccccccacccccccacc0ccccacc0ccc 43 | // 004:ccccceee8888cceeaaaa0cee888a0ceeccca0cccccca0c0c0cca0c0c0cca0c0c 44 | // 017:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 45 | // 018:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 46 | // 019:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 47 | // 020:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 48 | // 49 | 50 | // 51 | // 000:00000000ffffffff00000000ffffffff 52 | // 001:0123456789abcdeffedcba9876543210 53 | // 002:0123456789abcdef0123456789abcdef 54 | // 55 | 56 | // 57 | // 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000 58 | // 59 | 60 | // 61 | // 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 62 | // 63 | 64 | // 65 | // 000:100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 66 | // 67 | -------------------------------------------------------------------------------- /templates/zig/wasmdemo.wasmp: -------------------------------------------------------------------------------- 1 | -- desc: WASM Introduction 2 | -- script: wasm 3 | 4 | """"""""""""""""""""""""""""""""""""""" 5 | WASM is a binary format. The demo 6 | binary code is embedded in this 7 | cartridge, the source code is not. 8 | Run the cart to see the demo. 9 | 10 | This demo exits for completeness, but 11 | you can't (yet) develop WASM projects 12 | using the built-in editor. 13 | 14 | The code used to build this project 15 | can be found in the TIC-80 repo: 16 | 17 | https://github.com/nesbox/TIC-80 18 | /demos/wasm/ 19 | 20 | This demo was built with Zig, but many 21 | languages are supported. You simply 22 | build your project with your external 23 | compiler, then import the final WASM 24 | binary into your cartridge: 25 | 26 | import binary out.wasm 27 | 28 | To learn more visit our Wiki and 29 | the 'Getting Started with WASM' page. 30 | 31 | " 32 | -- 33 | -- 001:eccccccccc888888caaaaaaaca888888cacccccccacc0ccccacc0ccccacc0ccc 34 | -- 002:ccccceee8888cceeaaaa0cee888a0ceeccca0ccc0cca0c0c0cca0c0c0cca0c0c 35 | -- 003:eccccccccc888888caaaaaaaca888888cacccccccacccccccacc0ccccacc0ccc 36 | -- 004:ccccceee8888cceeaaaa0cee888a0ceeccca0cccccca0c0c0cca0c0c0cca0c0c 37 | -- 017:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 38 | -- 018:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 39 | -- 019:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 40 | -- 020:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 41 | -- 42 | 43 | -- 44 | -- 000:00000000ffffffff00000000ffffffff 45 | -- 001:0123456789abcdeffedcba9876543210 46 | -- 002:0123456789abcdef0123456789abcdef 47 | -- 48 | 49 | -- 50 | -- 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000 51 | -- 52 | 53 | -- 54 | -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 55 | -- 56 | 57 | -------------------------------------------------------------------------------- /src/ext/png.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2021 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include 26 | 27 | typedef struct 28 | { 29 | u8* data; 30 | s32 size; 31 | } png_buffer; 32 | 33 | typedef union 34 | { 35 | struct 36 | { 37 | u8 r; 38 | u8 g; 39 | u8 b; 40 | u8 a; 41 | }; 42 | 43 | u8 data[4]; 44 | 45 | u32 value; 46 | } png_rgba; 47 | 48 | typedef struct 49 | { 50 | s32 width; 51 | s32 height; 52 | 53 | union 54 | { 55 | png_rgba* pixels; 56 | u32* values; 57 | u8* data; 58 | }; 59 | } png_img; 60 | 61 | png_buffer png_create(s32 size); 62 | 63 | png_img png_read(png_buffer buf); 64 | png_buffer png_write(png_img src); 65 | 66 | png_buffer png_encode(png_buffer cover, png_buffer cart); 67 | png_buffer png_decode(png_buffer cover); 68 | -------------------------------------------------------------------------------- /templates/c/wasmdemo.wasmp: -------------------------------------------------------------------------------- 1 | -- desc: WASM Introduction 2 | -- script: wasm 3 | 4 | """"""""""""""""""""""""""""""""""""""" 5 | WASM is a binary format. The demo 6 | binary code is embedded in this 7 | cartridge, the source code is not. 8 | Run the cart to see the demo. 9 | 10 | This demo exits for completeness, but 11 | you can't (yet) develop WASM projects 12 | using the built-in editor. 13 | 14 | The code used to build this project 15 | can be found in the TIC-80 repo: 16 | 17 | https://github.com/nesbox/TIC-80/templates/c 18 | 19 | This demo was built with C, but many 20 | languages are supported. You simply 21 | build your project with your external 22 | compiler, then import the final WASM 23 | binary into your cartridge: 24 | 25 | import binary out.wasm 26 | 27 | See README.md for details. 28 | 29 | To learn more visit our Wiki and 30 | the 'Getting Started with WASM' page. 31 | 32 | " 33 | -- 34 | -- 001:eccccccccc888888caaaaaaaca888888cacccccccacc0ccccacc0ccccacc0ccc 35 | -- 002:ccccceee8888cceeaaaa0cee888a0ceeccca0ccc0cca0c0c0cca0c0c0cca0c0c 36 | -- 003:eccccccccc888888caaaaaaaca888888cacccccccacccccccacc0ccccacc0ccc 37 | -- 004:ccccceee8888cceeaaaa0cee888a0ceeccca0cccccca0c0c0cca0c0c0cca0c0c 38 | -- 017:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 39 | -- 018:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 40 | -- 019:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 41 | -- 020:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 42 | -- 43 | 44 | -- 45 | -- 000:00000000ffffffff00000000ffffffff 46 | -- 001:0123456789abcdeffedcba9876543210 47 | -- 002:0123456789abcdef0123456789abcdef 48 | -- 49 | 50 | -- 51 | -- 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000 52 | -- 53 | 54 | -- 55 | -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 56 | -- 57 | 58 | -------------------------------------------------------------------------------- /templates/d/wasmdemo.wasmp: -------------------------------------------------------------------------------- 1 | -- desc: WASM Introduction 2 | -- script: wasm 3 | 4 | """"""""""""""""""""""""""""""""""""""" 5 | WASM is a binary format. The demo 6 | binary code is embedded in this 7 | cartridge, the source code is not. 8 | Run the cart to see the demo. 9 | 10 | This demo exits for completeness, but 11 | you can't (yet) develop WASM projects 12 | using the built-in editor. 13 | 14 | The code used to build this project 15 | can be found in the TIC-80 repo: 16 | 17 | https://github.com/nesbox/TIC-80/templates/d 18 | 19 | This demo was built with D, but many 20 | languages are supported. You simply 21 | build your project with your external 22 | compiler, then import the final WASM 23 | binary into your cartridge: 24 | 25 | import binary out.wasm 26 | 27 | See README.md for details. 28 | 29 | To learn more visit our Wiki and 30 | the 'Getting Started with WASM' page. 31 | 32 | " 33 | -- 34 | -- 001:eccccccccc888888caaaaaaaca888888cacccccccacc0ccccacc0ccccacc0ccc 35 | -- 002:ccccceee8888cceeaaaa0cee888a0ceeccca0ccc0cca0c0c0cca0c0c0cca0c0c 36 | -- 003:eccccccccc888888caaaaaaaca888888cacccccccacccccccacc0ccccacc0ccc 37 | -- 004:ccccceee8888cceeaaaa0cee888a0ceeccca0cccccca0c0c0cca0c0c0cca0c0c 38 | -- 017:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 39 | -- 018:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 40 | -- 019:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 41 | -- 020:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 42 | -- 43 | 44 | -- 45 | -- 000:00000000ffffffff00000000ffffffff 46 | -- 001:0123456789abcdeffedcba9876543210 47 | -- 002:0123456789abcdef0123456789abcdef 48 | -- 49 | 50 | -- 51 | -- 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000 52 | -- 53 | 54 | -- 55 | -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 56 | -- 57 | 58 | -------------------------------------------------------------------------------- /src/api/lua_api.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | s32 luaopen_lpeg(lua_State *lua); 33 | 34 | extern void initLuaAPI(tic_core* core); 35 | extern void callLuaTick(tic_mem* tic); 36 | extern void callLuaBoot(tic_mem* tic); 37 | extern void callLuaScanlineName(tic_mem* tic, s32 row, void* data, const char* name); 38 | extern void callLuaScanline(tic_mem* tic, s32 row, void* data); 39 | extern void callLuaBorder(tic_mem* tic, s32 row, void* data); 40 | extern void callLuaOverline(tic_mem* tic, void* data); 41 | extern void callLuaMenu(tic_mem* tic, s32 index, void* data); 42 | extern void closeLua(tic_mem* tic); 43 | extern void callLuaTick(tic_mem* tic); 44 | extern void lua_open_builtins(lua_State *lua); 45 | -------------------------------------------------------------------------------- /src/studio/screens/start.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "studio/studio.h" 26 | 27 | #define CART_SIG "TIC.CART" 28 | 29 | typedef struct 30 | { 31 | u8 sig[STRLEN(CART_SIG)]; 32 | s32 appSize; 33 | s32 cartSize; 34 | } EmbedHeader; 35 | 36 | typedef struct Start Start; 37 | 38 | typedef struct stage { 39 | void(*fn)(Start*); 40 | u8 ticks; 41 | } Stage; 42 | 43 | struct Start 44 | { 45 | Studio* studio; 46 | tic_mem* tic; 47 | 48 | bool initialized; 49 | Stage stages[5]; 50 | 51 | u32 stage; 52 | s32 ticks; 53 | bool play; 54 | 55 | char text[STUDIO_TEXT_BUFFER_SIZE]; 56 | u8 color[STUDIO_TEXT_BUFFER_SIZE]; 57 | 58 | bool embed; 59 | 60 | void (*tick)(Start*); 61 | }; 62 | 63 | void initStart(Start* start, Studio* studio, const char* cart); 64 | void freeStart(Start* start); 65 | -------------------------------------------------------------------------------- /demos/wasm/wasmdemo.wasmp: -------------------------------------------------------------------------------- 1 | -- desc: WASM Introduction 2 | -- script: wasm 3 | 4 | """"""""""""""""""""""""""""""""""""""" 5 | WASM is a binary format. The demo 6 | binary code is embedded in this 7 | cartridge, the source code is not. 8 | Run the cart to see the demo. 9 | 10 | This demo exits for completeness, but 11 | you can't (yet) develop WASM projects 12 | using the built-in editor. 13 | 14 | The code used to build this project 15 | can be found in the TIC-80 repo: 16 | 17 | https://github.com/nesbox/TIC-80 18 | /demos/wasm/ 19 | 20 | This demo was built with Zig, but many 21 | languages are supported. You simply 22 | build your project with your external 23 | compiler, then import the final WASM 24 | binary into your cartridge: 25 | 26 | import binary out.wasm 27 | 28 | To learn more visit our Wiki and 29 | the 'Getting Started with WASM' page. 30 | 31 | " 32 | -- 33 | -- 001:eccccccccc888888caaaaaaaca888888cacccccccacc0ccccacc0ccccacc0ccc 34 | -- 002:ccccceee8888cceeaaaa0cee888a0ceeccca0ccc0cca0c0c0cca0c0c0cca0c0c 35 | -- 003:eccccccccc888888caaaaaaaca888888cacccccccacccccccacc0ccccacc0ccc 36 | -- 004:ccccceee8888cceeaaaa0cee888a0ceeccca0cccccca0c0c0cca0c0c0cca0c0c 37 | -- 017:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 38 | -- 018:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 39 | -- 019:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 40 | -- 020:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 41 | -- 42 | 43 | -- 44 | -- 000:00000000ffffffff00000000ffffffff 45 | -- 001:0123456789abcdeffedcba9876543210 46 | -- 002:0123456789abcdef0123456789abcdef 47 | -- 48 | 49 | -- 50 | -- 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000 51 | -- 52 | 53 | -- 54 | -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 55 | -- 56 | 57 | -- 58 | -- 000:100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 59 | -- 60 | -------------------------------------------------------------------------------- /templates/c/Makefile: -------------------------------------------------------------------------------- 1 | ifndef WASI_SDK_PATH 2 | $(error Download the WASI SDK (https://github.com/WebAssembly/wasi-sdk) and set $$WASI_SDK_PATH) 3 | endif 4 | 5 | CC = "$(WASI_SDK_PATH)/bin/clang" --sysroot="$(WASI_SDK_PATH)/share/wasi-sysroot" 6 | CXX = "$(WASI_SDK_PATH)/bin/clang++" --sysroot="$(WASI_SDK_PATH)/share/wasi-sysroot" 7 | 8 | # Optional dependency from binaryen for smaller builds 9 | WASM_OPT = wasm-opt 10 | WASM_OPT_FLAGS = -Oz --zero-filled-memory --strip-producers 11 | 12 | # Whether to build for debugging instead of release 13 | DEBUG = 0 14 | 15 | # Compilation flags 16 | CFLAGS = -W -Wall -Wextra -Werror -Wno-unused -Wconversion -Wsign-conversion -MMD -MP -fno-exceptions 17 | ifeq ($(DEBUG), 1) 18 | CFLAGS += -DDEBUG -O0 -g 19 | else 20 | CFLAGS += -DNDEBUG -Oz -flto 21 | endif 22 | 23 | # Linker flags 24 | LDFLAGS = -Wl,-zstack-size=8192,--no-entry,--import-memory -mexec-model=reactor \ 25 | -Wl,--initial-memory=262144,--max-memory=262144,--global-base=98304 26 | ifeq ($(DEBUG), 1) 27 | LDFLAGS += -Wl,--export-all,--no-gc-sections 28 | else 29 | LDFLAGS += -Wl,--strip-all,--gc-sections,--lto-O3 -Oz 30 | endif 31 | 32 | OBJECTS = $(patsubst src/%.c, build/%.o, $(wildcard src/*.c)) 33 | OBJECTS += $(patsubst src/%.cpp, build/%.o, $(wildcard src/*.cpp)) 34 | DEPS = $(OBJECTS:.o=.d) 35 | 36 | ifeq ($(OS), Windows_NT) 37 | MKDIR_BUILD = if not exist build md build 38 | RMDIR = rd /s /q 39 | else 40 | MKDIR_BUILD = mkdir -p build 41 | RMDIR = rm -rf 42 | endif 43 | 44 | all: build/cart.wasm 45 | 46 | # Link cart.wasm from all object files and run wasm-opt 47 | build/cart.wasm: $(OBJECTS) 48 | $(CXX) -o $@ $(OBJECTS) $(LDFLAGS) 49 | ifneq ($(DEBUG), 1) 50 | ifeq (, $(shell command -v $(WASM_OPT))) 51 | @echo Tip: $(WASM_OPT) was not found. Install it from binaryen for smaller builds! 52 | else 53 | $(WASM_OPT) $(WASM_OPT_FLAGS) $@ -o $@ 54 | endif 55 | endif 56 | 57 | # Compile C sources 58 | build/%.o: src/%.c 59 | @$(MKDIR_BUILD) 60 | $(CC) -c $< -o $@ $(CFLAGS) 61 | 62 | # Compile C++ sources 63 | build/%.o: src/%.cpp 64 | @$(MKDIR_BUILD) 65 | $(CXX) -c $< -o $@ $(CFLAGS) 66 | 67 | .PHONY: clean 68 | clean: 69 | $(RMDIR) build 70 | 71 | -include $(DEPS) -------------------------------------------------------------------------------- /src/studio/net.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "tic80_types.h" 26 | 27 | typedef struct tic_net tic_net; 28 | 29 | typedef struct 30 | { 31 | enum 32 | { 33 | net_get_progress, 34 | net_get_done, 35 | net_get_error, 36 | } type; 37 | 38 | union 39 | { 40 | struct 41 | { 42 | s32 size; 43 | s32 total; 44 | } progress; 45 | 46 | struct 47 | { 48 | s32 size; 49 | u8* data; 50 | } done; 51 | 52 | struct 53 | { 54 | s32 code; 55 | } error; 56 | }; 57 | 58 | void* calldata; 59 | const char* url; 60 | 61 | } net_get_data; 62 | 63 | typedef void(*net_get_callback)(const net_get_data*); 64 | 65 | tic_net* tic_net_create(const char* host); 66 | 67 | void tic_net_get(tic_net* net, const char* url, net_get_callback callback, void* calldata); 68 | void tic_net_close(tic_net* net); 69 | void tic_net_start(tic_net *net); 70 | void tic_net_end(tic_net *net); 71 | -------------------------------------------------------------------------------- /src/system/sdl/kbdlabels.inl: -------------------------------------------------------------------------------- 1 | {"ESC", 0*8+3, 0*8+3, true}, 2 | 3 | {"F1", 2*8+4, 0*8+3, true}, 4 | {"F2", 4*8+4, 0*8+3, true}, 5 | {"F3", 6*8+4, 0*8+3, true}, 6 | {"F4", 8*8+4, 0*8+3, true}, 7 | {"F5", 10*8+4, 0*8+3, true}, 8 | {"F6", 12*8+4, 0*8+3, true}, 9 | {"F7", 14*8+4, 0*8+3, true}, 10 | {"F8", 16*8+4, 0*8+3, true}, 11 | {"F9", 18*8+4, 0*8+3, true}, 12 | {"F10", 20*8+3, 0*8+3, true}, 13 | 14 | {"TAB", 0*8+3, 2*8+4, true}, 15 | {"`", 2*8+3, 2*8+3, false, "~"}, 16 | {"[", 4*8+3, 2*8+3, false, "{"}, 17 | {"]", 6*8+3, 2*8+3, false, "}"}, 18 | {";", 8*8+3, 2*8+3, false, ":"}, 19 | {"'", 10*8+3, 2*8+3, false, "\""}, 20 | {"-", 12*8+3, 2*8+3, false, "_"}, 21 | {"=", 14*8+3, 2*8+3, false, "+"}, 22 | {"/", 16*8+3, 2*8+3, false, "?"}, 23 | {"F11", 18*8+3, 2*8+3, true}, 24 | {"F12", 20*8+3, 2*8+3, true}, 25 | 26 | {"1", 0*8+3, 4*8+3, false, "!"}, 27 | {"2", 2*8+3, 4*8+3, false, "@"}, 28 | {"3", 4*8+3, 4*8+3, false, "#"}, 29 | {"4", 6*8+3, 4*8+3, false, "$"}, 30 | {"5", 8*8+3, 4*8+3, false, "%"}, 31 | {"6", 10*8+3, 4*8+3, false, "^"}, 32 | {"7", 12*8+3, 4*8+3, false, "&"}, 33 | {"8", 14*8+3, 4*8+3, false, "*"}, 34 | {"9", 16*8+3, 4*8+3, false, "("}, 35 | {"0", 18*8+3, 4*8+3, false, ")"}, 36 | {"BAC", 20*8+3, 4*8+4, true}, 37 | 38 | {"Q", 0*8+3, 6*8+3}, 39 | {"W", 2*8+3, 6*8+3}, 40 | {"E", 4*8+3, 6*8+3}, 41 | {"R", 6*8+3, 6*8+3}, 42 | {"T", 8*8+3, 6*8+3}, 43 | {"Y", 10*8+3, 6*8+3}, 44 | {"U", 12*8+3, 6*8+3}, 45 | {"I", 14*8+3, 6*8+3}, 46 | {"O", 16*8+3, 6*8+3}, 47 | {"P", 18*8+3, 6*8+3}, 48 | {"\\", 20*8+3, 6*8+3, false, "|"}, 49 | 50 | {"A", 1*8+3, 8*8+3}, 51 | {"S", 3*8+3, 8*8+3}, 52 | {"D", 5*8+3, 8*8+3}, 53 | {"F", 7*8+3, 8*8+3}, 54 | {"G", 9*8+3, 8*8+3}, 55 | {"H", 11*8+3, 8*8+3}, 56 | {"J", 13*8+3, 8*8+3}, 57 | {"K", 15*8+3, 8*8+3}, 58 | {"L", 17*8+3, 8*8+3}, 59 | {"ENTER", 19*8+3, 8*8+4, true}, 60 | 61 | {"Z", 2*8+3, 10*8+3}, 62 | {"X", 4*8+3, 10*8+3}, 63 | {"C", 6*8+3, 10*8+3}, 64 | {"V", 8*8+3, 10*8+3}, 65 | {"B", 10*8+3, 10*8+3}, 66 | {"N", 12*8+3, 10*8+3}, 67 | {"M", 14*8+3, 10*8+3}, 68 | {",", 16*8+3, 10*8+3, false, "<"}, 69 | {".", 18*8+3, 10*8+3, false, ">"}, 70 | 71 | {"CTRL", 0*8+5, 12*8+4, true}, 72 | {"ALT", 3*8+3, 12*8+4, true}, 73 | {"INS", 12*8+3, 12*8+4, true}, 74 | {"DEL", 14*8+3, 12*8+4, true}, 75 | -------------------------------------------------------------------------------- /src/system/libretro/libretro_core_options_intl.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBRETRO_CORE_OPTIONS_INTL_H__ 2 | #define LIBRETRO_CORE_OPTIONS_INTL_H__ 3 | 4 | #if defined(_MSC_VER) && (_MSC_VER >= 1500 && _MSC_VER < 1900) 5 | /* https://support.microsoft.com/en-us/kb/980263 */ 6 | #pragma execution_character_set("utf-8") 7 | #pragma warning(disable:4566) 8 | #endif 9 | 10 | #include "libretro-common/include/libretro.h" 11 | 12 | /* 13 | ******************************** 14 | * VERSION: 1.3 15 | ******************************** 16 | * 17 | * - 1.3: Move translations to libretro_core_options_intl.h 18 | * - libretro_core_options_intl.h includes BOM and utf-8 19 | * fix for MSVC 2010-2013 20 | * - Added HAVE_NO_LANGEXTRA flag to disable translations 21 | * on platforms/compilers without BOM support 22 | * - 1.2: Use core options v1 interface when 23 | * RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION is >= 1 24 | * (previously required RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION == 1) 25 | * - 1.1: Support generation of core options v0 retro_core_option_value 26 | * arrays containing options with a single value 27 | * - 1.0: First commit 28 | */ 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | /* 35 | ******************************** 36 | * Core Option Definitions 37 | ******************************** 38 | */ 39 | 40 | /* RETRO_LANGUAGE_JAPANESE */ 41 | 42 | /* RETRO_LANGUAGE_FRENCH */ 43 | 44 | /* RETRO_LANGUAGE_SPANISH */ 45 | 46 | /* RETRO_LANGUAGE_GERMAN */ 47 | 48 | /* RETRO_LANGUAGE_ITALIAN */ 49 | 50 | /* RETRO_LANGUAGE_DUTCH */ 51 | 52 | /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ 53 | 54 | /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */ 55 | 56 | /* RETRO_LANGUAGE_RUSSIAN */ 57 | 58 | /* RETRO_LANGUAGE_KOREAN */ 59 | 60 | /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */ 61 | 62 | /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */ 63 | 64 | /* RETRO_LANGUAGE_ESPERANTO */ 65 | 66 | /* RETRO_LANGUAGE_POLISH */ 67 | 68 | /* RETRO_LANGUAGE_VIETNAMESE */ 69 | 70 | /* RETRO_LANGUAGE_ARABIC */ 71 | 72 | /* RETRO_LANGUAGE_GREEK */ 73 | 74 | /* RETRO_LANGUAGE_TURKISH */ 75 | 76 | /* RETRO_LANGUAGE_SLOVAK */ 77 | 78 | /* RETRO_LANGUAGE_PERSIAN */ 79 | 80 | /* RETRO_LANGUAGE_HEBREW */ 81 | 82 | /* RETRO_LANGUAGE_ASTURIAN */ 83 | 84 | /* RETRO_LANGUAGE_FINNISH */ 85 | 86 | #ifdef __cplusplus 87 | } 88 | #endif 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /src/studio/screens/menu.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "tic80_types.h" 26 | 27 | typedef struct Menu Menu; 28 | struct tic_mem; 29 | struct Studio; 30 | 31 | Menu* studio_menu_create(struct Studio* studio); 32 | void studio_menu_tick(Menu* menu); 33 | 34 | typedef s32(*MenuOptionGetHandler)(void*); 35 | typedef void(*MenuOptionSetHandler)(void*, s32); 36 | 37 | typedef struct 38 | { 39 | const char** values; 40 | s32 count; 41 | MenuOptionGetHandler get; 42 | MenuOptionSetHandler set; 43 | s32 width; 44 | s32 pos; 45 | } MenuOption; 46 | 47 | typedef void(*MenuItemHandler)(void*, s32); 48 | 49 | typedef struct 50 | { 51 | const char* label; 52 | MenuItemHandler handler; 53 | 54 | MenuOption* option; 55 | const char* help; 56 | bool back; 57 | s32 width; 58 | } MenuItem; 59 | 60 | void studio_menu_init(Menu* menu, const MenuItem* items, s32 rows, s32 pos, s32 backPos, MenuItemHandler handler, void* data); 61 | bool studio_menu_back(Menu* menu); 62 | void studio_menu_free(Menu* menu); 63 | 64 | void studio_menu_anim(struct tic_mem* tic, s32 ticks); 65 | void studio_menu_anim_scanline(struct tic_mem* tic, s32 row, void* data); 66 | -------------------------------------------------------------------------------- /src/system/sdl/keycodes.inl: -------------------------------------------------------------------------------- 1 | [tic_key_unknown] = SDLK_UNKNOWN, 2 | [tic_key_a] = SDLK_a, 3 | [tic_key_b] = SDLK_b, 4 | [tic_key_c] = SDLK_c, 5 | [tic_key_d] = SDLK_d, 6 | [tic_key_e] = SDLK_e, 7 | [tic_key_f] = SDLK_f, 8 | [tic_key_g] = SDLK_g, 9 | [tic_key_h] = SDLK_h, 10 | [tic_key_i] = SDLK_i, 11 | [tic_key_j] = SDLK_j, 12 | [tic_key_k] = SDLK_k, 13 | [tic_key_l] = SDLK_l, 14 | [tic_key_m] = SDLK_m, 15 | [tic_key_n] = SDLK_n, 16 | [tic_key_o] = SDLK_o, 17 | [tic_key_p] = SDLK_p, 18 | [tic_key_q] = SDLK_q, 19 | [tic_key_r] = SDLK_r, 20 | [tic_key_s] = SDLK_s, 21 | [tic_key_t] = SDLK_t, 22 | [tic_key_u] = SDLK_u, 23 | [tic_key_v] = SDLK_v, 24 | [tic_key_w] = SDLK_w, 25 | [tic_key_x] = SDLK_x, 26 | [tic_key_y] = SDLK_y, 27 | [tic_key_z] = SDLK_z, 28 | 29 | [tic_key_0] = SDLK_0, 30 | [tic_key_1] = SDLK_1, 31 | [tic_key_2] = SDLK_2, 32 | [tic_key_3] = SDLK_3, 33 | [tic_key_4] = SDLK_4, 34 | [tic_key_5] = SDLK_5, 35 | [tic_key_6] = SDLK_6, 36 | [tic_key_7] = SDLK_7, 37 | [tic_key_8] = SDLK_8, 38 | [tic_key_9] = SDLK_9, 39 | 40 | [tic_key_minus] = SDLK_MINUS, 41 | [tic_key_equals] = SDLK_EQUALS, 42 | [tic_key_leftbracket] = SDLK_LEFTBRACKET, 43 | [tic_key_rightbracket] = SDLK_RIGHTBRACKET, 44 | [tic_key_backslash] = SDLK_BACKSLASH, 45 | [tic_key_semicolon] = SDLK_SEMICOLON, 46 | [tic_key_apostrophe] = SDLK_QUOTE, 47 | [tic_key_grave] = SDLK_BACKQUOTE, 48 | [tic_key_comma] = SDLK_COMMA, 49 | [tic_key_period] = SDLK_PERIOD, 50 | [tic_key_slash] = SDLK_SLASH, 51 | [tic_key_space] = SDLK_SPACE, 52 | [tic_key_tab] = SDLK_TAB, 53 | [tic_key_return] = SDLK_RETURN, 54 | [tic_key_backspace] = SDLK_BACKSPACE, 55 | [tic_key_delete] = SDLK_DELETE, 56 | [tic_key_insert] = SDLK_INSERT, 57 | [tic_key_pageup] = SDLK_PAGEUP, 58 | [tic_key_pagedown] = SDLK_PAGEDOWN, 59 | [tic_key_home] = SDLK_HOME, 60 | [tic_key_end] = SDLK_END, 61 | [tic_key_up] = SDLK_UP, 62 | [tic_key_down] = SDLK_DOWN, 63 | [tic_key_left] = SDLK_LEFT, 64 | [tic_key_right] = SDLK_RIGHT, 65 | [tic_key_capslock] = SDLK_CAPSLOCK, 66 | [tic_key_ctrl] = SDLK_LCTRL, 67 | [tic_key_shift] = SDLK_LSHIFT, 68 | [tic_key_alt] = SDLK_LALT, 69 | [tic_key_escape] = SDLK_ESCAPE, 70 | 71 | [tic_key_f1] = SDLK_F1, 72 | [tic_key_f2] = SDLK_F2, 73 | [tic_key_f3] = SDLK_F3, 74 | [tic_key_f4] = SDLK_F4, 75 | [tic_key_f5] = SDLK_F5, 76 | [tic_key_f6] = SDLK_F6, 77 | [tic_key_f7] = SDLK_F7, 78 | [tic_key_f8] = SDLK_F8, 79 | [tic_key_f9] = SDLK_F9, 80 | [tic_key_f10] = SDLK_F10, 81 | [tic_key_f11] = SDLK_F11, 82 | [tic_key_f12] = SDLK_F12, 83 | -------------------------------------------------------------------------------- /templates/d/README.md: -------------------------------------------------------------------------------- 1 | # D Starter Project Template 2 | 3 | ## Pre-requisites 4 | 5 | - [LDC](https://wiki.dlang.org/LDC) 6 | - [WASI libc](https://github.com/WebAssembly/wasi-libc) 7 | 8 | ### WASI libc 9 | 10 | WASI libc's [README](https://github.com/WebAssembly/wasi-libc#usage) states 11 | that "the easiest way to get started with this is to use wask-sdk, which 12 | includes a build of WASI libc in its sysroot." 13 | 14 | Just [building WASI libc from source](https://github.com/WebAssembly/wasi-libc#building-from-source) 15 | works too, for the purpose of programming TIC-80 games in D. Let's say you 16 | install into ```$HOME/wasi-sdk/share/wasi-sysroot```, which then look like this: 17 | 18 | ``` 19 | % ls -l 20 | total 12 21 | drwxr-xr-x 10 pierce pierce 4096 Apr 24 16:19 include/ 22 | drwxr-xr-x 3 pierce pierce 4096 Apr 24 16:19 lib/ 23 | drwxr-xr-x 3 pierce pierce 4096 Apr 24 16:19 share/ 24 | ``` 25 | 26 | ## Files in this template 27 | 28 | - ```buildcart.sh``` - convenience script to build and run the game cartridge 29 | - ```buildwasm.sh``` - convenience script to build and run the Wasm program 30 | - ```dub.json``` - D's dub package description file 31 | - ```Makefile``` - convenience Makefile that invokes ```dub``` 32 | - ```wasmdemo.wasmp``` - TIC-80 Wasm 'script' file. Note the embedded game assets data at the end of the file. 33 | 34 | ## Building your game 35 | 36 | Define the environment variable WASI_SDK_PATH; e.g., if you installed WASI 37 | libc into ```$HOME/wasi-sdk/share/wasi-sysroot```, then ```export WASI_SDK_PATH=$HOME/wasi-sdk```. 38 | 39 | Edit ```src/main.d``` to implement your game. You are of course free to 40 | organize your code in more than one D source file. 41 | 42 | If you create sprites, map, music, etc., for your game, remember to 43 | replace the game asset data at the end of ```wasmdemo.wasmp``` with 44 | your creations. 45 | 46 | To build the Wasm file, execute ```make```. This generates ```cart.wasm``` 47 | in the current directory. To run: 48 | 49 | ``` 50 | % tic80 --fs . --cmd 'load wasmdemo.wasmp & import binary cart.wasm & run & exit' 51 | ``` 52 | 53 | The script ```buildwasm.sh``` contains above steps as a convenience. 54 | 55 | To build a TIC-80 cartridge, first build the Wasm file, then build the 56 | cartridge file: 57 | 58 | ``` 59 | % tic80 --fs . --cmd 'load wasmdemo.wasmp & import binary cart.wasm & save game.tic & exit' 60 | ``` 61 | 62 | You can then run your cartridge as follows: 63 | 64 | ``` 65 | % tic80 --fs . --cmd 'load game.tic & run & exit' 66 | ``` 67 | 68 | The script ```buildcart.sh``` does the above steps as a convenience. 69 | 70 | -------------------------------------------------------------------------------- /src/studio/screens/surf.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "studio/studio.h" 26 | 27 | typedef struct Surf Surf; 28 | 29 | struct Surf 30 | { 31 | Studio* studio; 32 | tic_mem* tic; 33 | struct tic_fs* fs; 34 | struct tic_net* net; 35 | struct Console* console; 36 | 37 | bool init; 38 | bool loading; 39 | s32 ticks; 40 | 41 | struct 42 | { 43 | s32 pos; 44 | s32 target; 45 | struct SurfItem* items; 46 | s32 count; 47 | } menu; 48 | 49 | struct 50 | { 51 | struct 52 | { 53 | s32 topBarY; 54 | s32 bottomBarY; 55 | s32 menuX; 56 | s32 menuHeight; 57 | s32 coverFade; 58 | s32 pos; 59 | } val; 60 | 61 | Movie* movie; 62 | 63 | Movie idle; 64 | Movie show; 65 | Movie play; 66 | Movie move; 67 | 68 | struct 69 | { 70 | Movie show; 71 | Movie hide; 72 | } gotodir; 73 | 74 | struct 75 | { 76 | Movie show; 77 | Movie hide; 78 | } goback; 79 | 80 | } anim; 81 | 82 | void(*tick)(Surf* surf); 83 | void(*resume)(Surf* surf); 84 | void (*scanline)(tic_mem* tic, s32 row, void* data); 85 | }; 86 | 87 | void initSurf(Surf* surf, Studio* studio, struct Console* console); 88 | void freeSurf(Surf* surf); 89 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vendor/blip-buf"] 2 | path = vendor/blip-buf 3 | url = https://github.com/nesbox/blip-buf.git 4 | shallow = true 5 | [submodule "vendor/dirent"] 6 | path = vendor/dirent 7 | url = https://github.com/tronkko/dirent.git 8 | shallow = true 9 | [submodule "vendor/duktape"] 10 | path = vendor/duktape 11 | url = https://github.com/svaarala/duktape-releases.git 12 | shallow = true 13 | [submodule "vendor/giflib"] 14 | path = vendor/giflib 15 | url = https://github.com/nesbox/giflib.git 16 | shallow = true 17 | [submodule "vendor/lpeg"] 18 | path = vendor/lpeg 19 | url = https://github.com/nesbox/lpeg.git 20 | shallow = true 21 | [submodule "vendor/lua"] 22 | path = vendor/lua 23 | url = https://github.com/lua/lua.git 24 | shallow = true 25 | [submodule "vendor/sdl-gpu"] 26 | path = vendor/sdl-gpu 27 | url = https://github.com/grimfang4/sdl-gpu.git 28 | shallow = true 29 | [submodule "vendor/sokol"] 30 | path = vendor/sokol 31 | url = https://github.com/floooh/sokol.git 32 | shallow = true 33 | [submodule "vendor/squirrel"] 34 | path = vendor/squirrel 35 | url = https://github.com/albertodemichelis/squirrel.git 36 | shallow = true 37 | [submodule "vendor/wren"] 38 | path = vendor/wren 39 | url = https://github.com/wren-lang/wren.git 40 | shallow = true 41 | [submodule "vendor/zlib"] 42 | path = vendor/zlib 43 | url = https://github.com/madler/zlib.git 44 | shallow = true 45 | [submodule "vendor/zip"] 46 | path = vendor/zip 47 | url = https://github.com/kuba--/zip.git 48 | shallow = true 49 | [submodule "vendor/moonscript"] 50 | path = vendor/moonscript 51 | url = https://github.com/nesbox/moonscript.git 52 | shallow = true 53 | [submodule "vendor/argparse"] 54 | path = vendor/argparse 55 | url = https://github.com/cofyc/argparse.git 56 | shallow = true 57 | [submodule "vendor/circle-stdlib"] 58 | path = vendor/circle-stdlib 59 | url = https://github.com/smuehlst/circle-stdlib.git 60 | shallow = true 61 | [submodule "vendor/libuv"] 62 | path = vendor/libuv 63 | url = https://github.com/libuv/libuv.git 64 | shallow = true 65 | [submodule "vendor/http-parser"] 66 | path = vendor/http-parser 67 | url = https://github.com/nodejs/http-parser.git 68 | shallow = true 69 | [submodule "vendor/libpng"] 70 | path = vendor/libpng 71 | url = https://github.com/glennrp/libpng.git 72 | shallow = true 73 | [submodule "vendor/sdl2"] 74 | path = vendor/sdl2 75 | url = https://github.com/libsdl-org/SDL.git 76 | [submodule "mruby"] 77 | path = vendor/mruby 78 | url = https://github.com/mruby/mruby.git 79 | [submodule "vendor/wasm3"] 80 | path = vendor/wasm3 81 | url = https://github.com/wasm3/wasm3.git 82 | -------------------------------------------------------------------------------- /src/studio/editors/music.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "studio/studio.h" 26 | 27 | typedef struct Music Music; 28 | 29 | struct Music 30 | { 31 | Studio* studio; 32 | tic_mem* tic; 33 | tic_music* src; 34 | 35 | u8 track; 36 | s32 frame; 37 | 38 | struct 39 | { 40 | s32 pos; 41 | s32 start; 42 | bool active; 43 | 44 | } scroll; 45 | 46 | bool beat34; 47 | bool follow; 48 | bool sustain; 49 | bool loop; 50 | bool on[TIC_SOUND_CHANNELS]; 51 | 52 | struct 53 | { 54 | s32 octave; 55 | s32 sfx; 56 | } last; 57 | 58 | struct 59 | { 60 | s32 col; 61 | tic_point edit; 62 | 63 | struct 64 | { 65 | tic_point start; 66 | tic_rect rect; 67 | bool drag; 68 | } select; 69 | } tracker; 70 | 71 | struct 72 | { 73 | s32 col; 74 | tic_point edit; 75 | s8 note[TIC_SOUND_CHANNELS]; 76 | } piano; 77 | 78 | enum 79 | { 80 | MUSIC_TRACKER_TAB, 81 | MUSIC_PIANO_TAB, 82 | MUSIC_TAB_COUNT, 83 | } tab; 84 | 85 | struct 86 | { 87 | const char* label; 88 | s32 x; 89 | s32 start; 90 | } drag; 91 | 92 | u32 tickCounter; 93 | 94 | struct History* history; 95 | 96 | void(*tick)(Music*); 97 | void(*event)(Music*, StudioEvent); 98 | }; 99 | 100 | void initMusic(Music*, Studio* studio, tic_music* src); 101 | void freeMusic(Music* music); 102 | -------------------------------------------------------------------------------- /src/studio/anim.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | typedef enum 26 | { 27 | AnimLinear, 28 | AnimEaseIn, 29 | AnimEaseOut, 30 | AnimEaseInOut, 31 | AnimEaseInCubic, 32 | AnimEaseOutCubic, 33 | AnimEaseInOutCubic, 34 | AnimEaseInQuart, 35 | AnimEaseOutQuart, 36 | AnimEaseInOutQuart, 37 | AnimEaseInQuint, 38 | AnimEaseOutQuint, 39 | AnimEaseInOutQuint, 40 | AnimEaseInSine, 41 | AnimEaseOutSine, 42 | AnimEaseInOutSine, 43 | AnimEaseInExpo, 44 | AnimEaseOutExpo, 45 | AnimEaseInOutExpo, 46 | AnimEaseInCirc, 47 | AnimEaseOutCirc, 48 | AnimEaseInOutCirc, 49 | AnimEaseInBack, 50 | AnimEaseOutBack, 51 | AnimEaseInOutBack, 52 | AnimEaseInElastic, 53 | AnimEaseOutElastic, 54 | AnimEaseInOutElastic, 55 | AnimEaseInBounce, 56 | AnimEaseOutBounce, 57 | AnimEaseInOutBounce, 58 | } AnimEffect; 59 | 60 | typedef struct 61 | { 62 | s32 start; 63 | s32 end; 64 | s32 time; 65 | 66 | s32 *value; 67 | 68 | AnimEffect effect; 69 | } Anim; 70 | 71 | typedef struct 72 | { 73 | void(*done)(void *data); 74 | 75 | s32 time; 76 | s32 tick; 77 | 78 | s32 count; 79 | Anim* items; 80 | } Movie; 81 | 82 | #define MOVIE_DEF(TIME, DONE, ...) \ 83 | { \ 84 | .time = TIME, \ 85 | .done = DONE, \ 86 | .count = COUNT_OF(((Anim[])__VA_ARGS__)), \ 87 | .items = MOVE((Anim[])__VA_ARGS__), \ 88 | } 89 | 90 | void processAnim(Movie* movie, void* data); 91 | Movie* resetMovie(Movie* movie); 92 | -------------------------------------------------------------------------------- /src/system/n3ds/utils.c: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2020 Adrian "asie" Siekierka 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. 22 | 23 | #include 24 | 25 | #include <3ds.h> 26 | #include 27 | #include 28 | 29 | #include "utils.h" 30 | 31 | static int npot(int v) { 32 | v--; 33 | v |= v >> 1; 34 | v |= v >> 2; 35 | v |= v >> 4; 36 | v |= v >> 8; 37 | v |= v >> 16; 38 | v++; 39 | return v; 40 | } 41 | 42 | bool ctr_load_png(C3D_Tex* tex, const char* name, texture_location loc) 43 | { 44 | png_image img; 45 | u32 *data; 46 | 47 | memset(&img, 0, sizeof(png_image)); 48 | img.version = PNG_IMAGE_VERSION; 49 | 50 | if (!png_image_begin_read_from_file(&img, name)) { 51 | return false; 52 | } 53 | 54 | img.format = PNG_FORMAT_ABGR; 55 | 56 | if (loc == TEXTURE_TARGET_VRAM) { 57 | C3D_TexInitVRAM(tex, npot(img.width), npot(img.height), GPU_RGBA8); 58 | } else { 59 | C3D_TexInit(tex, npot(img.width), npot(img.height), GPU_RGBA8); 60 | } 61 | data = linearAlloc(tex->width * tex->height * sizeof(u32)); 62 | 63 | if (!png_image_finish_read(&img, NULL, data, tex->width * sizeof(u32), NULL)) { 64 | linearFree(data); 65 | C3D_TexDelete(tex); 66 | return false; 67 | } 68 | 69 | GSPGPU_FlushDataCache(data, tex->width * tex->height * sizeof(u32)); 70 | 71 | C3D_SyncDisplayTransfer(data, GX_BUFFER_DIM(tex->width, tex->height), 72 | tex->data, GX_BUFFER_DIM(tex->width, tex->height), 73 | GX_TRANSFER_FLIP_VERT(1) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_RAW_COPY(0) | 74 | GX_TRANSFER_IN_FORMAT(GPU_RGBA8) | GX_TRANSFER_OUT_FORMAT(GPU_RGBA8) 75 | | GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)); 76 | 77 | linearFree(data); 78 | png_image_free(&img); 79 | return true; 80 | } -------------------------------------------------------------------------------- /src/studio/editors/sprite.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "studio/studio.h" 26 | #include "tilesheet.h" 27 | 28 | typedef struct Sprite Sprite; 29 | 30 | struct Sprite 31 | { 32 | Studio* studio; 33 | tic_mem* tic; 34 | 35 | tic_tiles* src; 36 | tic_tilesheet sheet; 37 | 38 | u32 tickCounter; 39 | tic_point previousMouse; 40 | 41 | u16 index; 42 | u8 color; 43 | u8 color2; 44 | u8 size; 45 | u8 brushSize; 46 | u16 x,y; 47 | bool advanced; 48 | 49 | tic_blit blit; 50 | 51 | struct 52 | { 53 | bool edit; 54 | bool vbank1; 55 | s32 focus; 56 | } palette; 57 | 58 | struct 59 | { 60 | tic_rect rect; 61 | tic_point start; 62 | bool drag; 63 | u8* back; 64 | u8* front; 65 | } select; 66 | 67 | enum 68 | { 69 | SPRITE_DRAW_MODE, 70 | SPRITE_PICK_MODE, 71 | SPRITE_SELECT_MODE, 72 | SPRITE_FILL_MODE, 73 | } mode; 74 | 75 | struct History* history; 76 | 77 | struct 78 | { 79 | struct 80 | { 81 | s32 bank; 82 | s32 page; 83 | } pos; 84 | 85 | Movie* movie; 86 | 87 | Movie idle; 88 | Movie bank; 89 | Movie page; 90 | 91 | } anim; 92 | 93 | void (*tick)(Sprite*); 94 | void (*event)(Sprite*, StudioEvent); 95 | void (*scanline)(tic_mem* tic, s32 row, void* data); 96 | }; 97 | 98 | typedef struct 99 | { 100 | s32 cell_w, cell_h, cols, rows, length; 101 | } tic_palette_dimensions; 102 | 103 | void initSprite(Sprite*, Studio* studio, tic_tiles* src); 104 | void freeSprite(Sprite*); 105 | 106 | -------------------------------------------------------------------------------- /src/studio/editors/map.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "studio/studio.h" 26 | #include "tilesheet.h" 27 | 28 | typedef struct Map Map; 29 | 30 | struct Map 31 | { 32 | Studio* studio; 33 | tic_mem* tic; 34 | 35 | tic_map* src; 36 | 37 | s32 tickCounter; 38 | 39 | enum 40 | { 41 | MAP_DRAW_MODE = 0, 42 | MAP_DRAG_MODE, 43 | MAP_SELECT_MODE, 44 | MAP_FILL_MODE, 45 | } mode; 46 | 47 | struct 48 | { 49 | bool grid; 50 | bool draw; 51 | tic_point start; 52 | } canvas; 53 | 54 | struct 55 | { 56 | bool keep; 57 | tic_rect rect; 58 | tic_point start; 59 | bool drag; 60 | 61 | tic_blit blit; 62 | } sheet; 63 | 64 | struct 65 | { 66 | s32 x; 67 | s32 y; 68 | 69 | tic_point start; 70 | 71 | bool active; 72 | bool gesture; 73 | 74 | } scroll; 75 | 76 | struct 77 | { 78 | tic_rect rect; 79 | tic_point start; 80 | bool drag; 81 | } select; 82 | 83 | u8* paste; 84 | 85 | struct History* history; 86 | 87 | struct 88 | { 89 | struct 90 | { 91 | s32 sheet; 92 | s32 bank; 93 | s32 page; 94 | } pos; 95 | 96 | Movie* movie; 97 | 98 | Movie idle; 99 | Movie show; 100 | Movie hide; 101 | Movie bank; 102 | Movie page; 103 | 104 | } anim; 105 | 106 | void (*tick)(Map*); 107 | void (*event)(Map*, StudioEvent); 108 | void (*scanline)(tic_mem* tic, s32 row, void* data); 109 | }; 110 | 111 | void initMap(Map*, Studio* studio, tic_map* src); 112 | void freeMap(Map* map); 113 | -------------------------------------------------------------------------------- /include/tic80_config.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #if !defined(TIC_BUILD_WITH_LUA) && \ 26 | !defined(TIC_BUILD_WITH_MOON) && \ 27 | !defined(TIC_BUILD_WITH_FENNEL) && \ 28 | !defined(TIC_BUILD_WITH_JS) && \ 29 | !defined(TIC_BUILD_WITH_WREN) && \ 30 | !defined(TIC_BUILD_WITH_SQUIRREL) && \ 31 | !defined(TIC_BUILD_WITH_WASM) 32 | 33 | # define TIC_BUILD_WITH_LUA 1 34 | # define TIC_BUILD_WITH_MOON 1 35 | # define TIC_BUILD_WITH_FENNEL 1 36 | # define TIC_BUILD_WITH_JS 1 37 | # define TIC_BUILD_WITH_WREN 1 38 | # define TIC_BUILD_WITH_SQUIRREL 1 39 | # define TIC_BUILD_WITH_WASM 1 40 | 41 | #endif 42 | 43 | #if defined(TIC_BUILD_WITH_FENNEL) || defined(TIC_BUILD_WITH_MOON) 44 | # define TIC_BUILD_WITH_LUA 1 45 | #endif 46 | 47 | #if defined(__APPLE__) 48 | // TODO: this disables macos config 49 | # include "AvailabilityMacros.h" 50 | # include "TargetConditionals.h" 51 | // # ifndef TARGET_OS_IPHONE 52 | # undef __TIC_MACOSX__ 53 | # define __TIC_MACOSX__ 1 54 | // # endif /* TARGET_OS_IPHONE */ 55 | #endif /* defined(__APPLE__) */ 56 | 57 | #if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) 58 | # undef __TIC_WINDOWS__ 59 | # define __TIC_WINDOWS__ 1 60 | #endif 61 | 62 | #if defined(ANDROID) || defined(__ANDROID__) 63 | # undef __TIC_ANDROID__ 64 | # define __TIC_ANDROID__ 1 65 | #elif (defined(linux) || defined(__linux) || defined(__linux__)) 66 | # undef __TIC_LINUX__ 67 | # define __TIC_LINUX__ 1 68 | #endif 69 | 70 | #ifndef TIC80_API 71 | # if defined(TIC80_SHARED) 72 | # if defined(__TIC_WINDOWS__) 73 | # define TIC80_API __declspec(dllexport) 74 | # elif defined(__TIC_LINUX__) 75 | # define TIC80_API __attribute__ ((visibility("default"))) 76 | # endif 77 | # else 78 | # define TIC80_API 79 | # endif 80 | #endif 81 | -------------------------------------------------------------------------------- /src/tic.c: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | #include "api.h" 28 | #include "tools.h" 29 | #include "cart.h" 30 | 31 | static void onTrace(void* data, const char* text, u8 color) 32 | { 33 | tic80* tic = (tic80*)data; 34 | 35 | if(tic->callback.trace) 36 | tic->callback.trace(text, color); 37 | } 38 | 39 | static void onError(void* data, const char* info) 40 | { 41 | tic80* tic = (tic80*)data; 42 | 43 | if(tic->callback.error) 44 | tic->callback.error(info); 45 | } 46 | 47 | static void onExit(void* data) 48 | { 49 | tic80* tic = (tic80*)data; 50 | 51 | if(tic->callback.exit) 52 | tic->callback.exit(); 53 | } 54 | 55 | tic80* tic80_create(s32 samplerate, tic80_pixel_color_format format) 56 | { 57 | return &tic_core_create(samplerate, format)->product; 58 | } 59 | 60 | TIC80_API void tic80_load(tic80* tic, void* cart, s32 size) 61 | { 62 | tic_mem* mem = (tic_mem*)tic; 63 | 64 | tic_cart_load(&mem->cart, cart, size); 65 | tic_api_reset(mem); 66 | } 67 | 68 | TIC80_API void tic80_tick(tic80* tic, tic80_input input, u64 (*counter)(), u64 (*freq)()) 69 | { 70 | tic_mem* mem = (tic_mem*)tic; 71 | 72 | mem->ram->input = input; 73 | 74 | tic_tick_data tickData = (tic_tick_data) 75 | { 76 | .error = onError, 77 | .trace = onTrace, 78 | .exit = onExit, 79 | .data = tic, 80 | .start = 0, 81 | .counter = counter, 82 | .freq = freq 83 | }; 84 | 85 | tic_core_tick_start(mem); 86 | tic_core_tick(mem, &tickData); 87 | tic_core_tick_end(mem); 88 | tic_core_blit(mem); 89 | } 90 | 91 | TIC80_API void tic80_sound(tic80* tic) 92 | { 93 | tic_mem* mem = (tic_mem*)tic; 94 | tic_core_synth_sound(mem); 95 | } 96 | 97 | TIC80_API void tic80_delete(tic80* tic) 98 | { 99 | tic_mem* mem = (tic_mem*)tic; 100 | tic_core_close(mem); 101 | } 102 | -------------------------------------------------------------------------------- /demos/palette.lua: -------------------------------------------------------------------------------- 1 | -- title: palette demo 2 | -- author: Nesbox 3 | -- desc: how to switch palatte in runtime 4 | -- script: lua 5 | -- input: gamepad 6 | 7 | local W=240 8 | local H=136 9 | 10 | -- palette address 11 | local ADDR=0x3FC0 12 | 13 | local PALETTES = 14 | { 15 | {name="SWEETIE-16", data="1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7333c57566c8694b0c2f4f4f4"}, 16 | {name="DB16", data="140c1c44243430346d4e4a4e854c30346524d04648757161597dced27d2c8595a16daa2cd2aa996dc2cadad45edeeed6"}, 17 | {name="PICO-8", data="0000007e25531d2b535f574fab5236008751ff004d83769cff77a8ffa300c2c3c700e756ffccaa29adfffff024fff1e8"}, 18 | {name="ARNE16", data="0000001b2632005784493c2ba4642244891abe26332f484e31a2f2eb89319d9d9da3ce27e06f8bb2dceff7e26bffffff"}, 19 | {name="EDG16", data="193d3f3f2832743f399e2835b86f50327345e53b444f67810484d1fb922bafbfd263c64de4a6722ce8f4ffe762ffffff"}, 20 | {name="A64", data="0000004c3435313a9148545492562b509450b148638080787655a28385cf9cabb19ccc47cd93738fbfd5bbc840ede6c8"}, 21 | {name="C64", data="00000057420040318d5050508b542955a0498839327878788b3f967869c49f9f9f94e089b8696267b6bdbfce72ffffff"}, 22 | {name="VIC20", data="000000772d2642348ba85fb4b668627e70caa8734a559e4ae99df5e9b287bdcc7185d4dc92df87c5ffffffffb0ffffff"}, 23 | {name="CGA", data="000000aa00000000aa555555aa550000aa00ff5555aaaaaa5555ffaa00aa00aaaa55ff55ff55ff55ffffffff55ffffff"}, 24 | {name="SLIFE", data="0000001226153f28117a2222513155d13b27286fb85d853acc8218e07f8a9b8bff68c127c7b581b3e868a8e4d4ffffff"}, 25 | {name="JMP", data="000000191028833129453e78216c4bdc534b7664fed365c846af45e18d79afaab9d6b97b9ec2e8a1d685e9d8a1f5f4eb"}, 26 | {name="CGARNE", data="0000002234d15c2e788a36225e606e0c7e45e23d69aa5c3d4c81fb44aacceb8a60b5b5b56cd9477be2f9ffd93fffffff"}, 27 | {name="PSYG", data="0000001b1e29003308362747084a3c443f41a2324e52524c546a0073615064647c516cbf77785be08b799ea4a7cbe8f7"}, 28 | {name="EROGE", data="0d080d2a23494f2b247d384032535f825b314180a0c16c5bc591547bb24e74adbbe89973bebbb2f0bd77fbdf9bfff9e4"}, 29 | {name="EISLAND", data="051625794765686086567864ca657e8686918184abcc8d867ea78839d4b98dbcd29dc085edc38de6d1d1f5e17af6f6bf"}, 30 | } 31 | 32 | 33 | local t=0 34 | local index=1 35 | 36 | -- update palette 37 | function updpal() 38 | local pal=PALETTES[index].data 39 | for i=1,#pal,2 do 40 | poke(ADDR+i//6*3+i//2%3,tonumber(pal:sub(i,i+1),16)) 41 | end 42 | end 43 | 44 | updpal() 45 | 46 | function TIC() 47 | 48 | -- handle input 49 | if btnp(0,20,5) and index>1 then 50 | index=index-1 51 | updpal() 52 | end 53 | if btnp(1,20,5) and index<#PALETTES then 54 | index=index+1 55 | updpal() 56 | end 57 | 58 | if btnp(4)or btnp(5)then exit()end 59 | 60 | -- draw 61 | 62 | cls(15) 63 | 64 | print("SELECT PALETTE",6,6,0) 65 | 66 | for i,v in pairs(PALETTES) do 67 | print(v.name,12,12+i*6,0) 68 | end 69 | 70 | print(">",6+(t//16%2),12+index*6,0) 71 | 72 | local S=12 73 | 74 | -- draw palette 75 | for i=0,16-1 do 76 | for j=0,S-1 do 77 | line(W-j-i*S,H,W,H-j-i*S,i) 78 | end 79 | end 80 | 81 | t=t+1 82 | end 83 | 84 | -- 85 | -- 000:140c1c44243430346d4e4a4e854c30346524d04648757161597dced27d2c8595a16daa2cd2aa996dc2cadad45edeeed6 86 | -- 87 | 88 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at grigoruk@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /src/studio/fs.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include 26 | #include 27 | 28 | typedef bool(*fs_list_callback)(const char* name, const char* title, const char* hash, s32 id, void* data, bool dir); 29 | typedef void(*fs_done_callback)(void* data); 30 | typedef void(*fs_isdir_callback)(bool dir, void* data); 31 | typedef void(*fs_load_callback)(const u8* buffer, s32 size, void* data); 32 | 33 | typedef struct tic_fs tic_fs; 34 | struct tic_net; 35 | 36 | tic_fs* tic_fs_create (const char* path, struct tic_net* net); 37 | const char* tic_fs_path (tic_fs* fs, const char* name); 38 | const char* tic_fs_pathroot (tic_fs* fs, const char* name); 39 | 40 | void tic_fs_enum (tic_fs* fs, fs_list_callback onItem, fs_done_callback onDone, void* data); 41 | void tic_fs_isdir_async (tic_fs* fs, const char* name, fs_isdir_callback callback, void* data); 42 | void tic_fs_hashload (tic_fs* fs, const char* name, const char* hash, fs_load_callback callback, void* data); 43 | bool tic_fs_delfile (tic_fs* fs, const char* name); 44 | bool tic_fs_deldir (tic_fs* fs, const char* name); 45 | bool tic_fs_save (tic_fs* fs, const char* name, const void* data, s32 size, bool overwrite); 46 | bool tic_fs_saveroot (tic_fs* fs, const char* name, const void* data, s32 size, bool overwrite); 47 | void* tic_fs_load (tic_fs* fs, const char* name, s32* size); 48 | void* tic_fs_loadroot (tic_fs* fs, const char* name, s32* size); 49 | bool tic_fs_makedir (tic_fs* fs, const char* name); 50 | bool tic_fs_exists (tic_fs* fs, const char* name); 51 | void tic_fs_openfolder (tic_fs* fs); 52 | bool tic_fs_isdir (tic_fs* fs, const char* dir); 53 | bool tic_fs_ispubdir (tic_fs* fs); 54 | void tic_fs_changedir (tic_fs* fs, const char* dir); 55 | void tic_fs_dir (tic_fs* fs, char* out); 56 | void tic_fs_dirback (tic_fs* fs); 57 | void tic_fs_homedir (tic_fs* fs); 58 | 59 | u64 fs_date (const char* name); 60 | bool fs_exists (const char* name); 61 | void* fs_read (const char* path, s32* size); 62 | bool fs_write (const char* path, const void* data, s32 size); 63 | -------------------------------------------------------------------------------- /demos/p3d.lua: -------------------------------------------------------------------------------- 1 | -- title: 3D demo 2 | -- author: by Filippo 3 | -- desc: 3D demo 4 | -- script: lua 5 | -- input: gamepad 6 | 7 | t=0 8 | 9 | cx=0 10 | cy=0 11 | cz=200 12 | pivot={x=0,y=0,z=0} 13 | angle=0 14 | points={} 15 | pal={15,14,9,6,8,2,1} 16 | 17 | function createCube(t) 18 | --Init points for cube 19 | points={} 20 | local l 21 | l = 5 + math.abs((math.sin(t/100))*10) 22 | local p 23 | for x=-3,3 do 24 | for y=-3,3 do 25 | for z=-3,3 do 26 | p={x=x*l, 27 | y=y*l, 28 | z=z*l, 29 | c=pal[4+z]} 30 | table.insert(points,p) 31 | end 32 | end 33 | end 34 | end 35 | 36 | function createCurve(t) 37 | --Init points for 3d curve 38 | points={} 39 | local i=0 40 | local l 41 | l1 = math.abs(5*(math.cos(t/50))) 42 | for u=-70,70,15 do 43 | local r1 = math.cos(math.rad(u))*30 44 | for v=1,360,15 do 45 | local x = math.sin(math.rad(v)) 46 | local y = math.cos(math.rad(v)) 47 | p={x=x*r1, 48 | y=y*r1, 49 | z=(u/(l1+0.7)+v/5), 50 | c=pal[1+i%7]} 51 | table.insert(points,p) 52 | end 53 | i=i+1 54 | end 55 | end 56 | 57 | 58 | function p2d(p3d) 59 | local fov = 180 60 | local x0 = p3d.x + cx 61 | local y0 = p3d.y + cy 62 | local z0 = p3d.z + cz 63 | local x2d = fov * x0 / z0 64 | local y2d = fov * y0 / z0 65 | 66 | x2d = x2d + 120 --center w 67 | y2d = y2d + 68 --center h 68 | 69 | return x2d,y2d 70 | end 71 | 72 | function rotate(p3d,center,ax,ay,az) 73 | local a,b,c 74 | local a1,b1,c1 75 | local a2,b2,c2 76 | local a3,b2,c3 77 | local np3d={x=0,y=0,z=0,c=0} 78 | 79 | a = p3d.x-center.x 80 | b = p3d.y-center.y 81 | c = p3d.z-center.z 82 | 83 | a1 = a*math.cos(az)-b*math.sin(az) 84 | b1 = a*math.sin(az)+b*math.cos(az) 85 | c1 = c 86 | 87 | c2 = c1*math.cos(ay)-a1*math.sin(ay) 88 | a2 = c1*math.sin(ay)+a1*math.cos(ay) 89 | b2 = b1 90 | 91 | b3 = b2*math.cos(ax)-c2*math.sin(ax) 92 | c3 = b2*math.sin(ax)+c2*math.cos(ax) 93 | a3 = a2 94 | 95 | np3d.x=a3 96 | np3d.y=b3 97 | np3d.z=c3 98 | np3d.c=p3d.c 99 | return np3d 100 | end 101 | 102 | function zsort(p1,p2) 103 | return p1.z>p2.z 104 | end 105 | 106 | function TIC() 107 | 108 | if btn(0) then cy=cy+1 end 109 | if btn(1) then cy=cy-1 end 110 | if btn(2) then cx=cx+1 end 111 | if btn(3) then cx=cx-1 end 112 | if btn(4) then cz=cz+1 end 113 | if btn(5) then cz=cz-1 end 114 | 115 | cls(10) 116 | --Create points 117 | if(t%900<450) then 118 | createCube(t) 119 | else 120 | createCurve(t) 121 | end 122 | 123 | --Rotate points 124 | for k,p in pairs(points)do 125 | pr = rotate(p,pivot, 126 | angle, 127 | angle/2, 128 | angle/4) 129 | points[k] = pr 130 | end 131 | 132 | --Z Sort 133 | table.sort(points,zsort) 134 | 135 | --Draw points 136 | for k,p in pairs(points)do 137 | i,j = p2d(p) 138 | rect(i,j,6,6,p.c) 139 | end 140 | 141 | angle = angle + 0.05 142 | t=t+1 143 | end 144 | 145 | -- 146 | -- 001:a000000aa0f00f0aaaaaaaaaaafaaa6aafffaaaaaafaa6aaaaaaaaaa33333333 147 | -- 002:a000000aa060060aaaaaaaaaaafaaa6aafffaaaaaafaa6aaaaaaaaaa33333333 148 | -- 016:000000000000000000000000fe96821300000000000000000000000000000000 149 | -- 150 | 151 | -- 152 | -- 000:140c1c44243430346d4e4a4e854c30346524d04648757161597dced27d2c8595a16daa2cd2aa996dc2cadad45edeeed6 153 | -- 154 | 155 | -------------------------------------------------------------------------------- /src/studio/screens/console.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "studio/studio.h" 26 | #include "studio/fs.h" 27 | 28 | typedef enum 29 | { 30 | CART_SAVE_OK, 31 | CART_SAVE_ERROR, 32 | CART_SAVE_MISSING_NAME, 33 | } CartSaveResult; 34 | 35 | typedef struct Console Console; 36 | typedef struct CommandDesc CommandDesc; 37 | 38 | struct Console 39 | { 40 | struct Config* config; 41 | 42 | struct 43 | { 44 | tic_point pos; 45 | s32 delay; 46 | } cursor; 47 | 48 | struct 49 | { 50 | s32 pos; 51 | s32 start; 52 | 53 | bool active; 54 | } scroll; 55 | 56 | struct 57 | { 58 | const char* start; 59 | const char* end; 60 | bool active; 61 | } select; 62 | 63 | char* text; 64 | u8* color; 65 | 66 | struct 67 | { 68 | char* text; 69 | size_t pos; 70 | } input; 71 | 72 | Studio* studio; 73 | tic_mem* tic; 74 | 75 | struct tic_fs* fs; 76 | struct tic_net* net; 77 | 78 | struct 79 | { 80 | char name[TICNAME_MAX]; 81 | char path[TICNAME_MAX]; 82 | } rom; 83 | 84 | struct 85 | { 86 | s32 index; 87 | s32 size; 88 | char** items; 89 | } history; 90 | 91 | u32 tickCounter; 92 | 93 | bool active; 94 | StartArgs args; 95 | 96 | struct 97 | { 98 | s32 count; 99 | s32 current; 100 | char** items; 101 | } commands; 102 | 103 | CommandDesc* desc; 104 | 105 | void(*load)(Console*, const char* path); 106 | bool(*loadCart)(Console*, const char* path); 107 | void(*loadByHash)(Console*, const char* name, const char* hash, const char* section, fs_done_callback callback, void* data); 108 | void(*updateProject)(Console*); 109 | void(*error)(Console*, const char*); 110 | void(*trace)(Console*, const char*, u8 color); 111 | void(*tick)(Console*); 112 | void(*done)(Console*); 113 | 114 | CartSaveResult(*save)(Console*); 115 | }; 116 | 117 | void initConsole(Console*, Studio* studio, struct tic_fs* fs, struct tic_net* net, struct Config* config, StartArgs args); 118 | void freeConsole(Console* console); 119 | -------------------------------------------------------------------------------- /src/system/sokol/player.c: -------------------------------------------------------------------------------- 1 | #include "system/sokol/sokol.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #define TIC80_WINDOW_TITLE "TIC-80" 11 | #define TIC80_DEFAULT_CART "cart.tic" 12 | 13 | static tic80* tic = NULL; 14 | 15 | static void app_init(void) 16 | { 17 | saudio_desc desc = {0}; 18 | desc.num_channels = 2; 19 | saudio_setup(&desc); 20 | 21 | FILE* file = fopen(TIC80_DEFAULT_CART, "rb"); 22 | 23 | if(file) 24 | { 25 | fseek(file, 0, SEEK_END); 26 | int size = ftell(file); 27 | fseek(file, 0, SEEK_SET); 28 | 29 | void* cart = malloc(size); 30 | if(cart) fread(cart, size, 1, file); 31 | fclose(file); 32 | 33 | if(cart) 34 | { 35 | printf("%s\n", "cart loaded"); 36 | tic = tic80_create(saudio_sample_rate(), TIC80_PIXEL_COLOR_RGBA8888); 37 | 38 | if(tic) 39 | { 40 | printf("%s\n", "tic created"); 41 | tic80_load(tic, cart, size); 42 | } 43 | } 44 | } 45 | 46 | sokol_gfx_init(TIC80_FULLWIDTH, TIC80_FULLHEIGHT, 1, 1, false, false); 47 | 48 | stm_setup(); 49 | } 50 | 51 | static tic80_input tic_input; 52 | 53 | static void app_frame(void) 54 | { 55 | if(tic) 56 | { 57 | tic80_tick(tic, tic_input); 58 | tic80_sound(tic); 59 | } 60 | 61 | sokol_gfx_draw(tic->screen); 62 | 63 | static float floatSamples[TIC80_SAMPLERATE * TIC80_SAMPLE_CHANNELS / TIC80_FRAMERATE]; 64 | 65 | for(s32 i = 0; i < tic->samples.count; i++) 66 | floatSamples[i] = (float)tic->samples.buffer[i] / SHRT_MAX; 67 | 68 | saudio_push(floatSamples, tic->samples.count / TIC80_SAMPLE_CHANNELS); 69 | } 70 | 71 | static void app_input(const sapp_event* event) 72 | { 73 | static const sapp_keycode Keys[] = 74 | { 75 | SAPP_KEYCODE_UP, 76 | SAPP_KEYCODE_DOWN, 77 | SAPP_KEYCODE_LEFT, 78 | SAPP_KEYCODE_RIGHT, 79 | 80 | SAPP_KEYCODE_Z, 81 | SAPP_KEYCODE_X, 82 | SAPP_KEYCODE_A, 83 | SAPP_KEYCODE_S, 84 | }; 85 | 86 | switch (event->type) 87 | { 88 | case SAPP_EVENTTYPE_KEY_DOWN: 89 | case SAPP_EVENTTYPE_KEY_UP: 90 | 91 | for (int i = 0; i < sizeof Keys / sizeof Keys[0]; i++) 92 | { 93 | if (event->key_code == Keys[i]) 94 | { 95 | if(event->type == SAPP_EVENTTYPE_KEY_DOWN) 96 | tic_input.gamepads.first.data |= (1 << i); 97 | else 98 | tic_input.gamepads.first.data &= ~(1 << i); 99 | } 100 | } 101 | break; 102 | default: 103 | break; 104 | } 105 | } 106 | 107 | static void app_cleanup(void) 108 | { 109 | if(tic) 110 | tic80_delete(tic); 111 | 112 | sg_shutdown(); 113 | } 114 | 115 | sapp_desc sokol_main(int argc, char* argv[]) { 116 | // args_init(argc, argv); 117 | return (sapp_desc) { 118 | .init_cb = app_init, 119 | .frame_cb = app_frame, 120 | .event_cb = app_input, 121 | .cleanup_cb = app_cleanup, 122 | .width = 3 * TIC80_FULLWIDTH, 123 | .height = 3 * TIC80_FULLHEIGHT, 124 | .window_title = TIC80_WINDOW_TITLE, 125 | .ios_keyboard_resizes_canvas = true 126 | }; 127 | } 128 | -------------------------------------------------------------------------------- /demos/bunny/moonmark.moon: -------------------------------------------------------------------------------- 1 | -- title: Bunnymark in MoonScript 2 | -- author: Rob Loach 3 | -- desc: Benchmarking tool to see how many bunnies can fly around the screen, using MoonScript. 4 | -- license: MIT License 5 | -- input: gamepad 6 | -- script: moon 7 | -- version: 1.1.0 8 | 9 | screenWidth = 240 10 | screenHeight = 136 11 | toolbarHeight = 6 12 | t = 0 13 | 14 | class Bunny 15 | @width: 26 16 | @height: 32 17 | 18 | new: => 19 | @x = math.random(0, screenWidth - @@width) 20 | @y = math.random(0, screenHeight - @@height) 21 | @speedX = math.random(-100, 100) / 60 22 | @speedY = math.random(-100, 100) / 60 23 | @sprite = 1 24 | 25 | draw: () => 26 | spr(@sprite, @x, @y, 1, 1, 0, 0, 4, 4) 27 | 28 | update: () => 29 | @x += @speedX 30 | @y += @speedY 31 | 32 | if @x + @@width > screenWidth 33 | @x = screenWidth - @@width 34 | @speedX *= -1 35 | if @x < 0 36 | @x = 0 37 | @speedX *= -1 38 | if @y + @@height > screenHeight 39 | @y = screenHeight - @@height 40 | @speedY *= -1 41 | if @y < toolbarHeight 42 | @y = toolbarHeight 43 | @speedY *= -1 44 | 45 | class FPS 46 | new: => 47 | @value = 0 48 | @frames = 0 49 | @lastTime = 0 50 | 51 | getValue: () => 52 | if time() - @lastTime <= 1000 53 | @frames += 1 54 | else 55 | @value = @frames 56 | @frames = 0 57 | @lastTime = time() 58 | return @value 59 | 60 | fps = FPS! 61 | bunnies = {} 62 | table.insert(bunnies, Bunny!) 63 | 64 | export TIC=-> 65 | -- music 66 | if t == 0 then 67 | music(0) 68 | if t == 6*64*2.375 then 69 | music(1) 70 | t = t + 1 71 | 72 | -- Input 73 | if btn(0) 74 | for i = 1, 5 75 | table.insert(bunnies, Bunny!) 76 | elseif btn(1) 77 | for i = 1, 5 78 | table.remove(bunnies, 1) 79 | 80 | -- Update 81 | for i, item in pairs bunnies 82 | item\update! 83 | 84 | -- Draw 85 | cls(15) 86 | for i, item in pairs bunnies 87 | item\draw! 88 | 89 | rect(0, 0, screenWidth, toolbarHeight, 0) 90 | print("Bunnies: " .. #bunnies, 1, 0, 11, false, 1, false) 91 | print("FPS: " .. fps\getValue!, screenWidth / 2, 0, 11, false, 1, false) 92 | 93 | -- 94 | -- 001:11111100111110dd111110dc111110dc111110dc111110dc111110dd111110dd 95 | -- 002:00011110ddd0110dccd0110dccd0110dccd0110dccd0110dcddd00dddddddddd 96 | -- 003:00001111dddd0111cccd0111cccd0111cccd0111cccd0111dcdd0111dddd0111 97 | -- 004:1111111111111111111111111111111111111111111111111111111111111111 98 | -- 017:111110dd111110dd111110dd111110dd10000ddd1eeeeddd1eeeeedd10000eed 99 | -- 018:d0ddddddd0ddddddddddddddddd0000dddddccddddddccdddddddddddddddddd 100 | -- 019:0ddd01110ddd0111dddd0111dddd0111ddddd000ddddddddddddddddddddd000 101 | -- 020:1111111111111111111111111111111101111111d0111111d011111101111111 102 | -- 033:111110ee111110ee111110ee111110ee111110ee111110ee111110ee111110ee 103 | -- 034:dddcccccddccccccddccccccddccccccddccccccdddcccccdddddddddddddddd 104 | -- 035:dddd0111cddd0111cddd0111cddd0111cddd0111dddd0111dddd0111dddd0111 105 | -- 036:1111111111111111111111111111111111111111111111111111111111111111 106 | -- 049:111110ee111110ee111110ee111110ee111110ee111110ee111110ee11111100 107 | -- 050:dddeeeeeddeeeeeed00000000111111101111111011111110111111111111111 108 | -- 051:eddd0111eedd01110eed011110ee011110ee011110ee011110ee011111001111 109 | -- 052:1111111111111111111111111111111111111111111111111111111111111111 110 | -- 111 | 112 | -- 113 | -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 114 | -- -------------------------------------------------------------------------------- /demos/bunny/rubymark.rb: -------------------------------------------------------------------------------- 1 | # title: Bunnymark in Ruby 2 | # author: Jeremiasz Nelz; based on the original work of Rob Loach 3 | # desc: Benchmarking tool to see how many bunnies can fly around the screen, using Ruby. 4 | # license: MIT License 5 | # input: gamepad 6 | # script: ruby 7 | # version: 0.1.0 8 | 9 | ScreenWidth = 240.0 10 | ScreenHeight = 136.0 11 | ToolbarHeight = 6 12 | $t = 0 13 | 14 | class Bunny 15 | @@width = 26.0 16 | @@height = 32.0 17 | 18 | def initialize 19 | @x = Float(rand(ScreenWidth - @@width)) 20 | @y = Float(rand(ScreenHeight - @@height)) 21 | @speed_x = Float(rand(200) - 100) / 60.0 22 | @speed_y = Float(rand(200) - 100) / 60.0 23 | @sprite = 1 24 | end 25 | 26 | def draw 27 | spr @sprite, @x, @y, 1, 1, 0, 0, 4, 4 28 | end 29 | 30 | def update 31 | @x += @speed_x 32 | @y += @speed_y 33 | 34 | if @x + @@width > ScreenWidth 35 | @x = ScreenWidth - @@width 36 | @speed_x *= -1.0 37 | end 38 | if @x < 0.0 39 | @x = 0.0 40 | @speed_x *= -1.0 41 | end 42 | if @y + @@height > ScreenHeight 43 | @y = ScreenHeight - @@height 44 | @speed_y *= -1.0 45 | end 46 | if @y < ToolbarHeight 47 | @y = ToolbarHeight 48 | @speed_y *= -1.0 49 | end 50 | end 51 | end 52 | 53 | class FPS 54 | def initialize 55 | @value = 0 56 | @frames = 0 57 | @last_time = -1000 58 | end 59 | 60 | def get 61 | d = time - @last_time 62 | if d <= 1000 63 | @frames += 1 64 | else 65 | @value = @frames 66 | @frames = 0 67 | @last_time = time 68 | end 69 | 70 | @value 71 | end 72 | end 73 | 74 | $fps = FPS.new 75 | $bunnies = [] 76 | $bunnies << Bunny.new 77 | 78 | def TIC 79 | # Music 80 | music(0) if $t.zero? 81 | 82 | music(1) if $t == 6*64*2.375 83 | $t += 1 84 | 85 | # Input 86 | 5.times { $bunnies << Bunny.new } if btn 0 87 | 5.times { $bunnies.pop } if btn 1 88 | 89 | # Update 90 | $bunnies.each &:update 91 | 92 | # Draw 93 | cls 15 94 | $bunnies.each &:draw 95 | 96 | rect 0, 0, ScreenWidth, ToolbarHeight, 0 97 | print "Bunnies: #{$bunnies.count}", 1, 0, 11, false, 1, false 98 | print "FPS: #{$fps.get}", ScreenWidth / 2, 0, 11, false, 1, false 99 | end 100 | 101 | # 102 | # 001:11111100111110dd111110dc111110dc111110dc111110dc111110dd111110dd 103 | # 002:00011110ddd0110dccd0110dccd0110dccd0110dccd0110dcddd00dddddddddd 104 | # 003:00001111dddd0111cccd0111cccd0111cccd0111cccd0111dcdd0111dddd0111 105 | # 004:1111111111111111111111111111111111111111111111111111111111111111 106 | # 017:111110dd111110dd111110dd111110dd10000ddd1eeeeddd1eeeeedd10000eed 107 | # 018:d0ddddddd0ddddddddddddddddd0000dddddccddddddccdddddddddddddddddd 108 | # 019:0ddd01110ddd0111dddd0111dddd0111ddddd000ddddddddddddddddddddd000 109 | # 020:1111111111111111111111111111111101111111d0111111d011111101111111 110 | # 033:111110ee111110ee111110ee111110ee111110ee111110ee111110ee111110ee 111 | # 034:dddcccccddccccccddccccccddccccccddccccccdddcccccdddddddddddddddd 112 | # 035:dddd0111cddd0111cddd0111cddd0111cddd0111dddd0111dddd0111dddd0111 113 | # 036:1111111111111111111111111111111111111111111111111111111111111111 114 | # 049:111110ee111110ee111110ee111110ee111110ee111110ee111110ee11111100 115 | # 050:dddeeeeeddeeeeeed00000000111111101111111011111110111111111111111 116 | # 051:eddd0111eedd01110eed011110ee011110ee011110ee011110ee011111001111 117 | # 052:1111111111111111111111111111111111111111111111111111111111111111 118 | # 119 | 120 | # 121 | # 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 122 | # 123 | 124 | -------------------------------------------------------------------------------- /src/studio/editors/code.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "studio/studio.h" 26 | 27 | typedef struct Code Code; 28 | 29 | struct Code 30 | { 31 | Studio* studio; 32 | tic_mem* tic; 33 | 34 | char* src; 35 | 36 | struct 37 | { 38 | struct 39 | { 40 | char* position; 41 | char* selection; 42 | s32 column; 43 | }; 44 | 45 | char* mouseDownPosition; 46 | s32 delay; 47 | } cursor; 48 | 49 | struct 50 | { 51 | s32 x; 52 | s32 y; 53 | 54 | tic_point start; 55 | 56 | bool active; 57 | 58 | } scroll; 59 | 60 | struct CodeState 61 | { 62 | struct 63 | { 64 | u8 syntax:3; 65 | u8 bookmark:1; 66 | u8 cursor:1; 67 | u8 temp:3; 68 | }; 69 | 70 | char sym; 71 | }* state; 72 | 73 | struct 74 | { 75 | char line[STUDIO_TEXT_BUFFER_WIDTH]; 76 | char size[STUDIO_TEXT_BUFFER_WIDTH]; 77 | tic_color color; 78 | }status; 79 | 80 | u32 tickCounter; 81 | 82 | struct History* history; 83 | 84 | enum 85 | { 86 | TEXT_DRAG_CODE, 87 | TEXT_FIND_MODE, 88 | TEXT_GOTO_MODE, 89 | TEXT_BOOKMARK_MODE, 90 | TEXT_OUTLINE_MODE, 91 | TEXT_EDIT_MODE, 92 | } mode; 93 | 94 | struct 95 | { 96 | char text[STUDIO_TEXT_BUFFER_WIDTH - sizeof "FIND:"]; 97 | 98 | char* prevPos; 99 | char* prevSel; 100 | } popup; 101 | 102 | struct 103 | { 104 | s32 line; 105 | } jump; 106 | 107 | struct 108 | { 109 | tic_outline_item* items; 110 | 111 | s32 size; 112 | s32 index; 113 | s32 scroll; 114 | } sidebar; 115 | 116 | const char* matchedDelim; 117 | bool altFont; 118 | bool shadowText; 119 | 120 | struct 121 | { 122 | s32 pos; 123 | s32 sidebar; 124 | 125 | Movie* movie; 126 | 127 | Movie idle; 128 | Movie show; 129 | Movie hide; 130 | 131 | } anim; 132 | 133 | void(*tick)(Code*); 134 | void(*escape)(Code*); 135 | void(*event)(Code*, StudioEvent); 136 | void(*update)(Code*); 137 | }; 138 | 139 | void initCode(Code*, Studio* studio); 140 | void freeCode(Code*); 141 | void codeGetPos(Code*, s32* x, s32* y); 142 | void codeSetPos(Code*, s32 x, s32 y); 143 | -------------------------------------------------------------------------------- /src/defines.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) 26 | #define MIN(a,b) ((a) < (b) ? (a) : (b)) 27 | #define MAX(a,b) ((a) > (b) ? (a) : (b)) 28 | #define MIN3(a,b,c) MIN(MIN(a, b), c) 29 | #define MAX3(a,b,c) MAX(MAX(a, b), c) 30 | #define CLAMP(v,a,b) (MIN(MAX(v,a),b)) 31 | #define SWAP(a, b, type) do { type temp = a; a = b; b = temp; } while (0) 32 | #define MEMCMP(a, b) (sizeof a == sizeof b && memcmp(&a, &b, sizeof a) == 0) 33 | #define ZEROMEM(p) memset(&p, 0, sizeof p) 34 | #define MOVE(...) memmove(malloc(sizeof __VA_ARGS__), &__VA_ARGS__, sizeof __VA_ARGS__) 35 | #define DEF2STR2(x) #x 36 | #define DEF2STR(x) DEF2STR2(x) 37 | #define STRLEN(str) (sizeof str - 1) 38 | #define CONCAT2(a, b) a ## b 39 | #define CONCAT(a, b) CONCAT2(a, b) 40 | #define MACROVAR(name) CONCAT(name, __LINE__) 41 | #define SCOPE(...) for(int MACROVAR(_i_) = 0; !MACROVAR(_i_); ++MACROVAR(_i_), __VA_ARGS__) 42 | #define FOR(type,it,list) for(type it = list, *MACROVAR(_end_) = it + COUNT_OF(list); it != MACROVAR(_end_); ++it) 43 | #define RFOR(type,it,list) for(type it = list + (COUNT_OF(list) - 1), *MACROVAR(_end_) = list; it >= MACROVAR(_end_); --it) 44 | #define NEW(o) (o*)malloc(sizeof(o)) 45 | #define FREE(ptr) do { if(ptr) free(ptr); } while (0) 46 | 47 | #define BITSET(a,b) ((a) | (1ULL<<(b))) 48 | #define BITCLEAR(a,b) ((a) & ~(1ULL<<(b))) 49 | #define BITFLIP(a,b) ((a) ^ (1ULL<<(b))) 50 | #define BITCHECK(a,b) (!!((a) & (1ULL<<(b)))) 51 | #define _BITSET(a,b) ((a) |= (1ULL<<(b))) 52 | #define _BITCLEAR(a,b) ((a) &= ~(1ULL<<(b))) 53 | #define _BITFLIP(a,b) ((a) ^= (1ULL<<(b))) 54 | 55 | #define REP0(...) 56 | #define REP1(...) __VA_ARGS__ 57 | #define REP2(...) REP1(__VA_ARGS__) __VA_ARGS__ 58 | #define REP3(...) REP2(__VA_ARGS__) __VA_ARGS__ 59 | #define REP4(...) REP3(__VA_ARGS__) __VA_ARGS__ 60 | #define REP5(...) REP4(__VA_ARGS__) __VA_ARGS__ 61 | #define REP6(...) REP5(__VA_ARGS__) __VA_ARGS__ 62 | #define REP7(...) REP6(__VA_ARGS__) __VA_ARGS__ 63 | #define REP8(...) REP7(__VA_ARGS__) __VA_ARGS__ 64 | #define REP9(...) REP8(__VA_ARGS__) __VA_ARGS__ 65 | #define REP10(...) REP9(__VA_ARGS__) __VA_ARGS__ 66 | 67 | #define REP(HUNDREDS,TENS,ONES,...) \ 68 | REP##HUNDREDS(REP10(REP10(__VA_ARGS__))) \ 69 | REP##TENS(REP10(__VA_ARGS__)) \ 70 | REP##ONES(__VA_ARGS__) 71 | -------------------------------------------------------------------------------- /src/tilesheet.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 4 | // Damien de Lemeny @ddelemeny // hello@ddelemeny.me 5 | 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | #pragma once 25 | 26 | #include "tools.h" 27 | 28 | typedef struct 29 | { 30 | u32 page_orig; 31 | u32 bank_orig; 32 | u32 nb_pages; 33 | u32 bank_size; 34 | u32 sheet_width; 35 | u32 tile_width; 36 | size_t ptr_size; 37 | u8 (*peek)(const void*, u32); 38 | void (*poke)(void*, u32, u8); 39 | } tic_blit_segment; 40 | 41 | typedef struct 42 | { 43 | const tic_blit_segment* segment; 44 | u8* ptr; 45 | } tic_tilesheet; 46 | 47 | typedef struct 48 | { 49 | const tic_blit_segment* segment; 50 | u32 offset; 51 | u8* ptr; 52 | } tic_tileptr; 53 | 54 | tic_tilesheet tic_tilesheet_get(u8 segment, u8* ptr); 55 | tic_tileptr tic_tilesheet_gettile(const tic_tilesheet* sheet, s32 index, bool local); 56 | 57 | inline u8 tic_tilesheet_getpix(const tic_tilesheet* sheet, s32 x, s32 y) 58 | { 59 | // tile coord 60 | u16 tile_index = ((y >> 3) << 4 ) + (x / sheet->segment->tile_width); 61 | // coord in tile 62 | u32 pix_addr = ((x & (sheet->segment->tile_width - 1)) + ((y & 7) * sheet->segment->tile_width)) ; 63 | return sheet->segment->peek(sheet->ptr+tile_index * sheet->segment->ptr_size, pix_addr); 64 | } 65 | 66 | inline void tic_tilesheet_setpix(const tic_tilesheet* sheet, s32 x, s32 y, u8 value) 67 | { 68 | // tile coord 69 | u16 tile_index = ((y >> 3) << 4 ) + (x / sheet->segment->tile_width); 70 | // coord in tile 71 | u32 pix_addr = ((x & (sheet->segment->tile_width - 1)) + ((y & 7) * sheet->segment->tile_width)) ; 72 | sheet->segment->poke(sheet->ptr + tile_index * sheet->segment->ptr_size, pix_addr, value); 73 | } 74 | 75 | inline u8 tic_tilesheet_gettilepix(const tic_tileptr* tile, s32 x, s32 y) 76 | { 77 | u32 addr = tile->offset + x + (y * tile->segment->tile_width); 78 | return tile->segment->peek(tile->ptr, addr); 79 | } 80 | 81 | inline void tic_tilesheet_settilepix(const tic_tileptr* tile, s32 x, s32 y, u8 value) 82 | { 83 | u32 addr = tile->offset + x + (y * tile->segment->tile_width); 84 | tile->segment->poke(tile->ptr, addr, value); 85 | } 86 | 87 | typedef struct 88 | { 89 | tic_bpp mode; 90 | u8 pages; 91 | u8 page; 92 | u8 bank; 93 | } tic_blit; 94 | 95 | inline s32 tic_blit_calc_segment(const tic_blit* blit) 96 | { 97 | return blit->pages * (2 + blit->bank) + blit->page; 98 | } 99 | 100 | inline void tic_blit_update_bpp(tic_blit* blit, tic_bpp bpp) 101 | { 102 | blit->mode = bpp; 103 | blit->pages = 4 / bpp; 104 | blit->page %= blit->pages; 105 | } 106 | 107 | inline s32 tic_blit_calc_index(const tic_blit* blit) 108 | { 109 | return blit->bank * blit->pages * TIC_BANK_SPRITES + blit->page * TIC_SPRITESHEET_COLS; 110 | } 111 | -------------------------------------------------------------------------------- /demos/bunny/jsmark.js: -------------------------------------------------------------------------------- 1 | // title: Bunnymark in JavaScript 2 | // author: Rob Loach 3 | // desc: Benchmarking tool to see how many bunnies can fly around the screen, using JavaScript. 4 | // license: MIT License 5 | // input: gamepad 6 | // script: js 7 | // version: 1.1.0 8 | 9 | const screenWidth = 240 10 | const screenHeight = 136 11 | const toolbarHeight = 6 12 | var t = 0 13 | 14 | function GetRandomValue(min, max) { 15 | return Math.random() * (max - min) + min 16 | } 17 | 18 | function Bunny() { 19 | this.x = GetRandomValue(0, screenWidth - Bunny.width) 20 | this.y = GetRandomValue(0, screenHeight - Bunny.height) 21 | this.speedX = GetRandomValue(-100, 100) / 60 22 | this.speedY = GetRandomValue(-100, 100) / 60 23 | this.sprite = 1 24 | 25 | this.draw = function() { 26 | spr(this.sprite, this.x, this.y, 1, 1, 0, 0, 4, 4) 27 | } 28 | 29 | this.update = function() { 30 | this.x += this.speedX 31 | this.y += this.speedY 32 | 33 | if (this.x + Bunny.width > screenWidth) { 34 | this.x = screenWidth - Bunny.width 35 | this.speedX *= -1 36 | } 37 | if (this.x < 0) { 38 | this.x = 0 39 | this.speedX *= -1 40 | } 41 | if (this.y + Bunny.height > screenHeight) { 42 | this.y = screenHeight - Bunny.height 43 | this.speedY *= -1 44 | } 45 | 46 | if (this.y < toolbarHeight) { 47 | this.y = toolbarHeight 48 | this.speedY *= -1 49 | } 50 | } 51 | } 52 | 53 | Bunny.width = 26 54 | Bunny.height = 32 55 | 56 | function FPS() { 57 | this.value = 0 58 | this.frames = 0 59 | this.lastTime = -1000 60 | this.getValue = function() { 61 | if (time() - this.lastTime <= 1000) { 62 | this.frames = this.frames + 1 63 | } 64 | else { 65 | this.value = this.frames 66 | this.frames = 0 67 | this.lastTime = time() 68 | } 69 | return this.value 70 | } 71 | } 72 | 73 | const fps = new FPS() 74 | const bunnies = [] 75 | bunnies.push(new Bunny()) 76 | 77 | function TIC() { 78 | // Music 79 | if (t==0) { 80 | music(0) 81 | } 82 | if (t == 6*64*2.375) { 83 | music(1) 84 | } 85 | t++ 86 | 87 | // Input 88 | if (btn(0)) { 89 | for (var i = 0; i < 5; i++) { 90 | bunnies.push(new Bunny()) 91 | } 92 | } 93 | else if (btn(1)) { 94 | for (var i = 0; i < 5; i++) { 95 | bunnies.pop() 96 | } 97 | } 98 | 99 | // Update 100 | for (var i in bunnies) { 101 | bunnies[i].update() 102 | } 103 | 104 | // Draw 105 | cls(15) 106 | for (var i in bunnies) { 107 | bunnies[i].draw() 108 | } 109 | rect(0, 0, screenWidth, toolbarHeight, 0) 110 | print("Bunnies: " + bunnies.length, 1, 0, 11, false, 1, false) 111 | print("FPS: " + fps.getValue(), screenWidth / 2, 0, 11, false, 1, false) 112 | } 113 | 114 | // 115 | // 001:11111100111110dd111110dc111110dc111110dc111110dc111110dd111110dd 116 | // 002:00011110ddd0110dccd0110dccd0110dccd0110dccd0110dcddd00dddddddddd 117 | // 003:00001111dddd0111cccd0111cccd0111cccd0111cccd0111dcdd0111dddd0111 118 | // 004:1111111111111111111111111111111111111111111111111111111111111111 119 | // 017:111110dd111110dd111110dd111110dd10000ddd1eeeeddd1eeeeedd10000eed 120 | // 018:d0ddddddd0ddddddddddddddddd0000dddddccddddddccdddddddddddddddddd 121 | // 019:0ddd01110ddd0111dddd0111dddd0111ddddd000ddddddddddddddddddddd000 122 | // 020:1111111111111111111111111111111101111111d0111111d011111101111111 123 | // 033:111110ee111110ee111110ee111110ee111110ee111110ee111110ee111110ee 124 | // 034:dddcccccddccccccddccccccddccccccddccccccdddcccccdddddddddddddddd 125 | // 035:dddd0111cddd0111cddd0111cddd0111cddd0111dddd0111dddd0111dddd0111 126 | // 036:1111111111111111111111111111111111111111111111111111111111111111 127 | // 049:111110ee111110ee111110ee111110ee111110ee111110ee111110ee11111100 128 | // 050:dddeeeeeddeeeeeed00000000111111101111111011111110111111111111111 129 | // 051:eddd0111eedd01110eed011110ee011110ee011110ee011110ee011111001111 130 | // 052:1111111111111111111111111111111111111111111111111111111111111111 131 | // 132 | 133 | // 134 | // 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 135 | // 136 | -------------------------------------------------------------------------------- /demos/music.lua: -------------------------------------------------------------------------------- 1 | -- title: Music Demo 2 | -- author: Tromino 3 | -- desc: music made with custom waveforms 4 | -- script: lua 5 | -- input: gamepad 6 | 7 | t=0 8 | x=104 9 | y=24 10 | 11 | function TIC() 12 | 13 | if btnp()~=0 then music(0) end 14 | 15 | cls(12) 16 | spr(1+(t%60)/30,x,y,-1,4) 17 | print("PRESS START TO RICH!",44,64) 18 | t=t+1 19 | end 20 | 21 | -- 22 | -- 001:0066600006066660ddddd666f0f0fff0fdfdff0f0ff00ffff0066ff00f66f000 23 | -- 002:8811188881811118ccccc111f8f8fff8fcfcff8f8ff88ffff8811ff88f11f888 24 | -- 25 | 26 | -- 27 | -- 000:17afadcf936f05789abc868ddc975310 28 | -- 001:49dece9dcb9789bccccba89aaaa98641 29 | -- 002:69abb9bbcccbba9cddcca989abaaa863 30 | -- 003:6799abbbba98767789987abccca98887 31 | -- 004:789abcbbaa9987777889aaaaaa998766 32 | -- 005:789abbbbbbaa9988888888999aaa9998 33 | -- 006:7888999aaaaaaaaa9999888999988887 34 | -- 007:77777788889999999999999988888777 35 | -- 008:9cdeeffffeddcb986432110111123457 36 | -- 009:abdeffffeedcba976543322111112256 37 | -- 010:8bdefffedccbbaa99887654321100147 38 | -- 011:8aceffedcbaa98888998877654221125 39 | -- 012:8bdeffeb976678899987766543211125 40 | -- 013:bdeeb8766667889aaaaa998877653347 41 | -- 014:01236deffffffffffffffeed64345420 42 | -- 43 | 44 | -- 45 | -- 000:000001000200030004000500060007000700070007000700070007000700070007000700070007000700070007000700070007000700070007000700309000000000 46 | -- 001:800081008200830084008500860087008700870087008700870087008700870087008700870087008700870087008700870087008700870087008700300000000000 47 | -- 002:40004000400040004100410041004100420042004200420043004300430043004400440044004400450045004500450046004600460046004700470010b000000000 48 | -- 003:08000800090009000a000a000b000b000c000c000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d000d0030b000000000 49 | -- 004:880f880f890f890f8a0f8a0f8b0f8b0f8c0f8c0f8d0f8d0f8d0f8d0f8d0f8d0f8d0f8d0f8d0f8d0f8d0f8d0f8d0f8d0f8d0f8d0f8d0f8d0f8d0f8d0f30b000000000 50 | -- 005:050e030102030104010602070207030704060506070509050b040c040c030d030d030d020c020b0209030803180317032604260435045504a405f405a09000000000 51 | -- 006:2f022e2f3e1f5f977fa79fb7afb7bfc7cfc7dfd7dfd7efe7efe7efe7eff7fff7fff7fff7fff7fff7fff7fff7fff7fff7fff7fff7fff7fff7fff7fff7c00000000000 52 | -- 53 | 54 | -- 55 | -- 000:8ff1069ff116bff1068ff116fff106bff1166ff108fff1168ff1086ff1186ff1088ff118fff1066ff118bff106fff1168ff106bff116bff1068ff116fff106bff1166ff108fff1168ff1086ff1186ff1088ff118fff1066ff118bff106fff1166ff106bff1169ff1066ff116dff1069ff1164ff108dff1166ff1084ff1184ff1086ff118dff1064ff1189ff106dff1166ff1069ff1169ff1066ff116dff1069ff1164ff108dff1166ff1084ff1184ff1086ff118dff1064ff1189ff106dff116 56 | -- 001:8ff1240000008ff1240000004ff1680000008ff1240000000000000000008ff1240000004ff1680000008ff1240000008ff1240000008ff1240000004ff1680000008ff1240000000000000000008ff1240000004ff1680000008ff1240000006ff1240000006ff1240000004ff1680000006ff1240000000000000000006ff1240000004ff1680000006ff1240000006ff1240000006ff1240000004ff1680000006ff1240000000000000000006ff1240000004ff1680000006ff124000000 57 | -- 002:8ff1380000000000000000000000000000000000000000006ff1380000000000000000000000000000000000000000008ff138000000000000000000fff138000000000000000000000000000000000000000000bff1380000000000000000009ff1380000000000000000000000000000000000000000006ff1380000000000000000000000000000000000000000009ff138000000000000000000dff138000000000000000000000000000000000000000000bff138000000000000000000 58 | -- 003:0000000000000000008ff1480000000000000000000000000000000000000000006ff1480000000000000000000000000000000000000000008ff148000000000000000000fff148000000000000000000000000000000000000000000bff1480000000000000000009ff1480000000000000000000000000000000000000000006ff1480000000000000000000000000000000000000000009ff148000000000000000000dff148000000000000000000000000000000000000000000bff148 59 | -- 60 | 61 | -- 62 | -- 000:1800001800001803011803010000000000000000000000000000000000000000000000000000000000000000000000000000ff 63 | -- 64 | 65 | -- 66 | -- 000:140c1c44243430346d4e4a4e854c30346524d04648757161597dced27d2c8595a16daa2cd2aa996dc2cadad45edeeed6 67 | -- 68 | 69 | -------------------------------------------------------------------------------- /demos/bunny/wrenmark.wren: -------------------------------------------------------------------------------- 1 | // title: Bunnymark in Wren 2 | // author: Rob Loach 3 | // desc: Benchmarking tool to see how many bunnies can fly around the screen, using Wren. 4 | // license: MIT License 5 | // input: gamepad 6 | // script: wren 7 | // version: 1.1.0 8 | 9 | import "random" for Random 10 | 11 | var ScreenWidth = 240 12 | var ScreenHeight = 136 13 | var ToolbarHeight = 6 14 | 15 | class Bunny { 16 | construct new(rand) { 17 | _x = rand.int(0, ScreenWidth - Bunny.width) 18 | _y = rand.int(0, ScreenHeight - Bunny.height) 19 | _speedX = rand.float(-100, 100) / 60 20 | _speedY = rand.float(-100, 100) / 60 21 | _sprite = 1 22 | } 23 | 24 | static width { 25 | return 26 26 | } 27 | static height { 28 | return 32 29 | } 30 | 31 | draw() { 32 | TIC.spr(_sprite, _x, _y, 1, 1, 0, 0, 4, 4) 33 | } 34 | 35 | update() { 36 | _x = _x + _speedX 37 | _y = _y + _speedY 38 | 39 | if (_x + Bunny.width > ScreenWidth) { 40 | _x = ScreenWidth - Bunny.width 41 | _speedX = _speedX * - 1 42 | } 43 | if (_x < 0) { 44 | _x = 0 45 | _speedX = _speedX * -1 46 | } 47 | if (_y + Bunny.height > ScreenHeight) { 48 | _y = ScreenHeight - Bunny.height 49 | _speedY = _speedY * -1 50 | } 51 | 52 | if (_y < ToolbarHeight) { 53 | _y = ToolbarHeight 54 | _speedY = _speedY * -1 55 | } 56 | } 57 | } 58 | 59 | class FPS { 60 | construct new() { 61 | _value = 0 62 | _frames = 0 63 | _lastTime = -1000 64 | } 65 | getValue() { 66 | if (TIC.time() - _lastTime <= 1000) { 67 | _frames = _frames + 1 68 | } else { 69 | _value = _frames 70 | _frames = 0 71 | _lastTime = TIC.time() 72 | } 73 | return _value 74 | } 75 | } 76 | 77 | class Game is TIC { 78 | construct new() { 79 | _fps = FPS.new() 80 | _random = Random.new() 81 | _bunnies = [Bunny.new(_random)] 82 | _t = 0 83 | } 84 | 85 | TIC() { 86 | // Music 87 | if (_t == 0) { 88 | TIC.music(0) 89 | } 90 | if (_t == 6*64*2.375) { 91 | TIC.music(1) 92 | } 93 | _t = _t + 1 94 | 95 | // Input 96 | if (TIC.btn(0)) { 97 | for (i in 1...5) { 98 | _bunnies.add(Bunny.new(_random)) 99 | } 100 | } else if (TIC.btn(1)) { 101 | for (i in 1...5) { 102 | if (_bunnies.count > 0) { 103 | _bunnies.removeAt(0) 104 | } 105 | } 106 | } 107 | 108 | // Update 109 | for (bunny in _bunnies) { 110 | bunny.update() 111 | } 112 | 113 | // Draw 114 | TIC.cls(15) 115 | for (bunny in _bunnies) { 116 | bunny.draw() 117 | } 118 | TIC.rect(0, 0, ScreenWidth, ToolbarHeight, 0) 119 | TIC.print("Bunnies: %(_bunnies.count)", 1, 0, 11, false, 1, false) 120 | TIC.print("FPS: %(_fps.getValue())", ScreenWidth / 2, 0, 11, false, 1, false) 121 | } 122 | } 123 | 124 | // 125 | // 001:11111100111110dd111110dc111110dc111110dc111110dc111110dd111110dd 126 | // 002:00011110ddd0110dccd0110dccd0110dccd0110dccd0110dcddd00dddddddddd 127 | // 003:00001111dddd0111cccd0111cccd0111cccd0111cccd0111dcdd0111dddd0111 128 | // 004:1111111111111111111111111111111111111111111111111111111111111111 129 | // 017:111110dd111110dd111110dd111110dd10000ddd1eeeeddd1eeeeedd10000eed 130 | // 018:d0ddddddd0ddddddddddddddddd0000dddddccddddddccdddddddddddddddddd 131 | // 019:0ddd01110ddd0111dddd0111dddd0111ddddd000ddddddddddddddddddddd000 132 | // 020:1111111111111111111111111111111101111111d0111111d011111101111111 133 | // 033:111110ee111110ee111110ee111110ee111110ee111110ee111110ee111110ee 134 | // 034:dddcccccddccccccddccccccddccccccddccccccdddcccccdddddddddddddddd 135 | // 035:dddd0111cddd0111cddd0111cddd0111cddd0111dddd0111dddd0111dddd0111 136 | // 036:1111111111111111111111111111111111111111111111111111111111111111 137 | // 049:111110ee111110ee111110ee111110ee111110ee111110ee111110ee11111100 138 | // 050:dddeeeeeddeeeeeed00000000111111101111111011111110111111111111111 139 | // 051:eddd0111eedd01110eed011110ee011110ee011110ee011110ee011111001111 140 | // 052:1111111111111111111111111111111111111111111111111111111111111111 141 | // 142 | 143 | // 144 | // 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 145 | // 146 | -------------------------------------------------------------------------------- /demos/bunny/squirrelmark.nut: -------------------------------------------------------------------------------- 1 | // title: Bunnymark in Squirrel 2 | // author: Rob Loach 3 | // desc: Benchmarking tool to see how many bunnies can fly around the screen, using Squirrel. 4 | // license: MIT License 5 | // input: gamepad 6 | // script: squirrel 7 | // version: 1.1.0 8 | 9 | local ScreenWidth = 240; 10 | local ScreenHeight = 136; 11 | local ToolbarHeight = 6; 12 | local t = 0; 13 | 14 | function rndfloat(max) { 15 | local roll = 1.0 * max * rand() / RAND_MAX; 16 | return roll; 17 | } 18 | 19 | function rndint(max) { 20 | local roll = 1.0 * max * rand() / RAND_MAX; 21 | return roll.tointeger(); 22 | } 23 | 24 | class Bunny { 25 | static width = 26; 26 | static height = 32; 27 | 28 | x = 0; 29 | y = 0; 30 | speedX = 0; 31 | speedY = 0; 32 | sprite = 1; 33 | 34 | constructor() { 35 | x = rndint(ScreenWidth - 26); 36 | y = rndint(ScreenHeight - 32); 37 | speedX = (rndfloat(200) - 100) / 60; 38 | speedY = (rndfloat(200) - 100) / 60; 39 | } 40 | 41 | function draw() { 42 | spr(sprite, x, y, 1, 1, 0, 0, 4, 4); 43 | } 44 | 45 | function update() { 46 | x = x + speedX; 47 | y = y + speedY; 48 | 49 | if (x + width > ScreenWidth) { 50 | x = ScreenWidth - width; 51 | speedX = speedX * - 1; 52 | } 53 | if (x < 0) { 54 | x = 0; 55 | speedX = speedX * -1; 56 | } 57 | if (y + height > ScreenHeight) { 58 | y = ScreenHeight - height; 59 | speedY = speedY * -1; 60 | } 61 | 62 | if (y < ToolbarHeight) { 63 | y = ToolbarHeight; 64 | speedY = speedY * -1; 65 | } 66 | } 67 | } 68 | 69 | class FPS { 70 | fps = 0; 71 | frames = 0; 72 | lastTime = -1000; 73 | 74 | function getValue() { 75 | if (time() - lastTime <= 1000) { 76 | frames = frames + 1; 77 | } else { 78 | fps = frames; 79 | frames = 0; 80 | lastTime = time(); 81 | } 82 | return fps; 83 | } 84 | } 85 | 86 | local fps = FPS(); 87 | local bunnies = [Bunny()]; 88 | 89 | function TIC() { 90 | // Music 91 | if (t==0) { 92 | music(0) 93 | } 94 | if (t == 6*64*2.375) { 95 | music(1) 96 | } 97 | t++ 98 | 99 | // Input 100 | if (btn(0)) { 101 | for (local i = 0; i < 5; i += 1) { 102 | bunnies.push(Bunny()); 103 | } 104 | } else if (btn(1)) { 105 | for (local i = 0; i < 5; i += 1) { 106 | if (bunnies.len() > 0) { 107 | bunnies.remove(0); 108 | } 109 | } 110 | } 111 | 112 | // Update 113 | foreach (i,bunny in bunnies) { 114 | bunny.update(); 115 | } 116 | 117 | // Draw 118 | cls(15) 119 | foreach (i,bunny in bunnies) { 120 | bunny.draw(); 121 | } 122 | rect(0, 0, ScreenWidth, ToolbarHeight, 0); 123 | print("Bunnies: " + bunnies.len().tostring(), 1, 0, 11, false, 1, false); 124 | print("FPS: " + fps.getValue().tostring(), ScreenWidth / 2, 0, 11, false, 1, false); 125 | } 126 | 127 | // 128 | // 001:11111100111110dd111110dc111110dc111110dc111110dc111110dd111110dd 129 | // 002:00011110ddd0110dccd0110dccd0110dccd0110dccd0110dcddd00dddddddddd 130 | // 003:00001111dddd0111cccd0111cccd0111cccd0111cccd0111dcdd0111dddd0111 131 | // 004:1111111111111111111111111111111111111111111111111111111111111111 132 | // 017:111110dd111110dd111110dd111110dd10000ddd1eeeeddd1eeeeedd10000eed 133 | // 018:d0ddddddd0ddddddddddddddddd0000dddddccddddddccdddddddddddddddddd 134 | // 019:0ddd01110ddd0111dddd0111dddd0111ddddd000ddddddddddddddddddddd000 135 | // 020:1111111111111111111111111111111101111111d0111111d011111101111111 136 | // 033:111110ee111110ee111110ee111110ee111110ee111110ee111110ee111110ee 137 | // 034:dddcccccddccccccddccccccddccccccddccccccdddcccccdddddddddddddddd 138 | // 035:dddd0111cddd0111cddd0111cddd0111cddd0111dddd0111dddd0111dddd0111 139 | // 036:1111111111111111111111111111111111111111111111111111111111111111 140 | // 049:111110ee111110ee111110ee111110ee111110ee111110ee111110ee11111100 141 | // 050:dddeeeeeddeeeeeed00000000111111101111111011111110111111111111111 142 | // 051:eddd0111eedd01110eed011110ee011110ee011110ee011110ee011111001111 143 | // 052:1111111111111111111111111111111111111111111111111111111111111111 144 | // 145 | 146 | // 147 | // 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 148 | // 149 | -------------------------------------------------------------------------------- /src/tools.h: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com 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. 22 | 23 | #pragma once 24 | 25 | #include "api.h" 26 | #include "tic.h" 27 | #include 28 | 29 | inline s32 tic_tool_sfx_pos(s32 speed, s32 ticks) 30 | { 31 | return speed > 0 ? ticks * (1 + speed) : ticks / (1 - speed); 32 | } 33 | 34 | #define POKE_N(P,I,V,A,B,C,D) do \ 35 | { \ 36 | u8* val = (u8*)(P) + ((I) >> (A)); \ 37 | u8 offset = ((I) & (B)) << (C); \ 38 | *val &= ~((D) << offset); \ 39 | *val |= ((V) & (D)) << offset; \ 40 | } while(0) 41 | 42 | #define PEEK_N(P,I,A,B,C,D) ( ( ((u8*)(P))[((I) >> (A))] >> ( ((I) & (B)) << (C) ) ) & (D) ) 43 | 44 | inline void tic_tool_poke4(void* addr, u32 index, u8 value) 45 | { 46 | POKE_N(addr, index, value, 1,1,2,15); 47 | } 48 | 49 | inline u8 tic_tool_peek4(const void* addr, u32 index) 50 | { 51 | return PEEK_N(addr, index, 1,1,2,15); 52 | } 53 | 54 | inline void tic_tool_poke2(void* addr, u32 index, u8 value) 55 | { 56 | POKE_N(addr, index, value, 2,3,1,3); 57 | } 58 | 59 | inline u8 tic_tool_peek2(const void* addr, u32 index) 60 | { 61 | return PEEK_N(addr, index, 2,3,1,3); 62 | } 63 | 64 | inline void tic_tool_poke1(void* addr, u32 index, u8 value) 65 | { 66 | POKE_N(addr, index, value, 3,7,0,1); 67 | } 68 | 69 | inline u8 tic_tool_peek1(const void* addr, u32 index) 70 | { 71 | return PEEK_N(addr, index, 3,7,0,1); 72 | } 73 | 74 | #undef PEEK_N 75 | #undef POKE_N 76 | 77 | inline u32 tic_rgba(const tic_rgb* c) 78 | { 79 | return (0xff << 24) | (c->b << 16) | (c->g << 8) | (c->r << 0); 80 | } 81 | 82 | inline s32 tic_modulo(s32 x, s32 m) 83 | { 84 | if(x >= m) return x % m; 85 | if(x < 0) return x % m + m; 86 | 87 | return x; 88 | } 89 | 90 | tic_blitpal tic_tool_palette_blit(const tic_palette* src, tic80_pixel_color_format fmt); 91 | 92 | bool tic_tool_parse_note(const char* noteStr, s32* note, s32* octave); 93 | s32 tic_tool_get_pattern_id(const tic_track* track, s32 frame, s32 channel); 94 | void tic_tool_set_pattern_id(tic_track* track, s32 frame, s32 channel, s32 id); 95 | bool tic_project_ext(const char* name); 96 | bool tic_tool_has_ext(const char* name, const char* ext); 97 | s32 tic_tool_get_track_row_sfx(const tic_track_row* row); 98 | void tic_tool_set_track_row_sfx(tic_track_row* row, s32 sfx); 99 | void tic_tool_str2buf(const char* str, s32 size, void* buf, bool flip); 100 | 101 | u32 tic_tool_zip(void* dest, s32 destSize, const void* source, s32 size); 102 | u32 tic_tool_unzip(void* dest, s32 bufSize, const void* source, s32 size); 103 | 104 | bool tic_tool_empty(const void* buffer, s32 size); 105 | #define EMPTY(BUFFER) (tic_tool_empty((BUFFER), sizeof (BUFFER))) 106 | 107 | bool tic_tool_flat4(const void* buffer, s32 size); 108 | #define FLAT4(BUFFER) (tic_tool_flat4((BUFFER), sizeof (BUFFER))) 109 | 110 | bool tic_tool_noise(const tic_waveform* wave); 111 | u32 tic_nearest_color(const tic_rgb* palette, const tic_rgb* color, s32 count); 112 | char* tic_tool_metatag(const char* code, const char* tag, const char* comment); -------------------------------------------------------------------------------- /src/ext/kiss_fft.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003-2010, Mark Borgerding. All rights reserved. 3 | * This file is part of KISS FFT - https://github.com/mborgerding/kissfft 4 | * 5 | * SPDX-License-Identifier: BSD-3-Clause 6 | * See COPYING file for more information. 7 | */ 8 | 9 | #ifndef KISS_FFT_H 10 | #define KISS_FFT_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | /* 22 | ATTENTION! 23 | If you would like a : 24 | -- a utility that will handle the caching of fft objects 25 | -- real-only (no imaginary time component ) FFT 26 | -- a multi-dimensional FFT 27 | -- a command-line utility to perform ffts 28 | -- a command-line utility to perform fast-convolution filtering 29 | 30 | Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c 31 | in the tools/ directory. 32 | */ 33 | 34 | #ifdef USE_SIMD 35 | # include 36 | # define kiss_fft_scalar __m128 37 | #define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes,16) 38 | #define KISS_FFT_FREE _mm_free 39 | #else 40 | #define KISS_FFT_MALLOC malloc 41 | #define KISS_FFT_FREE free 42 | #endif 43 | 44 | 45 | #ifdef FIXED_POINT 46 | #include 47 | # if (FIXED_POINT == 32) 48 | # define kiss_fft_scalar int32_t 49 | # else 50 | # define kiss_fft_scalar int16_t 51 | # endif 52 | #else 53 | # ifndef kiss_fft_scalar 54 | /* default is float */ 55 | # define kiss_fft_scalar float 56 | # endif 57 | #endif 58 | 59 | typedef struct { 60 | kiss_fft_scalar r; 61 | kiss_fft_scalar i; 62 | }kiss_fft_cpx; 63 | 64 | typedef struct kiss_fft_state* kiss_fft_cfg; 65 | 66 | /* 67 | * kiss_fft_alloc 68 | * 69 | * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. 70 | * 71 | * typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL); 72 | * 73 | * The return value from fft_alloc is a cfg buffer used internally 74 | * by the fft routine or NULL. 75 | * 76 | * If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc. 77 | * The returned value should be free()d when done to avoid memory leaks. 78 | * 79 | * The state can be placed in a user supplied buffer 'mem': 80 | * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, 81 | * then the function places the cfg in mem and the size used in *lenmem 82 | * and returns mem. 83 | * 84 | * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), 85 | * then the function returns NULL and places the minimum cfg 86 | * buffer size in *lenmem. 87 | * */ 88 | 89 | kiss_fft_cfg kiss_fft_alloc(int nfft, int inverse_fft, void* mem, size_t* lenmem); 90 | 91 | /* 92 | * kiss_fft(cfg,in_out_buf) 93 | * 94 | * Perform an FFT on a complex input buffer. 95 | * for a forward FFT, 96 | * fin should be f[0] , f[1] , ... ,f[nfft-1] 97 | * fout will be F[0] , F[1] , ... ,F[nfft-1] 98 | * Note that each element is complex and can be accessed like 99 | f[k].r and f[k].i 100 | * */ 101 | void kiss_fft(kiss_fft_cfg cfg, const kiss_fft_cpx* fin, kiss_fft_cpx* fout); 102 | 103 | /* 104 | A more generic version of the above function. It reads its input from every Nth sample. 105 | * */ 106 | void kiss_fft_stride(kiss_fft_cfg cfg, const kiss_fft_cpx* fin, kiss_fft_cpx* fout, int fin_stride); 107 | 108 | /* If kiss_fft_alloc allocated a buffer, it is one contiguous 109 | buffer and can be simply free()d when no longer needed*/ 110 | #define kiss_fft_free KISS_FFT_FREE 111 | 112 | /* 113 | Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up 114 | your compiler output to call this before you exit. 115 | */ 116 | void kiss_fft_cleanup(void); 117 | 118 | 119 | /* 120 | * Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5) 121 | */ 122 | int kiss_fft_next_fast_size(int n); 123 | 124 | /* for real ffts, we need an even size */ 125 | #define kiss_fftr_next_fast_size_real(n) \ 126 | (kiss_fft_next_fast_size( ((n)+1)>>1)<<1) 127 | 128 | #ifdef __cplusplus 129 | } 130 | #endif 131 | 132 | #endif 133 | -------------------------------------------------------------------------------- /demos/bunny/luamark.lua: -------------------------------------------------------------------------------- 1 | -- title: Bunnymark in Lua 2 | -- author: Rabia Alhaffar 3 | -- desc: Benchmarking tool to see how many bunnies can fly around the screen, using Lua. 4 | -- license: MIT License 5 | -- input: gamepad 6 | -- script: lua 7 | -- version: 1.1.0 8 | 9 | screenWidth = 240 10 | screenHeight = 136 11 | toolbarHeight = 6 12 | t = 0 13 | 14 | function randomFloat(lower, greater) 15 | return (math.random() * (greater - lower)) + lower; 16 | end 17 | 18 | Bunny = {width=0,height=0,x=0,y=0,speedX=0,speedY=0,sprite=0} 19 | 20 | function Bunny:new(o) 21 | o = o or {} 22 | setmetatable(o, self) 23 | self.__index = self 24 | self.width = 26 25 | self.height = 32 26 | self.x = math.random(0, screenWidth - self.width) 27 | self.y = math.random(0, screenHeight - self.height) 28 | self.speedX = randomFloat(-100, 100) / 60 29 | self.speedY = randomFloat(-100, 100) / 60 30 | self.sprite = 1 31 | return o 32 | end 33 | 34 | function Bunny:draw() 35 | spr(self.sprite, self.x, self.y, 1, 1, 0, 0, 4, 4) 36 | end 37 | 38 | function Bunny:update() 39 | self.x = self.x + self.speedX 40 | self.y = self.y + self.speedY 41 | 42 | if (self.x + self.width > screenWidth) then 43 | self.x = screenWidth - self.width 44 | self.speedX = self.speedX * -1 45 | end 46 | if (self.x < 0) then 47 | self.x = 0 48 | self.speedX = self.speedX * -1 49 | end 50 | if (self.y + self.height > screenHeight) then 51 | self.y = screenHeight - self.height 52 | self.speedY = self.speedY * -1 53 | end 54 | if (self.y < toolbarHeight) then 55 | self.y = toolbarHeight 56 | self.speedY = self.speedY * -1 57 | end 58 | end 59 | 60 | FPS = {} 61 | 62 | function FPS:new(o) 63 | o = o or {} 64 | setmetatable(o, self) 65 | self.__index = self 66 | self.value = 0 67 | self.frames = 0 68 | self.lastTime = 0 69 | return FPS 70 | end 71 | 72 | function FPS:getValue() 73 | if (time() - self.lastTime <= 1000) then 74 | self.frames = self.frames + 1 75 | else 76 | self.value = self.frames 77 | self.frames = 0 78 | self.lastTime = time() 79 | end 80 | return self.value 81 | end 82 | 83 | fps = FPS:new() 84 | bunnies = {} 85 | table.insert(bunnies, Bunny:new()) 86 | 87 | function TIC() 88 | -- music 89 | if t == 0 then 90 | music(0) 91 | end 92 | if t == 6*64*2.375 then 93 | music(1) 94 | end 95 | t = t + 1 96 | 97 | -- Input 98 | if btn(0) then 99 | for i = 1, 5 do 100 | table.insert(bunnies, Bunny:new()) 101 | end 102 | end 103 | if btn(1) then 104 | for i = 1, 5 do 105 | if next(bunnies) ~= nil then 106 | table.remove(bunnies, i0) 107 | end 108 | end 109 | end 110 | 111 | -- Update 112 | for i, item in pairs(bunnies) do 113 | item:update() 114 | end 115 | 116 | -- Draw 117 | cls(15) 118 | for i, item in pairs(bunnies) do 119 | item:draw() 120 | end 121 | 122 | rect(0, 0, screenWidth, toolbarHeight, 0) 123 | print("Bunnies: " .. #bunnies, 1, 0, 11, false, 1, false) 124 | print("FPS: " .. fps:getValue(), screenWidth / 2, 0, 11, false, 1, false) 125 | end 126 | 127 | -- 128 | -- 001:11111100111110dd111110dc111110dc111110dc111110dc111110dd111110dd 129 | -- 002:00011110ddd0110dccd0110dccd0110dccd0110dccd0110dcddd00dddddddddd 130 | -- 003:00001111dddd0111cccd0111cccd0111cccd0111cccd0111dcdd0111dddd0111 131 | -- 004:1111111111111111111111111111111111111111111111111111111111111111 132 | -- 017:111110dd111110dd111110dd111110dd10000ddd1eeeeddd1eeeeedd10000eed 133 | -- 018:d0ddddddd0ddddddddddddddddd0000dddddccddddddccdddddddddddddddddd 134 | -- 019:0ddd01110ddd0111dddd0111dddd0111ddddd000ddddddddddddddddddddd000 135 | -- 020:1111111111111111111111111111111101111111d0111111d011111101111111 136 | -- 033:111110ee111110ee111110ee111110ee111110ee111110ee111110ee111110ee 137 | -- 034:dddcccccddccccccddccccccddccccccddccccccdddcccccdddddddddddddddd 138 | -- 035:dddd0111cddd0111cddd0111cddd0111cddd0111dddd0111dddd0111dddd0111 139 | -- 036:1111111111111111111111111111111111111111111111111111111111111111 140 | -- 049:111110ee111110ee111110ee111110ee111110ee111110ee111110ee11111100 141 | -- 050:dddeeeeeddeeeeeed00000000111111101111111011111110111111111111111 142 | -- 051:eddd0111eedd01110eed011110ee011110ee011110ee011110ee011111001111 143 | -- 052:1111111111111111111111111111111111111111111111111111111111111111 144 | -- 145 | 146 | -- 147 | -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 148 | -- 149 | -------------------------------------------------------------------------------- /demos/bunny/wasmmark/src/main.zig: -------------------------------------------------------------------------------- 1 | // title: Bunnymark in Lua 2 | // author: Josh Goebel 3 | // desc: Benchmarking tool to see how many bunnies can fly around the screen, using WASM. 4 | // input: gamepad 5 | // script: wasm 6 | // version: 0.1 7 | 8 | const tic = @import("tic80.zig"); 9 | const std = @import("std"); 10 | const RndGen = std.rand.DefaultPrng; 11 | var rnd : std.rand.Random = undefined; 12 | 13 | const screenWidth = 240; 14 | const screenHeight = 136; 15 | const toolbarHeight = 6; 16 | var t : u32 = 0; 17 | 18 | fn randomFloat(lower: f32, greater: f32) f32 { 19 | return rnd.float(f32) * (greater-lower) + lower; 20 | } 21 | 22 | const Bunny = struct { 23 | width: f16 = 0, 24 | height: f16 = 0, 25 | x: f32 = 0, 26 | y: f32 = 0, 27 | speedX: f32 = 0, 28 | speedY: f32 = 0, 29 | sprite: u8 = 0, 30 | 31 | fn initBunny(self: *Bunny) void { 32 | self.width = 26; 33 | self.height = 32; 34 | self.sprite = 1; 35 | self.x = randomFloat(0, screenWidth - self.width); 36 | self.y = randomFloat(0, screenHeight - self.height); 37 | self.speedX = randomFloat(-100, 100) / 60; 38 | self.speedY = randomFloat(-100, 100) / 60; 39 | } 40 | 41 | fn draw(self: Bunny) void { 42 | tic.spr(self.sprite, @floatToInt(i32,self.x), @floatToInt(i32,self.y), .{ 43 | .transparent = &.{1}, 44 | .w = 4, 45 | .h = 4 46 | }); 47 | } 48 | 49 | fn update(self: *Bunny) void { 50 | self.x += self.speedX; 51 | self.y += self.speedY; 52 | if (self.x + self.width > screenWidth) { 53 | self.x = screenWidth - self.width; 54 | self.speedX = self.speedX * -1; 55 | } 56 | if (self.x < 0) { 57 | self.x = 0; 58 | self.speedX = self.speedX * -1; 59 | } 60 | if (self.y + self.height > screenHeight) { 61 | self.y = screenHeight - self.height; 62 | self.speedY = self.speedY * -1; 63 | } 64 | if (self.y < toolbarHeight) { 65 | self.y = toolbarHeight; 66 | self.speedY = self.speedY * -1; 67 | } 68 | } 69 | 70 | }; 71 | 72 | const FPS = struct { 73 | value: u32 = 0, 74 | frames: u32 = 0, 75 | lastTime: f32 = 0, 76 | 77 | fn initFPS(self: *FPS) void { 78 | self.value = 0; 79 | self.frames = 0; 80 | self.lastTime = 0; 81 | } 82 | 83 | fn getValue(self: *FPS) u32 { 84 | if (tic.time() - self.lastTime <= 1000) { 85 | self.frames += 1; 86 | } else { 87 | self.value = self.frames; 88 | self.frames = 0; 89 | self.lastTime = tic.time(); 90 | } 91 | return self.value; 92 | } 93 | }; 94 | 95 | const MAX_BUNNIES = 1200; 96 | var fps : FPS = undefined; 97 | var bunnyCount : usize = 0; 98 | var bunnies : [MAX_BUNNIES]Bunny = undefined; 99 | 100 | fn addBunny() void { 101 | if (bunnyCount >= MAX_BUNNIES) return; 102 | 103 | bunnies[bunnyCount].initBunny(); 104 | bunnyCount += 1; 105 | } 106 | 107 | fn removeBunny() void { 108 | if (bunnyCount==0) return; 109 | 110 | bunnyCount -= 1; 111 | } 112 | 113 | export fn testscreen() void { 114 | var i : usize = 0; 115 | 116 | while (i<2000) { 117 | // tic.ZERO.* = 0x99; 118 | tic.FRAMEBUFFER[i]=0x56; 119 | // tic.FRAMEBUFFER2.*[i]=0x67; 120 | // tic.ZERO[i]= 0x56; 121 | // bunnies[i].draw(); 122 | i += 1; 123 | } 124 | } 125 | 126 | export fn BOOT() void { 127 | rnd = RndGen.init(0).random(); 128 | fps.initFPS(); 129 | addBunny(); 130 | } 131 | 132 | export fn TIC() void { 133 | if (t==0) { 134 | tic.music(0, .{}); 135 | } 136 | if (t == 6*64*2.375) { 137 | tic.music(1, .{}); 138 | } 139 | t = t + 1; 140 | 141 | 142 | if (tic.btn(0)) { 143 | var i : i32 = 0; 144 | while (i<5) { 145 | addBunny(); 146 | i+=1; 147 | } 148 | } 149 | 150 | if (tic.btn(1)) { 151 | var i : i32 = 0; 152 | while (i<5) { 153 | removeBunny(); 154 | i+=1; 155 | } 156 | } 157 | 158 | // -- Update 159 | var i : u32 = 0; 160 | while (i 2 | 3 | // derived from keymap_it 4 | 5 | static const tic_keycode TicKeyboardCodes[256] = 6 | { 7 | tic_key_unknown, // KeyNone, 0x00 8 | tic_key_unknown, // KeyNone, 0x01 9 | tic_key_unknown, // KeyNone, 0x02 10 | tic_key_unknown, // KeyNone, 0x03 11 | tic_key_a, // 'a', 0x04 12 | tic_key_b, // 'b', 0x05 13 | tic_key_c, // 'c', 0x06 14 | tic_key_d, // 'd', 0x07 15 | tic_key_e, // 'e', 0x08 16 | tic_key_f, // 'f', 0x09 17 | tic_key_g, // 'g', 0x0A 18 | tic_key_h, // 'h', 0x0B 19 | tic_key_i, // 'i', 0x0C 20 | tic_key_j, // 'j', 0x0D 21 | tic_key_k, // 'k', 0x0E 22 | tic_key_l, // 'l', 0x0F 23 | tic_key_m, // 'm', 0x10 24 | tic_key_n, // 'n', 0x11 25 | tic_key_o, // 'o', 0x12 26 | tic_key_p, // 'p', 0x13 27 | tic_key_q, // 'q', 0x14 28 | tic_key_r, // 'r', 0x15 29 | tic_key_s, // 's', 0x16 30 | tic_key_t, // 't', 0x17 31 | tic_key_u, // 'u', 0x18 32 | tic_key_v, // 'v', 0x19 33 | tic_key_w, // 'w', 0x1A 34 | tic_key_x, // 'x', 0x1B 35 | tic_key_y, // 'y', 0x1C 36 | tic_key_z, // 'z', 0x1D 37 | tic_key_1, // '1', 0x1E 38 | tic_key_2, // '2', 0x1F 39 | tic_key_3, // '3', 0x20 40 | tic_key_4, // '4', 0x21 41 | tic_key_5, // '5', 0x22 42 | tic_key_6, // '6', 0x23 43 | tic_key_7, // '7', 0x24 44 | tic_key_8, // '8', 0x25 45 | tic_key_9, // '9', 0x26 46 | tic_key_0, // '0', 0x27 47 | tic_key_return, // KeyReturn, 0x28 48 | tic_key_escape, // KeyEscape, 0x29 49 | tic_key_backspace, // KeyBackspace, 0x2A 50 | tic_key_tab, // KeyTabulator, 0x2B 51 | tic_key_space, // KeySpace, 0x2C 52 | tic_key_apostrophe, // '\'', 0x2D 53 | tic_key_unknown, // C('?'), 0x2E -- ^ 54 | tic_key_leftbracket, // C('?'), 0x2F -- [ 55 | tic_key_rightbracket, // '+', 0x30 -- ] 56 | tic_key_unknown, // C('?'), 0x31 57 | tic_key_unknown, // C('?'), 0x32 58 | tic_key_unknown, // C('?'), 0x33 -- @ 59 | tic_key_unknown, // C('?'), 0x34 -- # 60 | tic_key_backslash, // '\\', 0x35 61 | tic_key_comma, // ',', 0x36 62 | tic_key_period, // '.', 0x37 63 | tic_key_minus, // '-', 0x38 64 | tic_key_capslock, // KeyCapsLock, 0x39 65 | tic_key_f1, // KeyF1, 0x3A 66 | tic_key_f2, // KeyF2, 0x3B 67 | tic_key_f3, // KeyF3, 0x3C 68 | tic_key_f4, // KeyF4, 0x3D 69 | tic_key_f5, // KeyF5, 0x3E 70 | tic_key_f6, // KeyF6, 0x3F 71 | tic_key_f7, // KeyF7, 0x40 72 | tic_key_f8, // KeyF8, 0x41 73 | tic_key_f9, // KeyF9, 0x42 74 | tic_key_f10, // KeyF10, 0x43 75 | tic_key_f11, // KeyF11, 0x44 76 | tic_key_f12, // KeyF12, 0x45 77 | tic_key_unknown, // KeyPrintScreen, 0x46 78 | tic_key_unknown, // KeyScrollLock, 0x47 79 | tic_key_unknown, // KeyPause, 0x48 80 | tic_key_insert, // KeyInsert, 0x49 81 | tic_key_home, // KeyHome, 0x4A 82 | tic_key_pageup, // KeyPageUp, 0x4B 83 | tic_key_delete, // KeyDelete, 0x4C 84 | tic_key_end, // KeyEnd, 0x4D 85 | tic_key_pagedown, // KeyPageDown, 0x4E 86 | tic_key_right, // KeyRight, 0x4F 87 | tic_key_left, // KeyLeft, 0x50 88 | tic_key_down, // KeyDown, 0x51 89 | tic_key_up, // KeyUp, 0x52 90 | tic_key_unknown, // KeyNumLock, 0x53 91 | tic_key_unknown, // KeyKP_Divide, 0x54 92 | tic_key_unknown, // KeyKP_Multiply, 0x55 93 | tic_key_unknown, // KeyKP_Subtract, 0x56 94 | tic_key_unknown, // KeyKP_Add, 0x57 95 | tic_key_unknown, // KeyKP_Enter, 0x58 96 | tic_key_unknown, // KeyEnd, 0x59 97 | tic_key_unknown, // KeyDown, 0x5A 98 | tic_key_unknown, // KeyPageDown, 0x5B 99 | tic_key_unknown, // KeyLeft, 0x5C 100 | tic_key_unknown, // KeyKP_Center, 0x5D 101 | tic_key_unknown, // KeyRight, 0x5E 102 | tic_key_unknown, // KeyHome, 0x5F 103 | tic_key_unknown, // KeyUp, 0x60 104 | tic_key_unknown, // KeyPageUp, 0x61 105 | tic_key_unknown, // KeyInsert, 0x62 106 | tic_key_unknown, // KeyDelete, 0x63 107 | tic_key_unknown, // '<', 0x64 108 | tic_key_unknown, // KeyApplication, 0x65 109 | tic_key_unknown, // KeyNone, 0x66 110 | tic_key_unknown, // KeyNone, 0x67 111 | tic_key_unknown, // KeyNone, 0x68 112 | tic_key_unknown, // KeyNone, 0x69 113 | tic_key_unknown, // KeyNone, 0x6A 114 | tic_key_unknown, // KeyNone, 0x6B 115 | tic_key_unknown, // KeyNone, 0x6C 116 | tic_key_unknown, // KeyNone, 0x6D 117 | tic_key_unknown, // KeyNone, 0x6E 118 | tic_key_unknown, // KeyNone, 0x6F 119 | tic_key_unknown, // KeyNone, 0x70 120 | tic_key_unknown, // KeyNone, 0x71 121 | tic_key_unknown, // KeyNone, 0x72 122 | tic_key_unknown, // KeyNone, 0x73 123 | tic_key_unknown, // KeyNone, 0x74 124 | tic_key_unknown, // KeyNone, 0x75 125 | tic_key_unknown, // KeyNone, 0x76 126 | tic_key_unknown, // KeyNone, 0x77 127 | tic_key_unknown, // KeyNone, 0x78 128 | tic_key_unknown, // KeyNone, 0x79 129 | tic_key_unknown, // KeyNone, 0x7A 130 | tic_key_unknown, // KeyNone, 0x7B 131 | tic_key_unknown, // KeyNone, 0x7C 132 | tic_key_unknown, // KeyNone, 0x7D 133 | tic_key_unknown, // KeyNone, 0x7E 134 | tic_key_unknown // KeyNone, 0x7F 135 | 136 | }; 137 | --------------------------------------------------------------------------------