Add SAF frontend

This commit is contained in:
Miloslav Ciz 2025-05-19 18:40:36 +02:00
parent bf2cd38337
commit c2bcf2d325
8 changed files with 131 additions and 40 deletions

View file

@ -65,31 +65,11 @@
{
return document.getElementById('canvas');
}
)(),
onRuntimeInitialized: function()
{
pressFunc = Module.cwrap('webButton','', ['number','number']);
}
)()
};
function down(button)
{
pressFunc(button,1);
}
function up(button)
{
pressFunc(button,0);
}
</script>
{{{ SCRIPT }}}
<table style="user-select:none; -moz-user-select: none; -ms-user-select:none; -webkit-user-select: none; -o-user-select:none;" onselectstart="return false;" unselectable="on">
<tr> <td></td> <td><button onmousedown="down(0)" ontouchstart="down(0)" onmouseup="up(0)" ontouchend="up(0)" onmouseout="up(0)" ontouchleave="(0)">U</button></td> <td></td> <td></td> <td><button onmousedown="down(4)" ontouchstart="down(4)" onmouseup="up(4)" ontouchend="up(4)" onmouseout="up(4)" ontouchleave="(4)">A</button></td> <td></td> <td></td> </tr>
<tr> <td><button onmousedown="down(3)" ontouchstart="down(3)" onmouseup="up(3)" ontouchend="up(3)" onmouseout="up(3)" ontouchleave="(3)">L</button></td> <td></td> <td><button onmousedown="down(1)" ontouchstart="down(1)" onmouseup="up(1)" ontouchend="up(1)" onmouseout="up(1)" ontouchleave="(1)">R</button></td> <td></td> <td></td> <td><button onmousedown="down(5)" ontouchstart="down(5)" onmouseup="up(5)" ontouchend="up(5)" onmouseout="up(5)" ontouchleave="(5)">B</button></td> <td></td> </tr>
<tr> <td></td> <td><button onmousedown="down(2)" ontouchstart="down(2)" onmouseup="up(2)" ontouchend="up(2)" onmouseout="up(2)" ontouchleave="(2)">D</button></td> <td></td> <td></td> <td></td> <td></td> <td></td> </tr>
</table>
</body>
</html>

View file

