diff --git a/port/boards/rv32emu/display.c b/port/boards/rv32emu/display.c index 6ea4f91..6349374 100644 --- a/port/boards/rv32emu/display.c +++ b/port/boards/rv32emu/display.c @@ -46,7 +46,7 @@ void qembd_vidinit() register int a7 asm("a7") = syscall_draw_frame; asm volatile("scall" - : "+r"(a0) : "r"(a1), "r"(a2), "r"(a7)); + : : "r"(a0), "r"(a1), "r"(a2), "r"(a7)); } void qembd_fillrect(uint8_t *src, uint32_t *clut, @@ -67,5 +67,5 @@ void qembd_refresh() register int a7 asm("a7") = syscall_draw_frame; asm volatile("scall" - : "+r"(a0) : "r"(a1), "r"(a2), "r"(a7)); + : : "r"(a0), "r"(a1), "r"(a2), "r"(a7)); } diff --git a/port/boards/rv32emu/main.c b/port/boards/rv32emu/main.c index 0344913..8e016c8 100644 --- a/port/boards/rv32emu/main.c +++ b/port/boards/rv32emu/main.c @@ -73,7 +73,7 @@ void qembd_udelay(uint32_t us) } int main(int c, char **v) -{ +{ return qembd_main(c, v); } @@ -214,3 +214,10 @@ int qembd_get_mouse_movement(mouse_movement_t *movement) mouse_movement.y = 0; return 0; } + +void qembd_set_relative_mode(bool enabled) { + register int a0 asm("a0") = enabled; + register int a7 asm("a7") = 0xfeed; + + asm volatile("scall" : : "r"(a0), "r"(a7)); +} diff --git a/winquake/common.c b/winquake/common.c index 1c45181..fe470c1 100644 --- a/winquake/common.c +++ b/winquake/common.c @@ -410,78 +410,6 @@ float Q_atof (char *str) } #endif /* !defined(__riscv) */ -/* -============================================================================ - BYTE ORDER FUNCTIONS -============================================================================ -*/ - -#ifdef SDL -#include "SDL_byteorder.h" -#endif - -qboolean bigendien; - -short (*BigShort) (short l); -short (*LittleShort) (short l); -int (*BigLong) (int l); -int (*LittleLong) (int l); -float (*BigFloat) (float l); -float (*LittleFloat) (float l); - -short ShortSwap (short l) -{ - byte b1,b2; - - b1 = l&255; - b2 = (l>>8)&255; - - return (b1<<8) + b2; -} - -short ShortNoSwap (short l) -{ - return l; -} - -int LongSwap (int l) -{ - byte b1,b2,b3,b4; - - b1 = l&255; - b2 = (l>>8)&255; - b3 = (l>>16)&255; - b4 = (l>>24)&255; - - return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; -} - -int LongNoSwap (int l) -{ - return l; -} - -float FloatSwap (float f) -{ - union - { - float f; - byte b[4]; - } dat1, dat2; - - - dat1.f = f; - dat2.b[0] = dat1.b[3]; - dat2.b[1] = dat1.b[2]; - dat2.b[2] = dat1.b[1]; - dat2.b[3] = dat1.b[0]; - return dat2.f; -} - -float FloatNoSwap (float f) -{ - return f; -} /* ============================================================================== @@ -1108,35 +1036,6 @@ COM_Init */ void COM_Init (char *basedir) { - byte swaptest[2] = {1,0}; - -// set the byte swapping variables in a portable manner -#ifdef SDL - // This is necessary because egcs 1.1.1 mis-compiles swaptest with -O2 - if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) -#else - if ( *(short *)swaptest == 1) -#endif - { - bigendien = false; - BigShort = ShortSwap; - LittleShort = ShortNoSwap; - BigLong = LongSwap; - LittleLong = LongNoSwap; - BigFloat = FloatSwap; - LittleFloat = FloatNoSwap; - } - else - { - bigendien = true; - BigShort = ShortNoSwap; - LittleShort = ShortSwap; - BigLong = LongNoSwap; - LittleLong = LongSwap; - BigFloat = FloatNoSwap; - LittleFloat = FloatSwap; - } - Cvar_RegisterVariable (®istered); Cvar_RegisterVariable (&cmdline); Cmd_AddCommand ("path", COM_Path_f); diff --git a/winquake/common.h b/winquake/common.h index c123ef0..16412d4 100644 --- a/winquake/common.h +++ b/winquake/common.h @@ -78,14 +78,72 @@ void InsertLinkAfter (link_t *l, link_t *after); //============================================================================ -extern qboolean bigendien; - -extern short (*BigShort) (short l); -extern short (*LittleShort) (short l); -extern int (*BigLong) (int l); -extern int (*LittleLong) (int l); -extern float (*BigFloat) (float l); -extern float (*LittleFloat) (float l); +/* + * ======================================================================== + * BYTE ORDER FUNCTIONS + * ======================================================================== + */ + +#undef MSB_FIRST +#undef LSB_FIRST +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define MSB_FIRST 1 +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define LSB_FIRST 1 +#else +#error "Invalid endianness macros" +#endif + +static inline short bswap16(short s) { + return ((s & 255) << 8) | ((s >> 8) & 255); +} +static inline int bswap32(int l) { + return + (((l >> 0) & 255) << 24) + | (((l >> 8) & 255) << 16) + | (((l >> 16) & 255) << 8) + | (((l >> 24) & 255) << 0); +} + +#ifdef MSB_FIRST +static inline short BigShort(short s) { return s; } +static inline int BigLong(int l) { return l; } +static inline float BigFloat(float f) { return f; } +static inline short LittleShort(short s) { return bswap16(s); } +static inline int LittleLong(int l) { return bswap32(l); } +static inline float LittleFloat(float f) { + union { + float f; + byte b[4]; + } dat1, dat2; + + dat1.f = f; + dat2.b[0] = dat1.b[3]; + dat2.b[1] = dat1.b[2]; + dat2.b[2] = dat1.b[1]; + dat2.b[3] = dat1.b[0]; + return dat2.f; +} +#else +static inline short BigShort(short s) { return bswap16(s); } +static inline int BigLong(int l) { return bswap32(l); } +static inline float BigFloat(float f) { + union { + float f; + byte b[4]; + } dat1, dat2; + + dat1.f = f; + dat2.b[0] = dat1.b[3]; + dat2.b[1] = dat1.b[2]; + dat2.b[2] = dat1.b[1]; + dat2.b[3] = dat1.b[0]; + return dat2.f; +} +static inline short LittleShort(short s) { return s; } +static inline int LittleLong(int l) { return l; } +static inline float LittleFloat(float f) { return f; } +#endif //============================================================================ diff --git a/winquake/mathlib.h b/winquake/mathlib.h index 1e551fb..ca6d038 100644 --- a/winquake/mathlib.h +++ b/winquake/mathlib.h @@ -27,6 +27,13 @@ typedef int fixed4_t; typedef int fixed8_t; typedef int fixed16_t; +/* min and max macros with type checking */ +#define qmax(a, b) ((a > b) ? a : b) +#define qmin(a, b) ((a < b) ? a : b) + +/* clamp macro with type checking */ +#define qclamp(var, min, max) qmax(qmin(var, max), min) + #ifdef M_PI #undef M_PI #endif diff --git a/winquake/menu.c b/winquake/menu.c index 12271ed..b765db8 100644 --- a/winquake/menu.c +++ b/winquake/menu.c @@ -23,6 +23,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "winquake.h" #endif +void qembd_set_relative_mode(bool enabled); + void (*vid_menudrawfn)(void); void (*vid_menukeyfn)(int key); @@ -287,6 +289,8 @@ int m_main_cursor; void M_Menu_Main_f (void) { + qembd_set_relative_mode(false); + if (key_dest != key_menu) { m_save_demonum = cls.demonum; @@ -321,6 +325,7 @@ void M_Main_Key (int key) cls.demonum = m_save_demonum; if (cls.demonum != -1 && !cls.demoplayback && cls.state != ca_connected) CL_NextDemo (); + qembd_set_relative_mode(true); break; case K_DOWNARROW: @@ -425,6 +430,7 @@ void M_SinglePlayer_Key (int key) Cbuf_AddText ("disconnect\n"); Cbuf_AddText ("maxplayers 1\n"); Cbuf_AddText ("map start\n"); + qembd_set_relative_mode(true); break; case 1: diff --git a/winquake/model.c b/winquake/model.c index e39d158..5ff447e 100644 --- a/winquake/model.c +++ b/winquake/model.c @@ -39,11 +39,6 @@ byte mod_novis[MAX_MAP_LEAFS/8]; model_t mod_known[MAX_MOD_KNOWN]; int mod_numknown; -// values for model_t's needload -#define NL_PRESENT 0 -#define NL_NEEDS_LOADED 1 -#define NL_UNREFERENCED 2 - /* =============== Mod_Init @@ -81,7 +76,7 @@ void *Mod_Extradata (model_t *mod) Mod_PointInLeaf =============== */ -mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) +mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) { mnode_t *node; float d; @@ -171,7 +166,8 @@ void Mod_ClearAll (void) for (i=0 , mod=mod_known ; ineedload = NL_UNREFERENCED; + if (mod->type != mod_alias) + mod->needload = true; //FIX FOR CACHE_ALLOC ERRORS: if (mod->type == mod_sprite) mod->cache.data = NULL; } @@ -187,7 +183,6 @@ model_t *Mod_FindName (char *name) { int i; model_t *mod; - model_t *avail = NULL; if (!name[0]) Sys_Error ("Mod_ForName: NULL name"); @@ -195,33 +190,19 @@ model_t *Mod_FindName (char *name) // // search the currently loaded models // - for (i=0 , mod=mod_known ; iname, name) ) break; - if (mod->needload == NL_UNREFERENCED) - if (!avail || mod->type != mod_alias) - avail = mod; } if (i == mod_numknown) { if (mod_numknown == MAX_MOD_KNOWN) - { - if (avail) - { - mod = avail; - if (mod->type == mod_alias) - if (Cache_Check (&mod->cache)) - Cache_Free (&mod->cache); - } - else - Sys_Error ("mod_numknown == MAX_MOD_KNOWN"); - } - else - mod_numknown++; + Sys_Error("mod_numknown == MAX_MOD_KNOWN"); strcpy (mod->name, name); - mod->needload = NL_NEEDS_LOADED; + mod->needload = true; + mod_numknown++; } return mod; @@ -238,8 +219,8 @@ void Mod_TouchModel (char *name) model_t *mod; mod = Mod_FindName (name); - - if (mod->needload == NL_PRESENT) + + if (!mod->needload) { if (mod->type == mod_alias) Cache_Check (&mod->cache); @@ -258,18 +239,10 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash) unsigned *buf; byte stackbuf[1024]; // avoid dirtying the cache heap - if (mod->type == mod_alias) - { - if (Cache_Check (&mod->cache)) - { - mod->needload = NL_PRESENT; - return mod; - } - } - else - { - if (mod->needload == NL_PRESENT) + if (!mod->needload) { + if (mod->type == mod_alias && Cache_Check(&mod->cache)) return mod; + return mod; // not cached at all } // @@ -299,7 +272,7 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash) // // call the apropriate loader - mod->needload = NL_PRESENT; + mod->needload = false; switch (LittleLong(*(unsigned *)buf)) { @@ -733,11 +706,25 @@ void CalcSurfaceExtents (msurface_t *s) else v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]]; + /* + * The (long double) casts below are important: The original code was + * written for x87 floating-point which uses 80-bit floats for + * intermediate calculations. But if you compile it without the casts + * for modern x86_64, the compiler will round each intermediate result + * to a 32-bit float, which introduces extra rounding error. + * + * This becomes a problem if the rounding error causes the light + * utilities and the engine to disagree about the lightmap size for + * some surfaces. + * + * Casting to (long double) keeps the intermediate values at at least + * 64 bits of precision, probably 128. + */ for (j=0 ; j<2 ; j++) { - val = v->position[0] * tex->vecs[j][0] + - v->position[1] * tex->vecs[j][1] + - v->position[2] * tex->vecs[j][2] + + val = (long double)v->position[0] * tex->vecs[j][0] + + (long double)v->position[1] * tex->vecs[j][1] + + (long double)v->position[2] * tex->vecs[j][2] + tex->vecs[j][3]; if (val < mins[j]) mins[j] = val; @@ -1863,15 +1850,8 @@ void Mod_Print (void) model_t *mod; Con_Printf ("Cached models:\n"); - for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++) - { - Con_Printf ("%8p : %s",mod->cache.data, mod->name); - if (mod->needload & NL_UNREFERENCED) - Con_Printf (" (!R)"); - if (mod->needload & NL_NEEDS_LOADED) - Con_Printf (" (!P)"); - Con_Printf ("\n"); - } + for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++) + Con_Printf("%8p : %s\n", mod->cache.data, mod->name); } diff --git a/winquake/model.h b/winquake/model.h index a0879b0..657982b 100644 --- a/winquake/model.h +++ b/winquake/model.h @@ -385,7 +385,7 @@ model_t *Mod_ForName (char *name, qboolean crash); void *Mod_Extradata (model_t *mod); // handles caching void Mod_TouchModel (char *name); -mleaf_t *Mod_PointInLeaf (float *p, model_t *model); +mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model); byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model); #endif // __MODEL__ diff --git a/winquake/r_main.c b/winquake/r_main.c index d6a2d80..dae014c 100644 --- a/winquake/r_main.c +++ b/winquake/r_main.c @@ -255,10 +255,7 @@ void R_NewMap (void) r_viewleaf = NULL; R_ClearParticles (); - r_cnumsurfs = r_maxsurfs.value; - - if (r_cnumsurfs <= MINSURFACES) - r_cnumsurfs = MINSURFACES; + r_cnumsurfs = qclamp((int)r_maxsurfs.value, MINSURFACES, MAXSURFACES); if (r_cnumsurfs > NUMSTACKSURFACES) { @@ -279,10 +276,7 @@ void R_NewMap (void) r_maxedgesseen = 0; r_maxsurfsseen = 0; - r_numallocatededges = r_maxedges.value; - - if (r_numallocatededges < MINEDGES) - r_numallocatededges = MINEDGES; + r_numallocatededges = qclamp((int)r_maxedges.value, MINEDGES, MAXEDGES); if (r_numallocatededges <= NUMSTACKEDGES) { diff --git a/winquake/r_shared.h b/winquake/r_shared.h index a5d6b9e..b6dc2c2 100644 --- a/winquake/r_shared.h +++ b/winquake/r_shared.h @@ -62,10 +62,19 @@ extern vec3_t vpn, base_vpn; extern vec3_t vright, base_vright; extern entity_t *currententity; -#define NUMSTACKEDGES 2400 -#define MINEDGES NUMSTACKEDGES -#define NUMSTACKSURFACES 800 +/* + * Min edges/surfaces are just a reasonable number to play the + * original id/hipnotic/rouge maps. Surfaces we want to reference + * using shorts to pack the edge_t struct into cache lines, so the + * upper limit on those is 16 bits. Edges is just 32 bit limited, but + * no need for quite that many if we don't have the surfs. + */ +#define NUMSTACKEDGES 2400 +#define NUMSTACKSURFACES 800 #define MINSURFACES NUMSTACKSURFACES +#define MINEDGES NUMSTACKEDGES +#define MAXSURFACES 0xffff +#define MAXEDGES (MAXSURFACES << 2) #define MAXSPANS 3000 // !!! if this is changed, it must be changed in asm_draw.h too !!! @@ -156,7 +165,7 @@ typedef struct edge_s fixed16_t u; fixed16_t u_step; struct edge_s *prev, *next; - unsigned short surfs[2]; + uint16_t surfs[2]; struct edge_s *nextremove; float nearzi; medge_t *owner;