Merge branch 'sokol'
This commit is contained in:
@@ -22,9 +22,9 @@
|
||||
|
||||
#include "file_dialog.h"
|
||||
|
||||
#include <SDL.h>
|
||||
#include <tic80_config.h>
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
#if defined(__TIC_WINDOWS__)
|
||||
|
||||
#include <windows.h>
|
||||
#include <commdlg.h>
|
||||
@@ -36,7 +36,7 @@ wchar_t* wcscpy(wchar_t *, const wchar_t *);
|
||||
void file_dialog_load(file_dialog_load_callback callback, void* data)
|
||||
{
|
||||
OPENFILENAMEW ofn;
|
||||
SDL_zero(ofn);
|
||||
memset(&ofn, 0, sizeof ofn);
|
||||
|
||||
wchar_t filename[MAX_PATH];
|
||||
memset(filename, 0, sizeof(filename));
|
||||
@@ -83,7 +83,7 @@ void file_dialog_load(file_dialog_load_callback callback, void* data)
|
||||
void file_dialog_save(file_dialog_save_callback callback, const char* name, const u8* buffer, size_t size, void* data, u32 mode)
|
||||
{
|
||||
OPENFILENAMEW ofn;
|
||||
SDL_zero(ofn);
|
||||
memset(&ofn, 0, sizeof ofn);
|
||||
|
||||
wchar_t filename[MAX_PATH];
|
||||
mbstowcs(filename, name, MAX_PATH);
|
||||
@@ -102,7 +102,7 @@ void file_dialog_save(file_dialog_save_callback callback, const char* name, cons
|
||||
fwrite(buffer, 1, size, file);
|
||||
fclose(file);
|
||||
|
||||
#if !defined(__WINDOWS__)
|
||||
#if !defined(__TIC_WINDOWS__)
|
||||
chmod(filename, mode);
|
||||
#endif
|
||||
callback(true, data);
|
||||
@@ -157,7 +157,7 @@ void file_dialog_save(file_dialog_save_callback callback, const char* name, cons
|
||||
callback(true, data);
|
||||
}
|
||||
|
||||
#elif defined(__LINUX__)
|
||||
#elif defined(__TIC_LINUX__)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -267,7 +267,7 @@ void file_dialog_save(file_dialog_save_callback callback, const char* name, cons
|
||||
callback(false, data);
|
||||
}
|
||||
|
||||
#elif defined(__MACOSX__)
|
||||
#elif defined(__TIC_MACOSX__)
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@@ -345,7 +345,7 @@ void file_dialog_save(file_dialog_save_callback callback, const char* name, cons
|
||||
callback(false, data);
|
||||
}
|
||||
|
||||
#elif defined(__ANDROID__)
|
||||
#elif defined(__TIC_ANDROID__)
|
||||
|
||||
#include <jni.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
#include "ticapi.h"
|
||||
#include "ext/file_dialog.h"
|
||||
|
||||
#define TIC80_OFFSET_LEFT ((TIC80_FULLWIDTH-TIC80_WIDTH)/2)
|
||||
#define TIC80_OFFSET_TOP ((TIC80_FULLHEIGHT-TIC80_HEIGHT)/2)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*setClipboardText)(const char* text);
|
||||
|
||||
@@ -1,683 +0,0 @@
|
||||
#include "../system.h"
|
||||
#include "../net.h"
|
||||
#include "../tools.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <SDL.h>
|
||||
|
||||
#define STUDIO_UI_SCALE 2
|
||||
#define STUDIO_PIXEL_FORMAT SDL_PIXELFORMAT_ABGR8888
|
||||
#define TEXTURE_SIZE (TIC80_FULLWIDTH)
|
||||
#define OFFSET_LEFT ((TIC80_FULLWIDTH-TIC80_WIDTH)/2)
|
||||
#define OFFSET_TOP ((TIC80_FULLHEIGHT-TIC80_HEIGHT)/2)
|
||||
|
||||
static struct
|
||||
{
|
||||
Studio* studio;
|
||||
|
||||
|
||||
SDL_Window* window;
|
||||
SDL_Renderer* renderer;
|
||||
SDL_Texture* texture;
|
||||
|
||||
struct
|
||||
{
|
||||
SDL_Joystick* ports[TIC_GAMEPADS];
|
||||
tic80_gamepads joystick;
|
||||
} gamepad;
|
||||
|
||||
struct
|
||||
{
|
||||
SDL_Texture* texture;
|
||||
const u8* src;
|
||||
} mouse;
|
||||
|
||||
Net* net;
|
||||
|
||||
struct
|
||||
{
|
||||
SDL_AudioSpec spec;
|
||||
SDL_AudioDeviceID device;
|
||||
SDL_AudioCVT cvt;
|
||||
} audio;
|
||||
} platform;
|
||||
|
||||
static void initSound()
|
||||
{
|
||||
SDL_AudioSpec want =
|
||||
{
|
||||
.freq = 44100,
|
||||
.format = AUDIO_S16,
|
||||
.channels = 1,
|
||||
.userdata = NULL,
|
||||
};
|
||||
|
||||
platform.audio.device = SDL_OpenAudioDevice(NULL, 0, &want, &platform.audio.spec, SDL_AUDIO_ALLOW_ANY_CHANGE);
|
||||
|
||||
SDL_BuildAudioCVT(&platform.audio.cvt, want.format, want.channels, platform.audio.spec.freq, platform.audio.spec.format, platform.audio.spec.channels, platform.audio.spec.freq);
|
||||
|
||||
if(platform.audio.cvt.needed)
|
||||
{
|
||||
platform.audio.cvt.len = platform.audio.spec.freq * sizeof(s16) / TIC_FRAMERATE;
|
||||
platform.audio.cvt.buf = SDL_malloc(platform.audio.cvt.len * platform.audio.cvt.len_mult);
|
||||
}
|
||||
}
|
||||
|
||||
static u8* getSpritePtr(tic_tile* tiles, s32 x, s32 y)
|
||||
{
|
||||
enum { SheetCols = (TIC_SPRITESHEET_SIZE / TIC_SPRITESIZE) };
|
||||
return tiles[x / TIC_SPRITESIZE + y / TIC_SPRITESIZE * SheetCols].data;
|
||||
}
|
||||
|
||||
static u8 getSpritePixel(tic_tile* tiles, s32 x, s32 y)
|
||||
{
|
||||
return tic_tool_peek4(getSpritePtr(tiles, x, y), (x % TIC_SPRITESIZE) + (y % TIC_SPRITESIZE) * TIC_SPRITESIZE);
|
||||
}
|
||||
|
||||
static void calcTextureRect(SDL_Rect* rect)
|
||||
{
|
||||
SDL_GetWindowSize(platform.window, &rect->w, &rect->h);
|
||||
|
||||
{
|
||||
enum{Width = TIC80_WIDTH, Height = TIC80_HEIGHT};
|
||||
|
||||
s32 discreteHeight = rect->h - rect->h % Height;
|
||||
s32 discreteWidth = Width * discreteHeight / Height;
|
||||
|
||||
rect->x = (rect->w - discreteWidth) / 2;
|
||||
rect->y = (rect->h - discreteHeight) / 2;
|
||||
|
||||
rect->w = discreteWidth;
|
||||
rect->h = discreteHeight;
|
||||
}
|
||||
}
|
||||
|
||||
static void processMouse()
|
||||
{
|
||||
s32 mx = 0, my = 0;
|
||||
s32 mb = SDL_GetMouseState(&mx, &my);
|
||||
|
||||
tic80_input* input = &platform.studio->tic->ram.input;
|
||||
|
||||
{
|
||||
input->mouse.x = input->mouse.y = 0;
|
||||
|
||||
SDL_Rect rect = {0, 0, 0, 0};
|
||||
calcTextureRect(&rect);
|
||||
|
||||
if(rect.w) input->mouse.x = (mx - rect.x) * TIC80_WIDTH / rect.w;
|
||||
if(rect.h) input->mouse.y = (my - rect.y) * TIC80_HEIGHT / rect.h;
|
||||
}
|
||||
|
||||
{
|
||||
input->mouse.left = mb & SDL_BUTTON_LMASK ? 1 : 0;
|
||||
input->mouse.middle = mb & SDL_BUTTON_MMASK ? 1 : 0;
|
||||
input->mouse.right = mb & SDL_BUTTON_RMASK ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void processKeyboard()
|
||||
{
|
||||
static const u8 KeyboardCodes[] =
|
||||
{
|
||||
#include "../keycodes.c"
|
||||
};
|
||||
|
||||
tic80_input* input = &platform.studio->tic->ram.input;
|
||||
input->keyboard.data = 0;
|
||||
|
||||
const u8* keyboard = SDL_GetKeyboardState(NULL);
|
||||
|
||||
for(s32 i = 0, c = 0; i < COUNT_OF(KeyboardCodes) && c < COUNT_OF(input->keyboard.keys); i++)
|
||||
if(keyboard[i] && KeyboardCodes[i] > tic_key_unknown)
|
||||
input->keyboard.keys[c++] = KeyboardCodes[i];
|
||||
}
|
||||
|
||||
static s32 getAxisMask(SDL_Joystick* joystick)
|
||||
{
|
||||
s32 mask = 0;
|
||||
|
||||
s32 axesCount = SDL_JoystickNumAxes(joystick);
|
||||
|
||||
for (s32 a = 0; a < axesCount; a++)
|
||||
{
|
||||
s32 axe = SDL_JoystickGetAxis(joystick, a);
|
||||
|
||||
if (axe)
|
||||
{
|
||||
if (a == 0)
|
||||
{
|
||||
if (axe > 16384) mask |= SDL_HAT_RIGHT;
|
||||
else if(axe < -16384) mask |= SDL_HAT_LEFT;
|
||||
}
|
||||
else if (a == 1)
|
||||
{
|
||||
if (axe > 16384) mask |= SDL_HAT_DOWN;
|
||||
else if (axe < -16384) mask |= SDL_HAT_UP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static s32 getJoystickHatMask(s32 hat)
|
||||
{
|
||||
tic80_gamepads gamepad;
|
||||
gamepad.data = 0;
|
||||
|
||||
gamepad.first.up = hat & SDL_HAT_UP;
|
||||
gamepad.first.down = hat & SDL_HAT_DOWN;
|
||||
gamepad.first.left = hat & SDL_HAT_LEFT;
|
||||
gamepad.first.right = hat & SDL_HAT_RIGHT;
|
||||
|
||||
return gamepad.data;
|
||||
}
|
||||
|
||||
static void processJoysticks()
|
||||
{
|
||||
platform.gamepad.joystick.data = 0;
|
||||
s32 index = 0;
|
||||
|
||||
for(s32 i = 0; i < COUNT_OF(platform.gamepad.ports); i++)
|
||||
{
|
||||
SDL_Joystick* joystick = platform.gamepad.ports[i];
|
||||
|
||||
if(joystick && SDL_JoystickGetAttached(joystick))
|
||||
{
|
||||
tic80_gamepad* gamepad = NULL;
|
||||
|
||||
switch(index)
|
||||
{
|
||||
case 0: gamepad = &platform.gamepad.joystick.first; break;
|
||||
case 1: gamepad = &platform.gamepad.joystick.second; break;
|
||||
case 2: gamepad = &platform.gamepad.joystick.third; break;
|
||||
case 3: gamepad = &platform.gamepad.joystick.fourth; break;
|
||||
}
|
||||
|
||||
if(gamepad)
|
||||
{
|
||||
gamepad->data |= getJoystickHatMask(getAxisMask(joystick));
|
||||
|
||||
for (s32 h = 0; h < SDL_JoystickNumHats(joystick); h++)
|
||||
gamepad->data |= getJoystickHatMask(SDL_JoystickGetHat(joystick, h));
|
||||
|
||||
s32 numButtons = SDL_JoystickNumButtons(joystick);
|
||||
if(numButtons >= 2)
|
||||
{
|
||||
gamepad->a = SDL_JoystickGetButton(joystick, 0);
|
||||
gamepad->b = SDL_JoystickGetButton(joystick, 1);
|
||||
|
||||
if(numButtons >= 4)
|
||||
{
|
||||
gamepad->x = SDL_JoystickGetButton(joystick, 2);
|
||||
gamepad->y = SDL_JoystickGetButton(joystick, 3);
|
||||
|
||||
for(s32 i = 5; i < numButtons; i++)
|
||||
{
|
||||
s32 back = SDL_JoystickGetButton(joystick, i);
|
||||
|
||||
if(back)
|
||||
{
|
||||
tic_mem* tic = platform.studio->tic;
|
||||
|
||||
for(s32 i = 0; i < TIC80_KEY_BUFFER; i++)
|
||||
{
|
||||
if(!tic->ram.input.keyboard.keys[i])
|
||||
{
|
||||
tic->ram.input.keyboard.keys[i] = tic_key_escape;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void processGamepad()
|
||||
{
|
||||
processJoysticks();
|
||||
|
||||
{
|
||||
platform.studio->tic->ram.input.gamepads.data = 0;
|
||||
platform.studio->tic->ram.input.gamepads.data |= platform.gamepad.joystick.data;
|
||||
}
|
||||
}
|
||||
|
||||
static void pollEvent()
|
||||
{
|
||||
tic80_input* input = &platform.studio->tic->ram.input;
|
||||
|
||||
{
|
||||
input->mouse.btns = 0;
|
||||
}
|
||||
|
||||
SDL_Event event;
|
||||
|
||||
while(SDL_PollEvent(&event))
|
||||
{
|
||||
switch(event.type)
|
||||
{
|
||||
case SDL_MOUSEWHEEL:
|
||||
{
|
||||
input->mouse.scrollx = event.wheel.x;
|
||||
input->mouse.scrolly = event.wheel.y;
|
||||
}
|
||||
break;
|
||||
case SDL_JOYDEVICEADDED:
|
||||
{
|
||||
s32 id = event.jdevice.which;
|
||||
|
||||
if (id < TIC_GAMEPADS)
|
||||
{
|
||||
if(platform.gamepad.ports[id])
|
||||
SDL_JoystickClose(platform.gamepad.ports[id]);
|
||||
|
||||
platform.gamepad.ports[id] = SDL_JoystickOpen(id);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_JOYDEVICEREMOVED:
|
||||
{
|
||||
s32 id = event.jdevice.which;
|
||||
|
||||
if (id < TIC_GAMEPADS && platform.gamepad.ports[id])
|
||||
{
|
||||
SDL_JoystickClose(platform.gamepad.ports[id]);
|
||||
platform.gamepad.ports[id] = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_WINDOWEVENT:
|
||||
switch(event.window.event)
|
||||
{
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED: platform.studio->updateProject(); break;
|
||||
}
|
||||
break;
|
||||
case SDL_QUIT:
|
||||
platform.studio->exit();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
processMouse();
|
||||
processKeyboard();
|
||||
processGamepad();
|
||||
}
|
||||
|
||||
static void blitTexture()
|
||||
{
|
||||
tic_mem* tic = platform.studio->tic;
|
||||
|
||||
SDL_Rect rect = {0, 0, 0, 0};
|
||||
calcTextureRect(&rect);
|
||||
|
||||
void* pixels = NULL;
|
||||
s32 pitch = 0;
|
||||
SDL_LockTexture(platform.texture, NULL, &pixels, &pitch);
|
||||
|
||||
platform.studio->tick();
|
||||
|
||||
memcpy(pixels, tic->screen, sizeof tic->screen);
|
||||
|
||||
SDL_UnlockTexture(platform.texture);
|
||||
|
||||
{
|
||||
enum {Top = OFFSET_TOP};
|
||||
enum {Left = OFFSET_LEFT};
|
||||
|
||||
SDL_Rect srcRect = {Left, Top, TIC80_WIDTH, TIC80_HEIGHT};
|
||||
|
||||
SDL_RenderCopy(platform.renderer, platform.texture, &srcRect, &rect);
|
||||
}
|
||||
}
|
||||
|
||||
static void blitSound()
|
||||
{
|
||||
tic_mem* tic = platform.studio->tic;
|
||||
|
||||
SDL_PauseAudioDevice(platform.audio.device, 0);
|
||||
|
||||
if(platform.audio.cvt.needed)
|
||||
{
|
||||
SDL_memcpy(platform.audio.cvt.buf, tic->samples.buffer, tic->samples.size);
|
||||
SDL_ConvertAudio(&platform.audio.cvt);
|
||||
SDL_QueueAudio(platform.audio.device, platform.audio.cvt.buf, platform.audio.cvt.len_cvt);
|
||||
}
|
||||
else SDL_QueueAudio(platform.audio.device, tic->samples.buffer, tic->samples.size);
|
||||
}
|
||||
|
||||
static void blitCursor(const u8* in)
|
||||
{
|
||||
if(!platform.mouse.texture)
|
||||
{
|
||||
platform.mouse.texture = SDL_CreateTexture(platform.renderer, STUDIO_PIXEL_FORMAT, SDL_TEXTUREACCESS_STREAMING, TIC_SPRITESIZE, TIC_SPRITESIZE);
|
||||
SDL_SetTextureBlendMode(platform.mouse.texture, SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
|
||||
if(platform.mouse.src != in)
|
||||
{
|
||||
platform.mouse.src = in;
|
||||
|
||||
void* pixels = NULL;
|
||||
s32 pitch = 0;
|
||||
SDL_LockTexture(platform.mouse.texture, NULL, &pixels, &pitch);
|
||||
|
||||
{
|
||||
const u8* end = in + sizeof(tic_tile);
|
||||
const u32* pal = tic_palette_blit(&platform.studio->tic->ram.vram.palette);
|
||||
u32* out = pixels;
|
||||
|
||||
while(in != end)
|
||||
{
|
||||
u8 low = *in & 0x0f;
|
||||
u8 hi = (*in & 0xf0) >> TIC_PALETTE_BPP;
|
||||
*out++ = low ? (*(pal + low) | 0xff000000) : 0;
|
||||
*out++ = hi ? (*(pal + hi) | 0xff000000) : 0;
|
||||
|
||||
in++;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockTexture(platform.mouse.texture);
|
||||
}
|
||||
|
||||
SDL_Rect rect = {0, 0, 0, 0};
|
||||
calcTextureRect(&rect);
|
||||
s32 scale = rect.w / TIC80_WIDTH;
|
||||
|
||||
SDL_Rect src = {0, 0, TIC_SPRITESIZE, TIC_SPRITESIZE};
|
||||
SDL_Rect dst = {0, 0, TIC_SPRITESIZE * scale, TIC_SPRITESIZE * scale};
|
||||
|
||||
SDL_GetMouseState(&dst.x, &dst.y);
|
||||
|
||||
if(platform.studio->config()->theme.cursor.pixelPerfect)
|
||||
{
|
||||
dst.x -= (dst.x - rect.x) % scale;
|
||||
dst.y -= (dst.y - rect.y) % scale;
|
||||
}
|
||||
|
||||
if(SDL_GetWindowFlags(platform.window) & SDL_WINDOW_MOUSE_FOCUS)
|
||||
SDL_RenderCopy(platform.renderer, platform.mouse.texture, &src, &dst);
|
||||
}
|
||||
|
||||
static void renderCursor()
|
||||
{
|
||||
if(platform.studio->tic->ram.vram.vars.cursor.system)
|
||||
{
|
||||
switch(platform.studio->tic->ram.vram.vars.cursor.sprite)
|
||||
{
|
||||
case tic_cursor_hand:
|
||||
{
|
||||
if(platform.studio->config()->theme.cursor.hand >= 0)
|
||||
{
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
blitCursor(platform.studio->config()->cart->bank0.tiles.data[platform.studio->config()->theme.cursor.hand].data);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
SDL_SetCursor(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case tic_cursor_ibeam:
|
||||
{
|
||||
if(platform.studio->config()->theme.cursor.ibeam >= 0)
|
||||
{
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
blitCursor(platform.studio->config()->cart->bank0.tiles.data[platform.studio->config()->theme.cursor.ibeam].data);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
SDL_SetCursor(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(platform.studio->config()->theme.cursor.arrow >= 0)
|
||||
{
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
blitCursor(platform.studio->config()->cart->bank0.tiles.data[platform.studio->config()->theme.cursor.arrow].data);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
SDL_SetCursor(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
blitCursor(platform.studio->tic->ram.sprites.data[platform.studio->tic->ram.vram.vars.cursor.sprite].data);
|
||||
}
|
||||
|
||||
// if(platform.mode == TIC_RUN_MODE && !platform.studio.tic->input.mouse)
|
||||
// {
|
||||
// SDL_ShowCursor(SDL_DISABLE);
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
|
||||
static void tick()
|
||||
{
|
||||
pollEvent();
|
||||
|
||||
if(platform.studio->quit)
|
||||
return;
|
||||
|
||||
SDL_RenderClear(platform.renderer);
|
||||
|
||||
blitTexture();
|
||||
renderCursor();
|
||||
|
||||
SDL_RenderPresent(platform.renderer);
|
||||
|
||||
blitSound();
|
||||
}
|
||||
|
||||
static const char* getAppFolder()
|
||||
{
|
||||
static char appFolder[FILENAME_MAX];
|
||||
|
||||
char* path = SDL_GetPrefPath(TIC_PACKAGE, TIC_NAME);
|
||||
strcpy(appFolder, path);
|
||||
SDL_free(path);
|
||||
|
||||
return appFolder;
|
||||
}
|
||||
|
||||
static void setClipboardText(const char* text)
|
||||
{
|
||||
SDL_SetClipboardText(text);
|
||||
}
|
||||
|
||||
static bool hasClipboardText()
|
||||
{
|
||||
return SDL_HasClipboardText();
|
||||
}
|
||||
|
||||
static char* getClipboardText()
|
||||
{
|
||||
return SDL_GetClipboardText();
|
||||
}
|
||||
|
||||
static void freeClipboardText(const char* text)
|
||||
{
|
||||
SDL_free((void*)text);
|
||||
}
|
||||
|
||||
static u64 getPerformanceCounter()
|
||||
{
|
||||
return SDL_GetPerformanceCounter();
|
||||
}
|
||||
|
||||
static u64 getPerformanceFrequency()
|
||||
{
|
||||
return SDL_GetPerformanceFrequency();
|
||||
}
|
||||
|
||||
static void goFullscreen()
|
||||
{
|
||||
SDL_SetWindowFullscreen(platform.window, SDL_GetWindowFlags(platform.window) & SDL_WINDOW_FULLSCREEN_DESKTOP ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
}
|
||||
|
||||
static void showMessageBox(const char* title, const char* message)
|
||||
{
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, title, message, NULL);
|
||||
}
|
||||
|
||||
static void setWindowTitle(const char* title)
|
||||
{
|
||||
SDL_SetWindowTitle(platform.window, title);
|
||||
}
|
||||
|
||||
#if defined(__WINDOWS__) || defined(__LINUX__) || defined(__MACOSX__)
|
||||
|
||||
static void openSystemPath(const char* path)
|
||||
{
|
||||
char command[FILENAME_MAX];
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
|
||||
sprintf(command, "explorer \"%s\"", path);
|
||||
|
||||
wchar_t wcommand[FILENAME_MAX];
|
||||
mbstowcs(wcommand, command, FILENAME_MAX);
|
||||
|
||||
_wsystem(wcommand);
|
||||
|
||||
#elif defined(__LINUX__)
|
||||
|
||||
sprintf(command, "xdg-open \"%s\"", path);
|
||||
system(command);
|
||||
|
||||
#elif defined(__MACOSX__)
|
||||
|
||||
sprintf(command, "open \"%s\"", path);
|
||||
system(command);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void openSystemPath(const char* path) {}
|
||||
|
||||
#endif
|
||||
|
||||
static void* getUrlRequest(const char* url, s32* size)
|
||||
{
|
||||
return netGetRequest(platform.net, url, size);
|
||||
}
|
||||
|
||||
static void preseed()
|
||||
{
|
||||
#if defined(__MACOSX__)
|
||||
srandom(time(NULL));
|
||||
random();
|
||||
#else
|
||||
srand(time(NULL));
|
||||
rand();
|
||||
#endif
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
s32 main(s32 argc, char **argv)
|
||||
{
|
||||
const char* folder = getAppFolder();
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK);
|
||||
|
||||
initSound();
|
||||
|
||||
platform.net = createNet();
|
||||
|
||||
platform.window = SDL_CreateWindow( TIC_TITLE, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
(TIC80_FULLWIDTH) * STUDIO_UI_SCALE,
|
||||
(TIC80_FULLHEIGHT) * STUDIO_UI_SCALE,
|
||||
SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
|
||||
platform.studio = studioInit(argc, argv, platform.audio.spec.freq, folder, &systemInterface);
|
||||
|
||||
platform.renderer = SDL_CreateRenderer(platform.window, -1, SDL_RENDERER_SOFTWARE);
|
||||
platform.texture = SDL_CreateTexture(platform.renderer, STUDIO_PIXEL_FORMAT, SDL_TEXTUREACCESS_STREAMING, TEXTURE_SIZE, TEXTURE_SIZE);
|
||||
|
||||
{
|
||||
u64 nextTick = SDL_GetPerformanceCounter();
|
||||
const u64 Delta = SDL_GetPerformanceFrequency() / TIC_FRAMERATE;
|
||||
|
||||
while (!platform.studio->quit)
|
||||
{
|
||||
nextTick += Delta;
|
||||
|
||||
tick();
|
||||
|
||||
{
|
||||
s64 delay = nextTick - SDL_GetPerformanceCounter();
|
||||
|
||||
if(delay < 0) nextTick -= delay;
|
||||
else SDL_Delay((u32)(delay * 1000 / SDL_GetPerformanceFrequency()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
platform.studio->close();
|
||||
|
||||
closeNet(platform.net);
|
||||
|
||||
if(platform.audio.cvt.buf)
|
||||
SDL_free(platform.audio.cvt.buf);
|
||||
|
||||
if(platform.mouse.texture)
|
||||
SDL_DestroyTexture(platform.mouse.texture);
|
||||
|
||||
SDL_DestroyTexture(platform.texture);
|
||||
SDL_DestroyRenderer(platform.renderer);
|
||||
SDL_DestroyWindow(platform.window);
|
||||
|
||||
SDL_CloseAudioDevice(platform.audio.device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,3 +1,25 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "system.h"
|
||||
#include "net.h"
|
||||
#include "tools.h"
|
||||
@@ -14,8 +36,6 @@
|
||||
|
||||
#define STUDIO_PIXEL_FORMAT GPU_FORMAT_RGBA
|
||||
#define TEXTURE_SIZE (TIC80_FULLWIDTH)
|
||||
#define OFFSET_LEFT ((TIC80_FULLWIDTH-TIC80_WIDTH)/2)
|
||||
#define OFFSET_TOP ((TIC80_FULLHEIGHT-TIC80_HEIGHT)/2)
|
||||
|
||||
#define KBD_COLS 22
|
||||
#define KBD_ROWS 17
|
||||
@@ -345,7 +365,7 @@ static void calcTextureRect(SDL_Rect* rect)
|
||||
|
||||
rect->y = rect->w > rect->h
|
||||
? (rect->h - discreteHeight) / 2
|
||||
: OFFSET_TOP*discreteWidth/Width;
|
||||
: TIC80_OFFSET_TOP*discreteWidth/Width;
|
||||
|
||||
rect->w = discreteWidth;
|
||||
rect->h = discreteHeight;
|
||||
@@ -381,8 +401,8 @@ static void processMouse()
|
||||
s32 x = -1, y = -1;
|
||||
if(crtMonitorEnabled())
|
||||
{
|
||||
if(rect.w) x = (mx - rect.x) * TIC80_FULLWIDTH / rect.w - OFFSET_LEFT;
|
||||
if(rect.h) y = (my - rect.y) * TIC80_FULLHEIGHT / rect.h - OFFSET_TOP;
|
||||
if(rect.w) x = (mx - rect.x) * TIC80_FULLWIDTH / rect.w - TIC80_OFFSET_LEFT;
|
||||
if(rect.h) y = (my - rect.y) * TIC80_FULLHEIGHT / rect.h - TIC80_OFFSET_TOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -833,7 +853,7 @@ static void blitGpuTexture(GPU_Target* screen, GPU_Image* texture)
|
||||
SDL_Rect rect = {0, 0, 0, 0};
|
||||
calcTextureRect(&rect);
|
||||
|
||||
enum {Header = OFFSET_TOP, Top = OFFSET_TOP, Left = OFFSET_LEFT};
|
||||
enum {Header = TIC80_OFFSET_TOP, Top = TIC80_OFFSET_TOP, Left = TIC80_OFFSET_LEFT};
|
||||
|
||||
s32 width = 0;
|
||||
SDL_GetWindowSize(platform.window, &width, NULL);
|
||||
@@ -887,7 +907,7 @@ static void renderKeyboard()
|
||||
SDL_Rect rect;
|
||||
SDL_GetWindowSize(platform.window, &rect.w, &rect.h);
|
||||
|
||||
GPU_Rect src = {OFFSET_LEFT, OFFSET_TOP, KBD_COLS*TIC_SPRITESIZE, KBD_ROWS*TIC_SPRITESIZE};
|
||||
GPU_Rect src = {TIC80_OFFSET_LEFT, TIC80_OFFSET_TOP, KBD_COLS*TIC_SPRITESIZE, KBD_ROWS*TIC_SPRITESIZE};
|
||||
float scale = rect.w/src.w;
|
||||
GPU_Rect dst = (GPU_Rect){0, rect.h - KBD_ROWS*TIC_SPRITESIZE*scale, scale, scale};
|
||||
|
||||
@@ -911,11 +931,11 @@ static void renderKeyboard()
|
||||
{
|
||||
if(key == KbdLayout[k])
|
||||
{
|
||||
GPU_Rect src = {(k % Cols)*TIC_SPRITESIZE + OFFSET_LEFT, (k / Cols)*TIC_SPRITESIZE + OFFSET_TOP,
|
||||
GPU_Rect src = {(k % Cols)*TIC_SPRITESIZE + TIC80_OFFSET_LEFT, (k / Cols)*TIC_SPRITESIZE + TIC80_OFFSET_TOP,
|
||||
TIC_SPRITESIZE, TIC_SPRITESIZE};
|
||||
|
||||
GPU_BlitScale(platform.keyboard.texture.down, &src, platform.gpu.screen,
|
||||
(src.x - OFFSET_LEFT) * dst.w, (src.y - OFFSET_TOP) * dst.h + dst.y, dst.w, dst.h);
|
||||
(src.x - TIC80_OFFSET_LEFT) * dst.w, (src.y - TIC80_OFFSET_TOP) * dst.h + dst.y, dst.w, dst.h);
|
||||
}
|
||||
}
|
||||
}
|
||||
421
src/system/sokol.c
Normal file
421
src/system/sokol.c
Normal file
@@ -0,0 +1,421 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "system/sokol.h"
|
||||
|
||||
static struct
|
||||
{
|
||||
Studio* studio;
|
||||
|
||||
struct
|
||||
{
|
||||
bool state[tic_keys_count];
|
||||
} keyboard;
|
||||
|
||||
struct
|
||||
{
|
||||
saudio_desc desc;
|
||||
float* samples;
|
||||
} audio;
|
||||
|
||||
char* clipboard;
|
||||
|
||||
} platform;
|
||||
|
||||
static void setClipboardText(const char* text)
|
||||
{
|
||||
if(platform.clipboard)
|
||||
{
|
||||
free(platform.clipboard);
|
||||
platform.clipboard = NULL;
|
||||
}
|
||||
|
||||
platform.clipboard = strdup(text);
|
||||
}
|
||||
|
||||
static bool hasClipboardText()
|
||||
{
|
||||
return platform.clipboard != NULL;
|
||||
}
|
||||
|
||||
static char* getClipboardText()
|
||||
{
|
||||
return platform.clipboard ? strdup(platform.clipboard) : NULL;
|
||||
}
|
||||
|
||||
static void freeClipboardText(const char* text)
|
||||
{
|
||||
free((void*)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)
|
||||
{
|
||||
sokol_gfx_init(TIC80_FULLWIDTH, TIC80_FULLHEIGHT, 1, 1, false, true);
|
||||
|
||||
platform.audio.samples = calloc(sizeof platform.audio.samples[0], saudio_sample_rate() / TIC_FRAMERATE * TIC_STEREO_CHANNLES);
|
||||
}
|
||||
|
||||
static void handleKeyboard()
|
||||
{
|
||||
tic_mem* tic = platform.studio->tic;
|
||||
|
||||
tic80_input* input = &tic->ram.input;
|
||||
input->keyboard.data = 0;
|
||||
|
||||
enum{BufSize = COUNT_OF(input->keyboard.keys)};
|
||||
|
||||
for(s32 i = 0, c = 0; i < COUNT_OF(platform.keyboard.state) && c < BufSize; i++)
|
||||
if(platform.keyboard.state[i])
|
||||
input->keyboard.keys[c++] = i;
|
||||
}
|
||||
|
||||
static void app_frame(void)
|
||||
{
|
||||
tic_mem* tic = platform.studio->tic;
|
||||
|
||||
if(platform.studio->quit) exit(0);
|
||||
|
||||
tic80_input* input = &tic->ram.input;
|
||||
|
||||
input->gamepads.data = 0;
|
||||
handleKeyboard();
|
||||
platform.studio->tick();
|
||||
|
||||
sokol_gfx_draw(platform.studio->tic->screen);
|
||||
|
||||
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);
|
||||
|
||||
input->mouse.scrollx = input->mouse.scrolly = 0;
|
||||
}
|
||||
|
||||
static void handleKeydown(sapp_keycode keycode, bool down)
|
||||
{
|
||||
static const tic_keycode KeyboardCodes[] =
|
||||
{
|
||||
[SAPP_KEYCODE_INVALID] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_SPACE] = tic_key_space,
|
||||
[SAPP_KEYCODE_APOSTROPHE] = tic_key_apostrophe,
|
||||
[SAPP_KEYCODE_COMMA] = tic_key_comma,
|
||||
[SAPP_KEYCODE_MINUS] = tic_key_minus,
|
||||
[SAPP_KEYCODE_PERIOD] = tic_key_period,
|
||||
[SAPP_KEYCODE_SLASH] = tic_key_slash,
|
||||
[SAPP_KEYCODE_0] = tic_key_0,
|
||||
[SAPP_KEYCODE_1] = tic_key_1,
|
||||
[SAPP_KEYCODE_2] = tic_key_2,
|
||||
[SAPP_KEYCODE_3] = tic_key_3,
|
||||
[SAPP_KEYCODE_4] = tic_key_4,
|
||||
[SAPP_KEYCODE_5] = tic_key_5,
|
||||
[SAPP_KEYCODE_6] = tic_key_6,
|
||||
[SAPP_KEYCODE_7] = tic_key_7,
|
||||
[SAPP_KEYCODE_8] = tic_key_8,
|
||||
[SAPP_KEYCODE_9] = tic_key_9,
|
||||
[SAPP_KEYCODE_SEMICOLON] = tic_key_semicolon,
|
||||
[SAPP_KEYCODE_EQUAL] = tic_key_equals,
|
||||
[SAPP_KEYCODE_A] = tic_key_a,
|
||||
[SAPP_KEYCODE_B] = tic_key_b,
|
||||
[SAPP_KEYCODE_C] = tic_key_c,
|
||||
[SAPP_KEYCODE_D] = tic_key_d,
|
||||
[SAPP_KEYCODE_E] = tic_key_e,
|
||||
[SAPP_KEYCODE_F] = tic_key_f,
|
||||
[SAPP_KEYCODE_G] = tic_key_g,
|
||||
[SAPP_KEYCODE_H] = tic_key_h,
|
||||
[SAPP_KEYCODE_I] = tic_key_i,
|
||||
[SAPP_KEYCODE_J] = tic_key_j,
|
||||
[SAPP_KEYCODE_K] = tic_key_k,
|
||||
[SAPP_KEYCODE_L] = tic_key_l,
|
||||
[SAPP_KEYCODE_M] = tic_key_m,
|
||||
[SAPP_KEYCODE_N] = tic_key_n,
|
||||
[SAPP_KEYCODE_O] = tic_key_o,
|
||||
[SAPP_KEYCODE_P] = tic_key_p,
|
||||
[SAPP_KEYCODE_Q] = tic_key_q,
|
||||
[SAPP_KEYCODE_R] = tic_key_r,
|
||||
[SAPP_KEYCODE_S] = tic_key_s,
|
||||
[SAPP_KEYCODE_T] = tic_key_t,
|
||||
[SAPP_KEYCODE_U] = tic_key_u,
|
||||
[SAPP_KEYCODE_V] = tic_key_v,
|
||||
[SAPP_KEYCODE_W] = tic_key_w,
|
||||
[SAPP_KEYCODE_X] = tic_key_x,
|
||||
[SAPP_KEYCODE_Y] = tic_key_y,
|
||||
[SAPP_KEYCODE_Z] = tic_key_z,
|
||||
[SAPP_KEYCODE_LEFT_BRACKET] = tic_key_leftbracket,
|
||||
[SAPP_KEYCODE_BACKSLASH] = tic_key_backslash,
|
||||
[SAPP_KEYCODE_RIGHT_BRACKET] = tic_key_rightbracket,
|
||||
[SAPP_KEYCODE_GRAVE_ACCENT] = tic_key_grave,
|
||||
[SAPP_KEYCODE_WORLD_1] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_WORLD_2] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_ESCAPE] = tic_key_escape,
|
||||
[SAPP_KEYCODE_ENTER] = tic_key_return,
|
||||
[SAPP_KEYCODE_TAB] = tic_key_tab,
|
||||
[SAPP_KEYCODE_BACKSPACE] = tic_key_backspace,
|
||||
[SAPP_KEYCODE_INSERT] = tic_key_insert,
|
||||
[SAPP_KEYCODE_DELETE] = tic_key_delete,
|
||||
[SAPP_KEYCODE_RIGHT] = tic_key_right,
|
||||
[SAPP_KEYCODE_LEFT] = tic_key_left,
|
||||
[SAPP_KEYCODE_DOWN] = tic_key_down,
|
||||
[SAPP_KEYCODE_UP] = tic_key_up,
|
||||
[SAPP_KEYCODE_PAGE_UP] = tic_key_pageup,
|
||||
[SAPP_KEYCODE_PAGE_DOWN] = tic_key_pagedown,
|
||||
[SAPP_KEYCODE_HOME] = tic_key_home,
|
||||
[SAPP_KEYCODE_END] = tic_key_end,
|
||||
[SAPP_KEYCODE_CAPS_LOCK] = tic_key_capslock,
|
||||
[SAPP_KEYCODE_SCROLL_LOCK] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_NUM_LOCK] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_PRINT_SCREEN] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_PAUSE] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_F1] = tic_key_f1,
|
||||
[SAPP_KEYCODE_F2] = tic_key_f2,
|
||||
[SAPP_KEYCODE_F3] = tic_key_f3,
|
||||
[SAPP_KEYCODE_F4] = tic_key_f4,
|
||||
[SAPP_KEYCODE_F5] = tic_key_f5,
|
||||
[SAPP_KEYCODE_F6] = tic_key_f6,
|
||||
[SAPP_KEYCODE_F7] = tic_key_f7,
|
||||
[SAPP_KEYCODE_F8] = tic_key_f8,
|
||||
[SAPP_KEYCODE_F9] = tic_key_f9,
|
||||
[SAPP_KEYCODE_F10] = tic_key_f10,
|
||||
[SAPP_KEYCODE_F11] = tic_key_f11,
|
||||
[SAPP_KEYCODE_F12] = tic_key_f12,
|
||||
[SAPP_KEYCODE_F13] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_F14] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_F15] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_F16] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_F17] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_F18] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_F19] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_F20] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_F21] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_F22] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_F23] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_F24] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_F25] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_KP_0] = tic_key_0,
|
||||
[SAPP_KEYCODE_KP_1] = tic_key_1,
|
||||
[SAPP_KEYCODE_KP_2] = tic_key_2,
|
||||
[SAPP_KEYCODE_KP_3] = tic_key_3,
|
||||
[SAPP_KEYCODE_KP_4] = tic_key_4,
|
||||
[SAPP_KEYCODE_KP_5] = tic_key_5,
|
||||
[SAPP_KEYCODE_KP_6] = tic_key_6,
|
||||
[SAPP_KEYCODE_KP_7] = tic_key_7,
|
||||
[SAPP_KEYCODE_KP_8] = tic_key_8,
|
||||
[SAPP_KEYCODE_KP_9] = tic_key_9,
|
||||
[SAPP_KEYCODE_KP_DECIMAL] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_KP_DIVIDE] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_KP_MULTIPLY] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_KP_SUBTRACT] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_KP_ADD] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_KP_ENTER] = tic_key_return,
|
||||
[SAPP_KEYCODE_KP_EQUAL] = tic_key_equals,
|
||||
[SAPP_KEYCODE_LEFT_SHIFT] = tic_key_shift,
|
||||
[SAPP_KEYCODE_LEFT_CONTROL] = tic_key_ctrl,
|
||||
[SAPP_KEYCODE_LEFT_ALT] = tic_key_alt,
|
||||
[SAPP_KEYCODE_LEFT_SUPER] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_RIGHT_SHIFT] = tic_key_shift,
|
||||
[SAPP_KEYCODE_RIGHT_CONTROL] = tic_key_ctrl,
|
||||
[SAPP_KEYCODE_RIGHT_ALT] = tic_key_alt,
|
||||
[SAPP_KEYCODE_RIGHT_SUPER] = tic_key_unknown,
|
||||
[SAPP_KEYCODE_MENU] = tic_key_unknown,
|
||||
|
||||
};
|
||||
|
||||
tic_key key = KeyboardCodes[keycode];
|
||||
|
||||
if(key > tic_key_unknown)
|
||||
{
|
||||
// ALT+TAB fix
|
||||
if(key == tic_key_tab && platform.keyboard.state[tic_key_alt])
|
||||
platform.keyboard.state[tic_key_alt] = false;
|
||||
|
||||
platform.keyboard.state[key] = down;
|
||||
}
|
||||
}
|
||||
|
||||
static void processMouse(sapp_mousebutton btn, s32 down)
|
||||
{
|
||||
tic80_input* input = &platform.studio->tic->ram.input;
|
||||
|
||||
switch(btn)
|
||||
{
|
||||
case SAPP_MOUSEBUTTON_LEFT: input->mouse.left = down; break;
|
||||
case SAPP_MOUSEBUTTON_MIDDLE: input->mouse.middle = down; break;
|
||||
case SAPP_MOUSEBUTTON_RIGHT: input->mouse.right = down; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static void app_input(const sapp_event* event)
|
||||
{
|
||||
tic80_input* input = &platform.studio->tic->ram.input;
|
||||
|
||||
switch(event->type)
|
||||
{
|
||||
case SAPP_EVENTTYPE_KEY_DOWN:
|
||||
handleKeydown(event->key_code, true);
|
||||
break;
|
||||
case SAPP_EVENTTYPE_KEY_UP:
|
||||
handleKeydown(event->key_code, false);
|
||||
break;
|
||||
case SAPP_EVENTTYPE_MOUSE_MOVE:
|
||||
{
|
||||
struct {s32 x, y, w, h;}rect;
|
||||
sokol_calc_viewport(&rect.x, &rect.y, &rect.w, &rect.h);
|
||||
|
||||
s32 mx = -1, my = -1;
|
||||
if(rect.w) mx = ((s32)event->mouse_x - rect.x) * TIC80_FULLWIDTH / rect.w - TIC80_OFFSET_LEFT;
|
||||
if(rect.h) my = ((s32)event->mouse_y - rect.y) * TIC80_FULLHEIGHT / rect.h - TIC80_OFFSET_TOP;
|
||||
|
||||
input->mouse.x = mx >= 0 && mx < 0xff ? mx : 0xff;
|
||||
input->mouse.y = my >= 0 && my < 0xff ? my : 0xff;
|
||||
}
|
||||
break;
|
||||
case SAPP_EVENTTYPE_MOUSE_DOWN:
|
||||
processMouse(event->mouse_button, 1); break;
|
||||
break;
|
||||
case SAPP_EVENTTYPE_MOUSE_UP:
|
||||
processMouse(event->mouse_button, 0); break;
|
||||
break;
|
||||
case SAPP_EVENTTYPE_MOUSE_SCROLL:
|
||||
input->mouse.scrollx = event->scroll_x;
|
||||
input->mouse.scrolly = event->scroll_y;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
.high_dpi = true,
|
||||
};
|
||||
}
|
||||
34
src/system/sokol.h
Normal file
34
src/system/sokol.h
Normal file
@@ -0,0 +1,34 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sokol_app.h"
|
||||
#include "sokol_gfx.h"
|
||||
#include "sokol_time.h"
|
||||
#include "sokol_audio.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void sokol_calc_viewport(int* x, int* y, int* w, int* h);
|
||||
void sokol_gfx_init(int w, int h, int sx, int sy, bool integer_scale, bool portrait_top_align);
|
||||
void sokol_gfx_draw(const uint32_t* ptr);
|
||||
268
src/system/sokol_gfx.c
Normal file
268
src/system/sokol_gfx.c
Normal file
@@ -0,0 +1,268 @@
|
||||
#include "sokol.h"
|
||||
|
||||
static struct
|
||||
{
|
||||
sg_draw_state upscale_draw_state;
|
||||
sg_pass upscale_pass;
|
||||
sg_draw_state draw_state;
|
||||
int fb_width;
|
||||
int fb_height;
|
||||
int fb_aspect_scale_x;
|
||||
int fb_aspect_scale_y;
|
||||
|
||||
bool integer_scale;
|
||||
bool portrait_top_align;
|
||||
} sokol_gfx;
|
||||
|
||||
#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 sokol_gfx_init(int w, int h, int sx, int sy, bool integer_scale, bool portrait_top_align) {
|
||||
sokol_gfx.fb_width = w;
|
||||
sokol_gfx.fb_height = h;
|
||||
sokol_gfx.fb_aspect_scale_x = sx;
|
||||
sokol_gfx.fb_aspect_scale_y = sy;
|
||||
sokol_gfx.integer_scale = integer_scale;
|
||||
sokol_gfx.portrait_top_align = portrait_top_align;
|
||||
|
||||
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
|
||||
};
|
||||
sokol_gfx.upscale_draw_state.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||
.size = sizeof(verts),
|
||||
.content = verts,
|
||||
});
|
||||
sokol_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
|
||||
};
|
||||
sokol_gfx.draw_state.pipeline = sg_make_pipeline(&pip_desc);
|
||||
pip_desc.blend.depth_format = SG_PIXELFORMAT_NONE;
|
||||
sokol_gfx.upscale_draw_state.pipeline = sg_make_pipeline(&pip_desc);
|
||||
|
||||
/* a texture with the emulator's raw pixel data */
|
||||
sokol_gfx.upscale_draw_state.fs_images[0] = sg_make_image(&(sg_image_desc){
|
||||
.width = sokol_gfx.fb_width,
|
||||
.height = sokol_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 */
|
||||
sokol_gfx.draw_state.fs_images[0] = sg_make_image(&(sg_image_desc){
|
||||
.render_target = true,
|
||||
.width = 2*sokol_gfx.fb_width,
|
||||
.height = 2*sokol_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 */
|
||||
sokol_gfx.upscale_pass = sg_make_pass(&(sg_pass_desc){
|
||||
.color_attachments[0].image = sokol_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 } }
|
||||
};
|
||||
|
||||
void sokol_calc_viewport(int* x, int* y, int* w, int* h)
|
||||
{
|
||||
int vp_x = 0, vp_y = 0, vp_w = sapp_width(), vp_h = sapp_height();
|
||||
|
||||
if (vp_w * sokol_gfx.fb_height < vp_h * sokol_gfx.fb_width)
|
||||
{
|
||||
int discreteWidth = vp_w - (sokol_gfx.integer_scale ? vp_w % sokol_gfx.fb_width : 0);
|
||||
int discreteHeight = sokol_gfx.fb_height * discreteWidth / sokol_gfx.fb_width;
|
||||
|
||||
vp_x = (vp_w - discreteWidth) / 2;
|
||||
vp_y = sokol_gfx.portrait_top_align && vp_w < vp_h
|
||||
? 0
|
||||
: (vp_h - discreteHeight) / 2;
|
||||
|
||||
vp_w = discreteWidth;
|
||||
vp_h = discreteHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
int discreteHeight = vp_h - (sokol_gfx.integer_scale ? vp_h % sokol_gfx.fb_height : 0);
|
||||
int discreteWidth = sokol_gfx.fb_width * discreteHeight / sokol_gfx.fb_height;
|
||||
|
||||
vp_x = (vp_w - discreteWidth) / 2;
|
||||
vp_y = (vp_h - discreteHeight) / 2;
|
||||
|
||||
vp_w = discreteWidth;
|
||||
vp_h = discreteHeight;
|
||||
}
|
||||
|
||||
*x = vp_x;
|
||||
*y = vp_y;
|
||||
*w = vp_w;
|
||||
*h = vp_h;
|
||||
}
|
||||
|
||||
|
||||
static void apply_viewport(void) {
|
||||
|
||||
int vp_x, vp_y, vp_w, vp_h;
|
||||
sokol_calc_viewport(&vp_x, &vp_y, &vp_w, &vp_h);
|
||||
|
||||
sg_apply_viewport(vp_x, vp_y, vp_w, vp_h, true);
|
||||
}
|
||||
|
||||
void sokol_gfx_draw(const uint32_t* ptr) {
|
||||
|
||||
/* copy emulator pixel data into upscaling source texture */
|
||||
sg_update_image(sokol_gfx.upscale_draw_state.fs_images[0], &(sg_image_content){
|
||||
.subimage[0][0] = {
|
||||
.ptr = ptr,
|
||||
.size = sokol_gfx.fb_width*sokol_gfx.fb_height*sizeof ptr[0]
|
||||
}
|
||||
});
|
||||
|
||||
/* upscale the original framebuffer 2x with nearest filtering */
|
||||
sg_begin_pass(sokol_gfx.upscale_pass, &gfx_upscale_pass_action);
|
||||
sg_apply_draw_state(&sokol_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(&sokol_gfx.draw_state);
|
||||
sg_draw(0, 4, 1);
|
||||
sg_end_pass();
|
||||
sg_commit();
|
||||
}
|
||||
36
src/system/sokol_impl.c
Normal file
36
src/system/sokol_impl.c
Normal file
@@ -0,0 +1,36 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#define SOKOL_IMPL
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
#ifndef WM_MOUSEHWHEEL
|
||||
#define WM_MOUSEHWHEEL 0x020E
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include "sokol_app.h"
|
||||
#include "sokol_gfx.h"
|
||||
#include "sokol_time.h"
|
||||
#include "sokol_audio.h"
|
||||
28
src/system/sokol_impl.m
Normal file
28
src/system/sokol_impl.m
Normal file
@@ -0,0 +1,28 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#define SOKOL_IMPL
|
||||
|
||||
#include "sokol_app.h"
|
||||
#include "sokol_gfx.h"
|
||||
#include "sokol_time.h"
|
||||
#include "sokol_audio.h"
|
||||
Reference in New Issue
Block a user