shithub: npe

Download patch

ref: c68d3e221d9b372e250fcec40e01c6e5176abe8b
parent: 2bf42bfc7ce8fae05401547e03cda1a181f89a95
author: Jacob Moody <moody@posixcafe.org>
date: Mon Aug 4 06:43:28 EDT 2025

make nanobsp work with npe

--- a/include/npe/SDL2/SDL.h
+++ b/include/npe/SDL2/SDL.h
@@ -31,14 +31,48 @@
 typedef int SDL_RendererFlip;
 typedef struct SDL_DisplayMode SDL_DisplayMode;
 typedef int SDL_SystemCursor;
-typedef union SDL_Color SDL_Color;
+typedef struct SDL_Color SDL_Color;
 typedef struct SDL_Palette SDL_Palette;
 typedef struct SDL_RendererInfo SDL_RendererInfo;
 typedef struct SDL_mutex SDL_mutex;
 
+struct SDL_Rect {
+	int x, y, w, h;
+};
+
+struct SDL_Color {
+    Uint8 r;
+    Uint8 g;
+    Uint8 b;
+    Uint8 a;
+};
+
+struct SDL_Palette {
+	int ncolors;
+	SDL_Color *colors;
+};
+
+struct SDL_PixelFormat {
+	SDL_Palette *palette;
+	int format;
+	int BytesPerPixel;
+};
+
+struct SDL_Surface {
+	SDL_PixelFormat *format;
+	SDL_Rect clip_rect;
+	Uint32 flags;
+	Uint32 key;
+	int keyset;
+	int w, h;
+	int pitch;
+	int n;
+	void *i;
+	uchar *pixels;
+};
+
 #pragma incomplete SDL_Cursor
 #pragma incomplete SDL_Renderer
-#pragma incomplete SDL_Surface
 #pragma incomplete SDL_Texture
 #pragma incomplete SDL_Window
 
@@ -116,6 +150,9 @@
 void SDL_RenderGetScale(SDL_Renderer *renderer, float *scaleX, float *scaleY);
 void SDL_GetWindowSize(SDL_Window *window, int *w, int *h);
 void SDL_GetWindowPosition(SDL_Window *window, int *x, int *y);
+void SDL_SetWindowMinimumSize(SDL_Window *window, int min_w, int min_h);
+Uint32 SDL_GetWindowPixelFormat(SDL_Window *window);
+SDL_bool SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp, Uint32 *Rmask, Uint32 *Gmask, Uint32 *Bmask, Uint32 *Amask);
 Uint32 SDL_GetMouseState(int *x, int *y);
 SDL_bool SDL_IsTextInputActive(void);
 void SDL_StartTextInput(void);
@@ -135,6 +172,7 @@
 void SDL_DestroyRenderer(SDL_Renderer *renderer);
 void SDL_DestroyWindow(SDL_Window *window);
 int SDL_GetDisplayUsableBounds(int displayIndex, SDL_Rect *rect);
+int SDL_GetDisplayBounds(int displayIndex, SDL_Rect *rect);
 int SDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode *mode);
 void SDL_SetWindowTitle(SDL_Window *window, char *title);
 int SDL_SetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode blendMode);
@@ -148,6 +186,7 @@
 void SDL_EnableScreenSaver(void);
 Uint32 SDL_GetTicks(void);
 int SDL_GetRendererOutputSize(SDL_Renderer *renderer, int *w, int *h);
+int SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_RendererInfo *info);
 void SDL_RenderGetViewport(SDL_Renderer *rebderer, SDL_Rect *rect);
 int SDL_SaveBMP(SDL_Surface *s, const char *file);
 void SDL_ClearError(void);
@@ -164,6 +203,7 @@
 void SDL_ShowWindow(SDL_Window *w);
 int SDL_RenderSetIntegerScale(SDL_Renderer *r, SDL_bool enable);
 int SDL_GetNumVideoDisplays(void);
+int SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture);
 void SDL_SetModState(SDL_Keymod modstate);
 SDL_mutex* SDL_CreateMutex(void);
 void SDL_DestroyMutex(SDL_mutex*);
