diff --git a/CMakeLists.txt b/CMakeLists.txt index 350c977..61f1759 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.13) if (DEFINED ENV{DEVKITPRO}) set(DEVKITPRO $ENV{DEVKITPRO}) +else() + message("Please set DEVKITPRO in your environment. export DEVKITPRO=devkitpro") endif() set(CMAKE_TOOLCHAIN_FILE "${DEVKITPRO}/cmake/Wii.cmake") diff --git a/source/.gitignore b/source/.gitignore new file mode 100644 index 0000000..f8f794e --- /dev/null +++ b/source/.gitignore @@ -0,0 +1 @@ +game.c diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index fb0fe92..0fc4071 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1,3 +1,10 @@ -add_executable(WiiDuktape main.c) +add_custom_command( + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/asset_generator.py ${CMAKE_CURRENT_SOURCE_DIR}/game.js ${CMAKE_CURRENT_SOURCE_DIR}/game.c + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/game.c + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/game.js + COMMENT "Creating game.c from game.js" +) + +add_executable(WiiDuktape main.c game.c) target_link_libraries(WiiDuktape duktape) ogc_create_dol(WiiDuktape) diff --git a/source/asset_generator.py b/source/asset_generator.py new file mode 100755 index 0000000..5a616db --- /dev/null +++ b/source/asset_generator.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 + +from pathlib import Path +import argparse + +parser = argparse.ArgumentParser() + +parser.add_argument("input") +parser.add_argument("output") + +args = parser.parse_args() + +script = Path(args.input).read_text().replace("\n", "\\n").replace('"', '\\"') + +code = f""" +const char* program = "{script}"; +""" + +with open(args.output, 'w') as f: + f.write(code) diff --git a/source/game.js b/source/game.js new file mode 100644 index 0000000..6da2202 --- /dev/null +++ b/source/game.js @@ -0,0 +1,19 @@ +const PAD_BUTTON_START = 0x1000; +const PAD_BUTTON_A = 0x0100; + +while (wii.running) { + wii.pad.scan_pads(); + + const pressed = wii.pad.buttons_down(); + + if (pressed & PAD_BUTTON_START) { + wii.print("exiting from js"); + wii.exit(); + } + + if (pressed & PAD_BUTTON_A) { + wii.print("a pressed"); + } + + wii.video.wait_vsync(); +} diff --git a/source/main.c b/source/main.c index 5660993..3c04970 100644 --- a/source/main.c +++ b/source/main.c @@ -1,23 +1,88 @@ #include #include #include -#include +#include #include static void *xfb = NULL; static GXRModeObj *rmode = NULL; +extern const char* program; static duk_ret_t native_print(duk_context *ctx) { printf("%s\n", duk_to_string(ctx, 0)); return 0; } +static duk_ret_t native_exit(duk_context *ctx) { + duk_push_global_object(ctx); + duk_push_string(ctx, "wii"); + duk_get_prop(ctx, -2); + duk_push_boolean(ctx, false); + duk_put_prop_string(ctx, -2, "running"); +} + +static void duk_fatal_error(void *udata, const char *msg) { + printf("an error has occured: %s\n", msg); +} + +static duk_ret_t video_wait_vsync(duk_context *ctx) { + VIDEO_WaitVSync(); + return 0; +} + +static duk_ret_t pad_scan_pads() { + PAD_ScanPads(); + return 0; +} + +static duk_ret_t pad_buttons_down(duk_context *ctx) { + u32 pressed = PAD_ButtonsDown(0); + duk_push_number(ctx, pressed); + return 1; +} + +static void define_pad_object(duk_context *ctx) { + duk_idx_t pad_obj = duk_push_object(ctx); + + duk_push_c_function(ctx, pad_scan_pads, 0); + duk_put_prop_string(ctx, pad_obj, "scan_pads"); + + duk_push_c_function(ctx, pad_buttons_down, 0); + duk_put_prop_string(ctx, pad_obj, "buttons_down"); +} + +static void define_video_object(duk_context *ctx) { + duk_idx_t video_obj = duk_push_object(ctx); + + duk_push_c_function(ctx, video_wait_vsync, 0); + duk_put_prop_string(ctx, video_obj, "wait_vsync"); +} + +static void define_wii_object(duk_context *ctx) { + duk_idx_t wii_obj = duk_push_object(ctx); + + duk_push_c_function(ctx, native_print, 1); + duk_put_prop_string(ctx, wii_obj, "print"); + + duk_push_c_function(ctx, native_exit, 0); + duk_put_prop_string(ctx, wii_obj, "exit"); + + define_pad_object(ctx); + duk_put_prop_string(ctx, wii_obj, "pad"); + + define_video_object(ctx); + duk_put_prop_string(ctx, wii_obj, "video"); + + duk_push_boolean(ctx, true); + duk_put_prop_string(ctx, wii_obj, "running"); +} + int main(int argc, char **argv) { // Initialise the video system VIDEO_Init(); // This function initialises the attached controllers - WPAD_Init(); + PAD_Init(); // Obtain the preferred video mode from the system // This will correspond to the settings in the Wii menu @@ -51,31 +116,17 @@ int main(int argc, char **argv) { // e.g. printf ("\x1b[%d;%dH", row, column ); printf("\x1b[2;0H"); - // printf("Hello World!"); + duk_context *ctx = duk_create_heap(NULL, NULL, NULL, NULL, duk_fatal_error); - duk_context *ctx = duk_create_heap_default(); - duk_push_c_function(ctx, native_print, 1); - duk_put_global_string(ctx, "print"); + define_wii_object(ctx); + duk_put_global_string(ctx, "wii"); - duk_eval_string_noresult(ctx, "while (1) {print('hello world')}"); + duk_eval_string_noresult(ctx, program); - while(1) { + printf("destroying heap\n"); + duk_destroy_heap(ctx); - // Call WPAD_ScanPads each loop, this reads the latest controller states - // WPAD_ScanPads(); - - // WPAD_ButtonsDown tells us which buttons were pressed in this loop - // this is a "one shot" state which will not fire again until the button has been released - // u32 pressed = WPAD_ButtonsDown(0); - - // We return to the launcher application via exit - // if ( pressed & WPAD_BUTTON_HOME ) exit(0); - // printf("Hello World!"); - // duk_eval_string_noresult(ctx, "print('hello, world!');"); - - // Wait for the next frame - VIDEO_WaitVSync(); - } + printf("exit time\n"); return 0; }