sokol: renderer works with studio
This commit is contained in:
		| @@ -542,8 +542,18 @@ foreach(TIC80_OUTPUT ${TIC80_OUTPUTS}) | |||||||
| 	endif() | 	endif() | ||||||
|  |  | ||||||
| 	if(SOKOL_RENDERER) | 	if(SOKOL_RENDERER) | ||||||
| 		add_dependencies(${TIC80_OUTPUT} sokol) | 		# TODO fix Pro tic80lib | ||||||
| 		target_link_libraries(${TIC80_OUTPUT} sokol) | 		add_dependencies(${TIC80_OUTPUT} tic80lib sokol) | ||||||
|  | 		target_link_libraries(${TIC80_OUTPUT} tic80lib sokol) | ||||||
|  |  | ||||||
|  | 		if(APPLE) | ||||||
|  | 			target_compile_definitions(${TIC80_OUTPUT} PRIVATE SOKOL_METAL) | ||||||
|  | 		elseif(WIN32) | ||||||
|  | 			target_compile_definitions(${TIC80_OUTPUT} PRIVATE SOKOL_D3D11) | ||||||
|  | 		elseif(LINUX) | ||||||
|  | 			target_compile_definitions(${TIC80_OUTPUT} PRIVATE SOKOL_GLCORE33) | ||||||
|  | 		endif() | ||||||
|  |  | ||||||
| 	else() | 	else() | ||||||
| 		if(NOT EMSCRIPTEN) | 		if(NOT EMSCRIPTEN) | ||||||
| 			add_dependencies(${TIC80_OUTPUT} SDL2main SDL2-static) | 			add_dependencies(${TIC80_OUTPUT} SDL2main SDL2-static) | ||||||
|   | |||||||
| @@ -228,7 +228,7 @@ static void apply_viewport(void) { | |||||||
|     sg_apply_viewport(vp_x, vp_y, vp_w, vp_h, true); |     sg_apply_viewport(vp_x, vp_y, vp_w, vp_h, true); | ||||||
| } | } | ||||||
|  |  | ||||||
| void gfx_draw() { | static void gfx_draw() { | ||||||
|  |  | ||||||
|     /* copy emulator pixel data into upscaling source texture */ |     /* copy emulator pixel data into upscaling source texture */ | ||||||
|     sg_update_image(gfx.upscale_draw_state.fs_images[0], &(sg_image_content){ |     sg_update_image(gfx.upscale_draw_state.fs_images[0], &(sg_image_content){ | ||||||
|   | |||||||
| @@ -1,25 +1,421 @@ | |||||||
| #include "sokol_app.h" | #include <sokol_app.h> | ||||||
| #include "sokol_gfx.h" | #include <sokol_gfx.h> | ||||||
| #include "sokol_time.h" | #include <sokol_time.h> | ||||||
| #include "sokol_audio.h" | #include <sokol_audio.h> | ||||||
|  |  | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <time.h> | ||||||
| #include <limits.h> | #include <limits.h> | ||||||
|  |  | ||||||
| #include <tic80.h> | #include "system.h" | ||||||
|  |  | ||||||
| sapp_desc sokol_main(int argc, char* argv[]) | static struct | ||||||
| { | { | ||||||
|     return (sapp_desc) {0}; | 	Studio* studio; | ||||||
|     //     .init_cb = app_init, |  | ||||||
|     //     .frame_cb = app_frame, | 	struct | ||||||
|     //     .event_cb = app_input, | 	{ | ||||||
|     //     .cleanup_cb = app_cleanup, | 		saudio_desc desc; | ||||||
|     //     .width = 3 * TIC80_FULLWIDTH, | 		float* samples; | ||||||
|     //     .height = 3 * TIC80_FULLHEIGHT, | 	} audio; | ||||||
|     //     .window_title = "TIC-80 with Sokol renderer", |  | ||||||
|     //     .ios_keyboard_resizes_canvas = true | 	struct { | ||||||
|     // }; | 	    sg_draw_state upscale_draw_state; | ||||||
|  | 	    sg_pass upscale_pass; | ||||||
|  | 	    sg_draw_state draw_state; | ||||||
|  | 	    s32 fb_width; | ||||||
|  | 	    s32 fb_height; | ||||||
|  | 	    s32 fb_aspect_scale_x; | ||||||
|  | 	    s32 fb_aspect_scale_y; | ||||||
|  | 	} gfx; | ||||||
|  | 	 | ||||||
|  | } platform; | ||||||
|  |  | ||||||
|  | #if defined(SOKOL_GLCORE33) | ||||||
|  | static const char* gfx_vs_src = | ||||||
|  |     "#version 330\n" | ||||||
|  |     "in vec2 in_pos;\n" | ||||||
|  |     "in vec2 in_uv;\n" | ||||||
|  |     "out vec2 uv;\n" | ||||||
|  |     "void main() {\n" | ||||||
|  |     "  gl_Position = vec4(in_pos*2.0-1.0, 0.5, 1.0);\n" | ||||||
|  |     "  uv = in_uv;\n" | ||||||
|  |     "}\n"; | ||||||
|  | static const char* gfx_fs_src = | ||||||
|  |     "#version 330\n" | ||||||
|  |     "uniform sampler2D tex;\n" | ||||||
|  |     "in vec2 uv;\n" | ||||||
|  |     "out vec4 frag_color;\n" | ||||||
|  |     "void main() {\n" | ||||||
|  |     "  frag_color = texture(tex, uv);\n" | ||||||
|  |     "}\n"; | ||||||
|  | #elif defined(SOKOL_GLES2) | ||||||
|  | static const char* gfx_vs_src = | ||||||
|  |     "attribute vec2 in_pos;\n" | ||||||
|  |     "attribute vec2 in_uv;\n" | ||||||
|  |     "varying vec2 uv;\n" | ||||||
|  |     "void main() {\n" | ||||||
|  |     "  gl_Position = vec4(in_pos*2.0-1.0, 0.5, 1.0);\n" | ||||||
|  |     "  uv = in_uv;\n" | ||||||
|  |     "}\n"; | ||||||
|  | static const char* gfx_fs_src = | ||||||
|  |     "precision mediump float;\n" | ||||||
|  |     "uniform sampler2D tex;" | ||||||
|  |     "varying vec2 uv;\n" | ||||||
|  |     "void main() {\n" | ||||||
|  |     "  gl_FragColor = texture2D(tex, uv);\n" | ||||||
|  |     "}\n"; | ||||||
|  | #elif defined(SOKOL_METAL) | ||||||
|  | static const char* gfx_vs_src = | ||||||
|  |     "#include <metal_stdlib>\n" | ||||||
|  |     "using namespace metal;\n" | ||||||
|  |     "struct vs_in {\n" | ||||||
|  |     "  float2 pos [[attribute(0)]];\n" | ||||||
|  |     "  float2 uv [[attribute(1)]];\n" | ||||||
|  |     "};\n" | ||||||
|  |     "struct vs_out {\n" | ||||||
|  |     "  float4 pos [[position]];\n" | ||||||
|  |     "  float2 uv;\n" | ||||||
|  |     "};\n" | ||||||
|  |     "vertex vs_out _main(vs_in in [[stage_in]]) {\n" | ||||||
|  |     "  vs_out out;\n" | ||||||
|  |     "  out.pos = float4(in.pos*2.0-1.0, 0.5, 1.0);\n" | ||||||
|  |     "  out.uv = in.uv;\n" | ||||||
|  |     "  return out;\n" | ||||||
|  |     "}\n"; | ||||||
|  | static const char* gfx_fs_src = | ||||||
|  |     "#include <metal_stdlib>\n" | ||||||
|  |     "using namespace metal;\n" | ||||||
|  |     "struct fs_in {\n" | ||||||
|  |     "  float2 uv;\n" | ||||||
|  |     "};\n" | ||||||
|  |     "fragment float4 _main(fs_in in [[stage_in]], texture2d<float> tex [[texture(0)]], sampler smp [[sampler(0)]]) {\n" | ||||||
|  |     "  return tex.sample(smp, in.uv);\n" | ||||||
|  |     "}\n"; | ||||||
|  | #elif defined(SOKOL_D3D11) | ||||||
|  | static const char* gfx_vs_src = | ||||||
|  |     "struct vs_in {\n" | ||||||
|  |     "  float2 pos: POS;\n" | ||||||
|  |     "  float2 uv:  UV;\n" | ||||||
|  |     "};\n" | ||||||
|  |     "struct vs_out {\n" | ||||||
|  |     "  float2 uv: TEXCOORD0;\n" | ||||||
|  |     "  float4 pos: SV_Position;\n" | ||||||
|  |     "};\n" | ||||||
|  |     "vs_out main(vs_in inp) {\n" | ||||||
|  |     "  vs_out outp;\n" | ||||||
|  |     "  outp.pos = float4(inp.pos*2.0-1.0, 0.5, 1.0);\n" | ||||||
|  |     "  outp.uv = inp.uv;\n" | ||||||
|  |     "  return outp;\n" | ||||||
|  |     "}\n"; | ||||||
|  | static const char* gfx_fs_src = | ||||||
|  |     "Texture2D<float4> tex: register(t0);\n" | ||||||
|  |     "sampler smp: register(s0);\n" | ||||||
|  |     "float4 main(float2 uv: TEXCOORD0): SV_Target0 {\n" | ||||||
|  |     "  return tex.Sample(smp, uv);\n" | ||||||
|  |     "}\n"; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | void gfx_init(s32 w, s32 h, s32 sx, s32 sy) { | ||||||
|  |     platform.gfx.fb_width = w; | ||||||
|  |     platform.gfx.fb_height = h; | ||||||
|  |     platform.gfx.fb_aspect_scale_x = sx; | ||||||
|  |     platform.gfx.fb_aspect_scale_y = sy; | ||||||
|  |     sg_setup(&(sg_desc){ | ||||||
|  |         .mtl_device = sapp_metal_get_device(), | ||||||
|  |         .mtl_renderpass_descriptor_cb = sapp_metal_get_renderpass_descriptor, | ||||||
|  |         .mtl_drawable_cb = sapp_metal_get_drawable, | ||||||
|  |         .d3d11_device = sapp_d3d11_get_device(), | ||||||
|  |         .d3d11_device_context = sapp_d3d11_get_device_context(), | ||||||
|  |         .d3d11_render_target_view_cb = sapp_d3d11_get_render_target_view, | ||||||
|  |         .d3d11_depth_stencil_view_cb = sapp_d3d11_get_depth_stencil_view | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     /* quad vertex buffers with and without flipped UVs */ | ||||||
|  |     float verts[] = { | ||||||
|  |         0.0f, 0.0f, 0.0f, 0.0f, | ||||||
|  |         1.0f, 0.0f, 1.0f, 0.0f, | ||||||
|  |         0.0f, 1.0f, 0.0f, 1.0f, | ||||||
|  |         1.0f, 1.0f,  1.0f, 1.0f | ||||||
|  |     }; | ||||||
|  |     float verts_flipped[] = { | ||||||
|  |         0.0f, 0.0f, 0.0f, 1.0f, | ||||||
|  |         1.0f, 0.0f, 1.0f, 1.0f, | ||||||
|  |         0.0f, 1.0f, 0.0f, 0.0f, | ||||||
|  |         1.0f, 1.0f,  1.0f, 0.0f | ||||||
|  |     }; | ||||||
|  |     platform.gfx.upscale_draw_state.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){ | ||||||
|  |         .size = sizeof(verts), | ||||||
|  |         .content = verts, | ||||||
|  |     }); | ||||||
|  |     platform.gfx.draw_state.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){ | ||||||
|  |         .size = sizeof(verts), | ||||||
|  |         .content = sg_query_feature(SG_FEATURE_ORIGIN_TOP_LEFT) ? verts : verts_flipped | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     /* a shader to render a textured quad */ | ||||||
|  |     sg_shader fsq_shd = sg_make_shader(&(sg_shader_desc){ | ||||||
|  |         .fs.images = { | ||||||
|  |             [0] = { .name="tex", .type=SG_IMAGETYPE_2D }, | ||||||
|  |         }, | ||||||
|  |         .vs.source = gfx_vs_src, | ||||||
|  |         .fs.source = gfx_fs_src, | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     /* 2 pipeline-state-objects, one for upscaling, one for rendering */ | ||||||
|  |     sg_pipeline_desc pip_desc = { | ||||||
|  |         .layout = { | ||||||
|  |             .attrs[0] = { .name="in_pos", .sem_name="POS", .format=SG_VERTEXFORMAT_FLOAT2 }, | ||||||
|  |             .attrs[1] = { .name="in_uv", .sem_name="UV", .format=SG_VERTEXFORMAT_FLOAT2 } | ||||||
|  |         }, | ||||||
|  |         .shader = fsq_shd, | ||||||
|  |         .primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP | ||||||
|  |     }; | ||||||
|  |     platform.gfx.draw_state.pipeline = sg_make_pipeline(&pip_desc); | ||||||
|  |     pip_desc.blend.depth_format = SG_PIXELFORMAT_NONE; | ||||||
|  |     platform.gfx.upscale_draw_state.pipeline = sg_make_pipeline(&pip_desc); | ||||||
|  |  | ||||||
|  |     /* a texture with the emulator's raw pixel data */ | ||||||
|  |     platform.gfx.upscale_draw_state.fs_images[0] = sg_make_image(&(sg_image_desc){ | ||||||
|  |         .width = platform.gfx.fb_width, | ||||||
|  |         .height = platform.gfx.fb_height, | ||||||
|  |         .pixel_format = SG_PIXELFORMAT_RGBA8, | ||||||
|  |         .usage = SG_USAGE_STREAM, | ||||||
|  |         .min_filter = SG_FILTER_NEAREST, | ||||||
|  |         .mag_filter = SG_FILTER_NEAREST, | ||||||
|  |         .wrap_u = SG_WRAP_CLAMP_TO_EDGE, | ||||||
|  |         .wrap_v = SG_WRAP_CLAMP_TO_EDGE | ||||||
|  |     }); | ||||||
|  |     /* a 2x upscaled render-target-texture */ | ||||||
|  |     platform.gfx.draw_state.fs_images[0] = sg_make_image(&(sg_image_desc){ | ||||||
|  |         .render_target = true, | ||||||
|  |         .width = 2*platform.gfx.fb_width, | ||||||
|  |         .height = 2*platform.gfx.fb_height, | ||||||
|  |         .pixel_format = SG_PIXELFORMAT_RGBA8, | ||||||
|  |         .min_filter = SG_FILTER_LINEAR, | ||||||
|  |         .mag_filter = SG_FILTER_LINEAR, | ||||||
|  |         .wrap_u = SG_WRAP_CLAMP_TO_EDGE, | ||||||
|  |         .wrap_v = SG_WRAP_CLAMP_TO_EDGE | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     /* a render pass for the 2x upscaling */ | ||||||
|  |     platform.gfx.upscale_pass = sg_make_pass(&(sg_pass_desc){ | ||||||
|  |         .color_attachments[0].image = platform.gfx.draw_state.fs_images[0] | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static const sg_pass_action gfx_upscale_pass_action = { | ||||||
|  |     .colors[0] = { .action = SG_ACTION_DONTCARE } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const sg_pass_action gfx_draw_pass_action = { | ||||||
|  |     .colors[0] = { .action = SG_ACTION_CLEAR, .val = { 0.05f, 0.05f, 0.05f, 1.0f } } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static void apply_viewport(void) { | ||||||
|  |     const s32 canvas_width = sapp_width(); | ||||||
|  |     const s32 canvas_height = sapp_height(); | ||||||
|  |     const float canvas_aspect = (float)canvas_width / (float)canvas_height; | ||||||
|  |     const float fb_aspect = (float)(platform.gfx.fb_width*platform.gfx.fb_aspect_scale_x) / (float)(platform.gfx.fb_height*platform.gfx.fb_aspect_scale_y); | ||||||
|  |     const s32 frame_x = 5; | ||||||
|  |     const s32 frame_y = 5; | ||||||
|  |     s32 vp_x, vp_y, vp_w, vp_h; | ||||||
|  |     if (fb_aspect < canvas_aspect) { | ||||||
|  |         vp_y = frame_y; | ||||||
|  |         vp_h = canvas_height - 2 * frame_y; | ||||||
|  |         vp_w = (s32) (canvas_height * fb_aspect) - 2 * frame_x; | ||||||
|  |         vp_x = (canvas_width - vp_w) / 2; | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         vp_x = frame_x; | ||||||
|  |         vp_w = canvas_width - 2 * frame_x; | ||||||
|  |         vp_h = (s32) (canvas_width / fb_aspect) - 2 * frame_y; | ||||||
|  |         vp_y = frame_y; | ||||||
|  |     } | ||||||
|  |     sg_apply_viewport(vp_x, vp_y, vp_w, vp_h, true); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void gfx_draw() { | ||||||
|  |  | ||||||
|  |     /* copy emulator pixel data into upscaling source texture */ | ||||||
|  |     sg_update_image(platform.gfx.upscale_draw_state.fs_images[0], &(sg_image_content){ | ||||||
|  |         .subimage[0][0] = {  | ||||||
|  |             .ptr = platform.studio->tic->screen, | ||||||
|  |             .size = platform.gfx.fb_width*platform.gfx.fb_height*sizeof platform.studio->tic->screen[0] | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     /* upscale the original framebuffer 2x with nearest filtering */ | ||||||
|  |     sg_begin_pass(platform.gfx.upscale_pass, &gfx_upscale_pass_action); | ||||||
|  |     sg_apply_draw_state(&platform.gfx.upscale_draw_state); | ||||||
|  |     sg_draw(0, 4, 1); | ||||||
|  |     sg_end_pass(); | ||||||
|  |  | ||||||
|  |     /* draw the final pass with linear filtering */ | ||||||
|  |     sg_begin_default_pass(&gfx_draw_pass_action, sapp_width(), sapp_height()); | ||||||
|  |     apply_viewport(); | ||||||
|  |     sg_apply_draw_state(&platform.gfx.draw_state); | ||||||
|  |     sg_draw(0, 4, 1); | ||||||
|  |     sg_end_pass(); | ||||||
|  |     sg_commit(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void setClipboardText(const char* text) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static bool hasClipboardText() | ||||||
|  | { | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char* getClipboardText() | ||||||
|  | { | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void freeClipboardText(const char* text) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static u64 getPerformanceCounter() | ||||||
|  | { | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static u64 getPerformanceFrequency() | ||||||
|  | { | ||||||
|  | 	return 1000; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void* getUrlRequest(const char* url, s32* size) | ||||||
|  | { | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void goFullscreen() | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void showMessageBox(const char* title, const char* message) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void setWindowTitle(const char* title) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void openSystemPath(const char* path) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void preseed() | ||||||
|  | { | ||||||
|  | #if defined(__TIC_MACOSX__) | ||||||
|  | 	srandom(time(NULL)); | ||||||
|  | 	random(); | ||||||
|  | #else | ||||||
|  | 	srand(time(NULL)); | ||||||
|  | 	rand(); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void pollEvent() | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void updateConfig() | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static System systemInterface =  | ||||||
|  | { | ||||||
|  | 	.setClipboardText = setClipboardText, | ||||||
|  | 	.hasClipboardText = hasClipboardText, | ||||||
|  | 	.getClipboardText = getClipboardText, | ||||||
|  | 	.freeClipboardText = freeClipboardText, | ||||||
|  |  | ||||||
|  | 	.getPerformanceCounter = getPerformanceCounter, | ||||||
|  | 	.getPerformanceFrequency = getPerformanceFrequency, | ||||||
|  |  | ||||||
|  | 	.getUrlRequest = getUrlRequest, | ||||||
|  |  | ||||||
|  | 	.fileDialogLoad = file_dialog_load, | ||||||
|  | 	.fileDialogSave = file_dialog_save, | ||||||
|  |  | ||||||
|  | 	.goFullscreen = goFullscreen, | ||||||
|  | 	.showMessageBox = showMessageBox, | ||||||
|  | 	.setWindowTitle = setWindowTitle, | ||||||
|  |  | ||||||
|  | 	.openSystemPath = openSystemPath, | ||||||
|  | 	.preseed = preseed, | ||||||
|  | 	.poll = pollEvent, | ||||||
|  | 	.updateConfig = updateConfig, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static void app_init(void) | ||||||
|  | { | ||||||
|  | 	gfx_init(TIC80_FULLWIDTH, TIC80_FULLHEIGHT, 1, 1); | ||||||
|  |  | ||||||
|  |     platform.audio.samples = calloc(sizeof platform.audio.samples[0], saudio_sample_rate() / TIC_FRAMERATE * TIC_STEREO_CHANNLES); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void app_frame(void) | ||||||
|  | { | ||||||
|  | 	tic_mem* tic = platform.studio->tic; | ||||||
|  |  | ||||||
|  | 	if(platform.studio->quit) | ||||||
|  | 	{ | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	platform.studio->tick(); | ||||||
|  |  | ||||||
|  | 	gfx_draw(); | ||||||
|  |  | ||||||
|  | 	s32 count = tic->samples.size / sizeof tic->samples.buffer[0]; | ||||||
|  |     for(s32 i = 0; i < count; i++) | ||||||
|  |         platform.audio.samples[i] = (float)tic->samples.buffer[i] / SHRT_MAX; | ||||||
|  |  | ||||||
|  |     saudio_push(platform.audio.samples, count / 2); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void app_input(const sapp_event* event) | ||||||
|  | { | ||||||
|  | 	 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void app_cleanup(void) | ||||||
|  | { | ||||||
|  | 	platform.studio->close(); | ||||||
|  | 	free(platform.audio.samples); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | sapp_desc sokol_main(s32 argc, char* argv[]) | ||||||
|  | { | ||||||
|  | 	memset(&platform, 0, sizeof platform); | ||||||
|  |  | ||||||
|  |     platform.audio.desc.num_channels = TIC_STEREO_CHANNLES; | ||||||
|  |     saudio_setup(&platform.audio.desc); | ||||||
|  |  | ||||||
|  | 	platform.studio = studioInit(argc, argv, saudio_sample_rate(), ".", &systemInterface); | ||||||
|  |  | ||||||
|  | 	const s32 Width = TIC80_FULLWIDTH * platform.studio->config()->uiScale; | ||||||
|  | 	const s32 Height = TIC80_FULLHEIGHT * platform.studio->config()->uiScale; | ||||||
|  |  | ||||||
|  | 	return(sapp_desc) | ||||||
|  | 	{ | ||||||
|  | 		.init_cb = app_init, | ||||||
|  | 		.frame_cb = app_frame, | ||||||
|  | 		.event_cb = app_input, | ||||||
|  | 		.cleanup_cb = app_cleanup, | ||||||
|  | 		.width = Width, | ||||||
|  | 		.height = Height, | ||||||
|  | 		.window_title = TIC_TITLE, | ||||||
|  | 		.ios_keyboard_resizes_canvas = true | ||||||
|  | 	}; | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Vadim Grigoruk
					Vadim Grigoruk