@@ -176,10 +216,14 @@
 int SDL_SetPaletteColors(SDL_Palette *palette, const SDL_Color *colors, int firstcolor, int ncolors);
 int SDL_SetSurfacePalette(SDL_Surface *s, SDL_Palette *palette);
 int SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);
+int SDL_LowerBlit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);
 int SDL_SoftStretch(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect);
 int SDL_LockTexture(SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch);
 int SDL_UnlockTexture(SDL_Texture *texture);
 int SDL_GetWindowBordersSize(SDL_Window *window, int *top, int *left, int *bot, int *right);
+
+#define SDL_min(x, y) (((x) < (y)) ? (x) : (y))
+#define SDL_max(x, y) (((x) > (y)) ? (x) : (y))
  
 enum {
 	SDL_QUERY = -1,
@@ -231,6 +275,7 @@
 	SDL_TEXTUREACCESS_TARGET = 0,
 	SDL_RENDERER_ACCELERATED = 0,
 	SDL_RENDERER_PRESENTVSYNC = 0,
+	SDL_RENDERER_TARGETTEXTURE = 0x8,
 	SDL_INIT_NOPARACHUTE = 0,
 	SDL_RENDERER_SOFTWARE = 0,
 	SDL_SWSURFACE = 0,
@@ -278,45 +323,11 @@
 	int x, y;
 };
 
