From fbd230bb6c918c6b2e94d09f6a10a32affea08bb Mon Sep 17 00:00:00 2001
From: Michael Fitzmayer <[EMAIL REDACTED]>
Date: Tue, 3 May 2022 17:51:49 +0200
Subject: [PATCH] Add support for the Nokia N-Gage (#5597)
* Add initial support for the Nokia N-Gage
* N-Gage: disable clipping for the time being, issue needs to be resolved later
* Move va_copy definition to SDL_internal.h
* Move stdlib.h include to SDL_config_ngage.h, much cleaner this way
* Remove redundant include, add HAVE_STDLIB_H
* Revert "N-Gage: disable clipping for the time being, issue needs to be resolved later"
This reverts commit 4f5f0fc36cc7f34fad05e45671dfa7b8dc32fd51.
* N-Gage: fix clipping issue by providing proper math functions
---
docs/README-ngage.md | 44 +++
docs/README.md | 1 +
include/SDL_config.h | 2 +
include/SDL_config_ngage.h | 89 +++++
include/SDL_platform.h | 4 +
src/SDL.c | 2 +
src/SDL_internal.h | 5 +-
src/dynapi/SDL_dynapi.h | 2 +
src/main/ngage/SDL_ngage_main.cpp | 82 +++++
src/thread/SDL_thread_c.h | 2 +
src/thread/ngage/SDL_sysmutex.cpp | 107 ++++++
src/thread/ngage/SDL_syssem.cpp | 195 +++++++++++
src/thread/ngage/SDL_systhread.cpp | 147 ++++++++
src/thread/ngage/SDL_systhread_c.h | 25 ++
src/timer/ngage/SDL_systimer.cpp | 100 ++++++
src/video/SDL_sysvideo.h | 1 +
src/video/SDL_video.c | 3 +
src/video/ngage/SDL_ngageevents.cpp | 200 +++++++++++
src/video/ngage/SDL_ngageevents_c.h | 28 ++
src/video/ngage/SDL_ngageframebuffer.cpp | 424 +++++++++++++++++++++++
src/video/ngage/SDL_ngageframebuffer_c.h | 38 ++
src/video/ngage/SDL_ngagevideo.cpp | 192 ++++++++++
src/video/ngage/SDL_ngagevideo.h | 75 ++++
src/video/ngage/SDL_ngagewindow.cpp | 129 +++++++
src/video/ngage/SDL_ngagewindow.h | 45 +++
25 files changed, 1941 insertions(+), 1 deletion(-)
create mode 100644 docs/README-ngage.md
create mode 100644 include/SDL_config_ngage.h
create mode 100644 src/main/ngage/SDL_ngage_main.cpp
create mode 100644 src/thread/ngage/SDL_sysmutex.cpp
create mode 100644 src/thread/ngage/SDL_syssem.cpp
create mode 100644 src/thread/ngage/SDL_systhread.cpp
create mode 100644 src/thread/ngage/SDL_systhread_c.h
create mode 100644 src/timer/ngage/SDL_systimer.cpp
create mode 100644 src/video/ngage/SDL_ngageevents.cpp
create mode 100644 src/video/ngage/SDL_ngageevents_c.h
create mode 100644 src/video/ngage/SDL_ngageframebuffer.cpp
create mode 100644 src/video/ngage/SDL_ngageframebuffer_c.h
create mode 100644 src/video/ngage/SDL_ngagevideo.cpp
create mode 100644 src/video/ngage/SDL_ngagevideo.h
create mode 100644 src/video/ngage/SDL_ngagewindow.cpp
create mode 100644 src/video/ngage/SDL_ngagewindow.h
diff --git a/docs/README-ngage.md b/docs/README-ngage.md
new file mode 100644
index 00000000000..73878874a00
--- /dev/null
+++ b/docs/README-ngage.md
@@ -0,0 +1,44 @@
+Nokia N-Gage
+============
+
+SDL2 port for Symbian S60v1/2 with a main focus on the Nokia N-Gage
+(Classic and QD) by [Michael Fitzmayer](https://github.com/mupfdev).
+
+Compiling
+---------
+
+SDL is part of the [N-Gage SDK.](https://github.com/ngagesdk) project.
+The library is included in the
+[toolchain](https://github.com/ngagesdk/ngage-toolchain) as a
+sub-module.
+
+A complete example project based on SDL2 can be found in the GitHub
+account of the SDK: [Example
+project](https://github.com/ngagesdk/wordle).
+
+Current level of implementation
+-------------------------------
+
+The video driver currently provides full screen video support with
+keyboard input.
+
+At the moment only the software renderer works.
+
+Audio is not yet implemented.
+
+Acknowledgements
+----------------
+
+Thanks to Hannu Viitala, Kimmo Kinnunen and Markus Mertama for the
+valuable insight into Symbian programming. Without the SDL 1.2 port for
+CDoom, this adaptation would not have been possible.
+
+I would like to thank my friends
+[Razvan](https://twitter.com/bewarerazvan) and [Dan
+Whelan](https://danwhelan.ie/), for their continuous support. Without
+you and the [N-Gage community](https://discord.gg/dbUzqJ26vs), I would
+have lost my patience long ago.
+
+Last but not least, I would like to say a special thank you to the
+[EKA2L1](https://12z1.com/) team. Thank you for all your patience and
+support in troubleshooting.
diff --git a/docs/README.md b/docs/README.md
index efbe3ad0ed6..fd0078a5cf4 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -51,6 +51,7 @@ More documentation and FAQs are available online at [the wiki](http://wiki.libsd
- [Windows](README-windows.md)
- [WinRT](README-winrt.md)
- [PSVita](README-vita.md)
+- [Nokia N-Gage](README-ngage.md)
If you need help with the library, or just want to discuss SDL related
issues, you can join the [SDL Discourse](https://discourse.libsdl.org/),
diff --git a/include/SDL_config.h b/include/SDL_config.h
index 7afefabe252..7499885155f 100644
--- a/include/SDL_config.h
+++ b/include/SDL_config.h
@@ -43,6 +43,8 @@
#include "SDL_config_os2.h"
#elif defined(__EMSCRIPTEN__)
#include "SDL_config_emscripten.h"
+#elif defined(__NGAGE__)
+#include "SDL_config_ngage.h"
#else
/* This is a minimal configuration just to get SDL running on new platforms. */
#include "SDL_config_minimal.h"
diff --git a/include/SDL_config_ngage.h b/include/SDL_config_ngage.h
new file mode 100644
index 00000000000..07f92541e2e
--- /dev/null
+++ b/include/SDL_config_ngage.h
@@ -0,0 +1,89 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_ngage_h_
+#define SDL_config_ngage_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+typedef unsigned long uintptr_t;
+
+#define HAVE_STDARG_H 1
+#define HAVE_STDDEF_H 1
+#define HAVE_STDIO_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_MATH_H 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_EXP 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_LOG10 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SQRT 1
+#define HAVE_TAN 1
+#define HAVE_MALLOC 1
+#define SDL_MAIN_NEEDED 1
+#define LACKS_SYS_MMAN_H 1
+
+/* Enable the N-Gage thread support (src/thread/ngage/\*.c) */
+#define SDL_THREAD_NGAGE 1
+
+/* Enable the N-Gage timer support (src/timer/ngage/\*.c) */
+#define SDL_TIMER_NGAGE 1
+
+/* Enable the N=Hahe video driver (src/video/ngage/\*.c) */
+#define SDL_VIDEO_DRIVER_NGAGE 1
+
+/* Enable the dummy audio driver (src/audio/dummy/\*.c) */
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable the stub joystick driver (src/joystick/dummy/\*.c) */
+#define SDL_JOYSTICK_DISABLED 1
+
+/* Enable the stub haptic driver (src/haptic/dummy/\*.c) */
+#define SDL_HAPTIC_DISABLED 1
+
+/* Enable the stub HIDAPI */
+#define SDL_HIDAPI_DISABLED 1
+
+/* Enable the stub sensor driver (src/sensor/dummy/\*.c) */
+#define SDL_SENSOR_DISABLED 1
+
+/* Enable the stub shared object loader (src/loadso/dummy/\*.c) */
+#define SDL_LOADSO_DISABLED 1
+
+/* Enable the dummy filesystem driver (src/filesystem/dummy/\*.c) */
+#define SDL_FILESYSTEM_DUMMY 1
+
+#endif /* SDL_config_ngage_h_ */
diff --git a/include/SDL_platform.h b/include/SDL_platform.h
index efa93e3fc13..2663e143efc 100644
--- a/include/SDL_platform.h
+++ b/include/SDL_platform.h
@@ -65,6 +65,10 @@
#undef __LINUX__ /* do we need to do this? */
#define __ANDROID__ 1
#endif
+#if defined(__NGAGE__)
+#undef __NGAGE__
+#define __NGAGE__ 1
+#endif
#if defined(__APPLE__)
/* lets us know what version of Mac OS X we're compiling on */
diff --git a/src/SDL.c b/src/SDL.c
index 92300f59a32..82861c76d41 100644
--- a/src/SDL.c
+++ b/src/SDL.c
@@ -567,6 +567,8 @@ SDL_GetPlatform(void)
return "PlayStation Portable";
#elif __VITA__
return "PlayStation Vita";
+#elif __NGAGE__
+ return "Nokia N-Gage";
#else
return "Unknown (see SDL_platform.h)";
#endif
diff --git a/src/SDL_internal.h b/src/SDL_internal.h
index 2ec32f69767..7d3f9cd9e5f 100644
--- a/src/SDL_internal.h
+++ b/src/SDL_internal.h
@@ -27,7 +27,10 @@
#endif
/* Do our best to make sure va_copy is working */
-#if defined(_MSC_VER) && _MSC_VER <= 1800
+#if defined(__NGAGE__)
+#undef va_copy
+#define va_copy(dst, src) dst = src
+#elif defined(_MSC_VER) && _MSC_VER <= 1800
/* Visual Studio 2013 tries to link with _vacopy in the C runtime. Newer versions do an inline assignment */
#undef va_copy
#define va_copy(dst, src) dst = src
diff --git a/src/dynapi/SDL_dynapi.h b/src/dynapi/SDL_dynapi.h
index 452078b1a2a..e37444fd956 100644
--- a/src/dynapi/SDL_dynapi.h
+++ b/src/dynapi/SDL_dynapi.h
@@ -59,6 +59,8 @@
#define SDL_DYNAMIC_API 0 /* Turn off for static analysis, so reports are more clear. */
#elif defined(__VITA__)
#define SDL_DYNAMIC_API 0 /* vitasdk doesn't support dynamic linking */
+#elif defined(__NGAGE__)
+#define SDL_DYNAMIC_API 0 /* The N-Gage doesn't support dynamic linking either */
#elif defined(DYNAPI_NEEDS_DLOPEN) && !defined(HAVE_DLOPEN)
#define SDL_DYNAMIC_API 0 /* we need dlopen(), but don't have it.... */
#endif
diff --git a/src/main/ngage/SDL_ngage_main.cpp b/src/main/ngage/SDL_ngage_main.cpp
new file mode 100644
index 00000000000..bb0f07c26a0
--- /dev/null
+++ b/src/main/ngage/SDL_ngage_main.cpp
@@ -0,0 +1,82 @@
+/*
+ EPOC version (originally for SDL 1.2) by Hannu Viitala
+ (hannu.j.viitala@mbnet.fi).
+*/
+#include "../../SDL_internal.h"
+
+/* Include the SDL main definition header */
+#include "SDL_main.h"
+
+#include <e32std.h>
+#include <e32def.h>
+#include <e32svr.h>
+#include <e32base.h>
+#include <estlib.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <w32std.h>
+#include <apgtask.h>
+
+#include "SDL_error.h"
+
+extern "C" int main(int argc, char *argv[]);
+
+TInt E32Main()
+{
+ /* Get the clean-up stack */
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+
+ /* Arrange for multi-threaded operation */
+ SpawnPosixServerThread();
+
+ /* Get args and environment */
+ int argc = 0;
+ char** argv = 0;
+ char** envp = 0;
+
+ __crt0(argc,argv,envp);
+
+ /* Start the application! */
+
+ /* Create stdlib */
+ _REENT;
+
+ /* Set process and thread priority and name */
+
+ RThread currentThread;
+ RProcess thisProcess;
+ TParse exeName;
+ exeName.Set(thisProcess.FileName(), NULL, NULL);
+ currentThread.Rename(exeName.Name());
+ currentThread.SetProcessPriority(EPriorityLow);
+ currentThread.SetPriority(EPriorityMuchLess);
+
+ /* Increase heap size */
+ RHeap* newHeap = NULL;
+ RHeap* oldHeap = NULL;
+ TInt heapSize = 7500000;
+ int ret;
+
+ newHeap = User::ChunkHeap(NULL, heapSize, heapSize, KMinHeapGrowBy);
+
+ if (NULL == newHeap)
+ {
+ ret = 3;
+ goto cleanup;
+ }
+ else
+ {
+ oldHeap = User::SwitchHeap(newHeap);
+ /* Call stdlib main */
+ ret = main(argc, argv);
+ }
+
+cleanup:
+ _cleanup();
+
+ CloseSTDLIB();
+ delete cleanup;
+ return ret;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/thread/SDL_thread_c.h b/src/thread/SDL_thread_c.h
index fb0885a2db3..b4df526d1cc 100644
--- a/src/thread/SDL_thread_c.h
+++ b/src/thread/SDL_thread_c.h
@@ -40,6 +40,8 @@
#include "stdcpp/SDL_systhread_c.h"
#elif SDL_THREAD_OS2
#include "os2/SDL_systhread_c.h"
+#elif SDL_THREAD_NGAGE
+#include "ngage/SDL_systhread_c.h"
#else
#error Need thread implementation for this platform
#include "generic/SDL_systhread_c.h"
diff --git a/src/thread/ngage/SDL_sysmutex.cpp b/src/thread/ngage/SDL_sysmutex.cpp
new file mode 100644
index 00000000000..a79b8ae0e04
--- /dev/null
+++ b/src/thread/ngage/SDL_sysmutex.cpp
@@ -0,0 +1,107 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+/* An implementation of mutexes using semaphores */
+
+#include <e32std.h>
+
+#include "SDL_thread.h"
+#include "SDL_systhread_c.h"
+
+struct SDL_mutex
+{
+ TInt handle;
+};
+
+extern TInt CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny*, TAny*);
+
+static TInt NewMutex(const TDesC& aName, TAny* aPtr1, TAny*)
+{
+ return ((RMutex*)aPtr1)->CreateGlobal(aName);
+}
+
+/* Create a mutex */
+SDL_mutex *
+SDL_CreateMutex(void)
+{
+ RMutex rmutex;
+
+ TInt status = CreateUnique(NewMutex, &rmutex, NULL);
+ if(status != KErrNone)
+ {
+ SDL_SetError("Couldn't create mutex.");
+ }
+ SDL_mutex* mutex = new /*(ELeave)*/ SDL_mutex;
+ mutex->handle = rmutex.Handle();
+ return(mutex);
+}
+
+/* Free the mutex */
+void
+SDL_DestroyMutex(SDL_mutex * mutex)
+{
+ if (mutex)
+ {
+ RMutex rmutex;
+ rmutex.SetHandle(mutex->handle);
+ rmutex.Signal();
+ rmutex.Close();
+ delete(mutex);
+ mutex = NULL;
+ }
+}
+
+/* Lock the mutex */
+int
+SDL_LockMutex(SDL_mutex * mutex)
+{
+ if (mutex == NULL)
+ {
+ SDL_SetError("Passed a NULL mutex.");
+ return -1;
+ }
+
+ RMutex rmutex;
+ rmutex.SetHandle(mutex->handle);
+ rmutex.Wait();
+
+ return(0);
+}
+
+/* Unlock the mutex */
+int
+SDL_mutexV(SDL_mutex * mutex)
+{
+ if ( mutex == NULL )
+ {
+ SDL_SetError("Passed a NULL mutex.");
+ return -1;
+ }
+
+ RMutex rmutex;
+ rmutex.SetHandle(mutex->handle);
+ rmutex.Signal();
+
+ return(0);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/thread/ngage/SDL_syssem.cpp b/src/thread/ngage/SDL_syssem.cpp
new file mode 100644
index 00000000000..f7e97ad52e7
--- /dev/null
+++ b/src/thread/ngage/SDL_syssem.cpp
@@ -0,0 +1,195 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+/* An implementation of semaphores using mutexes and condition variables */
+
+#include <e32std.h>
+
+#include "SDL_error.h"
+#include "SDL_thread.h"
+
+#define SDL_MUTEX_TIMEOUT -2
+
+struct SDL_semaphore
+{
+ TInt handle;
+ TInt count;
+};
+
+struct TInfo
+{
+ TInfo(TInt aTime, TInt aHandle) :
+ iTime(aTime), iHandle(aHandle), iVal(0) {}
+ TInt iTime;
+ TInt iHandle;
+ TInt iVal;
+};
+
+extern TInt CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny*, TAny*);
+
+static TBool RunThread(TAny* aInfo)
+{
+ TInfo* info = STATIC_CAST(TInfo*, aInfo);
+ User::After(info->iTime);
+ RSemaphore sema;
+ sema.SetHandle(info->iHandle);
+ sema.Signal();
+ info->iVal = SDL_MUTEX_TIMEOUT;
+ return 0;
+}
+
+static TInt
+NewThread(const TDesC& aName, TAny* aPtr1, TAny* aPtr2)
+{
+ return ((RThread*)(aPtr1))->Create
+ (aName,
+ RunThread,
+ KDefaultStackSize,
+ NULL,
+ aPtr2);
+}
+
+static TInt NewSema(const TDesC& aName, TAny* aPtr1, TAny* aPtr2)
+{
+ TInt value = *((TInt*) aPtr2);
+ return ((RSemaphore*)aPtr1)->CreateGlobal(aName, value);
+}
+
+static void WaitAll(SDL_sem *sem)
+{
+ RSemaphore sema;
+ sema.SetHandle(sem->handle);
+ sema.Wait();
+ while(sem->count < 0)
+ {
+ sema.Wait();
+ }
+}
+
+SDL_sem *
+SDL_CreateSemaphore(Uint32 initial_value)
+{
+ RSemaphore s;
+ TInt status = CreateUnique(NewSema, &s, &initial_value);
+ if(status != KErrNone)
+ {
+ SDL_SetError("Couldn't create semaphore");
+ }
+ SDL_semaphore* sem = new /*(ELeave)*/ SDL_semaphore;
+ sem->handle = s.Handle();
+ sem->count = initial_value;
+ return(sem);
+}
+
+void
+SDL_DestroySemaphore(SDL_sem * sem)
+{
+ if (sem)
+ {
+ RSemaphore sema;
+ sema.SetHandle(sem->handle);
+ sema.Signal(sema.Count());
+ sema.Close();
+ delete sem;
+ sem = NULL;
+ }
+}
+
+int
+SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
+{
+ if (! sem)
+ {
+ SDL_SetError("Passed a NULL sem");
+ return -1;
+ }
+
+ if (timeout == SDL_MUTEX_MAXWAIT)
+ {
+ WaitAll(sem);
+ return SDL_MUTEX_MAXWAIT;
+ }
+
+ RThread thread;
+ TInfo* info = new (ELeave)TInfo(timeout, sem->handle);
+ TInt status = CreateUnique(NewThread, &thread, info);
+
+ if(status != KErrNone)
+ {
+ return status;
+ }
+
+ thread.Resume();
+ WaitAll(sem);
+
+ if(thread.ExitType() == EExitPending)
+ {
+ thread.Kill(SDL_MUTEX_TIMEOUT);
+ }
+
+ thread.Close();
+ return info->iVal;
+}
+
+int
+SDL_SemTryWait(SDL_sem *sem)
+{
+ if(sem->count > 0)
+ {
+ sem->count--;
+ }
+ return SDL_MUTEX_TIMEOUT;
+}
+
+int
+SDL_SemWait(SDL_sem * sem)
+{
+ return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
+}
+
+Uint32
+SDL_SemValue(SDL_sem * sem)
+{
+ if (! sem)
+ {
+ SDL_SetError("Passed a NULL sem.");
+ return 0;
+ }
+ return sem->count;
+}
+
+int
+SDL_SemPost(SDL_sem * sem)
+{
+ if (! sem)
+ {
+ SDL_SetError("Passed a NULL sem.");
+ return -1;
+ }
+ sem->count++;
+ RSemaphore sema;
+ sema.SetHandle(sem->handle);
+ sema.Signal();
+ return 0;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/thread/ngage/SDL_systhread.cpp b/src/thread/ngage/SDL_systhread.cpp
new file mode 100644
index 00000000000..18596d99469
--- /dev/null
+++ b/src/thread/ngage/SDL_systhread.cpp
@@ -0,0 +1,147 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_THREAD_NGAGE
+
+/* N-Gage thread management routines for SDL */
+
+#include <e32std.h>
+
+extern "C" {
+#undef NULL
+#include "SDL_error.h"
+#include "SDL_thread.h"
+#include "../SDL_systhread.h"
+#include "../SDL_thread_c.h"
+};
+
+static int object_count;
+
+static int
+RunThread(TAny* data)
+{
+ SDL_RunThread((SDL_Thread*)data);
+ return(0);
+}
+
+static TInt
+NewThread(const TDesC& aName, TAny* aPtr1, TAny* aPtr2)
+{
+ return ((RThread*)(aPtr1))->Create
+ (aName,
+ RunThread,
+ KDefaultStackSize,
+ NULL,
+ aPtr2);
+}
+
+int
+CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny* aPtr1, TAny* aPtr2)
+{
+ TBuf<16> name;
+ TInt status = KErrNone;
+ do
+ {
+ object_count++;
+ name.Format(_L("SDL_%x"), object_count);
+ status = aFunc(name, aPtr1, aPtr2);
+ }
+ while(status == KErrAlreadyExists);
+ return status;
+}
+
+int
+SDL_SYS_CreateThread(SDL_Thread *thread)
+{
+ RThread rthread;
+
+ TInt status = CreateUnique(NewThread, &rthread, thread);
+ if (status != KErrNone)
+ {
+ delete(((RThread*)(thread->handle)));
+ thread->handle = NULL;
+ SDL_SetError("Not enough resources to create thread");
+ return(-1);
+ }
+
+ rthread.Resume();
+ thread->handle = rthread.Handle();
+ return(0);
+}
+
+void
+SDL_SYS_SetupThread(const char *name)
+{
+ return;
+}
+
+SDL_threadID
+SDL_ThreadID(void)
+{
+ RThread current;
+ TThreadId id = current.Id();
+ return id;
+}
+
+int
+SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
+{
+ return (0);
+}
+
+void
+SDL_SYS_WaitThread(SDL_Thread * thread)
+{
+ RThread t;
+ t.Open(thread->threadid);
+ if(t.ExitReason() == EExitPending)
+ {
+ TRequestStatus status;
+ t.Logon(status);
+ User::WaitForRequest(status);
+ }
+ t.Close();
+}
+
+void
+SDL_SYS_DetachThread(SDL_Thread * thread)
+{
+ return;
+}
+
+/* WARNING: This function is really a last resort.
+ * Threads should be signaled and then exit by themselves.
+ * TerminateThread() doesn't perform stack and DLL cleanup.
+ */
+void
+SDL_SYS_KillThread(SDL_Thread *thread)
+{
+ RThread rthread;
+ rthread.SetHandle(thread->handle);
+ rthread.Kill(0);
+ rthread.Close();
+}
+
+#endif /* SDL_THREAD_NGAGE */
+
+/* vim: ts=4 sw=4
+ */
diff --git a/src/thread/ngage/SDL_systhread_c.h b/src/thread/ngage/SDL_systhread_c.h
new file mode 100644
index 00000000000..dedceb3965a
--- /dev/null
+++ b/src/thread/ngage/SDL_systhread_c.h
@@ -0,0 +1,25 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+typedef int SYS_ThreadHandle;
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/timer/ngage/SDL_systimer.cpp b/src/timer/ngage/SDL_systimer.cpp
new file mode 100644
index 00000000000..543d8494d75
--- /dev/null
+++ b/src/timer/ngage/SDL_systimer.cpp
@@ -0,0 +1,100 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if defined(SDL_TIMER_NGAGE)
+
+#include <e32std.h>
+#include <e32hal.h>
+
+#include "SDL_timer.h"
+
+static SDL_bool ticks_started = SDL_FALSE;
+static TUint start = 0;
+static TInt tickPeriodMilliSeconds;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+SDL_TicksInit(void)
+{
+ if (ticks_started)
+ {
+ return;
+ }
+ ticks_started = SDL_TRUE;
+ start = User::TickCount();
+
+ TTimeIntervalMicroSeconds32 period;
+ TInt tmp = UserHal::TickPeriod(period);
+
+ (void)tmp; /* Suppress redundant warning. */
+
+ tickPeriodMilliSeconds = period.Int() / 1000;
+}
+
+void
+SDL_TicksQuit(void)
+{
+ ticks_started = SDL_FALSE;
+}
+
+Uint64
+SDL_GetTicks64(void)
+{
+ if (! ticks_started)
+ {
+ SDL_TicksInit();
+ }
+
+ TUint deltaTics = User::TickCount() - start;
+
+ // Overlaps early, but should do the trick for now.
+ return (Uint64)(deltaTics * tickPeriodMilliSeconds);
+}
+
+Uint64
+SDL_GetPerformanceCounter(void)
+{
+ return (Uint64)User::TickCount();
+}
+
+Uint64
+SDL_GetPerformanceFrequency(void)
+{
+ return 1000000;
+}
+
+void
+SDL_Delay(Uint32 ms)
+{
+ User::After(TTimeIntervalMicroSeconds32(ms * 1000));
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SDL_TIMER_NGAGE */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index b68b92c3786..cea3f542c9c 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -457,6 +457,7 @@ extern VideoBootStrap VIVANTE_bootstrap;
extern VideoBootStrap Emscripten_bootstrap;
extern VideoBootStrap QNX_bootstrap;
extern VideoBootStrap OFFSCREEN_bootstrap;
+extern VideoBootStrap NGAGE_bootstrap;
extern VideoBootStrap OS2DIVE_bootstrap;
extern VideoBootStrap OS2VMAN_bootstrap;
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 2b896c44ba2..059316a5dd5 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -118,6 +118,9 @@ static VideoBootStrap *bootstrap[] = {
#if SDL_VIDEO_DRIVER_OFFSCREEN
&OFFSCREEN_bootstrap,
#endif
+#if SDL_VIDEO_DRIVER_NGAGE
+ &NGAGE_bootstrap,
+#endif
#if SDL_VIDEO_DRIVER_OS2
&OS2DIVE_bootstrap,
&OS2VMAN_bootstrap,
diff --git a/src/video/ngage/SDL_ngageevents.cpp b/src/video/ngage/SDL_ngageevents.cpp
new file mode 100644
index 00000000000..239f6b62c59
--- /dev/null
+++ b/src/video/ngage/SDL_ngageevents.cpp
@@ -0,0 +1,200 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_NGAGE
+
+/* Being a ngage driver, there's no event stream. We just define stubs for
+ most of the API. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../events/SDL_events_c.h"
+#include "../../events/SDL_keyboard_c.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "SDL_ngagevideo.h"
+#include "SDL_ngageevents_c.h"
+
+int HandleWsEvent(_THIS, const TWsEvent& aWsEvent);
+
+void
+NGAGE_PumpEvents(_THIS)
+{
+ SDL_VideoData *phdata = (SDL_VideoData*)_this->driverdata;
+
+ while (phdata->NGAGE_WsEventStatus != KRequestPending)
+ {
+ phdata->NGAGE_WsSession.GetEvent(phdata->NGAGE_WsEvent);
+
+ HandleWsEvent(_this, phdata->NGAGE_WsEvent);
+
+ phdata->NGAGE_WsEventStatus = KRequestPending;
+ phdata->NGAGE_WsSession.EventReady(&phdata->NGAGE_WsEventStatus);
+ }
+}
+
+/*****************************************************************************/
+/* Internal */
+/*****************************************************************************/
+
+#include <bautils.h>
+#include <hal.h>
+
+extern void DisableKeyBlocking(_THIS);
+extern void RedrawWindowL(_THIS);
+
+TBool isCursorVisible = EFalse;
+
+static SDL_Scancode ConvertScancode(_THIS, int key)
+{
+ SDL_Keycode keycode;
+
+ switch(key)
+ {
+ case EStdKeyBackspace: // Clear key
+ keycode = SDLK_BACKSPACE;
+ break;
+ case 0x31: // 1
+ keycode = SDLK_1;
+ break;
+ case 0x32: // 2
+ keycode = SDLK_2;
+ break;
+ case 0x33: // 3
+ keycode = SDLK_3;
+ break;
+ case 0x34: // 4
+ keycode = SDLK_4;
+ break;
+ case 0x35: // 5
+ keycode = SDLK_5;
+ break;
+ case 0x36: // 6
+
(Patch may be truncated, please check the link at the top of this post.)