Enable compiling to wasm

This commit is contained in:
mattiasgustavsson 2024-03-07 18:37:31 +01:00
parent 1d1a4230e6
commit b97424b84e
12 changed files with 335 additions and 108 deletions

50
doom.c
View File

@ -8,16 +8,42 @@
#pragma warning( disable: 4133 ) #pragma warning( disable: 4133 )
#pragma warning( disable: 4142 ) #pragma warning( disable: 4142 )
#ifdef _WIN32
#define strcasecmp stricmp #define strcasecmp stricmp
#define strncasecmp strnicmp #define strncasecmp strnicmp
#else
#include <strings.h>
#endif
#define CONCAT_IMPL( x, y ) x##y #define CONCAT_IMPL( x, y ) x##y
#define CONCAT( x, y ) CONCAT_IMPL( x, y ) #define CONCAT( x, y ) CONCAT_IMPL( x, y )
#define rcsid CONCAT( rcsid, __COUNTER__ ) #define rcsid CONCAT( rcsid, __COUNTER__ )
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
int doom_access( char const* _FileName, int _AccessMode ) {
FILE* f = fopen( _FileName, "rb" );
if( f ) {
fclose(f);
return 0;
}
return 1;
}
#ifdef _WIN32
#include "libs_win32/unistd.h"
#else
#include <unistd.h>
#endif
#undef access
#define access doom_access
#define open doom_open #define open doom_open
#define close doom_close #define close doom_close
#include "libs_win32/unistd.h"
#include "linuxdoom-1.10/am_map.c" #include "linuxdoom-1.10/am_map.c"
#include "linuxdoom-1.10/doomdef.c" #include "linuxdoom-1.10/doomdef.c"
#include "linuxdoom-1.10/doomstat.c" #include "linuxdoom-1.10/doomstat.c"
@ -31,7 +57,6 @@
#include "linuxdoom-1.10/hu_lib.c" #include "linuxdoom-1.10/hu_lib.c"
#include "linuxdoom-1.10/hu_stuff.c" #include "linuxdoom-1.10/hu_stuff.c"
#include "linuxdoom-1.10/info.c" #include "linuxdoom-1.10/info.c"
#include "linuxdoom-1.10/i_main.c"
#include "linuxdoom-1.10/m_argv.c" #include "linuxdoom-1.10/m_argv.c"
#include "linuxdoom-1.10/m_bbox.c" #include "linuxdoom-1.10/m_bbox.c"
#include "linuxdoom-1.10/m_cheat.c" #include "linuxdoom-1.10/m_cheat.c"
@ -86,7 +111,6 @@
#undef open #undef open
#undef close #undef close
#include <io.h>
#include "linuxdoom-1.10/m_menu.c" #include "linuxdoom-1.10/m_menu.c"
#include "linuxdoom-1.10/m_misc.c" #include "linuxdoom-1.10/m_misc.c"
#define strupr xstrupr #define strupr xstrupr
@ -105,7 +129,14 @@
#undef MINLONG #undef MINLONG
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <time.h>
#ifdef __wasm__
#define APP_WASM
#define WA_CORO_IMPLEMENT_NANOSLEEP
#else
#define APP_WINDOWS #define APP_WINDOWS
#endif
#define APP_LOG( ctx, level, message ) #define APP_LOG( ctx, level, message )
#define boolean HACK_TO_MAKE_BOOLEAN_NOT_BE_DEFINED #define boolean HACK_TO_MAKE_BOOLEAN_NOT_BE_DEFINED
#define APP_IMPLEMENTATION #define APP_IMPLEMENTATION
@ -118,6 +149,7 @@
#define CRTEMU_IMPLEMENTATION #define CRTEMU_IMPLEMENTATION
#include "libs_win32/crtemu.h" #include "libs_win32/crtemu.h"
#ifndef __wasm__
#define THREAD_IMPLEMENTATION #define THREAD_IMPLEMENTATION
#if defined( __TINYC__ ) #if defined( __TINYC__ )
typedef struct _RTL_CONDITION_VARIABLE { PVOID Ptr; } RTL_CONDITION_VARIABLE, *PRTL_CONDITION_VARIABLE; typedef struct _RTL_CONDITION_VARIABLE { PVOID Ptr; } RTL_CONDITION_VARIABLE, *PRTL_CONDITION_VARIABLE;
@ -128,6 +160,8 @@
#endif #endif
#include "libs_win32/thread.h" #include "libs_win32/thread.h"
#undef THREAD_IMPLEMENTATION #undef THREAD_IMPLEMENTATION
#endif
#undef boolean #undef boolean
#define MUS_IMPLEMENTATION #define MUS_IMPLEMENTATION
@ -147,6 +181,16 @@
#include "libs_win32/soundfont.c" #include "libs_win32/soundfont.c"
#ifdef __wasm__
WaCoro user_coro;
WA_EXPORT(user_thread_proc) int user_thread_proc( void* user_data ) {
D_DoomMain ();
return 0;
}
#endif
#include "linuxdoom-1.10/i_sound.c" #include "linuxdoom-1.10/i_sound.c"
#include "linuxdoom-1.10/i_video.c" #include "linuxdoom-1.10/i_video.c"
#include "linuxdoom-1.10/i_system.c" #include "linuxdoom-1.10/i_system.c"
#include "linuxdoom-1.10/i_main.c"