-struct SDL_Rect {
-	int x, y, w, h;
-};
-
-struct SDL_Surface {
-	SDL_PixelFormat *format;
-	SDL_Rect clip_rect;
-	Uint32 flags;
-	Uint32 key;
-	int keyset;
-	int w, h;
-	int pitch;
-	int n;
-	void *i;
-	uchar *pixels;
-};
-
 struct SDL_DisplayMode {
 	int format;
 	int w;
 	int h;
 	int refresh_rate;
-};
-
-union SDL_Color {
-	struct {
-		Uint8 r, g, b, a;
-	};
-};
-
-struct SDL_Palette {
-	int ncolors;
-	SDL_Color *colors;
-};
-
-struct SDL_PixelFormat {
-	SDL_Palette *palette;
-	int format;
-	int BytesPerPixel;
 };
 
 struct SDL_RendererInfo {
--- a/include/npe/SDL2/SDL_audio.h
+++ b/include/npe/SDL2/SDL_audio.h
@@ -52,4 +52,20 @@
 void SDL_PauseAudioDevice(SDL_AudioDeviceID, SDL_bool);
 void SDL_CloseAudioDevice(SDL_AudioDeviceID);
 
+void SDL_PauseAudio(int pause_on);
+
+typedef Uint16 SDL_AudioFormat;
+typedef struct SDL_AudioCVT SDL_AudioCVT;
+struct SDL_AudioCVT
+{
+	SDL_AudioFormat src_format;
+	SDL_AudioFormat dst_format;
+	Uint8 *buf;
+	int len;
+	int len_mult;
+};
+
+int SDL_BuildAudioCVT(SDL_AudioCVT *cvt, SDL_AudioFormat src_format, Uint8 src_channels, int src_rate, SDL_AudioFormat dst_format, Uint8 dst_channels, int dst_rate);
+int SDL_ConvertAudio(SDL_AudioCVT *cvt);
+
 #endif
--- a/include/npe/SDL2/SDL_events.h
+++ b/include/npe/SDL2/SDL_events.h
@@ -2,6 +2,7 @@
 #define _npe_SDL_events_h_
 
 enum {
+	SDL_FIRSTEVENT,
 	SDL_KEYDOWN,
 	SDL_KEYUP,
 	SDL_JOYAXISMOTION,
@@ -31,6 +32,7 @@
 	SDL_WINDOWEVENT_CLOSE,
 	SDL_JOYBALLMOTION,
 	SDL_JOYHATMOTION,
+	SDL_LASTEVENT,
 
 	SDL_PRESSED = SDL_KEYDOWN,
 	SDL_RELEASED = SDL_KEYUP,
--- a/include/npe/SDL2/SDL_mixer.h
+++ b/include/npe/SDL2/SDL_mixer.h
@@ -20,6 +20,7 @@
 
 typedef void (*Mix_EffectFunc_t)(int chan, void *stream, int len, void *udata);
 typedef void (*Mix_EffectDone_t)(int chan, void *udata);
+typedef void (*Mix_MixCallback)(void *udata, Uint8 *stream, int len);
 
 int Mix_OpenAudio(int,Uint16,int,int);
 char* Mix_GetError(void);
@@ -41,6 +42,11 @@
 int Mix_PlayMusic(Mix_Music *music, int loops);
 Mix_Music* Mix_LoadMUS_RW(SDL_RWops *src, int freesrc);
 Mix_Music* Mix_LoadMUS(char *filename);
+int Mix_SetPanning(int channel, Uint8 left, Uint8 right);
+int Mix_Playing(int channel);
+int Mix_QuerySpec(int *frequency, Uint16 *format, int *channels);
+int Mix_AllocateChannels(int numchans);
+void Mix_HookMusic(Mix_MixCallback mix_func, void *arg);
 
 enum {
 	MIX_INIT_MID = 1,
@@ -48,6 +54,7 @@
 	MIX_DEFAULT_FORMAT = 1,
 
 	SDL_MIX_MAXVOLUME = 100,
+	MIX_MAX_VOLUME = SDL_MIX_MAXVOLUME,
 };
 
 #endif
--- a/include/npe/SDL2/SDL_version.h
+++ b/include/npe/SDL2/SDL_version.h
@@ -9,4 +9,7 @@
 
 void SDL_GetVersion(SDL_version *v);
 
+#define SDL_VERSIONNUM(X, Y, Z)	((X)*1000 + (Y)*100 + (Z))
+#define SDL_COMPILEDVERSION SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL)
+
 #endif
--- a/include/npe/errno.h
+++ b/include/npe/errno.h
@@ -6,6 +6,7 @@
 enum {
 	ENOENT = 2,
 	EACCES = 13,
+	EISDIR = 14,
 	EINVAL = 22,
 	ERANGE = 34,
 	ENAMETOOLONG = 36,
--- a/libnpe_sdl2/audio.c
+++ b/libnpe_sdl2/audio.c
@@ -122,6 +122,12 @@
 	}
 }
 
+void
+SDL_PauseAudio(int pause_on)
+{
+	SDL_PauseAudioDevice(1, pause_on);
+}
+
 static int
 convspec(SDL_AudioSpec *s, char *spec, int n)
 {
@@ -142,6 +148,24 @@
 		ssz = fmts[s->format].ssz;
 
 	return ssz;
+}
+
+// https://wiki.libsdl.org/SDL2/SDL_ConvertAudio
+int
+SDL_ConvertAudio(SDL_AudioCVT *cvt)
+{
+	USED(cvt);
+	return 0;
+}
+
+// https://wiki.libsdl.org/SDL2/SDL_BuildAudioCVT
+int
+SDL_BuildAudioCVT(SDL_AudioCVT *cvt, SDL_AudioFormat src_format, Uint8 src_channels, int src_rate, SDL_AudioFormat dst_format, Uint8 dst_channels, int dst_rate)
+{
+	USED(cvt);
+	USED(src_format, src_channels, src_rate);
+	USED(dst_format, dst_channels, dst_rate);
+	return 0;
 }
 
 static void
--- a/libnpe_sdl2/mixer.c
+++ b/libnpe_sdl2/mixer.c
@@ -244,3 +244,46 @@
 		SDL_RWclose(src);
 	return m;
 }
+
+// https://wiki.libsdl.org/SDL2_mixer/Mix_AllocateChannels
+int
+Mix_AllocateChannels(int numchans)
+{
+	USED(numchans);
+	return 0;
+}
+
+// https://wiki.libsdl.org/SDL2_mixer/Mix_SetPanning
+int
+Mix_SetPanning(int channel, Uint8 left, Uint8 right)
+{
+	USED(channel, left, right);
+	return 0;
+}
+
+// https://wiki.libsdl.org/SDL2_mixer/Mix_HookMusic
+void
+Mix_HookMusic(Mix_MixCallback mix_func, void *arg)
+{
+	USED(mix_func, arg);
+}
+
+int
+Mix_QuerySpec(int *frequency, Uint16 *format, int *channels)
+{
+	if(frequency != nil)
+		*frequency = 44100;
+	if(format != nil)
+		*format = AUDIO_S16LSB;
+	if(channels != nil)
+		*channels = 2;
+	return 0;
+}
+
+// https://wiki.libsdl.org/SDL2_mixer/Mix_Playing
+int
+Mix_Playing(int channel)
+{
+	USED(channel);
+	return 0;
+}
--- a/libnpe_sdl2/sdl2.c
+++ b/libnpe_sdl2/sdl2.c
@@ -23,6 +23,7 @@
 
 static SDL_Window onewin;
 static SDL_Renderer oneren;
