From 9f1b00d39de85ac49c2b6e2cfccca231991e2ee0 Mon Sep 17 00:00:00 2001 From: Fries Date: Thu, 20 Jun 2024 18:41:49 -0700 Subject: [PATCH] add file support file loading is implemented with an asset generator script that reads all the files in the data folder and converts them into c arrays and puts them inside a c source file. --- data/background-day.png | Bin 0 -> 7026 bytes data/yellowbird-midflap.png | Bin 0 -> 425 bytes dependencies/GRRLIB/CMakeLists.txt | 6 +++- source/.gitignore | 1 + source/CMakeLists.txt | 11 +++++-- source/data.h | 5 +++ source/data_asset_generator.py | 50 +++++++++++++++++++++++++++++ source/game.js | 13 ++++++-- source/grrlib_duk.c | 43 ++++++++++++++++++++++++- source/main.c | 27 ++++++++++++++-- 10 files changed, 148 insertions(+), 8 deletions(-) create mode 100644 data/background-day.png create mode 100644 data/yellowbird-midflap.png create mode 100644 source/data.h create mode 100755 source/data_asset_generator.py diff --git a/data/background-day.png b/data/background-day.png new file mode 100644 index 0000000000000000000000000000000000000000..afcb5ec982a3de74cb9186f6af3ba329d63a22bb GIT binary patch literal 7026 zcmeHMc~nzZw-41;{rnWsDkwu#RBAyGum}c-Rs<0ZLKS4LMkW~|Qv!q#+gd4QNG(J3 zV-!WOkRXH*2qdvZiGX1yfrJnxLL?yx0g?cjUg-Plt+(F)?~ks#?%L~|d-gv2{?0zX zv-iEZS0P?I{&nDA003Zz_eBqX0KniN0Pq=L>lgZ-!}Mlrz1SRm?#ej;pc%7Wee-jD z`ylk9{}lir^B4ed?>+#quJ5|{2>?ht2>=Mc2LR4I0sxHfmXrNl^$)(d<>Tc6&~04R zl)55)&$hc4gHiy1ov$};gA(hVrU1Z!RBw-S*V5TyE(a4ii85YH`vby?B#Yl&R!-3! z7w^BUa5nl^kAppS%VxV@>h9hB_ph(dZ#FX7igEpE^P$}i2W7W%UoTp{^7#_vAOCxj z%|dfCBhS%|Um5F*7<@g7C0BNLuj9f9f#dUk2=T&*G^JpDe_$Lbf*$DrO3m!)q0~{_NYqlvG<~z(!J7X?{ z^z0GaE9qOeUW9Ib4SiB@w{!+rR7(ymuuVT29wBijnfBvMWbp$+QvqT9b$p^nDmee% zy;EKm1};%^UkzLW1)ZAd*mb^qxnC}8LaTHAFCFh6-fQRE^EtQRGx30sZ>QmLYK#37 z-wb`4!y652PJZ^;h>h9b+K@jg;)(FxJD~e43;Bil!7imWX1*TVbr z%=9~UI)Sk*)8BG zJO(CxEwC7Y&J~qeH}sDl*gqYI0lE4?G7}@GAT=(<73sH-yscz+bPA~iX0kiKFD)q; ztDA|A%V3tOmZngzQyvAFCM=7kt$SxF#P5JQj>$G6T`WD5;lb(k^NP}}7wFL*m4C7i z_EikJ2O$eb-J_=SEyN^h2=Z6u%%hGA+9307ZZ;{AR^K>qa$O$99IInO*olnNV9nTU z4FO`>$zQ6J_7UBSMOsf+m5|uLbE*l-b(=7stL_P5=hFo1mTbsA#yAnY@C*cUNw6GI zsgZywLa%Xzil1@3Rvm2C-E_k35p)io&l|8%=dj{hA~4W7E|>6)Rq7H8TfPuF8C&p9 zD^kX}usb0Q6{qspKBh**j?#*BZNDECy&^l~f5)=9$YRaxxyC%CBe+v*$HUFWSw4tR ztv;QEtap%|zKsikZTia!s?i-`KipW%B`Z_#BWw#cb##xgci%j+9d}U(vR_(LCMn+c zz)`5vwz-T0TPvpJNBNmI#zv)8)_Iwe=7DeZp0HaeqI1NeZec9bji-oSGbjoJqc&(zZ z+CqGj7k7PX#fN*XUM8ru2lVcsQhb(SdnjrR z(x4r<1Df}W0&%yJaR@f!__?|M{fPx6qk#(Nn0VfcjswOA-pzbZrs!Jn zu8H2X)@y;QD;?{rr)M&Y;oPyq;IfllRNxfXaAG2y%NE77$TE3-H59@0=n^&8u8 z-m*Fh=7e%JUXfDw@NB2eX*%`sFw#)gDW=X8jL2@SfWIsMCXiVb7HhFGd3>NWhge~v z_hsN+)2-GciGd!jyZzVQ&?@IKx(w5GDr{Di?`({@i=jZMQ zu#m0H4B+K&J0b*JYoS3x^#SYiE&^a z=?%&oWX+Z^GA*l(S5>M~Pw zW+pDG{FMgv1G~Qp72CDueMAW|m0KMSxfPL1x5KfZENfESHE?He;DluR3KB-t;C;*U z%-!MoNs{!~{3M#SZ!o0&YVfQqJQUfar%|6c`B!4OQnaRqpVkCn-}`V;siov2FnVF$ z?ks1I_-)}m+t{U5cUY#yGPCQT)~*&moqRxC=ic@BPyay4&u&Rd50PJG#*9V}tR3A( zhv4bnJ`_e~@X~f+5U3cdEv$Y%8#3p4_EnHQN)TW!3#FJNhA~hQPbXU~K+LXDapCT)!nDpi8KI){AeZ)V3l@9?bN_F8#@gl!?yW<|Dfdj#0_d_L zK(EA=DBA~cIJ5RA?my6s2#U_IA4x|v3Z$_orm1HTE>7L@Fb8#EPV78~I=)*i2FYc4 z;-oHZ{8Sd%yo|c)fx}{Oq|8{>g(*t7lVmJ2mgd?)&XzRe4aFbdXJ&+QyrKFfEwlBV z0Rer!$qPPwgIRW2 z3*`(isT6YuyUzyMo$VX!LZ*A+u*nyVm)pm4;K_F>u2JIK=`_OkXWQmSej7_doi*c7 z%mQ88K4v{(7^USRr(n7T6j>{}gm^PMULYn@;BO*}1s!no@2gq7r}0zM`SgaTV#)+# zj@It(wkYS~a}trnE@|ITw{SMyLbE;u*@?&UGp-5wVi4$Q@&Wz+eV(_J&IH>>EUMiO z6dI_YZ%~2ZZ6|ComB8N}`{YjC`eG2Yt@6pl2&3pBmmMn*%lu{c{(VP7k=Y}OS^ib+C>8TlLeYmyL$WYcj>T~d(eo0J#a)g5X{n0hquS^&+$^k%LMqF#4yQgfwHpdO(whG zN>B8D#r4Z(DKPG2y9ihfK^TH@mlySTw@+R;d?$%XATmpXFn@3X4=wtf*|qY-NFv@wf8~%WamqRUr)o0j>^Z zi+^uM4H-GA+x0_H(qG^77de4|%A?0mWQZ~=!_0N~q2*>x>HEQ^Hslc8?d)W3@|ZGV zP{e0sh-GavvXCSxJCM)mk;XF(TVZR|H00?%KP5V)ZLjD>;4g_D9d`KF=AUW=@dRBr z1+Fyj1ZLUrgfIj%^GEX3uXj4zTR>my-h9PUG?oxbRgAKPXC!kKZEt_=jh@U~XgCy= zfPY^Cj}&^UsiQx_T_YGg4 zL{4nLL)oo-fJ(v*{EilQQmWn#Ml@n*X_RoU#S|IxTp1zB&>?RYMw26Jizyb*T~5E) zw*E6#7mR$4k0#mDGBjCw7K!Leb!J`9!K@;i#>Com%ekv_ zX(Kbt#sPEnAVPak0nV&`(pD!^sxPZGLIH`tqZ<|ZV2LzHGGb)40&#N3cWdI%VW6X5JwaIDC7o3g?zjPce^EcPiYq+^g{nscuSpV`wlZRPLFO>R%B8#6XUdm2i zMwj?snzSWG-=KX-|08mWaK$o68k(ot@dg3WPW?=~u2%|OF-On)yIC)xXZjevZxl2O z%W5a=;!hKjc>f}l*dNqmZnc!$h!ACRCG2O4`YQCSg9ue5Ksn*I1;3I4mE^gR1D!~?) z-hozt7@Q0X|GNb}j}PJKZ>mQtH+|M}C3{)LE64ix)j>Cp z6-IK>zDy`plX$C{`X~+=F2aT7TSPj9D_BNX4)aSbAL@@Ykd!%lX=N8}J=)zISTEH9 zhxt>#Li@y@?4z6G-LlI}g?6SvzshX}Iq+LYl2BR9o0|FFdUZ(H;1nME$YX|N)SLXy zFFv$E6j3&Y*X;qmNP$$L$j5Yn(`t4MMQjtM&wVM^dN^VQbTwcpE6bN0B5g}%u7`KF zp3-KCZr(z0wmu!FLqzj6Q)qCe8rI{Mr{ghr<{CGhFokyG(xmARmpiEq#3J23`Z`I# zH=2FO@h*lPFEzD49E^F`YaFh*Joc?d9cZh&84q&}Y;kNYN@l@ZT=Ne;ABNPR!c9p< z<9SK&hI|%Hc|z*Qgv=#)w4%`BkHK+PY2fUmLLFljKf%gg3dS`}t~O3V%={KK;EIB_ z(`rSQ!9|BPb(}6!AM0@sFOPm`^byOltvnBlCzc^cLO>79@ORx7KsE$f2_r=6X;4EC z%7wmzyS!b?ORD&5h~Fym5{gV&ZMQy`=MsIs>99hz(7_LOLY=hCMaGRmVXc#*>`i9r zEf8pnG<@Zhz;4_k;XrhfQlxu-#|OEdnHL6 zZzWDVn{mRc%zCQJUgE-fnoVM-c|~Sb3@<82Av03+Yxt5R@mh!~Ezjgo8@%PcZay(k zhrk0vB^$YbD_9kBWJkHg&*!^+7${e?aRI%ovp0n>}@HNwpldeKmFyH zW?Nse_tA-hCf0;fWYC?qEv+L7<%%Heb6b6uH}S#xOqff69g%Q|-;q0BI-#-4^c)=X z{1W%YAUGv4)a|?%dw^;N12dsuMcQ6|Q@{?l5Dq4)DJya%vn=ItEAMOR>6dp4s~N-P z$)MO-Ob6a+#2Nj9DIJ0wV|(M2d+u1tsN;E>Y)H+NwM-c^OQo+%B}aEGzPjSB>oNAS ztfoNUlVehB5oGAlxbuT}sk8`p`iPL2(uQY87fMZ4~ct*uA8NSFOh(_@SIArj$4P14!PY##d?Y+!N&e%@8hL->udoZMCYwCv3}w8%c7)1t<_jI=eb zxASe!j~^>ma@my;FDrYew|Ggb-UJnD-OqR1tL3t^t(u^F+Wx*W7M(TOs8F#mCOhYi z3cG-QQjPahl-p!M5=!B=@Dj9L5$%Ve)mz#2if{W-;;b~;`B*QQ6*u(y=@HjvT^+6( zfB%b?D~8B!DpdKBX*GYykEv`o4I6BpuDIZ=z z0{fMG`oi$e20>dTvzwS{I(ImDFl!?1Aa_)yr~~IYs8MXh&xIr~+q+o#B*98n(Hq@^ zt}epsYKPhSLeC?o@Sf9*NsBM_LiCk=0}t#9qPuhCX>Q3r3&<-y@XOP{PN1ss{C+Ir z(@nfIYn7j4u^kww+g?hL8co&$k&XmfbaFb`|~{?1`& zi%v>C)wQTbIX6Z-zw>U=jrD`nMk;912wGqs-tfjM)e*Jt8*2DWV7Q~e!*%j9`aaLRbv4~$XS~7ID?dRw} zA=b^laiF@e=`GiRhMeqJD?_-(P?dd!jNYi9H}Cq*6Y!7te+_{aY+Q6Z@lR)+gZ`(~ z(bNk!Qg7c(jXVQQj?@c)!%2IW6DJ){*xO&TcRq8{;f%eD^+~5QCr^I(+NJw{C?vpc b$3|uR-wMAWen9IL0NxiM9{6v+|M9;7ImZIa literal 0 HcmV?d00001 diff --git a/data/yellowbird-midflap.png b/data/yellowbird-midflap.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca3c2d034b2332726bb6157591ee3319900c2fc GIT binary patch literal 425 zcmeAS@N?(olHy`uVBq!ia0vp^N0k@DU)Otn z{rdG|yYcmBXZ~0)JZRAQ|NsAjlBe20X~vQuzhDN3XE)M7oFs2|7ml`jQ>%a+&H|6f zVg?3oVGw3ym^DWND9B#o>Fdh=n3;!xN%;9M)g3^gOivfb5Q)pJ7ccT2P~cz*2-_hV zaZog3q4tiZ*WX=k-CFeW?_KXB9ZGT)DW}32LR~d)aPO9UxKJfwxlGFf6@%Z?=Pl^{ zvG%BD+$I544c4p8tvx5#F1#mwQfZCt4!*T6202kV(`MNHKjQ6|w8gBn>)PVeKuc9i zTq8@t-i!lHI literal 0 HcmV?d00001 diff --git a/dependencies/GRRLIB/CMakeLists.txt b/dependencies/GRRLIB/CMakeLists.txt index 4ec456f..e8d8757 100644 --- a/dependencies/GRRLIB/CMakeLists.txt +++ b/dependencies/GRRLIB/CMakeLists.txt @@ -5,7 +5,7 @@ project(GRRLIB) find_package(PkgConfig REQUIRED) pkg_check_modules(PNG REQUIRED libpng) pkg_check_modules(FREETYPE REQUIRED freetype2) - +pkg_check_modules(JPEG REQUIRED libjpeg) set(GRRLIB_DIR ./source/GRRLIB/GRRLIB) set(PNGU_DIR ./source/GRRLIB/lib/pngu) @@ -29,6 +29,7 @@ set(grrlib_sources ${GRRLIB_DIR}/GRRLIB_print.c ${GRRLIB_DIR}/GRRLIB_render.c ${GRRLIB_DIR}/GRRLIB_snapshot.c + ${GRRLIB_DIR}/GRRLIB_texEdit.c ${GRRLIB_DIR}/GRRLIB_ttf.c ) @@ -36,7 +37,10 @@ add_library(GRRLIB ${grrlib_sources}) target_link_libraries(GRRLIB PRIVATE pngu) target_link_libraries(GRRLIB PRIVATE ${FREETYPE_LIBRARIES}) target_link_libraries(GRRLIB PRIVATE fat) +target_link_libraries(GRRLIB PRIVATE ${JPEG_LIBRARIES}) + target_include_directories(GRRLIB PRIVATE ${FREETYPE_INCLUDE_DIRS}) +target_include_directories(GRRLIB PRIVATE ${JPEG_INCLUDE_DIRS}) target_include_directories(GRRLIB PUBLIC ${GRRLIB_DIR}) diff --git a/source/.gitignore b/source/.gitignore index f8f794e..6f9be50 100644 --- a/source/.gitignore +++ b/source/.gitignore @@ -1 +1,2 @@ game.c +data_generated.c diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 5a9ef26..7aefc3f 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1,11 +1,18 @@ 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 + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/game.js ${CMAKE_CURRENT_SOURCE_DIR}/asset_generator.py COMMENT "Creating game.c from game.js" ) -add_executable(WiiDuktape main.c grrlib_duk.c game.c) +add_custom_command( + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/data_asset_generator.py ${CMAKE_SOURCE_DIR}/data ${CMAKE_CURRENT_SOURCE_DIR}/data_generated.c + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/data_generated.c + DEPENDS ${CMAKE_SOURCE_DIR}/data ${CMAKE_CURRENT_SOURCE_DIR}/data_asset_generator.py + COMMENT "Creating data_generated.c from the data directory" +) + +add_executable(WiiDuktape main.c grrlib_duk.c game.c data_generated.c) target_link_libraries(WiiDuktape duktape) target_link_libraries(WiiDuktape GRRLIB) ogc_create_dol(WiiDuktape) diff --git a/source/data.h b/source/data.h new file mode 100644 index 0000000..04ea762 --- /dev/null +++ b/source/data.h @@ -0,0 +1,5 @@ +#ifndef DATA_H +#define DATA_H +#include +int get_file_pointer(const char* filename, void ** data, size_t * size); +#endif diff --git a/source/data_asset_generator.py b/source/data_asset_generator.py new file mode 100755 index 0000000..88d575f --- /dev/null +++ b/source/data_asset_generator.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +import argparse +from pathlib import Path +from PIL import Image + +parser = argparse.ArgumentParser() +parser.add_argument("input") +parser.add_argument("output") + +args = parser.parse_args() + +input = Path(args.input) +output = Path(args.output) + +if not input.exists(): + print("Input " + str(input.absolute()) + " not found.") + raise SystemExit(1) + +file_array = list() + +for child in Path(input).iterdir(): + if child.is_file(): + file_array.append({"filename": child.name, "data": child.read_bytes()}) + +def generate_data(): + string_list = list() + for index, data in enumerate(file_array): + hexList = list() + for byte in data["data"]: + hexList.append(f"0x{byte:02x}") + string_list.append(f"unsigned char data{index}[] = {{ {','.join(hexList)} }};") + return '\n'.join(string_list) + +def generate_hashmap_init(): + string_list = list() + for index, data in enumerate(file_array): + string_list.append(f"if (strcmp(filename, \"{data["filename"]}\") == 0) {{ *data = &data{index}; *size = sizeof(data{index}); return 1; }}") + return f"""int get_file_pointer(const char* filename, void ** data, size_t * size) {{ +{'\n'.join(string_list)} +return 0; +}}""" + +code = f"""#include \"data.h\" +#include +{generate_data()} +{generate_hashmap_init()} +""" + +with open(output, 'w') as f: + f.write(code) diff --git a/source/game.js b/source/game.js index c68d0a1..d95b03e 100644 --- a/source/game.js +++ b/source/game.js @@ -11,6 +11,7 @@ const PAD_BUTTON_START = 0x1000; const PAD_BUTTON_A = 0x0100; const RED_COLOR = rgba(255, 0, 0, 255); const GREEN_COLOR = rgba(0, 255, 0, 255); +const WHITE_COLOR = rgba(255, 255, 255, 255); function rgba_compare(rgba1, rgba2) { return (rgba1[0] == rgba2[0]) && @@ -20,6 +21,7 @@ function rgba_compare(rgba1, rgba2) { } globalThis.rectangle_color = RED_COLOR; +globalThis.background = null; function swap_colors() { if (rgba_compare(rectangle_color, RED_COLOR)) { @@ -30,6 +32,11 @@ function swap_colors() { } function start() { + const background = wii.get_file("background-day.png"); + const bird = wii.get_file("yellowbird-midflap.png"); + + globalThis.background = wii.grrlib.load_texture(background); + globalThis.bird = wii.grrlib.load_texture(bird); } function update() { @@ -45,6 +52,8 @@ function update() { swap_colors(); } - wii.grrlib.fill_screen(rgba(255, 255, 255, 255)); - wii.grrlib.rectangle(0, 0, 320, 240, rectangle_color, true); + wii.grrlib.fill_screen(WHITE_COLOR); + // wii.grrlib.rectangle(0, 0, 320, 240, rectangle_color, true); + wii.grrlib.draw_img(320, 0, background, 0, 1, 1, WHITE_COLOR); + wii.grrlib.draw_img(0, 0, bird, 0, 1, 1, WHITE_COLOR); } diff --git a/source/grrlib_duk.c b/source/grrlib_duk.c index ea2f197..82c7f0b 100644 --- a/source/grrlib_duk.c +++ b/source/grrlib_duk.c @@ -1,4 +1,6 @@ #include "grrlib_duk.h" +#include "duk_config.h" +#include "duktape.h" #include static unsigned int get_color(duk_context *ctx, duk_idx_t index) { @@ -16,7 +18,6 @@ static duk_ret_t grrlib_fill_screen(duk_context *ctx) { static duk_ret_t grrlib_rectangle(duk_context *ctx) { float x = duk_to_number(ctx, 0); - float y = duk_to_number(ctx, 1); float width = duk_to_number(ctx, 2); float height = duk_to_number(ctx, 3); @@ -29,6 +30,40 @@ static duk_ret_t grrlib_rectangle(duk_context *ctx) { return 0; } +static duk_ret_t grrlib_load_texture(duk_context *ctx) { + void* file_ptr; + duk_push_string(ctx, "file_ptr"); + duk_get_prop(ctx, 0); + file_ptr = duk_get_pointer(ctx, -1); + duk_pop(ctx); + + size_t size; + duk_push_string(ctx, "size"); + duk_get_prop(ctx, 0); + size = duk_get_number(ctx, -1); + duk_pop(ctx); + + GRRLIB_texImg* texture = GRRLIB_LoadTexture(file_ptr); + + duk_push_pointer(ctx, texture); + + return 1; +} + +static duk_ret_t grrlib_draw_img(duk_context *ctx) { + float xPos = duk_to_number(ctx, 0); + float yPos = duk_to_number(ctx, 1); + void * texture = duk_get_pointer(ctx, 2); + float degrees = duk_to_number(ctx, 3); + float scaleX = duk_to_number(ctx, 4); + float scaleY = duk_to_number(ctx, 5); + unsigned int color = get_color(ctx, 6); + + GRRLIB_DrawImg(xPos, yPos, texture, degrees, scaleX, scaleY, color); + + return 0; +} + void define_grrlib_object(duk_context *ctx) { duk_idx_t grrlib_obj = duk_push_object(ctx); @@ -37,4 +72,10 @@ void define_grrlib_object(duk_context *ctx) { duk_push_c_function(ctx, grrlib_rectangle, 6); duk_put_prop_string(ctx, grrlib_obj, "rectangle"); + + duk_push_c_function(ctx, grrlib_load_texture, 1); + duk_put_prop_string(ctx, grrlib_obj, "load_texture"); + + duk_push_c_function(ctx, grrlib_draw_img, 7); + duk_put_prop_string(ctx, grrlib_obj, "draw_img"); } diff --git a/source/main.c b/source/main.c index 5c71b3a..cf2266d 100644 --- a/source/main.c +++ b/source/main.c @@ -1,6 +1,8 @@ #include #include +#include #include "grrlib_duk.h" +#include "data.h" extern const char* program; static bool running = true; @@ -30,6 +32,27 @@ static duk_ret_t pad_buttons_down(duk_context *ctx) { return 1; } +static duk_ret_t get_file(duk_context *ctx) { + const char* filename = duk_to_string(ctx, 0); + + void* ptr; + size_t size; + + if (get_file_pointer(filename, &ptr, &size)) { + duk_idx_t file_obj = duk_push_object(ctx); + + duk_push_number(ctx, size); + duk_put_prop_string(ctx, file_obj, "size"); + + duk_push_pointer(ctx, ptr); + duk_put_prop_string(ctx, file_obj, "file_ptr"); + + return 1; + } + + return duk_error(ctx, DUK_ERR_ERROR, "Error trying to get the file %s.", filename); +} + static void define_pad_object(duk_context *ctx) { duk_idx_t pad_obj = duk_push_object(ctx); @@ -55,8 +78,8 @@ static void define_wii_object(duk_context *ctx) { define_grrlib_object(ctx); duk_put_prop_string(ctx, wii_obj, "grrlib"); - duk_push_boolean(ctx, true); - duk_put_prop_string(ctx, wii_obj, "running"); + duk_push_c_function(ctx, get_file, 1); + duk_put_prop_string(ctx, wii_obj, "get_file"); } int main(int argc, char **argv) {