View File

@ -4296,7 +4296,7 @@ int app_run( int (*app_proc)( app_t*, void* ), void* user_data, void* memctx, vo
app_fatal_error( app, "OpenGL init fail" ); app_fatal_error( app, "OpenGL init fail" );
goto init_failed; goto init_failed;
} }
WaCoroInitNew( NULL, NULL, NULL, 0 ); //WaCoroInitNew( NULL, NULL, NULL, 0 );
result = app_proc( app, user_data ); result = app_proc( app, user_data );
init_failed: init_failed:

View File

@ -1749,8 +1749,8 @@ void crtemu_coordinates_window_to_bitmap( crtemu_t* crtemu, int width, int heigh
float yc = ( yp - 0.5f ) * 2.0f; float yc = ( yp - 0.5f ) * 2.0f;
xc *= 1.1f; xc *= 1.1f;
yc *= 1.1f; yc *= 1.1f;
//xc *= 1.0f + powf( ( fabsf( yc ) / 5.0f ), 2.0f); //xc *= 1.0f + powf( ( fabs( yc ) / 5.0f ), 2.0f);
//yc *= 1.0f + powf( ( fabsf( xc ) / 4.0f ), 2.0f); //yc *= 1.0f + powf( ( fabs( xc ) / 4.0f ), 2.0f);
float yt = ( yc >= 0.0f ? yc : -yc ) / 5.0f; float yt = ( yc >= 0.0f ? yc : -yc ) / 5.0f;
float xt = ( xc >= 0.0f ? xc : -xc ) / 4.0f; float xt = ( xc >= 0.0f ? xc : -xc ) / 4.0f;
xc *= 1.0f + ( yt * yt ); xc *= 1.0f + ( yt * yt );
@ -1806,8 +1806,8 @@ void crtemu_coordinates_window_to_bitmap( crtemu_t* crtemu, int width, int heigh
float yc = ( yp - 0.5f ) * 2.0f; float yc = ( yp - 0.5f ) * 2.0f;
xc *= 1.1f; xc *= 1.1f;
yc *= 1.1f; yc *= 1.1f;
//xc *= 1.0f + powf( ( fabsf( yc ) / 5.0f ), 2.0f); //xc *= 1.0f + powf( ( fabs( yc ) / 5.0f ), 2.0f);
//yc *= 1.0f + powf( ( fabsf( xc ) / 4.0f ), 2.0f); //yc *= 1.0f + powf( ( fabs( xc ) / 4.0f ), 2.0f);
float yt = ( yc >= 0.0f ? yc : -yc ) / 5.0f; float yt = ( yc >= 0.0f ? yc : -yc ) / 5.0f;
float xt = ( xc >= 0.0f ? xc : -xc ) / 4.0f; float xt = ( xc >= 0.0f ? xc : -xc ) / 4.0f;
xc *= 1.0f + ( yt * yt ); xc *= 1.0f + ( yt * yt );

View File

@ -877,7 +877,7 @@ void D_DoomMain (void)
if (M_CheckParm("-cdrom")) if (M_CheckParm("-cdrom"))
{ {
printf(D_CDROM); printf(D_CDROM);
mkdir("c:\\doomdata"); //mkdir("c:\\doomdata");
strcpy (basedefault,"c:/doomdata/default.cfg"); strcpy (basedefault,"c:/doomdata/default.cfg");
} }

View File

@ -31,6 +31,11 @@ rcsid[] = "$Id: i_main.c,v 1.4 1997/02/03 22:45:10 b1 Exp $";
#include "m_argv.h" #include "m_argv.h"
#include "d_main.h" #include "d_main.h"
int app_proc_thread()
{
return app_run( app_proc, 0, 0, 0, 0 );
}
int int
main main
( int argc, ( int argc,
@ -39,7 +44,25 @@ main
myargc = argc; myargc = argc;
myargv = argv; myargv = argv;
D_DoomMain (); #ifndef __wasm__
#if defined( __TINYC__ )
HMODULE kernel = LoadLibrary( "kernel32" );
InitializeConditionVariable = GetProcAddress( kernel, "InitializeConditionVariable");
WakeConditionVariable = GetProcAddress( kernel, "WakeConditionVariable");
SleepConditionVariableCS = GetProcAddress( kernel, "SleepConditionVariableCS");
#endif
thread_signal_init( &vblank_signal );
thread_mutex_init( &mus_mutex );
#endif
thread_atomic_int_store( &app_running, 1 );
#ifdef _WIN32
thread_create( app_proc_thread, 0, THREAD_STACK_SIZE_DEFAULT );
thread_signal_wait( &vblank_signal, THREAD_SIGNAL_WAIT_INFINITE );
D_DoomMain ();
#else
app_run( app_proc, 0, 0, 0, 0 );
#endif
return 0; return 0;
} }

View File

@ -1,4 +1,4 @@
#ifdef _WIN32 #if defined( _WIN32 ) || defined( __wasm__ )
#define SAMPLECOUNT 512 #define SAMPLECOUNT 512
#define NUM_CHANNELS 8 #define NUM_CHANNELS 8
@ -522,7 +522,9 @@ struct music_t {
int left_over; int left_over;
} music = { NULL, 1, 0 }; } music = { NULL, 1, 0 };
#ifndef __wasm__
thread_mutex_t mus_mutex; thread_mutex_t mus_mutex;
#endif
static void* musics[ 16 ]; static void* musics[ 16 ];
@ -574,7 +576,9 @@ void
I_PlaySong I_PlaySong
( int handle, ( int handle,
int looping ){ int looping ){
#ifndef __wasm__
thread_mutex_lock( &mus_mutex ); thread_mutex_lock( &mus_mutex );
#endif
if( music.mus ) { if( music.mus ) {
mus_destroy( music.mus ); mus_destroy( music.mus );
music.mus = NULL; music.mus = NULL;
@ -588,17 +592,23 @@ I_PlaySong
music.reset = 1; music.reset = 1;
} }
} }
#ifndef __wasm__
thread_mutex_unlock( &mus_mutex ); thread_mutex_unlock( &mus_mutex );
#endif
} }
// Stops a song over 3 seconds. // Stops a song over 3 seconds.
void I_StopSong(int handle){ void I_StopSong(int handle){
#ifndef __wasm__
thread_mutex_lock( &mus_mutex ); thread_mutex_lock( &mus_mutex );
#endif
// TODO: fadeout // TODO: fadeout
mus_destroy( music.mus ); mus_destroy( music.mus );
music.mus = NULL; music.mus = NULL;
music.left_over = 0; music.left_over = 0;
music.reset = 1; music.reset = 1;
#ifndef __wasm__
thread_mutex_unlock( &mus_mutex ); thread_mutex_unlock( &mus_mutex );
#endif
} }
// See above (register), then think backwards // See above (register), then think backwards
void I_UnRegisterSong(int handle){ void I_UnRegisterSong(int handle){
@ -610,11 +620,15 @@ void I_UnRegisterSong(int handle){
void render_music( short* sample_pairs, int sample_pairs_count, tsf* sound_font ) { void render_music( short* sample_pairs, int sample_pairs_count, tsf* sound_font ) {
#ifndef __wasm__
thread_mutex_lock( &mus_mutex ); thread_mutex_lock( &mus_mutex );
#endif
mus_t* mus = music.mus; mus_t* mus = music.mus;
if( !mus ) { if( !mus ) {
memset( sample_pairs, 0, sizeof( short ) * sample_pairs_count * 2 ); memset( sample_pairs, 0, sizeof( short ) * sample_pairs_count * 2 );
#ifndef __wasm__
thread_mutex_unlock( &mus_mutex ); thread_mutex_unlock( &mus_mutex );
#endif
return; return;
} }
if( music.reset ) { if( music.reset ) {
@ -638,7 +652,9 @@ void render_music( short* sample_pairs, int sample_pairs_count, tsf* sound_font
} }
if( left_over ) { if( left_over ) {
music.left_over = left_over; music.left_over = left_over;
#ifndef __wasm__
thread_mutex_unlock( &mus_mutex ); thread_mutex_unlock( &mus_mutex );
#endif
return; return;
} }
@ -733,7 +749,9 @@ void render_music( short* sample_pairs, int sample_pairs_count, tsf* sound_font
} }
} }
music.left_over = left_over; music.left_over = left_over;
#ifndef __wasm__
thread_mutex_unlock( &mus_mutex ); thread_mutex_unlock( &mus_mutex );
#endif
} }
#else #else

View File

@ -50,6 +50,7 @@ void I_ShutdownSound(void);
void I_SetChannels(); void I_SetChannels();
// Get raw data lump index for sound descriptor. // Get raw data lump index for sound descriptor.
struct sfxinfo_t;
int I_GetSfxLumpNum (struct sfxinfo_t* sfxinfo ); int I_GetSfxLumpNum (struct sfxinfo_t* sfxinfo );

View File

@ -20,7 +20,8 @@
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#if _WIN32 #if defined( _WIN32 ) || defined( __wasm__ )
#include "doomtype.h" #include "doomtype.h"
#include "doomdef.h" #include "doomdef.h"
#include "doomstat.h" #include "doomstat.h"
@ -51,12 +52,23 @@ byte* I_ZoneBase (int *size)
// returns current time in tics. // returns current time in tics.
int I_GetTime (void) int I_GetTime (void)
{ {
LARGE_INTEGER large; #ifdef _WIN32
LARGE_INTEGER large;
LARGE_INTEGER freq; LARGE_INTEGER freq;
QueryPerformanceCounter( &large ); QueryPerformanceCounter( &large );
QueryPerformanceFrequency( &freq ); QueryPerformanceFrequency( &freq );
return large.QuadPart * TICRATE / freq.QuadPart; return large.QuadPart * TICRATE / freq.QuadPart;
#else
struct timespec t;
clock_gettime( CLOCK_MONOTONIC_RAW, &t );
uint64_t curr_clock = (FRAMETIMER_U64)t.tv_sec;
curr_clock *= 1000000000ull;
curr_clock += (FRAMETIMER_U64)t.tv_nsec;
return (int)( ( curr_clock * TICRATE ) / 1000000000 );
#endif
} }

View File

@ -21,7 +21,7 @@
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifdef _WIN32 #if defined( _WIN32 ) || defined( __wasm__ )
#include "doomtype.h" #include "doomtype.h"
#include <inttypes.h> #include <inttypes.h>
@ -36,14 +36,17 @@
uint8_t app_palette[256 * 3]; uint8_t app_palette[256 * 3];
uint8_t* app_screen; uint8_t* app_screen;
#ifndef __wasm__
thread_atomic_int_t app_running; thread_atomic_int_t app_running;
#else
int app_running;
int thread_atomic_int_load( int* v ) { return *v; };
void thread_atomic_int_store( int* v, int x ) { *v = x; };
#endif
event_t event_queue[ 256 ] = {0}; #ifndef __wasm__
int events_count = 0;
thread_mutex_t event_mutex;
thread_signal_t vblank_signal; thread_signal_t vblank_signal;
#endif
void sound_callback( APP_S16* sample_pairs, int sample_pairs_count, void* user_data ) { void sound_callback( APP_S16* sample_pairs, int sample_pairs_count, void* user_data ) {
tsf* sound_font = (tsf*) user_data; tsf* sound_font = (tsf*) user_data;
if( sample_pairs_count == SAMPLECOUNT * 4 ) { if( sample_pairs_count == SAMPLECOUNT * 4 ) {
@ -57,16 +60,55 @@ void sound_callback( APP_S16* sample_pairs, int sample_pairs_count, void* user_d
render_music( sample_pairs, sample_pairs_count, sound_font ); render_music( sample_pairs, sample_pairs_count, sound_font );
} }
int counter = 0; static int keystate[ APP_KEYCOUNT ] = { 0 };
int mouserelx;
int mouserely;
int g_tickcount = 0;
int app_proc( app_t* app, void* user_data ) int app_proc( app_t* app, void* user_data )
{ {
app_screenmode( app, APP_SCREENMODE_FULLSCREEN ); #ifndef __wasm__
app_screenmode( app, APP_SCREENMODE_FULLSCREEN );
#else
app_screenmode( app, APP_SCREENMODE_WINDOW );
#endif
app_interpolation( app, APP_INTERPOLATION_NONE ); app_interpolation( app, APP_INTERPOLATION_NONE );
app_displays_t displays = app_displays( app );
if( displays.count > 0 ) {
int disp = 0;
for( int i = 0; i < displays.count; ++i ) {
if( displays.displays[ i ].x == 0 && displays.displays[ i ].y == 0 ) {
disp = i;
break;
}
}
int scrwidth = displays.displays[ disp ].width - 80;
int scrheight = displays.displays[ disp ].height - 80;
int aspect_width = (int)( ( scrheight * 4.25f ) / 3 );
int aspect_height = (int)( ( scrwidth * 3 ) / 4.25f );
int target_width, target_height;
if( aspect_height <= scrheight ) {
target_width = scrwidth;
target_height = aspect_height;
} else {
target_width = aspect_width;
target_height = scrheight;
}
int x = displays.displays[ disp ].x + ( displays.displays[ disp ].width - target_width ) / 2;
int y = displays.displays[ disp ].y + ( displays.displays[ disp ].height - target_height ) / 2;
int w = target_width;
int h = target_height;
app_window_pos( app, x, y );
app_window_size( app, w, h );
}
uint8_t* screen_buffer_xbgr = (uint8_t*)malloc( SCREENWIDTH * SCREENHEIGHT * 4 ); uint8_t* screen_buffer_xbgr = (uint8_t*)malloc( SCREENWIDTH * SCREENHEIGHT * 4 );
frametimer_t* frametimer = frametimer_create( 0); frametimer_t* frametimer = frametimer_create( 0);
frametimer_lock_rate( frametimer, 60 ); frametimer_lock_rate( frametimer, TICRATE );
crtemu_t* crtemu = crtemu_create( CRTEMU_TYPE_LITE,0 ); crtemu_t* crtemu = crtemu_create( CRTEMU_TYPE_LITE,0 );
@ -76,8 +118,33 @@ int app_proc( app_t* app, void* user_data )
tsf* sound_font = tsf_load_memory( soundfont, sizeof( soundfont ) ); tsf* sound_font = tsf_load_memory( soundfont, sizeof( soundfont ) );
app_sound( app, SAMPLECOUNT * 4 * 2, sound_callback, sound_font ); app_sound( app, SAMPLECOUNT * 4 * 2, sound_callback, sound_font );
#ifndef __wasm__
thread_signal_raise( &vblank_signal );
#endif
#ifdef __wasm__
// WebAssembly has no real threads so we use coroutines which can switch context between two
// callstacks to simulate the behavior from native platforms
user_coro = WaCoroInitNew( user_thread_proc, "user_thread_proc", 0, 0 );
WaCoroSwitch(user_coro);
#endif
while( thread_atomic_int_load(&app_running) && app_yield( app ) != APP_STATE_EXIT_REQUESTED ) while( thread_atomic_int_load(&app_running) && app_yield( app ) != APP_STATE_EXIT_REQUESTED )
{ {
app_input_t input = app_input( app );
for( int i = 0; i < input.count; ++i ) {
if( input.events[i].type==APP_INPUT_KEY_DOWN ) {
if( input.events[i].data.key < APP_KEYCOUNT ) {
keystate[input.events[i].data.key] = 1;
}
} else if( input.events[i].type==APP_INPUT_KEY_UP ) {
if( input.events[i].data.key < APP_KEYCOUNT ) {
keystate[input.events[i].data.key] = 0;
}
} else if( input.events[i].type==APP_INPUT_MOUSE_DELTA ) {
mouserelx = (int)(input.events[i].data.mouse_delta.x*8.0f);
mouserely = (int)(input.events[i].data.mouse_delta.y*8.0f);
}
}
if( app_screen ) if( app_screen )
{ {
for( int i = 0; i < SCREENWIDTH * SCREENHEIGHT; ++i ) for( int i = 0; i < SCREENWIDTH * SCREENHEIGHT; ++i )
@ -91,12 +158,15 @@ int app_proc( app_t* app, void* user_data )
} }
frametimer_update( frametimer ); frametimer_update( frametimer );
++counter; ++g_tickcount;
#ifndef __wasm__
thread_signal_raise( &vblank_signal ); thread_signal_raise( &vblank_signal );
#endif
crtemu_present( crtemu, ( counter * 1000000ULL) / 60, (APP_U32*)screen_buffer_xbgr, SCREENWIDTH, SCREENHEIGHT, 0xffffff, 0x000000 ); crtemu_present( crtemu, ( g_tickcount * 1000000ULL) / TICRATE, (APP_U32*)screen_buffer_xbgr, SCREENWIDTH, SCREENHEIGHT, 0xffffff, 0x000000 );
app_present( app, 0, 0, 0, 0xffffffff, 0x00000000); app_present( app, 0, 0, 0, 0xffffffff, 0x00000000);
#ifdef __wasm__
WaCoroSwitch(user_coro);
#endif
} }
app_sound( app, 0, NULL, NULL ); app_sound( app, 0, NULL, NULL );
tsf_close( sound_font ); tsf_close( sound_font );
@ -104,28 +174,11 @@ int app_proc( app_t* app, void* user_data )
return 0; return 0;
} }
int app_proc_thread()
{
thread_mutex_init( &mus_mutex );
return app_run( app_proc, 0, 0, 0, 0 );
thread_mutex_term( &mus_mutex );
}
void I_InitGraphics (void) void I_InitGraphics (void)
{ {
#if defined( __TINYC__ )
HMODULE kernel = LoadLibrary( "kernel32" );
InitializeConditionVariable = GetProcAddress( kernel, "InitializeConditionVariable");
WakeConditionVariable = GetProcAddress( kernel, "WakeConditionVariable");
SleepConditionVariableCS = GetProcAddress( kernel, "SleepConditionVariableCS");
#endif
thread_mutex_init( &event_mutex );
thread_signal_init( &vblank_signal );
app_screen = (uint8_t*)malloc( SCREENWIDTH * SCREENHEIGHT ); app_screen = (uint8_t*)malloc( SCREENWIDTH * SCREENHEIGHT );
thread_atomic_int_store( &app_running, 1 );
thread_create( app_proc_thread, 0, THREAD_STACK_SIZE_DEFAULT );
} }
void I_ShutdownGraphics(void) void I_ShutdownGraphics(void)
@ -135,7 +188,6 @@ void I_ShutdownGraphics(void)
free( app_screen ); free( app_screen );
app_screen = 0; app_screen = 0;
thread_signal_term( &vblank_signal );
} }
// Takes full 8 bit values. // Takes full 8 bit values.
@ -158,6 +210,9 @@ void I_SetPalette (byte* palette)
void I_UpdateNoBlit (void) void I_UpdateNoBlit (void)
{ {
#ifdef __wasm__
WaCoroSwitch(0);
#endif
} }
void I_FinishUpdate (void) void I_FinishUpdate (void)
@ -175,49 +230,50 @@ void I_FinishUpdate (void)
// Can call D_PostEvent. // Can call D_PostEvent.
void I_StartTic (void) void I_StartTic (void)
{ {
static int prev[ 256 ] = { 0 }; static int prev[ APP_KEYCOUNT ] = { 0 };
int keys[ 256 ]; int keys[ APP_KEYCOUNT ];
for( int i = 0; i < 256; ++i ) keys[ i ] = ( GetAsyncKeyState( i ) & 0x8000 ) != 0; for( int i = 0; i < APP_KEYCOUNT; ++i ) keys[ i ] = keystate[ i ];
for( int i = 0; i < 255; ++i ) for( int i = 0; i < APP_KEYCOUNT; ++i )
{ {
int key = 0; int key = 0;
switch( i ) switch( i )
{ {
case VK_RSHIFT: key = KEY_RSHIFT; break; case 97: key = KEY_F1; break;
case VK_RCONTROL: key = KEY_RCTRL; break; case 98: key = KEY_F2; break;
case VK_MENU: key = KEY_RALT; break; case 99: key = KEY_F3; break;
case VK_BACK: key = KEY_BACKSPACE; break; case 100: key = KEY_F4; break;
case VK_PAUSE: key = KEY_PAUSE; break; case 101: key = KEY_F5; break;
case VK_TAB: key = KEY_TAB; break; case 102: key = KEY_F6; break;
case VK_F1: key = KEY_F1; break; case 103: key = KEY_F7; break;
case VK_F2: key = KEY_F2; break; case 104: key = KEY_F8; break;
case VK_F3: key = KEY_F3; break; case 105: key = KEY_F9; break;
case VK_F4: key = KEY_F4; break; case 106: key = KEY_F10; break;
case VK_F5: key = KEY_F5; break; case 107: key = KEY_F11; break;
case VK_F6: key = KEY_F6; break; case 108: key = KEY_F12; break;
case VK_F7: key = KEY_F7; break; case 8: key = KEY_TAB; break;
case VK_F8: key = KEY_F8; break; case APP_KEY_OEM_MINUS: key = KEY_MINUS; break;
case VK_F9: key = KEY_F9; break; case APP_KEY_OEM_PLUS: key = KEY_EQUALS; break;
case VK_F10: key = KEY_F10; break; case APP_KEY_BACK: key = KEY_BACKSPACE; break;
case VK_F11: key = KEY_F11; break; case APP_KEY_UP: key = KEY_UPARROW; break;
case VK_F12: key = KEY_F12; break; case APP_KEY_DOWN: key = KEY_DOWNARROW; break;
case VK_UP: key = KEY_UPARROW; break; case APP_KEY_LEFT: key = KEY_LEFTARROW; break;
case VK_DOWN: key = KEY_DOWNARROW; break; case APP_KEY_RIGHT: key = KEY_RIGHTARROW; break;
case VK_LEFT: key = KEY_LEFTARROW; break; case 20: key = KEY_ESCAPE; break;
case VK_RIGHT: key = KEY_RIGHTARROW; break; case APP_KEY_SHIFT: key = KEY_RSHIFT; break;
case VK_ESCAPE: key = KEY_ESCAPE; break; case APP_KEY_CONTROL: key = KEY_RCTRL; break;
case VK_SHIFT: key = KEY_RSHIFT; break; case APP_KEY_RMENU: key = KEY_RALT; break;
case VK_CONTROL: key = KEY_RCTRL; break; case APP_KEY_LMENU: key = KEY_LALT; break;
case VK_RMENU: key = KEY_RALT; break; case APP_KEY_RETURN: key = KEY_ENTER; break;
case VK_LMENU: key = KEY_LALT; break; case 14: key = KEY_PAUSE; break;
case VK_RETURN: key = KEY_ENTER; break; case APP_KEY_SPACE: key = ' '; break;
case VK_SPACE: key = ' '; break; }
case VK_OEM_PLUS: key = KEY_EQUALS; break; if( i >= APP_KEY_A && i <= APP_KEY_Z ) {
case VK_OEM_MINUS: key = KEY_MINUS; break; key = 'a' + ( i - APP_KEY_A );
default: }
key = tolower( i ); if( i >= APP_KEY_0 && i <= APP_KEY_9 ) {
key = '0' + ( i - APP_KEY_0 );
} }
if( keys[ i ] && !prev[ i ] ) if( keys[ i ] && !prev[ i ] )
@ -237,30 +293,32 @@ void I_StartTic (void)
prev[ i ] = keys[ i ]; prev[ i ] = keys[ i ];
} }
RECT r; int relx = mouserelx;
GetClientRect( GetDesktopWindow(), &r ); int rely = mouserely;
r.bottom -= r.top; mouserelx= 0;
r.right -= r.left; mouserely= 0;
POINT pos;
GetCursorPos( &pos );
pos.x -= r.right / 2;
pos.y -= r.bottom / 2;
event_t ev; if( relx || rely ) {
ev.type = ev_mouse; event_t ev;
ev.data1 = 0; ev.type = ev_mouse;
ev.data2 = pos.x << 2; ev.data1 = 0;
ev.data3 = -pos.y << 2; ev.data2 = relx << 2;
D_PostEvent( &ev ); ev.data3 = -rely << 2;
SetCursorPos(r.right / 2,r.bottom / 2); D_PostEvent( &ev );
}
} }
// Wait for vertical retrace or pause a bit. // Wait for vertical retrace or pause a bit.
void I_WaitVBL(int count) void I_WaitVBL(int count)
{ {
int c = counter; #ifndef __wasm__
while ( counter - c < count ) int c = g_tickcount;
while ( g_tickcount - c < count )
thread_signal_wait( &vblank_signal, 1000 ); thread_signal_wait( &vblank_signal, 1000 );
#endif
#ifdef __wasm__
WaCoroSwitch(0);
#endif
} }
void I_ReadScreen (byte* scr) void I_ReadScreen (byte* scr)

View File

@ -146,8 +146,8 @@ M_ReadFile
handle = open (name, O_RDONLY | O_BINARY, 0666); handle = open (name, O_RDONLY | O_BINARY, 0666);
if (handle == -1) if (handle == -1)
I_Error ("Couldn't read file %s", name); I_Error ("Couldn't read file %s", name);
if (fstat (handle,&fileinfo) == -1) // if (fstat (handle,&fileinfo) == -1)
I_Error ("Couldn't read file %s", name); //I_Error ("Couldn't read file %s", name);
length = fileinfo.st_size; length = fileinfo.st_size;
buf = Z_Malloc (length, PU_STATIC, NULL); buf = Z_Malloc (length, PU_STATIC, NULL);
count = read (handle, buf, length); count = read (handle, buf, length);
@ -237,7 +237,7 @@ default_t defaults[] =
{"show_messages",&showMessages, 1}, {"show_messages",&showMessages, 1},
#ifdef _WIN32 #if defined( _WIN32 ) || defined( __wasm__)
{"key_right",&key_right, KEY_RIGHTARROW}, {"key_right",&key_right, KEY_RIGHTARROW},
{"key_left",&key_left, KEY_LEFTARROW}, {"key_left",&key_left, KEY_LEFTARROW},
{"key_up",&key_up, KEY_UPARROW}, {"key_up",&key_up, KEY_UPARROW},

View File

@ -73,11 +73,12 @@ void strupr (char* s)
int wadfilelength (int handle) int wadfilelength (int handle)
{ {
struct stat fileinfo; struct stat fileinfo;
int p = lseek(handle, 0,SEEK_CUR);
lseek(handle, 0, SEEK_END);
int res = lseek(handle,0,SEEK_CUR);
lseek(handle, p, SEEK_SET);
if (fstat (handle,&fileinfo) == -1) return res;
I_Error ("Error fstating");
return fileinfo.st_size;
} }
@ -573,4 +574,3 @@ void W_Profile (void)
fclose (f); fclose (f);
} }

71
template.html Normal file
View File

@ -0,0 +1,71 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<title>doom-crt</title>
<meta name="apple-mobile-web-app-title" content="doom-crt">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<style type="text/css">
html, body, #a {
margin: 0;
padding: 0;
background:black;
color:white;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
#a {
width:100vw;
height:75vw;
max-height:100vh;
max-width:133.33vh;
margin: auto;
position: absolute;
top:0;bottom:0;
left:0;right:0;
}
#wa_canvas {
display:block;
outline:0;
margin:0 auto;
width:1440px;
height:1080px;
max-width:100%;
max-height:100%;
}
#wa_log {
position: absolute;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
top: 0;
bottom: 0;
margin-top: auto;
margin-bottom: auto;
width: 300px;
height: 200px;
font-size: 1.5em;
font-weight: bold;
text-align: center;
}
</style></head>
<body>
<div id="a">
<canvas id="wa_canvas" onclick="window.focus();" oncontextmenu="event.preventDefault()"></canvas>
<div id="wa_log">Loading...</div>
</div>
<script>
var WA = { canvas: document.getElementById('wa_canvas'), started: function() { document.getElementById('wa_log').style.display = 'none'; window.focus();}, };
{{{js}}}
</script>
</body>
</html>