+static SDL_Texture backtex, *target = &backtex;
 static Memimage *back;
 static u8int *backcopy;
 static Image *front;
@@ -80,31 +81,54 @@
 }
 
 static int
-chan2mask(Uint32 chan, Uint32 *rm, Uint32 *gm, Uint32 *bm, Uint32 *am)
+chan2mask(Uint32 chan, int *bpp, Uint32 *rm, Uint32 *gm, Uint32 *bm, Uint32 *am)
 {
 	switch(chan){
 	case ARGB32:
 		*am = 0xFF000000;
-	if(0){
+		*rm = 0x00FF0000;
+		*gm = 0x0000FF00;
+		*bm = 0x000000FF;
+		*bpp = 32;
+		break;
 	case XRGB32:
 		*am = 0x00000000;
-	}
-	case RGB24:
 		*rm = 0x00FF0000;
 		*gm = 0x0000FF00;
 		*bm = 0x000000FF;
+		*bpp = 32;
 		break;
 	case ABGR32:
 		*am = 0xFF000000;
-	if(0){
+		*rm = 0x000000FF;
+		*gm = 0x0000FF00;
+		*bm = 0x00FF0000;
+		*bpp = 32;
 	case XBGR32:
 		*am = 0x00000000;
-	}
-	case BGR24:
+		*rm = 0x000000FF;
+		*gm = 0x0000FF00;
 		*bm = 0x00FF0000;
+		*bpp = 32;
+		break;
+	case RGB24:
+		*am = 0x00000000;
+		*rm = 0x00FF0000;
 		*gm = 0x0000FF00;
+		*bm = 0x000000FF;
+		*bpp = 24;
+		break;
+	case BGR24:
+		*am = 0x00000000;
 		*rm = 0x000000FF;
+		*gm = 0x0000FF00;
+		*bm = 0x00FF0000;
+		*bpp = 24;
 		break;
+	case CMAP8:
+		*am = *rm = *gm = *bm = 0x00000000;
+		*bpp = 8;
+		break;
 	default:
 		assert(0);
 	}
@@ -190,6 +214,8 @@
 int
 SDL_Init(int mask)
 {
+	int bpp;
+
 	/* FIXME actually use the mask? */
 	USED(mask);
 
@@ -198,6 +224,8 @@
 
 	if(mask == 0)
 		return 0;
+	if(screen != nil)
+		return 0;
 
 	if(memimageinit() < 0)
 		goto err;
@@ -208,7 +236,7 @@
 	npe_sdl.scale = 1;
 	physw = Dx(screen->r);
 	physh = Dy(screen->r);
-	if(chan2mask(screen->chan, &defmask.r, &defmask.g, &defmask.b, &defmask.a) < 0){
+	if(chan2mask(screen->chan, &bpp, &defmask.r, &defmask.g, &defmask.b, &defmask.a) < 0){
 		werrstr("SDL_Init: unsupported screen channel");
 		return -1;
 	}
@@ -527,9 +555,10 @@
 }
 
 SDL_Surface *
-SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int w, int h, int bpp, Uint32 fmt)
+SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int w, int h, int fbpp, Uint32 fmt)
 {
 	SDL_Surface *s;
+	int bpp;
 	ulong chan;
 	Uint32 rm, gm, bm, am;
 
@@ -537,7 +566,9 @@
 		werrstr("SDL_CreateRGBSurfaceWithFormat: FIXME format %8ux not implemented", fmt);
 		return nil;
 	}