@ -66,6 +66,10 @@ void LCR_audioSetEngineIntensity(uint8_t value)
*/
void LCR_audioPlaySound(uint8_t sound)
{
#ifdef LCR_PLAY_SOUND_CALLBACK
LCR_PLAY_SOUND_CALLBACK(sound)
#endif
LCR_LOG2("playing sound");
LCR_audio.soundPlayed = sound;
LCR_audio.soundPlayedFrame = 0;

1
data
View file

@ -142,3 +142,4 @@ details
#RLCtiny5 00'10'362;00LCtiny5;5c14d8b6 0000314:00a1:0179:00a1:0089:0071:0093:0031:00c3:0041:0059:0031:0023:0161:0033:0081:0083:0051:0049:0131:0053:0091:0093:0041:00a3:00d1:0063:0051:0093:0041:0293:00a1:0149:0031
#BLCtiny5;
#RLCtiny5 00'09'240;00LCtiny5;5c14d8b6 0000280:0011:00b3:0051:0049:0061:0099:0091:0059:0041:0059:0041:0079:0021:0093:0061:0059:0033:0181:0119:0051:0079:0051:0033:0071:00b3:0091:0033:0071:0043:0031:0033:0051:03d3:0031:0079
#RLCtiny1 00'13'695;00LCtiny1;ae1ab677 0000415:0011:0093:0041:00a9:0041:0119:0031:0073:0031:0059:0031:0063:0021:01a9:00b1:0089:0041:01b3:0051:0023:00b1:0065:0041:00e9:01d1:0029:0171:0083:00f1:0010:0201:0049:0161:0033:0111:0049:00a1:0039:0071:00b9:0011:0183

80
frontend_saf.c Normal file
View file

@ -0,0 +1,80 @@
/*
SAF frontend for Licar.
*/
#define SAF_PLATFORM_SDL2
#define SAF_SETTING_ENABLE_SAVES 0
#define SAF_PROGRAM_NAME "Licar"
#include "saf.h"
#define LCR_SETTING_RESOLUTION_X SAF_SCREEN_WIDTH
#define LCR_SETTING_RESOLUTION_Y SAF_SCREEN_HEIGHT
#define LCR_SETTING_FPS SAF_FPS
#define LCR_SETTING_MUSIC 0
#define LCR_SETTING_ENABLE_DATA_FILE 0
#define LCR_SETTING_332_COLOR 1
#define LCR_SETTING_SKY_SIZE 1
#define LCR_SETTING_CAR_ANIMATION_SUBDIVIDE 0
#define LCR_PLAY_SOUND_CALLBACK(s) playSound(s);
void playSound(uint8_t sound);
#include "game.h"
void playSound(uint8_t sound)
{
switch (sound)
{
case LCR_SOUND_CLICK: SAF_playSound(SAF_SOUND_CLICK); break;
case LCR_SOUND_CRASH_SMALL: SAF_playSound(SAF_SOUND_BUMP); break;
case LCR_SOUND_CRASH_BIG: SAF_playSound(SAF_SOUND_BOOM); break;
case LCR_SOUND_FAN: SAF_playSound(SAF_SOUND_BEEP); break;
case LCR_SOUND_ACCELERATOR: SAF_playSound(SAF_SOUND_BEEP); break;
default: break;
}
}
void LCR_drawPixel(unsigned long index, uint16_t color)
{
SAF_drawPixel(index % SAF_SCREEN_WIDTH,index / SAF_SCREEN_WIDTH,color);
}
char LCR_getNextDataFileChar(void)
{
return 0;
}
void LCR_appendDataStr(const char *str)
{
}
uint8_t LCR_keyPressed(uint8_t key)
{
switch (key)
{
case LCR_KEY_UP: return SAF_buttonPressed(SAF_BUTTON_UP); break;
case LCR_KEY_RIGHT: return SAF_buttonPressed(SAF_BUTTON_RIGHT); break;
case LCR_KEY_DOWN: return SAF_buttonPressed(SAF_BUTTON_DOWN); break;
case LCR_KEY_LEFT: return SAF_buttonPressed(SAF_BUTTON_LEFT); break;
case LCR_KEY_A: return SAF_buttonPressed(SAF_BUTTON_A); break;
case LCR_KEY_B: return SAF_buttonPressed(SAF_BUTTON_B); break;
default: break;
}
return 0;
}
void LCR_sleep(uint16_t timeMs)
{
}
void SAF_init(void)
{
LCR_gameInit(0,0);
}
uint8_t SAF_loop(void)
{
return LCR_gameStep(SAF_time());
}

View file

@ -148,13 +148,6 @@ void LCR_sleep(uint16_t timeMs)
#endif
}
#ifdef __EMSCRIPTEN__
void webButton(uint8_t key, uint8_t down) // HTML button pressed
{
// TODO
}
#endif
void LCR_drawPixel(unsigned long index, uint16_t color)
{
screen[index] = color;

28
game.h
View file

@ -176,6 +176,15 @@ uint8_t LCR_gameGetNextAudioSample(void);
#define LCR_LOADING_COMMAND ;
#endif
/**
This macro may be redefined to a command that will be executed upon certain
sound. This can be used if the platform can't play the game's 8 bit audio but
wants to play it's own sounds, e.g. beeps.
*/
#ifndef LCR_PLAY_SOUND_CALLBACK
#define LCR_PLAY_SOUND_CALLBACK(s) ;
#endif
/*
To make the game log FPS define a macro named LCR_FPS_GET_MS to a command that
evaluates to the current number of milliseconds since some given time. It
@ -1196,7 +1205,7 @@ void LCR_gameTimeToStr(uint32_t timeMS, char *str)
void LCR_gameDrawPopupMessage(void)
{
#define _TEXT_SIZE 5
#define _TEXT_SIZE 1 + 4 * (LCR_EFFECTIVE_RESOLUTION_Y > 96)
#define _OFFSET_V (LCR_EFFECTIVE_RESOLUTION_Y / 8)
int textH = LCR_rendererComputeTextHeight(_TEXT_SIZE);
@ -1267,28 +1276,31 @@ void LCR_gameDraw3DView(void)
str[2] = '0' + val % 10;
str[3] = 0;
#define _FONT_SIZE (1 + (LCR_EFFECTIVE_RESOLUTION_Y > 96))
LCR_rendererDrawText(str,LCR_EFFECTIVE_RESOLUTION_X - // speed (bot., right)
LCR_rendererComputeTextWidth(str,2) - LCR_GUI_GAP,
LCR_EFFECTIVE_RESOLUTION_Y - LCR_rendererComputeTextHeight(2) -
LCR_GUI_GAP,0,2);
LCR_rendererComputeTextWidth(str,_FONT_SIZE) - LCR_GUI_GAP,
LCR_EFFECTIVE_RESOLUTION_Y - LCR_rendererComputeTextHeight(_FONT_SIZE) -
LCR_GUI_GAP,0,_FONT_SIZE);
LCR_gameTimeToStr(LCR_timeTicksToMS(LCR_game.runTime),str);
if (LCR_game.state != LCR_GAME_STATE_RUN_FINISHED)
LCR_rendererDrawText(str,LCR_GUI_GAP,LCR_EFFECTIVE_RESOLUTION_Y -
2 * (LCR_rendererComputeTextHeight(2) + LCR_GUI_GAP),0,2);
2 * (LCR_rendererComputeTextHeight(_FONT_SIZE) + LCR_GUI_GAP),0,_FONT_SIZE);
else
LCR_rendererDrawText(str,((LCR_EFFECTIVE_RESOLUTION_X -
LCR_rendererComputeTextWidth(str,4)) / 2),
LCR_EFFECTIVE_RESOLUTION_Y / 2,
LCR_game.runTime <= LCR_currentMap.targetTime ?
LCR_CONVERT_COLOR(0x0700) : LCR_CONVERT_COLOR(0x4208),4);
LCR_CONVERT_COLOR(0x0700) : LCR_CONVERT_COLOR(0x4208),2 * _FONT_SIZE);
LCR_gameTimeToStr(LCR_currentMap.targetTime * LCR_RACING_TICK_MS,str);
LCR_rendererDrawText(str,LCR_GUI_GAP,LCR_EFFECTIVE_RESOLUTION_Y -
LCR_rendererComputeTextHeight(2) - LCR_GUI_GAP,
LCR_CONVERT_COLOR(0x4208),2);
LCR_rendererComputeTextHeight(_FONT_SIZE) - LCR_GUI_GAP,
LCR_CONVERT_COLOR(0x4208),_FONT_SIZE);
#undef _FONT_SIZE
}
void LCR_gameSaveReplay(void)

View file

@ -40,10 +40,17 @@ elif [ $PLATFORM = "csfml" ]; then
# - csfml (dev) package
COMMAND="${COMPILER} ${C_FLAGS} frontend_csfml.c -lcsfml-graphics -lcsfml-window -lcsfml-system -lcsfml-audio"
elif [ $PLATFORM = "saf" ]; then
# SAF build, requires:
# - saf.h
# - backend libraries (SDL2 by default)
SDL_FLAGS=`sdl2-config --cflags --libs`
COMMAND="${COMPILER} ${C_FLAGS} frontend_saf.c -lcsfml-graphics -I/use/local/include ${SDL_FLAGS}"
elif [ $PLATFORM = "emscripten" ]; then
# emscripten (browser Javascript) build, requires:
# - emscripten
COMMAND="../emsdk/upstream/emscripten/emcc ./frontend_sdl.c -s USE_SDL=2 -O3 -lopenal --shell-file HTMLshell.html -o licar.html -s EXPORTED_FUNCTIONS='[\"_main\",\"_webButton\"]' -s EXPORTED_RUNTIME_METHODS='[\"ccall\",\"cwrap\"]'"
COMMAND="../emsdk/upstream/emscripten/emcc ./frontend_sdl.c -s USE_SDL=2 -O3 -lopenal --shell-file HTMLshell.html -o licar.html -s EXPORTED_FUNCTIONS='[\"_main\"]' -s EXPORTED_RUNTIME_METHODS='[\"ccall\",\"cwrap\"]'"
else
echo "unknown frontend"
fi

View file

@ -34,6 +34,7 @@
#define S3L_Z_BUFFER 1
#define LCR_FONT_PIXEL_SIZE (1 + LCR_EFFECTIVE_RESOLUTION_X / 512)
#define LCR_ANIMATE_CAR (LCR_SETTING_CAR_ANIMATION_SUBDIVIDE != 0)
#define LCR_ANT_RESOLUTION (LCR_EFFECTIVE_RESOLUTION_Y <= 96)
#if LCR_SETTING_POTATO_GRAPHICS
#undef S3L_PERSPECTIVE_CORRECTION
@ -1951,8 +1952,14 @@ void LCR_rendererBlitImage(uint8_t index, unsigned int x, unsigned int y,
void LCR_rendererDrawMenu(const char *tabName,const char **items,
unsigned char itemCount,char selectedItem, char scroll)
{
#if !LCR_ANT_RESOLUTION
int stripHeight = (2 * LCR_EFFECTIVE_RESOLUTION_Y) / 7;
int stripHeight2 = LCR_EFFECTIVE_RESOLUTION_Y / 9;
#else
int stripHeight = 6;
int stripHeight2 = 0;
#endif
int i = 0;
#if !(LCR_SETTING_POTATO_GRAPHICS || LCR_SETTING_332_COLOR)
uint16_t effect = LCR_renderer.frame >> 1;
@ -1974,7 +1981,7 @@ void LCR_rendererDrawMenu(const char *tabName,const char **items,
++i;
}
#if LCR_SETTING_POTATO_GRAPHICS
#if LCR_SETTING_POTATO_GRAPHICS || LCR_ANT_RESOLUTION
while (i < stripHeight * LCR_EFFECTIVE_RESOLUTION_X)
{
LCR_gameDrawPixel(i,LCR_CONVERT_COLOR(0x73ae));
@ -2041,23 +2048,30 @@ void LCR_rendererDrawMenu(const char *tabName,const char **items,
(j == 0 || j == selectedItem + 1) ? LCR_CONVERT_COLOR(0xf79c) :
textColor,_FONT_SIZE);
#if LCR_ANT_RESOLUTION
i += LCR_rendererComputeTextHeight(_FONT_SIZE) + 3 * LCR_FONT_PIXEL_SIZE;
#else
if (j == 0)
i = stripHeight + stripHeight2;
i += LCR_rendererComputeTextHeight(_FONT_SIZE) + 6 * LCR_FONT_PIXEL_SIZE;
#endif
#undef _FONT_SIZE
}
#if !LCR_SETTING_POTATO_GRAPHICS
#if (!LCR_SETTING_POTATO_GRAPHICS) && (!LCR_ANT_RESOLUTION)
LCR_rendererBlitImage(21,(LCR_EFFECTIVE_RESOLUTION_X -
LCR_IMAGE_SIZE * (stripHeight / LCR_IMAGE_SIZE)) / 2,0,
stripHeight / LCR_IMAGE_SIZE,LCR_CONVERT_COLOR(0xffff));
#endif
#if !LCR_ANT_RESOLUTION
LCR_rendererDrawText(LCR_texts[LCR_TEXTS_VERSION],
LCR_EFFECTIVE_RESOLUTION_X / 64,LCR_EFFECTIVE_RESOLUTION_Y / 64,
LCR_CONVERT_COLOR(0xe71c),2);
#endif
LCR_renderer.frame++;
}