-	chan2mask(chan, &rm, &gm, &bm, &am);
+	chan2mask(chan, &bpp, &rm, &gm, &bm, &am);
+	if(bpp != fbpp && fbpp != 0)
+		sysfatal("FIXME SDL_CreateRGBSurfaceWithFormat passes wrong bpp for format: %d not %d", fbpp, bpp);
 	if((s = SDL_CreateRGBSurface(flags, w, h, bpp, rm, bm, gm, am)) == nil)
 		return nil;
 	return s;
@@ -665,7 +696,27 @@
 	return 0;
 }
 
+// https://wiki.libsdl.org/SDL2/SDL_LowerBlit
 int
+SDL_LowerBlit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect)
+{
+	return SDL_BlitSurface(src, srcrect, dst, dstrect);
+}
+
+// https://wiki.libsdl.org/SDL2/SDL_SetRenderTarget
+int
+SDL_SetRenderTarget(SDL_Renderer *, SDL_Texture *texture)
+{
+	if(texture == nil)
+		target = &backtex;
+	else
+		target = texture;
+	back = target->m;
+	npe_sdl.fullredraw = 1;
+	return 0;
+}
+
+int
 SDL_SoftStretch(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect)
 {
 	Rectangle r, r2;
@@ -777,6 +828,18 @@
 	}
 }
 
+SDL_bool
+SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp, Uint32 *Rmask, Uint32 *Gmask, Uint32 *Bmask, Uint32 *Amask)
+{
+	ulong c;
+
+	if(bpp == nil || Rmask == nil || Gmask == nil || Bmask == nil || Amask == nil)
+		return SDL_FALSE;
+	c = pixel2chan(format);
+	chan2mask(c, bpp, Rmask, Gmask, Bmask, Amask);
+	return SDL_TRUE;
+}
+
 Uint32
 SDL_MapRGB(SDL_PixelFormat *fmt, Uint8 r, Uint8 g, Uint8 b)
 {
@@ -861,6 +924,14 @@
 	return nil;
 }
 
+Uint32
+SDL_GetWindowPixelFormat(SDL_Window *)
+{
+	if(screen != nil)
+		return chan2pixel(screen->chan);
+	return 0;
+}
+
 SDL_Cursor *
 SDL_GetDefaultCursor(void)
 {
@@ -1046,6 +1117,7 @@
 			werrstr("SDL_RenderCopy: %r");
 			return -1;
 		}
+		target->m = back;
 		free(backcopy);
 		backcopy = malloc(logiw*logih*4);
 	}
@@ -1066,6 +1138,11 @@
 	uchar *rb;
 	int logiw, logih;
 
+	/* may be called before SDL_RenderCopy is ever called;
+	 * nanobsp does this during initialization */
+	if(back == nil)
+		return;
+
 	if(rend->logiw > 0 && rend->logih > 0){
 		logiw = rend->logiw;
 		logih = rend->logih;
@@ -1243,6 +1320,12 @@
 	}
 }
 
+void
+SDL_SetWindowMinimumSize(SDL_Window *window, int min_w, int min_h)
+{
+	SDL_SetWindowSize(window, min_w, min_h);
+}
+
 int
 SDL_ShowSimpleMessageBox(Uint32, char *title, char *message, SDL_Window *)
 {
@@ -1301,6 +1384,12 @@
 }
 
 int
+SDL_GetDisplayBounds(int displayIndex, SDL_Rect *r)
+{
+	return SDL_GetDisplayUsableBounds(displayIndex, r);
+}
+
+int
 SDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode *mode)
 {
 	if(displayIndex != 0)
@@ -1340,6 +1429,8 @@
 {
 	int f;
 
+	if(title == nil)
+		return;
 	if((f = open("/dev/label", OWRITE|OTRUNC|OCEXEC)) >= 0 || (f = open("/mnt/term/dev/label", OWRITE|OTRUNC|OCEXEC)) >= 0){
 		write(f, title, strlen(title));
 		close(f);
@@ -1425,6 +1516,16 @@
 		return -1;
 	}
 
+	return 0;
+}
+
+int
+SDL_GetRendererInfo(SDL_Renderer *, SDL_RendererInfo *info)
+{
+	if(info == nil)	
+		return -1;
+	info->max_texture_width = physw;
+	info->max_texture_height = physh;
 	return 0;
 }
 
--