From b407add14e47e12d738e7b3c4c4747fcdb5e069d Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Wed, 18 Dec 2019 01:26:24 +0100 Subject: [PATCH 01/93] neverball: port dir_list_files() to win32 --- share/dir.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/share/dir.c b/share/dir.c index 433d9dd50..51524e6ff 100644 --- a/share/dir.c +++ b/share/dir.c @@ -12,7 +12,11 @@ * General Public License for more details. */ +#ifndef _WIN32 #include +#else +#include +#endif #include #include @@ -21,17 +25,13 @@ #include "dir.h" #include "common.h" -/* - * HACK: MinGW provides numerous POSIX extensions to MSVCRT, including - * dirent.h, so parasti ever so lazily has not bothered to port the - * code below to FindFirstFile et al. - */ - List dir_list_files(const char *path) { - DIR *dir; List files = NULL; +#ifndef _WIN32 + DIR *dir; + if ((dir = opendir(path))) { struct dirent *ent; @@ -46,6 +46,24 @@ List dir_list_files(const char *path) closedir(dir); } +#else + HANDLE hFind; + WIN32_FIND_DATA FindFileData; + + hFind = FindFirstFile(path, &FindFileData); + if (hFind != INVALID_HANDLE_VALUE) + { + BOOL status = TRUE; + while(status != FALSE) + { + //FIXME: Handle wide strings? + files = list_cons(strdup(FindFileData.cFileName), files); + + FindNextFile(hFind, &FindFileData); + } + FindClose(hFind); + } +#endif return files; } From 365e4d5cfe06b2afa717cdd6d7849998ff5f3a64 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Wed, 18 Dec 2019 01:26:52 +0100 Subject: [PATCH 02/93] neverball: port dir_exists() to win32 --- share/dir.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/share/dir.c b/share/dir.c index 51524e6ff..3a434422e 100644 --- a/share/dir.c +++ b/share/dir.c @@ -140,6 +140,7 @@ void dir_free(Array items) int dir_exists(const char *path) { +#ifndef _WIN32 DIR *dir; if ((dir = opendir(path))) @@ -148,4 +149,10 @@ int dir_exists(const char *path) return 1; } return 0; +#else + DWORD dwAttrib = GetFileAttributes(path); + + return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && + (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) ? 1 : 0; +#endif } From aa02e657a24f165037e285c730b964a435036ed1 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Wed, 18 Dec 2019 01:25:24 +0100 Subject: [PATCH 03/93] neverball: pick xbox home path for NXDK --- share/base_config.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/share/base_config.c b/share/base_config.c index c07f175ca..858f3fe20 100644 --- a/share/base_config.c +++ b/share/base_config.c @@ -23,8 +23,10 @@ #include "fs.h" #ifdef _WIN32 +#ifndef NXDK #include #endif +#endif /*---------------------------------------------------------------------------*/ @@ -52,6 +54,7 @@ static const char *pick_data_path(const char *arg_data_path) static const char *pick_home_path(void) { #ifdef _WIN32 +#ifndef NXDK static char path[MAX_PATH]; if (SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, path) == S_OK) @@ -68,6 +71,10 @@ static const char *pick_home_path(void) } else return fs_base_dir(); +#else + //FIXME: Xbox + return fs_base_dir(); +#endif #else const char *path; From b4b62186085aa7199ba431db930a020ed621f46f Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Wed, 18 Dec 2019 01:25:56 +0100 Subject: [PATCH 04/93] neverball: disable set_env_var() for NXDK --- share/common.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/share/common.c b/share/common.c index 49cc2c791..0c629f0be 100644 --- a/share/common.c +++ b/share/common.c @@ -332,11 +332,14 @@ int rand_between(int low, int high) #ifdef _WIN32 +#ifndef NXDK /* MinGW hides this from ANSI C. MinGW-w64 doesn't. */ _CRTIMP int _putenv(const char *envstring); +#endif int set_env_var(const char *name, const char *value) { +#ifndef NXDK if (name) { char str[MAXSTR]; @@ -348,6 +351,7 @@ int set_env_var(const char *name, const char *value) return (_putenv(str) == 0); } +#endif return 0; } From 8aa529ffd625343a6eb335109ac7c04645c0c660 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Wed, 18 Dec 2019 01:27:24 +0100 Subject: [PATCH 05/93] disable SDL_GL_SetAttribute for NXDK --- share/video.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/share/video.c b/share/video.c index c687e9389..61748ea17 100644 --- a/share/video.c +++ b/share/video.c @@ -154,6 +154,7 @@ int video_mode(int f, int w, int h) SDL_DestroyWindow(window); } +#ifndef NXDK #if ENABLE_OPENGLES SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); @@ -172,6 +173,7 @@ int video_mode(int f, int w, int h) SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); +#endif /* Try to set the currently specified mode. */ From d10ea3282763bc54344fa78bd2ae3f023cb4396e Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Wed, 18 Dec 2019 01:25:02 +0100 Subject: [PATCH 06/93] Add Dummy Xbox Port --- .gitignore | 7 + Makefile.nxdk | 125 ++ xbox/EGL/egl.h | 10 + xbox/EGL/eglplatform.h | 99 ++ xbox/GLES/gl.h | 320 +++++ xbox/Makefile-libjpeg-turbo.xbox | 74 ++ xbox/Makefile-libpng.xbox | 25 + xbox/Makefile-ogg.xbox | 8 + xbox/Makefile-vorbis.xbox | 31 + xbox/Makefile-zlib.xbox | 18 + xbox/_windows.h | 11 + xbox/alloca.h | 1 + xbox/direct.h | 1 + xbox/dirent.h | 13 + xbox/features.h | 0 xbox/malloc.h | 0 xbox/matrix.h | 318 +++++ xbox/neverballrc | 85 ++ xbox/sys/stat.h | 7 + xbox/sys/time.h | 10 + xbox/xbox.c | 1938 ++++++++++++++++++++++++++++++ 21 files changed, 3101 insertions(+) create mode 100644 Makefile.nxdk create mode 100644 xbox/EGL/egl.h create mode 100644 xbox/EGL/eglplatform.h create mode 100644 xbox/GLES/gl.h create mode 100644 xbox/Makefile-libjpeg-turbo.xbox create mode 100644 xbox/Makefile-libpng.xbox create mode 100644 xbox/Makefile-ogg.xbox create mode 100644 xbox/Makefile-vorbis.xbox create mode 100644 xbox/Makefile-zlib.xbox create mode 100644 xbox/_windows.h create mode 100644 xbox/alloca.h create mode 100644 xbox/direct.h create mode 100644 xbox/dirent.h create mode 100644 xbox/features.h create mode 100644 xbox/malloc.h create mode 100644 xbox/matrix.h create mode 100644 xbox/neverballrc create mode 100644 xbox/sys/stat.h create mode 100644 xbox/sys/time.h create mode 100644 xbox/xbox.c diff --git a/.gitignore b/.gitignore index 45237358b..ea47b41c9 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,10 @@ /mapc.exe /contrib/curve.exe /*.dll + +*.obj +/bin +/main.exe +/main.lib +/*.iso +/default.xbe diff --git a/Makefile.nxdk b/Makefile.nxdk new file mode 100644 index 000000000..bf1bb2928 --- /dev/null +++ b/Makefile.nxdk @@ -0,0 +1,125 @@ +NXDK_DIR = $(CURDIR)/../XboxDev/nxdk + +XBE_TITLE = NeverballX +OUTPUT_DIR = bin +GEN_XISO = $(XBE_TITLE).iso + +CFLAGS = + +CFLAGS += -ferror-limit=0 + +CFLAGS += -DENABLE_OPENGLES=1 +#CFLAGS += -DCONFIG_USER=\"$(USERDIR)\" \ +#CFLAGS += -DCONFIG_DATA=\"$(DATADIR)\" \ +#CFLAGS += -DCONFIG_LOCALE=\"$(LOCALEDIR)\" +CFLAGS += -I$(CURDIR)/share/ -I$(CURDIR)/xbox/ -D_CRTIMP= + +BALL_SRCS := \ + $(CURDIR)/share/lang.c \ + $(CURDIR)/share/st_common.c \ + $(CURDIR)/share/vec3.c \ + $(CURDIR)/share/base_image.c \ + $(CURDIR)/share/image.c \ + $(CURDIR)/share/solid_base.c \ + $(CURDIR)/share/solid_vary.c \ + $(CURDIR)/share/solid_draw.c \ + $(CURDIR)/share/solid_all.c \ + $(CURDIR)/share/mtrl.c \ + $(CURDIR)/share/part.c \ + $(CURDIR)/share/geom.c \ + $(CURDIR)/share/ball.c \ + $(CURDIR)/share/gui.c \ + $(CURDIR)/share/font.c \ + $(CURDIR)/share/theme.c \ + $(CURDIR)/share/base_config.c \ + $(CURDIR)/share/config.c \ + $(CURDIR)/share/video.c \ + $(CURDIR)/share/glext.c \ + $(CURDIR)/share/binary.c \ + $(CURDIR)/share/state.c \ + $(CURDIR)/share/audio.c \ + $(CURDIR)/share/text.c \ + $(CURDIR)/share/common.c \ + $(CURDIR)/share/list.c \ + $(CURDIR)/share/queue.c \ + $(CURDIR)/share/cmd.c \ + $(CURDIR)/share/array.c \ + $(CURDIR)/share/dir.c \ + $(CURDIR)/share/fbo.c \ + $(CURDIR)/share/glsl.c \ + $(CURDIR)/share/fs_common.c \ + $(CURDIR)/share/fs_png.c \ + $(CURDIR)/share/fs_jpg.c \ + $(CURDIR)/share/fs_ov.c \ + $(CURDIR)/share/log.c \ + $(CURDIR)/share/joy.c \ + $(CURDIR)/ball/hud.c \ + $(CURDIR)/ball/game_common.c \ + $(CURDIR)/ball/game_client.c \ + $(CURDIR)/ball/game_server.c \ + $(CURDIR)/ball/game_proxy.c \ + $(CURDIR)/ball/game_draw.c \ + $(CURDIR)/ball/score.c \ + $(CURDIR)/ball/level.c \ + $(CURDIR)/ball/progress.c \ + $(CURDIR)/ball/set.c \ + $(CURDIR)/ball/demo.c \ + $(CURDIR)/ball/demo_dir.c \ + $(CURDIR)/ball/util.c \ + $(CURDIR)/ball/st_conf.c \ + $(CURDIR)/ball/st_demo.c \ + $(CURDIR)/ball/st_save.c \ + $(CURDIR)/ball/st_goal.c \ + $(CURDIR)/ball/st_fail.c \ + $(CURDIR)/ball/st_done.c \ + $(CURDIR)/ball/st_level.c \ + $(CURDIR)/ball/st_over.c \ + $(CURDIR)/ball/st_play.c \ + $(CURDIR)/ball/st_set.c \ + $(CURDIR)/ball/st_start.c \ + $(CURDIR)/ball/st_title.c \ + $(CURDIR)/ball/st_help.c \ + $(CURDIR)/ball/st_name.c \ + $(CURDIR)/ball/st_shared.c \ + $(CURDIR)/ball/st_pause.c \ + $(CURDIR)/ball/st_ball.c \ + $(CURDIR)/ball/main.c + +BALL_SRCS += share/solid_sim_sol.c +BALL_SRCS += share/fs_stdio.c +BALL_SRCS += share/tilt_null.c +BALL_SRCS += share/hmd_null.c + +SRCS = $(BALL_SRCS) xbox/xbox.c +#SHADER_OBJS = ps.inl vs.inl + +# Add SDL +NXDK_SDL = y + +# Add vorbis and ogg +include $(CURDIR)/xbox/Makefile-vorbis.xbox +include $(CURDIR)/xbox/Makefile-ogg.xbox + +# Add libjpeg +include $(CURDIR)/xbox/Makefile-libjpeg-turbo.xbox + +# Add libpng (depends on zlib) +include $(CURDIR)/xbox/Makefile-zlib.xbox +include $(CURDIR)/xbox/Makefile-libpng.xbox + +# XGU +CFLAGS += -I$(CURDIR)/xbox/nxdk/lib + +all: $(OUTPUT_DIR)/default.xbe data $(GEN_XISO) + +# Add data to XISO +#FIXME: Copy files to $(OUTPUT_DIR) +data: force + @echo "Updating data" + @cp -r $(CURDIR)/data $(OUTPUT_DIR)/Neverball + @echo "Updating config" + @cp -r $(CURDIR)/xbox/neverballrc $(OUTPUT_DIR)/Neverball #FIXME: Buggy + +force: + +include $(NXDK_DIR)/Makefile diff --git a/xbox/EGL/egl.h b/xbox/EGL/egl.h new file mode 100644 index 000000000..dd0ae283e --- /dev/null +++ b/xbox/EGL/egl.h @@ -0,0 +1,10 @@ +typedef unsigned int EGLBoolean; +typedef void *EGLDisplay; +#include +typedef void *EGLConfig; +typedef void *EGLSurface; +typedef void *EGLContext; + +#define EGL_TRUE 1 + +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface); diff --git a/xbox/EGL/eglplatform.h b/xbox/EGL/eglplatform.h new file mode 100644 index 000000000..287ce2931 --- /dev/null +++ b/xbox/EGL/eglplatform.h @@ -0,0 +1,99 @@ +#ifndef __eglplatform_h_ +#define __eglplatform_h_ + +/* +** Copyright (c) 2007-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Platform-specific types and definitions for egl.h + * $Revision: 30994 $ on $Date: 2015-04-30 13:36:48 -0700 (Thu, 30 Apr 2015) $ + * + * Adopters may modify khrplatform.h and this file to suit their platform. + * You are encouraged to submit all modifications to the Khronos group so that + * they can be included in future versions of this file. Please submit changes + * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla) + * by filing a bug against product "EGL" component "Registry". + */ + +/* Macros used in EGL function prototype declarations. + * + * EGL functions should be prototyped as: + * + * EGLAPI return-type EGLAPIENTRY eglFunction(arguments); + * typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments); + * + * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h + */ + +#ifndef EGLAPI +#define EGLAPI +#endif + +#ifndef EGLAPIENTRY +#define EGLAPIENTRY +#endif +#define EGLAPIENTRYP EGLAPIENTRY* + +/* The types NativeDisplayType, NativeWindowType, and NativePixmapType + * are aliases of window-system-dependent types, such as X Display * or + * Windows Device Context. They must be defined in platform-specific + * code below. The EGL-prefixed versions of Native*Type are the same + * types, renamed in EGL 1.3 so all types in the API start with "EGL". + * + * Khronos STRONGLY RECOMMENDS that you use the default definitions + * provided below, since these changes affect both binary and source + * portability of applications using EGL running on different EGL + * implementations. + */ + +#if defined(NXDK) +typedef void *EGLNativeDisplayType; +typedef void *EGLNativePixmapType; +typedef void *EGLNativeWindowType; +#else +#error "Platform not recognized" +#endif + +/* EGL 1.2 types, renamed for consistency in EGL 1.3 */ +typedef EGLNativeDisplayType NativeDisplayType; +typedef EGLNativePixmapType NativePixmapType; +typedef EGLNativeWindowType NativeWindowType; + + +/* Define EGLint. This must be a signed integral type large enough to contain + * all legal attribute names and values passed into and out of EGL, whether + * their type is boolean, bitmask, enumerant (symbolic constant), integer, + * handle, or other. While in general a 32-bit integer will suffice, if + * handles are 64 bit types, then EGLint should be defined as a signed 64-bit + * integer type. + */ +typedef unsigned int EGLint; + + +/* C++ / C typecast macros for special EGL handle values */ +#if defined(__cplusplus) +#define EGL_CAST(type, value) (static_cast(value)) +#else +#define EGL_CAST(type, value) ((type) (value)) +#endif + +#endif /* __eglplatform_h */ diff --git a/xbox/GLES/gl.h b/xbox/GLES/gl.h new file mode 100644 index 000000000..55f43390a --- /dev/null +++ b/xbox/GLES/gl.h @@ -0,0 +1,320 @@ +typedef float GLfloat; +typedef int GLboolean; +typedef int GLenum; +typedef int GLint; +typedef int GLsizei; +typedef short GLshort; +typedef unsigned char GLubyte; +typedef unsigned int GLuint; +typedef unsigned short GLushort; +typedef void GLvoid; +typedef int GLsizeiptr; +typedef int GLintptr; +typedef unsigned int GLbitfield; + +#define GL_FALSE 0 +#define GL_TRUE 1 + + + +// Hopefully each of these is unique.. +#define GL_ALPHA_TEST 10001 + +#define GL_ALWAYS 10002 + +#define GL_AMBIENT 10003 + +#define GL_BACK 10004 + +#define GL_CCW 10005 + +#define GL_CLAMP_TO_EDGE 10006 + +#define GL_CLIP_PLANE0 10007 +#define GL_CLIP_PLANE1 10008 +#define GL_CLIP_PLANE2 10009 + +#define GL_COLOR_BUFFER_BIT 10010 + +#define GL_COLOR_MATERIAL 10011 + +#define GL_CULL_FACE 10012 + +#define GL_CW 10013 + +#define GL_DEPTH_BUFFER_BIT 10014 +#define GL_DEPTH_TEST 10015 + +#define GL_DIFFUSE 10016 +#define GL_EMISSION 10017 + +#define GL_EQUAL 10018 + +#define GL_EXTENSIONS 10019 + +#define GL_REPEAT 10020 + +#define GL_FLOAT 10021 + +#define GL_FRONT 10022 +#define GL_FRONT_AND_BACK 10023 + +#define GL_GEQUAL 10024 +#define GL_GREATER 10025 + +#define GL_KEEP 10026 + +#define GL_LEQUAL 10027 +#define GL_LESS 10028 + +#define GL_STENCIL_TEST 10029 + +#define GL_LIGHTING 10030 +#define GL_LIGHT_MODEL_AMBIENT 10031 +#define GL_LIGHT_MODEL_TWO_SIDE 10032 + +#define GL_LINEAR 10033 + +#define GL_LUMINANCE 10034 +#define GL_LUMINANCE_ALPHA 10035 + +#define GL_MAX_TEXTURE_SIZE 10036 +#define GL_MAX_TEXTURE_UNITS 10037 + +#define GL_MODELVIEW 10038 + +#define GL_NEVER 10039 + +#define GL_NORMAL_ARRAY 10040 + +#define GL_NOTEQUAL 10041 + +#define GL_ONE 10042 +#define GL_ONE_MINUS_SRC_ALPHA 10043 + +#define GL_PACK_ALIGNMENT 10044 + +#define GL_POINTS 10045 + +#define GL_POLYGON_OFFSET_FILL 10046 + +#define GL_POSITION 10047 + +#define GL_PROJECTION 10048 + +#define GL_RENDERER 10049 + +#define GL_REPLACE 10050 + +#define GL_RGB 10051 +#define GL_RGBA 10052 + +#define GL_SHININESS 10053 +#define GL_SPECULAR 10054 +#define GL_SRC_ALPHA 10055 + +#define GL_STENCIL_BUFFER_BIT 10056 + +#define GL_TEXTURE 10057 +#define GL_TEXTURE_2D 10058 +#define GL_TEXTURE_COORD_ARRAY 10059 + +#define GL_TEXTURE_MAG_FILTER 10060 +#define GL_TEXTURE_MIN_FILTER 10061 +#define GL_TEXTURE_WRAP_S 10062 +#define GL_TEXTURE_WRAP_T 10063 + +#define GL_TRIANGLES 10064 +#define GL_TRIANGLE_STRIP 10065 + +#define GL_UNPACK_ALIGNMENT 10066 + +#define GL_UNSIGNED_BYTE 10067 +#define GL_UNSIGNED_SHORT 10068 + +#define GL_VENDOR 10069 +#define GL_VERSION 10070 + +#define GL_VERTEX_ARRAY 10071 +#define GL_COLOR_ARRAY 10072 + +#define GL_SHORT 10073 + +#define GL_NORMALIZE 10074 +#define GL_BLEND 10075 + +#define GL_LIGHT0 10076 +#define GL_LIGHT1 10077 +#define GL_LIGHT2 10078 + +#define GL_COMBINE 10079 +#define GL_COMBINE_ALPHA 10080 +#define GL_COMBINE_RGB 10081 + +#define GL_INTERPOLATE 10082 +#define GL_MODULATE 10083 +#define GL_NEAREST 10084 + +#define GL_OPERAND0_ALPHA 10085 + +#define GL_OPERAND0_RGB 10086 +#define GL_OPERAND1_RGB 10087 +#define GL_OPERAND2_RGB 10088 + +#define GL_PREVIOUS 10089 +#define GL_PRIMARY_COLOR 10090 + +#define GL_SRC_COLOR 10091 + +#define GL_TEXTURE_ENV 10092 +#define GL_TEXTURE_ENV_MODE 10093 + + + +// Not used in neverball, only for completeness +#define GL_ONE_MINUS_SRC_COLOR 20000 +#define GL_SOURCE_ALPHA 20001 +#define GL_CONSTANT 20002 +#define GL_ALPHA 20003 +#define GL_NEAREST_MIPMAP_LINEAR 20004 + + + + + + + +// Defined in Neverball share/glext.h +#if 0 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_LINK_STATUS 0x8B82 +#define GL_MULTISAMPLE 0x809D +#define GL_POINT_DISTANCE_ATTENUATION 0x8129 +#define GL_POINT_SIZE_MAX 0x8127 +#define GL_POINT_SIZE_MIN 0x8126 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_VERTEX_SHADER 0x8B31 +#else +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_SRC0_RGB 0x8580 +#define GL_SRC1_RGB 0x8581 +#define GL_SRC2_RGB 0x8582 +#define GL_SRC0_ALPHA 0x8588 +#define GL_POINT_SPRITE 0x8861 +#define GL_COORD_REPLACE 0x8862 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#endif + + + + +// Funtion specifiers +#define GL_API +#define GL_APIENTRY + + +// Getters +GL_API void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data); +GL_API const GLubyte *GL_APIENTRY glGetString (GLenum name); + +// Clearing +GL_API void GL_APIENTRY glClear (GLbitfield mask); +GL_API void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); + +// Buffers +GL_API void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers); +GL_API void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); +GL_API void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage); +GL_API void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); +GL_API void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers); + +// Vertex buffers +GL_API void GL_APIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const void *pointer); +GL_API void GL_APIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const void *pointer); +GL_API void GL_APIENTRY glNormalPointer (GLenum type, GLsizei stride, const void *pointer); +GL_API void GL_APIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const void *pointer); + +// Draw calls +GL_API void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GL_API void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices); + +// Matrix functions +GL_API void GL_APIENTRY glMatrixMode (GLenum mode); +GL_API void GL_APIENTRY glLoadIdentity (void); +GL_API void GL_APIENTRY glMultMatrixf (const GLfloat *m); +GL_API void GL_APIENTRY glOrthof (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); +GL_API void GL_APIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z); +GL_API void GL_APIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +GL_API void GL_APIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z); +GL_API void GL_APIENTRY glPopMatrix (void); +GL_API void GL_APIENTRY glPushMatrix (void); + +// Framebuffer setup +GL_API void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); + +// Textures +GL_API void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures); +GL_API void GL_APIENTRY glBindTexture (GLenum target, GLuint texture); +GL_API void GL_APIENTRY glActiveTexture (GLenum texture); +GL_API void GL_APIENTRY glClientActiveTexture (GLenum texture); +GL_API void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); +GL_API void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +GL_API void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); + +// Renderstates +GL_API void GL_APIENTRY glAlphaFunc (GLenum func, GLfloat ref); +GL_API void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GL_API void GL_APIENTRY glClipPlanef (GLenum p, const GLfloat *eqn); +GL_API void GL_APIENTRY glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +GL_API void GL_APIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GL_API void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GL_API void GL_APIENTRY glDepthFunc (GLenum func); +GL_API void GL_APIENTRY glDepthMask (GLboolean flag); +GL_API void GL_APIENTRY glEnable (GLenum cap); +GL_API void GL_APIENTRY glDisable (GLenum cap); +GL_API void GL_APIENTRY glEnableClientState (GLenum array); +GL_API void GL_APIENTRY glDisableClientState (GLenum array); +GL_API void GL_APIENTRY glCullFace (GLenum mode); +GL_API void GL_APIENTRY glFrontFace (GLenum mode); + +// Stencil actions +GL_API void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GL_API void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); + +// Misc. +GL_API void GL_APIENTRY glPointParameterf (GLenum pname, GLfloat param); +GL_API void GL_APIENTRY glPointParameterfv (GLenum pname, const GLfloat *params); +GL_API void GL_APIENTRY glPointSize (GLfloat size); +GL_API void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); + +// TexEnv +GL_API void GL_APIENTRY glTexEnvi (GLenum target, GLenum pname, GLint param); + +// Pixel readback +GL_API void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); + +// Lighting +GL_API void GL_APIENTRY glLightModelf (GLenum pname, GLfloat param); +GL_API void GL_APIENTRY glLightModelfv (GLenum pname, const GLfloat *params); +GL_API void GL_APIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params); + +// Materials +GL_API void GL_APIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params); + +// Pixel pushing +GL_API void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); + diff --git a/xbox/Makefile-libjpeg-turbo.xbox b/xbox/Makefile-libjpeg-turbo.xbox new file mode 100644 index 000000000..9b5563ca2 --- /dev/null +++ b/xbox/Makefile-libjpeg-turbo.xbox @@ -0,0 +1,74 @@ +#FIXME: Depends on jconfig.h being fixed up; modify: +# //#define NEED_SYS_TYPES_H 1 +# //#define NEED_BSD_STRINGS 1 +# // #define __CHAR_UNSIGNED__ 1 +#FIXME: Depends on jconfigint.h being fixed up; modify: +# #define SIZEOF_SIZE_T 4 //@SIZE_T@ +# //#cmakedefine HAVE_BUILTIN_CTZL +# //#cmakedefine HAVE_INTRIN_H +#FIXME: Extend `#if !defined(__MINGW32__) && !defined(NXDK)` in tjutil.h + +#LIBJPEG_TURBO_DIR = $(NXDK_DIR)/lib/libjpeg-turbo +LIBJPEG_TURBO_DIR = $(CURDIR)/xbox/nxdk-libjpeg-turbo + +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcapimin.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcapistd.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jccoefct.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jccolor.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcdctmgr.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jchuff.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcicc.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcinit.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcmainct.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcmarker.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcmaster.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcomapi.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcparam.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcphuff.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcprepct.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcsample.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jctrans.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdapimin.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdapistd.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdatadst.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdatasrc.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdcoefct.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdcolor.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jddctmgr.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdhuff.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdicc.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdinput.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdmainct.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdmarker.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdmaster.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdmerge.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdphuff.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdpostct.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdsample.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdtrans.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jerror.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jfdctflt.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jfdctfst.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jfdctint.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jidctflt.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jidctfst.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jidctint.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jidctred.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jquant1.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jquant2.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jutils.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jmemmgr.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jmemnobs.c) + +#FIXME: Support simd/i386/*-mmx.asm and simd/i386/*-sse.asm +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jsimd_none.c) + +#FIXME: These 3 are optional, not sure why we require them right now +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jaricom.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcarith.c) +LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdarith.c) + +SRCS += $(LIBJPEG_TURBO_SRCS) +CFLAGS += -isystem $(LIBJPEG_TURBO_DIR) +# Ideally we'd use -D__MINGW32__ here, so we can compile this lib without +# changes, but that won't work with global CFLAGS diff --git a/xbox/Makefile-libpng.xbox b/xbox/Makefile-libpng.xbox new file mode 100644 index 000000000..d5ec84f08 --- /dev/null +++ b/xbox/Makefile-libpng.xbox @@ -0,0 +1,25 @@ +#FIXME: Needs to copy $(LIBPNG_DIR)/scripts/pnglibconf.h.prebuilt to $(LIBPNG_DIR)/pnglibconf.h; modify: +# //#define PNG_FLOATING_ARITHMETIC_SUPPORTED +# //#define PNG_FLOATING_POINT_SUPPORTED + +#LIBPNG_DIR = $(NXDK_DIR)/lib/libpng +LIBPNG_DIR = $(CURDIR)/xbox/nxdk-libpng + +LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/png.c) +LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngerror.c) +LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngget.c) +LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngmem.c) +LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngpread.c) +LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngread.c) +LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngrio.c) +LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngrtran.c) +LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngrutil.c) +LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngset.c) +LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngtrans.c) +LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngwio.c) +LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngwrite.c) +LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngwtran.c) +LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngwutil.c) + +SRCS += $(LIBPNG_SRCS) +CFLAGS += -isystem $(LIBPNG_DIR) diff --git a/xbox/Makefile-ogg.xbox b/xbox/Makefile-ogg.xbox new file mode 100644 index 000000000..1cec027f2 --- /dev/null +++ b/xbox/Makefile-ogg.xbox @@ -0,0 +1,8 @@ +#OGG_DIR = $(NXDK_DIR)/lib/ogg +OGG_DIR = $(CURDIR)/xbox/nxdk-ogg + +OGG_SRCS += $(wildcard $(OGG_DIR)/src/framing.c) +OGG_SRCS += $(wildcard $(OGG_DIR)/src/bitwise.c) + +SRCS += $(OGG_SRCS) +CFLAGS += -isystem $(OGG_DIR)/include diff --git a/xbox/Makefile-vorbis.xbox b/xbox/Makefile-vorbis.xbox new file mode 100644 index 000000000..87e4711ad --- /dev/null +++ b/xbox/Makefile-vorbis.xbox @@ -0,0 +1,31 @@ +#VORBIS_DIR = $(NXDK_DIR)/lib/vorbis +VORBIS_DIR = $(CURDIR)/xbox/nxdk-vorbis + +# libvorbis +VORBIS_SRCS += $(VORBIS_DIR)/lib/analysis.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/bitrate.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/block.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/codebook.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/envelope.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/floor0.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/floor1.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/info.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/lookup.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/lpc.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/lsp.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/mapping0.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/mdct.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/psy.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/registry.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/res0.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/sharedbook.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/smallft.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/synthesis.c +VORBIS_SRCS += $(VORBIS_DIR)/lib/window.c + +# libvorbisfile +VORBIS_SRCS += $(VORBIS_DIR)/lib/vorbisfile.c + +SRCS += $(VORBIS_SRCS) +CFLAGS += -isystem $(VORBIS_DIR)/include \ + -DHAVE_ALLOCA_H diff --git a/xbox/Makefile-zlib.xbox b/xbox/Makefile-zlib.xbox new file mode 100644 index 000000000..5dca0d4b9 --- /dev/null +++ b/xbox/Makefile-zlib.xbox @@ -0,0 +1,18 @@ +#ZLIB_DIR = $(NXDK_DIR)/lib/zlib +ZLIB_DIR = $(CURDIR)/xbox/nxdk-zlib + +ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/adler32.c) +ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/crc32.c) +ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/deflate.c) +ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/infback.c) +ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/inffast.c) +ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/inflate.c) +ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/inftrees.c) +ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/trees.c) +ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/zutil.c) + +#FIXME: gzip support + +SRCS += $(ZLIB_SRCS) +CFLAGS += -isystem $(ZLIB_DIR) \ + -DZ_SOLO diff --git a/xbox/_windows.h b/xbox/_windows.h new file mode 100644 index 000000000..1032f7266 --- /dev/null +++ b/xbox/_windows.h @@ -0,0 +1,11 @@ +// fileapi + +#include + +#define INVALID_FILE_ATTRIBUTES -1 + +DWORD GetFileAttributesA( + LPCSTR lpFileName +); + +#define GetFileAttributes(...) GetFileAttributesA(__VA_ARGS__) diff --git a/xbox/alloca.h b/xbox/alloca.h new file mode 100644 index 000000000..e7199ac77 --- /dev/null +++ b/xbox/alloca.h @@ -0,0 +1 @@ +#define alloca(size) __builtin_alloca(size) diff --git a/xbox/direct.h b/xbox/direct.h new file mode 100644 index 000000000..a56691700 --- /dev/null +++ b/xbox/direct.h @@ -0,0 +1 @@ +int _mkdir(const char *dirname); diff --git a/xbox/dirent.h b/xbox/dirent.h new file mode 100644 index 000000000..cda6ac95b --- /dev/null +++ b/xbox/dirent.h @@ -0,0 +1,13 @@ +typedef struct { + int pad; +} DIR; + +struct dirent { + char d_name[]; +}; + +DIR *opendir(const char *__name); +struct dirent *readdir(DIR *__dirp); +int closedir(DIR *__dirp); + + diff --git a/xbox/features.h b/xbox/features.h new file mode 100644 index 000000000..e69de29bb diff --git a/xbox/malloc.h b/xbox/malloc.h new file mode 100644 index 000000000..e69de29bb diff --git a/xbox/matrix.h b/xbox/matrix.h new file mode 100644 index 000000000..374b91f8f --- /dev/null +++ b/xbox/matrix.h @@ -0,0 +1,318 @@ +// Some helper with stolen math routines +// These might have come from https://github.com/intel/external-mesa/blob/master/src/mesa/math/m_matrix.c ? +//FIXME: Verify that these are conforming to GL spec + +#define _USE_MATH_DEFINES +#include + +typedef double GLdouble; + +static void _math_matrix_translate(GLfloat *m, GLfloat x, GLfloat y, GLfloat z ) { + m[12] = m[0] * x + m[4] * y + m[8] * z + m[12]; + m[13] = m[1] * x + m[5] * y + m[9] * z + m[13]; + m[14] = m[2] * x + m[6] * y + m[10] * z + m[14]; + m[15] = m[3] * x + m[7] * y + m[11] * z + m[15]; +} + +static void matrix_identity(float* out) { + memset(out, 0x00, 4 * 4 * sizeof(float)); + for(int i = 0; i < 4; i++) { + out[i*4+i] = 1.0f; + } +} + +static void _math_matrix_scale(GLfloat *m, GLfloat x, GLfloat y, GLfloat z ) { + m[0] *= x; m[4] *= y; m[8] *= z; + m[1] *= x; m[5] *= y; m[9] *= z; + m[2] *= x; m[6] *= y; m[10] *= z; + m[3] *= x; m[7] *= y; m[11] *= z; +} + + +bool invert(float invOut[16], const float m[16]) +{ + float inv[16], det; + int i; + + inv[0] = m[5] * m[10] * m[15] - + m[5] * m[11] * m[14] - + m[9] * m[6] * m[15] + + m[9] * m[7] * m[14] + + m[13] * m[6] * m[11] - + m[13] * m[7] * m[10]; + + inv[4] = -m[4] * m[10] * m[15] + + m[4] * m[11] * m[14] + + m[8] * m[6] * m[15] - + m[8] * m[7] * m[14] - + m[12] * m[6] * m[11] + + m[12] * m[7] * m[10]; + + inv[8] = m[4] * m[9] * m[15] - + m[4] * m[11] * m[13] - + m[8] * m[5] * m[15] + + m[8] * m[7] * m[13] + + m[12] * m[5] * m[11] - + m[12] * m[7] * m[9]; + + inv[12] = -m[4] * m[9] * m[14] + + m[4] * m[10] * m[13] + + m[8] * m[5] * m[14] - + m[8] * m[6] * m[13] - + m[12] * m[5] * m[10] + + m[12] * m[6] * m[9]; + + inv[1] = -m[1] * m[10] * m[15] + + m[1] * m[11] * m[14] + + m[9] * m[2] * m[15] - + m[9] * m[3] * m[14] - + m[13] * m[2] * m[11] + + m[13] * m[3] * m[10]; + + inv[5] = m[0] * m[10] * m[15] - + m[0] * m[11] * m[14] - + m[8] * m[2] * m[15] + + m[8] * m[3] * m[14] + + m[12] * m[2] * m[11] - + m[12] * m[3] * m[10]; + + inv[9] = -m[0] * m[9] * m[15] + + m[0] * m[11] * m[13] + + m[8] * m[1] * m[15] - + m[8] * m[3] * m[13] - + m[12] * m[1] * m[11] + + m[12] * m[3] * m[9]; + + inv[13] = m[0] * m[9] * m[14] - + m[0] * m[10] * m[13] - + m[8] * m[1] * m[14] + + m[8] * m[2] * m[13] + + m[12] * m[1] * m[10] - + m[12] * m[2] * m[9]; + + inv[2] = m[1] * m[6] * m[15] - + m[1] * m[7] * m[14] - + m[5] * m[2] * m[15] + + m[5] * m[3] * m[14] + + m[13] * m[2] * m[7] - + m[13] * m[3] * m[6]; + + inv[6] = -m[0] * m[6] * m[15] + + m[0] * m[7] * m[14] + + m[4] * m[2] * m[15] - + m[4] * m[3] * m[14] - + m[12] * m[2] * m[7] + + m[12] * m[3] * m[6]; + + inv[10] = m[0] * m[5] * m[15] - + m[0] * m[7] * m[13] - + m[4] * m[1] * m[15] + + m[4] * m[3] * m[13] + + m[12] * m[1] * m[7] - + m[12] * m[3] * m[5]; + + inv[14] = -m[0] * m[5] * m[14] + + m[0] * m[6] * m[13] + + m[4] * m[1] * m[14] - + m[4] * m[2] * m[13] - + m[12] * m[1] * m[6] + + m[12] * m[2] * m[5]; + + inv[3] = -m[1] * m[6] * m[11] + + m[1] * m[7] * m[10] + + m[5] * m[2] * m[11] - + m[5] * m[3] * m[10] - + m[9] * m[2] * m[7] + + m[9] * m[3] * m[6]; + + inv[7] = m[0] * m[6] * m[11] - + m[0] * m[7] * m[10] - + m[4] * m[2] * m[11] + + m[4] * m[3] * m[10] + + m[8] * m[2] * m[7] - + m[8] * m[3] * m[6]; + + inv[11] = -m[0] * m[5] * m[11] + + m[0] * m[7] * m[9] + + m[4] * m[1] * m[11] - + m[4] * m[3] * m[9] - + m[8] * m[1] * m[7] + + m[8] * m[3] * m[5]; + + inv[15] = m[0] * m[5] * m[10] - + m[0] * m[6] * m[9] - + m[4] * m[1] * m[10] + + m[4] * m[2] * m[9] + + m[8] * m[1] * m[6] - + m[8] * m[2] * m[5]; + + det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12]; + + if (det == 0) + return false; + + det = 1.0 / det; + + for (i = 0; i < 16; i++) + invOut[i] = inv[i] * det; + + return true; +} + +#define A(row,col) a[(col<<2)+row] +#define B(row,col) b[(col<<2)+row] +#define P(row,col) product[(col<<2)+row] +static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b ) +{ + GLint i; + for (i = 0; i < 4; i++) { + const GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3); + P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0); + P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1); + P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2); + P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3); + } +} +#undef A +#undef B +#undef P + +void ortho(float* r, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearval, GLdouble farval) { + //FIXME: Multiply this onto the existing stack - don't overwrite + + GLfloat m[16]; + +#define M(row,col) m[col*4+row] + M(0,0) = 2.0F / (right-left); + M(0,1) = 0.0F; + M(0,2) = 0.0F; + M(0,3) = -(right+left) / (right-left); + + M(1,0) = 0.0F; + M(1,1) = 2.0F / (top-bottom); + M(1,2) = 0.0F; + M(1,3) = -(top+bottom) / (top-bottom); + + M(2,0) = 0.0F; + M(2,1) = 0.0F; + M(2,2) = -2.0F / (farval-nearval); + M(2,3) = -(farval+nearval) / (farval-nearval); + + M(3,0) = 0.0F; + M(3,1) = 0.0F; + M(3,2) = 0.0F; + M(3,3) = 1.0F; +#undef M + + memcpy(r, m, sizeof(m)); +} + +void _math_matrix_rotate( GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z ) +{ + GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c; + + s = sinf( angle * M_PI / 180.0 ); + c = cosf( angle * M_PI / 180.0 ); + +#define M(row,col) m[col*4+row] + + const GLfloat mag = sqrtf(x * x + y * y + z * z); + + if (mag <= 1.0e-4F) { + /* no rotation, leave mat as-is */ + return; + } + + x /= mag; + y /= mag; + z /= mag; + + + /* + * Arbitrary axis rotation matrix. + * + * This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied + * like so: Rz * Ry * T * Ry' * Rz'. T is the final rotation + * (which is about the X-axis), and the two composite transforms + * Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary + * from the arbitrary axis to the X-axis then back. They are + * all elementary rotations. + * + * Rz' is a rotation about the Z-axis, to bring the axis vector + * into the x-z plane. Then Ry' is applied, rotating about the + * Y-axis to bring the axis vector parallel with the X-axis. The + * rotation about the X-axis is then performed. Ry and Rz are + * simply the respective inverse transforms to bring the arbitrary + * axis back to its original orientation. The first transforms + * Rz' and Ry' are considered inverses, since the data from the + * arbitrary axis gives you info on how to get to it, not how + * to get away from it, and an inverse must be applied. + * + * The basic calculation used is to recognize that the arbitrary + * axis vector (x, y, z), since it is of unit length, actually + * represents the sines and cosines of the angles to rotate the + * X-axis to the same orientation, with theta being the angle about + * Z and phi the angle about Y (in the order described above) + * as follows: + * + * cos ( theta ) = x / sqrt ( 1 - z^2 ) + * sin ( theta ) = y / sqrt ( 1 - z^2 ) + * + * cos ( phi ) = sqrt ( 1 - z^2 ) + * sin ( phi ) = z + * + * Note that cos ( phi ) can further be inserted to the above + * formulas: + * + * cos ( theta ) = x / cos ( phi ) + * sin ( theta ) = y / sin ( phi ) + * + * ...etc. Because of those relations and the standard trigonometric + * relations, it is pssible to reduce the transforms down to what + * is used below. It may be that any primary axis chosen will give the + * same results (modulo a sign convention) using thie method. + * + * Particularly nice is to notice that all divisions that might + * have caused trouble when parallel to certain planes or + * axis go away with care paid to reducing the expressions. + * After checking, it does perform correctly under all cases, since + * in all the cases of division where the denominator would have + * been zero, the numerator would have been zero as well, giving + * the expected result. + */ + + xx = x * x; + yy = y * y; + zz = z * z; + xy = x * y; + yz = y * z; + zx = z * x; + xs = x * s; + ys = y * s; + zs = z * s; + one_c = 1.0F - c; + + /* We already hold the identity-matrix so we can skip some statements */ + M(0,0) = (one_c * xx) + c; + M(0,1) = (one_c * xy) - zs; + M(0,2) = (one_c * zx) + ys; +/* M(0,3) = 0.0F; */ + + M(1,0) = (one_c * xy) + zs; + M(1,1) = (one_c * yy) + c; + M(1,2) = (one_c * yz) - xs; +/* M(1,3) = 0.0F; */ + + M(2,0) = (one_c * zx) - ys; + M(2,1) = (one_c * yz) + xs; + M(2,2) = (one_c * zz) + c; +/* M(2,3) = 0.0F; */ + +/* + M(3,0) = 0.0F; + M(3,1) = 0.0F; + M(3,2) = 0.0F; + M(3,3) = 1.0F; +*/ +#undef M +} diff --git a/xbox/neverballrc b/xbox/neverballrc new file mode 100644 index 000000000..64465ec36 --- /dev/null +++ b/xbox/neverballrc @@ -0,0 +1,85 @@ +fullscreen 0 +display 0 +width 640 +height 480 +stereo 0 +camera 0 +textures 1 +reflection 0 +multisample 8 +mipmap 1 +aniso 8 +background 1 +shadow 1 +audio_buff 2048 +mouse_sense 300 +mouse_response 50 +mouse_invert 0 +vsync 1 +hmd 0 +highdpi 0 +mouse_camera_1 none +mouse_camera_2 none +mouse_camera_3 none +mouse_camera_toggle middle +mouse_camera_l left +mouse_camera_r right +nice 0 +fps 0 +sound_volume 10 +music_volume 6 +joystick 1 +joystick_response 250 +joystick_axis_x0 0 +joystick_axis_y0 1 +joystick_axis_x1 3 +joystick_axis_y1 4 +joystick_axis_x0_invert 0 +joystick_axis_y0_invert 0 +joystick_axis_x1_invert 0 +joystick_axis_y1_invert 0 +joystick_button_a 0 +joystick_button_b 1 +joystick_button_x 2 +joystick_button_y 3 +joystick_button_l1 4 +joystick_button_r1 5 +joystick_button_l2 -1 +joystick_button_r2 -1 +joystick_button_select 6 +joystick_button_start 7 +joystick_dpad_l -1 +joystick_dpad_r -1 +joystick_dpad_u -1 +joystick_dpad_d -1 +key_camera_1 1 +key_camera_2 2 +key_camera_3 3 +key_camera_toggle E +key_camera_r D +key_camera_l S +key_forward Up +key_backward Down +key_left Left +key_right Right +key_restart R +key_score_next Tab +key_rotate_fast Left Shift +view_fov 50 +view_dp 75 +view_dc 25 +view_dz 200 +rotate_fast 300 +rotate_slow 150 +stats 0 +screenshot 0 +lock_goals 1 +camera_1_speed 250 +camera_2_speed 0 +camera_3_speed -1 +player Player +ball_file ball/basic-ball/basic-ball +wiimote_addr +replay_name %s-%l +language +theme classic diff --git a/xbox/sys/stat.h b/xbox/sys/stat.h new file mode 100644 index 000000000..961d554b9 --- /dev/null +++ b/xbox/sys/stat.h @@ -0,0 +1,7 @@ +#define F_OK 0 //FIXME: Should be in unistd.h? + +struct stat { int st_size; }; + +int stat(const char *pathname, struct stat *statbuf); +int access(const char *pathname, int mode); + diff --git a/xbox/sys/time.h b/xbox/sys/time.h new file mode 100644 index 000000000..106f97988 --- /dev/null +++ b/xbox/sys/time.h @@ -0,0 +1,10 @@ +struct timeval { + unsigned int tv_sec; + unsigned int tv_usec; +}; + +struct timezone { + int pad; +}; + +int gettimeofday(struct timeval *tv, struct timezone *tz); diff --git a/xbox/xbox.c b/xbox/xbox.c new file mode 100644 index 000000000..e9b58a24b --- /dev/null +++ b/xbox/xbox.c @@ -0,0 +1,1938 @@ +#include +#include +#include + +#include +#include + +static void _unimplemented(const char* fmt, ...) { + char buf[1024]; + va_list va; + va_start(va, fmt); + vsprintf(buf, fmt, va); + va_end(va); + debugPrint(buf); +} +#define unimplemented(fmt, ...) _unimplemented("%s (%s:%d) " fmt "\n", __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) + +// stdlib.h +#include + +int _putenv(const char *envstring) { + assert(false); //FIXME: Implement + return 0; +} + +// direct.h +#include "direct.h" + +int _mkdir(const char *dirname) { + debugPrint("Making dir '%s'\n", dirname); + CreateDirectoryA(dirname, NULL); //FIXME: Handle return value + return 0; +} + +// dirent.h +#include "dirent.h" + +#if 0 +DIR *opendir(const char *__name) { + assert(false); //FIXME: Implement + return NULL; +} + +struct dirent *readdir(DIR *__dirp) { + assert(false); //FIXME: Implement + return NULL; +} + +int closedir(DIR *__dirp) { + assert(false); //FIXME: Implement + return 0; +} +#endif + +// Some windows garbage + +#include + +DWORD GetFileAttributesA( + LPCSTR lpFileName +) { + debugPrint("GetFileAttributes '%s'\n", lpFileName); + return FILE_ATTRIBUTE_DIRECTORY; +} + +// sys/stat.h +#include "sys/stat.h" + +#include + +int stat(const char *pathname, struct stat *statbuf) { + debugPrint("stat file '%s'\n", pathname); + memset(statbuf, 0x00, sizeof(*statbuf)); + + int ret = -1; + FILE* f = fopen(pathname, "rb"); + if (f != NULL) { + ret = 0; + fseek(f, 0, SEEK_END); + statbuf->st_size = ftell(f); + fclose(f); + } + + return ret; +} + +int access(const char *pathname, int mode) { + assert(mode == F_OK); + int ret = -1; + FILE* f = fopen(pathname, "rb"); + if (f != NULL) { + ret = 0; + fclose(f); + } + debugPrint("access file '%s': %d\n", pathname, ret); + return ret; +} + +// sys/time.h +#include "sys/time.h" + +int gettimeofday(struct timeval *tv, struct timezone *tz) { + assert(false); //FIXME: Implement + return 0; +} + +// xgu.h +#include "xgu/xgu.h" +#include "xgu/xgux.h" + + +// GLES/gl.h +#include +#include +#include + +#include "GLES/gl.h" +//#include + + +typedef struct { + void* data; +} Object; + +typedef struct { + uint8_t* data; + size_t size; +} Buffer; +#define DEFAULT_BUFFER() \ + { \ + .data = NULL, \ + .size = 0 \ + } + +typedef struct { + GLsizei width; + GLsizei height; + size_t pitch; + void* data; + GLint min_filter; + GLint mag_filter; + GLint wrap_s; + GLint wrap_t; + GLenum internal_base_format; +} Texture; + +typedef struct { + GLenum env_mode; + GLfloat env_color[4]; + GLenum combine_rgb; + GLenum combine_alpha; + GLenum src_rgb[3]; + GLenum src_operand_rgb[3]; + GLenum src_alpha[3]; + GLenum src_operand_alpha[3]; +} TexEnv; + +//FIXME: Allow different pools +static Object* objects = NULL; +static GLuint object_count = 0; + +static GLuint unused_object() { + //FIXME: Find object slot where data is NULL + object_count += 1; + objects = realloc(objects, sizeof(Object) * object_count); + return object_count - 1; +} + +static void gen_objects(GLsizei n, GLuint* indices, const void* data, size_t size) { + for(int i = 0; i < n; i++) { + GLuint index = unused_object(); + + Object* object = &objects[index]; + object->data = malloc(size); + memcpy(object->data, data, size); + + indices[i] = 1 + index; + } +} + +static void del_objects(GLsizei n, const GLuint* indices) { + for(int i = 0; i < n; i++) { + + //FIXME: Also ignore non-existing names + if (indices[i] == 0) { + continue; + } + + GLuint index = indices[i] - 1; + + Object* object = &objects[index]; + + //FIXME: Call a handler routine? + + assert(object->data != NULL); + free(object->data); + object->data = NULL; + } +} + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#define MASK(mask, val) (((val) << (__builtin_ffs(mask)-1)) & (mask)) + +typedef struct { + struct { + bool enabled; + GLenum gl_type; + unsigned int size; + size_t stride; + const void* data; + } array; + float value[4]; +} Attrib; + +#define DEFAULT_TEXENV() \ + { \ + .env_mode = GL_MODULATE, \ + .src_rgb = { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT }, \ + .src_alpha = { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT }, \ + .src_operand_rgb = { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA}, \ + .src_operand_alpha = { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA }, \ + .env_color = { 0.0f, 0.0f, 0.0f, 0.0f }, \ + /*.scale_rgb = 1.0f,*/ \ + /*.scale_alpha = 1.0f*/ \ + } + +static unsigned int active_texture = 0; +static unsigned int client_active_texture = 0; + +TexEnv texenvs[4] = { + DEFAULT_TEXENV(), + DEFAULT_TEXENV(), + DEFAULT_TEXENV(), + DEFAULT_TEXENV() +}; + +typedef struct { + bool enabled; + //FIXME: Store other attributes? +} Light; + +typedef struct { + Attrib texture_coord_array[4]; + Attrib vertex_array; + Attrib color_array; + Attrib normal_array; + bool texture_2d[4]; //FIXME: Move into a texture unit array + GLuint texture_binding_2d[4]; + Light light[3]; //FIXME: no more needed in neverball +} State; +static State state = { + .texture_2d = { false, false, false, false }, + .texture_binding_2d = { 0, 0, 0, 0 } +}; + +#include "matrix.h" + +static uint32_t* set_enabled(uint32_t* p, GLenum cap, bool enabled) { + switch(cap) { + case GL_ALPHA_TEST: + p = xgu_set_alpha_test_enable(p, enabled); + break; + case GL_NORMALIZE: + unimplemented("GL_NORMALIZE"); //FIXME: Missing from XGU + break; + case GL_CULL_FACE: + p = xgu_set_cull_face_enable(p, enabled); + break; + case GL_DEPTH_TEST: + p = xgu_set_depth_test_enable(p, enabled); + break; + case GL_TEXTURE_2D: + state.texture_2d[active_texture] = enabled; + break; + case GL_BLEND: + p = xgu_set_blend_enable(p, enabled); + break; + case GL_LIGHT0: + case GL_LIGHT1: + case GL_LIGHT2: + state.light[cap - GL_LIGHT0].enabled = enabled; + break; + case GL_LIGHTING: + p = xgu_set_lighting_enable(p, enabled); + break; + case GL_COLOR_MATERIAL: + unimplemented(); //FIXME: !!! + break; + case GL_POLYGON_OFFSET_FILL: + unimplemented(); //FIXME: !!! + break; + case GL_POINT_SPRITE: + unimplemented(); //FIXME: !!! + break; + default: + unimplemented("%d", cap); + assert(false); + break; + } + return p; +} + +static void set_client_state_enabled(GLenum array, bool enabled) { + switch(array) { + case GL_TEXTURE_COORD_ARRAY: + state.texture_coord_array[client_active_texture].array.enabled = enabled; + break; + case GL_VERTEX_ARRAY: + state.vertex_array.array.enabled = enabled; + break; + case GL_COLOR_ARRAY: + state.color_array.array.enabled = enabled; + break; + case GL_NORMAL_ARRAY: + state.normal_array.array.enabled = enabled; + break; + default: + unimplemented("%d", array); + assert(false); + break; + } +} + +static XguPrimitiveType gl_to_xgu_primitive_type(GLenum mode) { + switch(mode) { + case GL_POINTS: return XGU_POINTS; + case GL_TRIANGLES: return XGU_TRIANGLES; + case GL_TRIANGLE_STRIP: return XGU_TRIANGLE_STRIP; + default: + unimplemented("%d", mode); + assert(false); + return -1; + } +} + +static XguStencilOp gl_to_xgu_stencil_op(GLenum op) { + switch(op) { + default: + unimplemented("%d", op); + assert(false); + return -1; + } +} + +static XguCullFace gl_to_xgu_cull_face(GLenum mode) { + switch(mode) { + case GL_FRONT: return XGU_CULL_FRONT; + case GL_BACK: return XGU_CULL_BACK; + case GL_FRONT_AND_BACK: return XGU_CULL_FRONT_AND_BACK; + default: + unimplemented("%d", mode); + assert(false); + return -1; + } +} + +static XguFrontFace gl_to_xgu_front_face(GLenum mode) { + switch(mode) { + case GL_CW: return XGU_FRONT_CW; + case GL_CCW: return XGU_FRONT_CCW; + default: + unimplemented("%d", mode); + assert(false); + return -1; + } +} + +static XguVertexArrayType gl_to_xgu_vertex_array_type(GLenum mode) { + switch(mode) { + case GL_FLOAT: return XGU_FLOAT; + case GL_SHORT: return NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_S32K; //FIXME: NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_S1; for normals? + case GL_UNSIGNED_BYTE: return NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_UB_OGL; //FIXME XGU_U8_XYZW ? + default: + unimplemented("%d", mode); + assert(false); + return -1; + } +} + +static XguBlendFactor gl_to_xgu_blend_factor(GLenum factor) { + switch(factor) { + case GL_ONE: return XGU_FACTOR_ONE; + case GL_SRC_ALPHA: return XGU_FACTOR_SRC_ALPHA; + case GL_ONE_MINUS_SRC_ALPHA: return XGU_FACTOR_ONE_MINUS_SRC_ALPHA; + default: + unimplemented("%d", factor); + assert(false); + return -1; + } +} + +static uint8_t f_to_u8(float f) { + assert(f >= 0.0f && f <= 1.0f); + return f * 0xFF; +} + +// 3.7.10 ES 1.1 FULL +#define DEFAULT_TEXTURE() \ + { \ + /* FIXME: Set up other fields */ \ + .width = 0, \ + .height = 0, \ + .pitch = 0, \ + .data = NULL, \ + .min_filter = GL_NEAREST_MIPMAP_LINEAR, \ + .mag_filter = GL_LINEAR, \ + .wrap_s = GL_REPEAT, \ + .wrap_t = GL_REPEAT, \ + .internal_base_format = 1, \ + /* .generate_mipmaps = false */ \ + } + +static Texture zero_texture = DEFAULT_TEXTURE(); + +static Texture* get_bound_texture(GLuint stage) { + GLuint texture = state.texture_binding_2d[stage]; + + if (texture == 0) { + return &zero_texture; + } + + Texture* object = objects[texture - 1].data; + assert(object != NULL); + + return object; +} + +#define _RC_ZERO 0x0 +#define _RC_DISCARD 0x0 +#define _RC_PRIMARY_COLOR 0x4 +#define _RC_TEXTURE 0x8 +#define _RC_SPARE0 0xC + +#define _RC_UNSIGNED 0x0 +#define _RC_UNSIGNED_INVERT 0x1 + + +static uint32_t* setup_texenv_output(uint32_t* p, + TexEnv* t, unsigned int texture, unsigned int stage, bool rgb, + bool ab, bool cd, bool sum) { + p = pb_push1(p, NV097_SET_COMBINER_COLOR_OCW + stage * 4, + MASK(NV097_SET_COMBINER_COLOR_OCW_AB_DST, ab ? _RC_SPARE0 : _RC_DISCARD) + | MASK(NV097_SET_COMBINER_COLOR_OCW_CD_DST, cd ? _RC_SPARE0 : _RC_DISCARD) + | MASK(NV097_SET_COMBINER_COLOR_OCW_SUM_DST, sum ? _RC_SPARE0 : _RC_DISCARD) + | MASK(NV097_SET_COMBINER_COLOR_OCW_MUX_ENABLE, 0) + | MASK(NV097_SET_COMBINER_COLOR_OCW_AB_DOT_ENABLE, 0) + | MASK(NV097_SET_COMBINER_COLOR_OCW_CD_DOT_ENABLE, 0) + | MASK(NV097_SET_COMBINER_COLOR_OCW_OP, NV097_SET_COMBINER_COLOR_OCW_OP_NOSHIFT)); + return p; +} + +static unsigned int gl_to_texenv_src(TexEnv* t, unsigned int texture, bool rgb, int arg) { + GLenum src = rgb ? t->src_rgb[arg] : t->src_alpha[arg]; + + //FIXME: Move to function? + switch(src) { + case GL_PREVIOUS: + if (texture == 0) { + return _RC_PRIMARY_COLOR; + } + return _RC_SPARE0; + case GL_PRIMARY_COLOR: return _RC_PRIMARY_COLOR; //FIXME: Name? + case GL_TEXTURE: return _RC_TEXTURE+texture; //FIXME: Get stage + default: + unimplemented("%d", src); + assert(false); + return gl_to_texenv_src(t, texture, rgb, -1); + } +} + +static unsigned int is_texenv_src_alpha(TexEnv* t, unsigned int texture, bool rgb, int arg) { + GLenum operand = rgb ? t->src_operand_rgb[arg] : t->src_operand_alpha[arg]; + + // Operand also checked for validity in `gl_to_texenv_src_map` + return operand == GL_SOURCE_ALPHA || operand == GL_ONE_MINUS_SRC_ALPHA; +} + +static bool is_texenv_src_inverted(TexEnv* t, int texture, bool rgb, int arg) { + bool invert; + GLenum operand = rgb ? t->src_operand_rgb[arg] : t->src_operand_alpha[arg]; + + if (rgb) { + assert(operand == GL_SRC_COLOR || + operand == GL_SRC_ALPHA || + operand == GL_ONE_MINUS_SRC_COLOR || + operand == GL_ONE_MINUS_SRC_ALPHA); + invert = (operand == GL_ONE_MINUS_SRC_COLOR || operand == GL_ONE_MINUS_SRC_ALPHA); + } else { + assert(operand == GL_SRC_ALPHA || + operand == GL_ONE_MINUS_SRC_ALPHA); + invert = (operand == GL_ONE_MINUS_SRC_ALPHA); + } + + return invert; +} + +static uint32_t* setup_texenv_src(uint32_t* p, + TexEnv* t, unsigned int texture, unsigned int stage, bool rgb, + unsigned int x_a, bool a_alpha, bool a_invert, + unsigned int x_b, bool b_alpha, bool b_invert, + unsigned int x_c, bool c_alpha, bool c_invert, + unsigned int x_d, bool d_alpha, bool d_invert) { + if (rgb) { + p = pb_push1(p, NV097_SET_COMBINER_COLOR_ICW + stage * 4, + MASK(NV097_SET_COMBINER_COLOR_ICW_A_SOURCE, x_a) | MASK(NV097_SET_COMBINER_COLOR_ICW_A_ALPHA, a_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_COLOR_ICW_A_MAP, a_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) + | MASK(NV097_SET_COMBINER_COLOR_ICW_B_SOURCE, x_b) | MASK(NV097_SET_COMBINER_COLOR_ICW_B_ALPHA, b_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_COLOR_ICW_B_MAP, b_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) + | MASK(NV097_SET_COMBINER_COLOR_ICW_C_SOURCE, x_c) | MASK(NV097_SET_COMBINER_COLOR_ICW_C_ALPHA, c_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_COLOR_ICW_C_MAP, c_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) + | MASK(NV097_SET_COMBINER_COLOR_ICW_D_SOURCE, x_d) | MASK(NV097_SET_COMBINER_COLOR_ICW_D_ALPHA, d_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_COLOR_ICW_D_MAP, d_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED)); + } else { + p = pb_push1(p, NV097_SET_COMBINER_ALPHA_ICW + stage * 4, + MASK(NV097_SET_COMBINER_ALPHA_ICW_A_SOURCE, x_a) | MASK(NV097_SET_COMBINER_ALPHA_ICW_A_ALPHA, a_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_ALPHA_ICW_A_MAP, a_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) + | MASK(NV097_SET_COMBINER_ALPHA_ICW_B_SOURCE, x_b) | MASK(NV097_SET_COMBINER_ALPHA_ICW_B_ALPHA, b_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_ALPHA_ICW_B_MAP, b_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) + | MASK(NV097_SET_COMBINER_ALPHA_ICW_C_SOURCE, x_c) | MASK(NV097_SET_COMBINER_ALPHA_ICW_C_ALPHA, c_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_ALPHA_ICW_C_MAP, c_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) + | MASK(NV097_SET_COMBINER_ALPHA_ICW_D_SOURCE, x_d) | MASK(NV097_SET_COMBINER_ALPHA_ICW_D_ALPHA, d_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_ALPHA_ICW_D_MAP, d_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED)); + } + return p; +} + +static void setup_texenv() { + + uint32_t* p = pb_begin(); + + //FIXME: This is an assumption on how this should be handled + // The GL ES 1.1 Full spec claism that only texture 0 uses Cp=Cf. + // However, what if unit 0 is inactive? Cp=Cf? Cp=undefined? + // Couldn't find an answer when skimming over spec. + GLuint rc_previous = _RC_PRIMARY_COLOR; + +#define _Cf _RC_PRIMARY_COLOR, true, false +#define _Af _RC_PRIMARY_COLOR, false, false +#define _Cs _RC_TEXTURE+texture, true, false +#define _As _RC_TEXTURE+texture, false, false +#define _Cp rc_previous, true, false +#define _Ap rc_previous, false, false +#define _Zero _RC_ZERO, true, false //FIXME: make dependent on portion (RGB/ALPHA)? +#define _One _RC_ZERO, true, true //FIXME: make dependent on portion (RGB/ALPHA)? + + // This function is meant to create a register combiner from texenvs + unsigned int stage = 0; + for(int texture = 0; texture < 4; texture++) { + + // Skip stage if texture is disabled + if (!state.texture_2d[texture]) { + continue; + } + + Texture* tx = get_bound_texture(texture); + TexEnv* t = &texenvs[texture]; + + switch(t->env_mode) { + case GL_REPLACE: + switch(tx->internal_base_format) { + case GL_ALPHA: + unimplemented(); + assert(false); + break; + case GL_LUMINANCE: case 1: + unimplemented(); + assert(false); + break; + case GL_LUMINANCE_ALPHA: case 2: + unimplemented(); + assert(false); + break; + case GL_RGB: case 3: + unimplemented(); + assert(false); + break; + case GL_RGBA: case 4: + unimplemented(); + assert(false); + break; + default: + unimplemented("%d\n", tx->internal_base_format); + assert(false); + break; + } + break; + case GL_MODULATE: + switch(tx->internal_base_format) { + + case GL_ALPHA: + unimplemented(); + assert(false); + break; + + case GL_LUMINANCE: case 1: + case GL_RGB: case 3: + + // Cv = Cp * Cs + // Av = Ap + p = setup_texenv_output(p, t, texture, stage, true, true, false, false); + p = setup_texenv_src(p, t, texture, stage, true, + _Cp, _Cs, + _Zero, _Zero); + p = setup_texenv_output(p, t, texture, stage, false, true, false, false); + p = setup_texenv_src(p, t, texture, stage, false, + _Ap, _One, + _Zero, _Zero); + break; + + case GL_LUMINANCE_ALPHA: case 2: + case GL_RGBA: case 4: + + // Cv = Cp * Cs + // Av = Ap * As + p = setup_texenv_output(p, t, texture, stage, true, true, false, false); + p = setup_texenv_src(p, t, texture, stage, true, + _Cp, _Cs, + _Zero, _Zero); + p = setup_texenv_output(p, t, texture, stage, false, true, false, false); + p = setup_texenv_src(p, t, texture, stage, false, + _Ap, _As, + _Zero, _Zero); + break; + + default: + unimplemented("%d\n", tx->internal_base_format); + assert(false); + break; + } + break; + case GL_COMBINE: { + + bool rgb; + +#define _Arg(i) \ + gl_to_texenv_src(t, texture, rgb, (i)), \ + is_texenv_src_alpha(t, texture, rgb, (i)), \ + is_texenv_src_inverted(t, texture, rgb, (i)) + +#define _OneMinusArg(i) \ + gl_to_texenv_src(t, texture, rgb, (i)), \ + is_texenv_src_alpha(t, texture, rgb, (i)), \ + !is_texenv_src_inverted(t, texture, rgb, (i)) + + rgb = true; + switch(t->combine_rgb) { + case GL_MODULATE: + //FIXME: Can potentially merge into previous stage + // Setup `spare0 = a * b` + p = setup_texenv_output(p, t, texture, stage, rgb, true, false, false); + p = setup_texenv_src(p, t, texture, stage, rgb, + _Arg(0), _Arg(1), + _Zero, _Zero); + break; + case GL_INTERPOLATE: + // Setup `spare0 = a * b + c * d` + p = setup_texenv_output(p, t, texture, stage, rgb, false, false, true); + p = setup_texenv_src(p, t, texture, stage, rgb, + _Arg(0), _Arg(2), + _Arg(1), _OneMinusArg(2)); + break; + default: + assert(false); + break; + } + + rgb = false; + switch(t->combine_alpha) { + case GL_REPLACE: + //FIXME: Can potentially merge into previous stage + // Setup `spare0 = a` + p = setup_texenv_output(p, t, texture, stage, rgb, true, false, false); + p = setup_texenv_src(p, t, texture, stage, rgb, + _Arg(0), _One, + _Zero, _Zero); + break; + default: + assert(false); + break; + } + + break; + } + default: + assert(false); + break; + } + + rc_previous = _RC_SPARE0; + stage++; + } + + // Add at least 1 dummy stage (spare0 = fragment color) + if (stage == 0) { + p = setup_texenv_output(p, NULL, 0, stage, true, true, false, false); + p = setup_texenv_src(p, NULL, 0, stage, true, + _Cf, _One, + _Zero, _Zero); + p = setup_texenv_output(p, NULL, 0, stage, false, true, false, false); + p = setup_texenv_src(p, NULL, 0, stage, false, + _Af, _One, + _Zero, _Zero); + stage++; + } + + // Set up final combiner + //FIXME: This could merge an earlier stage into final_product + //FIXME: Ensure this is `out.rgb = spare0.rgb; out.a = spare0.a;` + p = pb_push1(p, NV097_SET_COMBINER_CONTROL, + MASK(NV097_SET_COMBINER_CONTROL_FACTOR0, NV097_SET_COMBINER_CONTROL_FACTOR0_SAME_FACTOR_ALL) + | MASK(NV097_SET_COMBINER_CONTROL_FACTOR1, NV097_SET_COMBINER_CONTROL_FACTOR1_SAME_FACTOR_ALL) + | MASK(NV097_SET_COMBINER_CONTROL_ITERATION_COUNT, stage)); + p = pb_push1(p, NV097_SET_COMBINER_SPECULAR_FOG_CW0, + MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_A_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_A_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_A_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_B_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_B_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_B_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_C_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_C_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_C_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_D_SOURCE, _RC_SPARE0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_D_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_D_INVERSE, 0)); + p = pb_push1(p, NV097_SET_COMBINER_SPECULAR_FOG_CW1, + MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_E_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_E_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_E_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_F_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_F_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_F_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_G_SOURCE, _RC_SPARE0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_G_ALPHA, 1) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_G_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_SPECULAR_CLAMP, 0)); + + pb_end(p); +} + +static GLuint gl_array_buffer = 0; +static GLuint gl_element_array_buffer = 0; + +static GLuint* get_bound_buffer_store(GLenum target) { + switch(target) { + case GL_ARRAY_BUFFER: + return &gl_array_buffer; + case GL_ELEMENT_ARRAY_BUFFER: + return &gl_element_array_buffer; + default: + unimplemented("%d", target); + assert(false); + break; + } + return NULL; +} + +#define DEFAULT_MATRIX() \ + { \ + 1.0f, 0.0f, 0.0f, 0.0f, \ + 0.0f, 1.0f, 0.0f, 0.0f, \ + 0.0f, 0.0f, 1.0f, 0.0f, \ + 0.0f, 0.0f, 0.0f, 1.0f \ + } + +static float matrix_mv[16 * 4*4] = DEFAULT_MATRIX(); +static unsigned int matrix_mv_slot = 0; +static float matrix_p[16 * 4*4] = DEFAULT_MATRIX(); +static unsigned int matrix_p_slot = 0; +static float matrix_t[4][16 * 4*4] = { + DEFAULT_MATRIX(), + DEFAULT_MATRIX(), + DEFAULT_MATRIX(), + DEFAULT_MATRIX() +}; +static unsigned int matrix_t_slot[4] = { 0, 0, 0, 0 }; + +//FIXME: This code assumes that matrix_mv_slot is 0 +static unsigned int* matrix_slot = &matrix_mv_slot; +static float* matrix = &matrix_mv[0]; + + +typedef struct { + bool enabled; + float x; + float y; + float z; + float w; +} ClipPlane; +static ClipPlane clip_planes[3]; //FIXME: No more needed for neverball + + +static void setup_attrib(XguVertexArray array, Attrib* attrib) { + if (!attrib->array.enabled) { + uint32_t* p = pb_begin(); + // The following isn't 0, 0, 0 to avoid assert in XQEMU; anything with 0, x, 0 should work + p = xgu_set_vertex_data_array_format(p, array, 1, 0, 0); + p = xgu_set_vertex_data4f(p, array, attrib->value[0], attrib->value[1], attrib->value[2], attrib->value[3]); + pb_end(p); + return; + } + assert(attrib->array.size > 0); + xgux_set_attrib_pointer(array, gl_to_xgu_vertex_array_type(attrib->array.gl_type), attrib->array.size, attrib->array.stride, attrib->array.data); +} + +static bool is_texture_complete(Texture* tx) { + if (tx->width == 0) { return false; } + if (tx->height == 0) { return false; } + unimplemented(); //FIXME: Check mipmaps, filters, .. + return true; +} + +static unsigned int gl_to_xgu_texture_format(GLenum internalformat) { + switch(internalformat) { + case GL_LUMINANCE: return NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_Y8; + case GL_LUMINANCE_ALPHA: return NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_AY8; + case GL_RGB: return NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_X8R8G8B8; + case GL_RGBA: return NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_A8R8G8B8; + default: + unimplemented("%d", internalformat); + assert(false); + break; + } + return -1; +} + +static void setup_textures() { + + uint32_t* p; + + // Disable texture dependencies (unused) + //FIXME: init once? + p = pb_begin(); + p = pb_push1(p, NV097_SET_SHADER_OTHER_STAGE_INPUT, + MASK(NV097_SET_SHADER_OTHER_STAGE_INPUT_STAGE1, 0) + | MASK(NV097_SET_SHADER_OTHER_STAGE_INPUT_STAGE2, 0) + | MASK(NV097_SET_SHADER_OTHER_STAGE_INPUT_STAGE3, 0)); + pb_end(p); + + unsigned int clip_plane_index = 0; + unsigned int shaders[4]; + + for(int i = 0; i < 4; i++) { + + // Find texture object + Texture* tx = get_bound_texture(i); + + // Check if this unit is disabled + if (!state.texture_2d[i] || !is_texture_complete(tx)) { + + // Disable texture + p = pb_begin(); + p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_ENABLE(i),0x0003ffc0);//set stage 1 texture enable flags (bit30 disabled) + p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_WRAP(i),0x00030303);//set stage 1 texture modes (0x0W0V0U wrapping: 1=wrap 2=mirror 3=clamp 4=border 5=clamp to edge) + p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_FILTER(i),0x02022000);//set stage 1 texture filters (no AA, stage not even used) + pb_end(p); + + // Find the next used clip plane + while(clip_plane_index < ARRAY_SIZE(clip_planes)) { + if (clip_planes[clip_plane_index].enabled) { + break; + } + clip_plane_index++; + } + + // Set clip plane if one was found + if (clip_plane_index < ARRAY_SIZE(clip_planes)) { + const ClipPlane* clip_plane = &clip_planes[clip_plane_index]; + + // Set vertex attributes for the texture coordinates + Attrib attrib = { + .array = { .enabled = false }, + .value = { clip_plane->x, clip_plane->y, clip_plane->z, clip_plane->w } + }; + setup_attrib(XGU_TEXCOORD0_ARRAY+i, &attrib); + + // Setup shader + unimplemented(); //FIXME: This should be NV097_SET_SHADER_STAGE_PROGRAM_STAGE0_CLIP_PLANE + shaders[i] = NV097_SET_SHADER_STAGE_PROGRAM_STAGE0_PROGRAM_NONE; + + clip_plane_index++; + continue; + } + + // Disable texture shader if nothing depends on it + shaders[i] = NV097_SET_SHADER_STAGE_PROGRAM_STAGE0_PROGRAM_NONE; + + continue; + } + + // Sanity check texture + assert(tx->width != 0); + assert(tx->height != 0); + assert(tx->pitch != 0); + debugPrint("%d x %d [%d]\n", tx->width, tx->height, tx->pitch); + assert(tx->data != NULL); + + // Setup texture + shaders[i] = NV097_SET_SHADER_STAGE_PROGRAM_STAGE0_2D_PROJECTIVE; + p = pb_begin(); + //FIXME: Use NV097_SET_TEXTURE_FORMAT and friends + p = pb_push2(p,NV20_TCL_PRIMITIVE_3D_TX_OFFSET(i), (uintptr_t)tx->data & 0x03ffffff, 0x0001002A | (gl_to_xgu_texture_format(tx->internal_base_format) << 8)); //set stage 0 texture address & format + p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_NPOT_PITCH(i), tx->pitch<<16); //set stage 0 texture pitch (pitch<<16) + p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_NPOT_SIZE(i), (tx->width<<16) | tx->height); //set stage 0 texture width & height ((witdh<<16)|height) + unimplemented("Setup wrap"); //FIXME: !!! + p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_WRAP(i),0x00030303);//set stage 0 texture modes (0x0W0V0U wrapping: 1=wrap 2=mirror 3=clamp 4=border 5=clamp to edge) + p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_ENABLE(i),0x4003ffc0); //set stage 0 texture enable flags + unimplemented("Setup min and mag"); //FIXME: !!! + p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_FILTER(i),0x04074000); //set stage 0 texture filters (AA!) + pb_end(p); + + // Setup texture shader + p = pb_begin(); + p = pb_push1(p, NV097_SET_SHADER_STAGE_PROGRAM, + MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE0, shaders[0]) + | MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE1, shaders[1]) + | MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE2, shaders[2]) + | MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE3, shaders[3])); + pb_end(p); + } + + + // Assert that we handled all clip planes + while(clip_plane_index < ARRAY_SIZE(clip_planes)) { + assert(!clip_planes[clip_plane_index].enabled); + clip_plane_index++; + } +} + +static void setup_matrices() { + + + //FIXME: one time init? + uint32_t* p = pb_begin(); + + /* A generic identity matrix */ + const float m_identity[4*4] = DEFAULT_MATRIX(); + + //FIXME: p = xgu_set_skinning(p, XGU_SKINNING_OFF); + //FIXME: p = xgu_set_normalization(p, false); + //FIXME: p = xgu_set_lighting_enable(p, false); + + for(int i = 0; i < XGU_TEXTURE_COUNT; i++) { + //FIXME: p = xgu_set_texgen(p, XGU_TEXGEN_OFF); + //p = xgu_set_texture_matrix_enable(p, i, false); // FIXME: Set these to matrix_t[i] + //uint32_t* xgu_set_texture_matrix(uint32_t* p, uint32_t slot, const float m[4*4]) { + } + + pb_end(p); + + int width = pb_back_buffer_width(); + int height = pb_back_buffer_height(); + + + + + + // Update matrices + + //FIXME: Keep dirty bits + const float* matrix_p_now = &matrix_p[matrix_p_slot * 4*4]; + const float* matrix_mv_now = &matrix_mv[matrix_mv_slot * 4*4]; + + for(int i = 0; i < 4*4; i++) { + debugPrint("%d %d [%d]\n", matrix_p_slot, matrix_mv_slot, i); + assert(!isinf(matrix_p_now[i])); + assert(!isinf(matrix_mv_now[i])); + } + +#if 1 + { + static float m[4*4]; + memcpy(m, matrix_p_now, sizeof(m)); + matrix_p_now = m; + } + + if (true) { + float m[4*4]; + matrix_identity(m); + _math_matrix_scale(m, 1.0f/640.0f, 1.0f/480.0f, 1.0f); + float t[4*4]; + memcpy(t, matrix_p_now, sizeof(t)); + matmul4(matrix_p_now, t, m); + } + if (true) { + float m[4*4]; + matrix_identity(m); + _math_matrix_translate(m, 0.0f, 0.0f, 0.0f); + float t[4*4]; + memcpy(t, matrix_p_now, sizeof(t)); + matmul4(matrix_p_now, t, m); + } +#endif + + + //FIXME: Could be wrong + float matrix_c_now[4*4]; + matmul4(matrix_c_now, matrix_mv_now, matrix_p_now); + + for(int i = 0; i < 4*4; i++) { + assert(!isinf(matrix_p_now[i])); + assert(!isinf(matrix_mv_now[i])); + assert(!isinf(matrix_c_now[i])); + } + + for(int i = 0; i < XGU_WEIGHT_COUNT; i++) { + p = xgu_set_model_view_matrix(p, i, matrix_mv_now); //FIXME: Not sure when used? + p = xgu_set_inverse_model_view_matrix(p, i, m_identity); //FIXME: Not sure when used? + } + + + /* Set up all states for hardware vertex pipeline */ + //FIXME: Might need inverse or some additional transform + p = pb_begin(); + p = xgu_set_transform_execution_mode(p, XGU_FIXED, XGU_RANGE_MODE_USER); + //FIXME: p = xgu_set_fog_enable(p, false); + p = xgu_set_projection_matrix(p, matrix_p_now); //FIXME: Unused in XQEMU + p = xgu_set_composite_matrix(p, matrix_c_now); //FIXME: Always used in XQEMU? + p = xgu_set_viewport_offset(p, 0.0f, 0.0f, 0.0f, 0.0f); + p = xgu_set_viewport_scale(p, 1.0f / width, 1.0f / height, 1.0f / (float)0xFFFF, 1.0f); //FIXME: Ignored?! + pb_end(p); + +} + +static void prepare_drawing() { + debugPrint("Preparing to draw\n"); + + //FIXME: Track dirty bits + + // Setup lights from state.light[].enabled + //FIXME: This uses a mask: p = xgu_set_light_enable(p, ); + + // Setup attributes + setup_attrib(XGU_VERTEX_ARRAY, &state.vertex_array); + setup_attrib(XGU_COLOR_ARRAY, &state.color_array); + setup_attrib(XGU_NORMAL_ARRAY, &state.normal_array); + setup_attrib(XGU_TEXCOORD0_ARRAY, &state.texture_coord_array[0]); + + // Set up all matrices etc. + setup_matrices(); + + // Setup textures + setup_textures(); + + // Set the register combiner + setup_texenv(); + +#if 1 + // Set some safe state + uint32_t* p = pb_begin(); + p = xgu_set_cull_face_enable(p, false); + p = xgu_set_depth_test_enable(p, false); + p = xgu_set_lighting_enable(p, false); + + p = xgu_set_alpha_test_enable(p, false); + p = xgu_set_blend_enable(p, false); + pb_end(p); +#endif +} + + + + + + + +GL_API void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data) { + switch(pname) { + case GL_MAX_TEXTURE_SIZE: + data[0] = 1024; //FIXME: We can do more probably + break; + case GL_MAX_TEXTURE_UNITS: + data[0] = 4; + break; + default: + unimplemented("%d", pname); + assert(false); + break; + } +} + +GL_API const GLubyte *GL_APIENTRY glGetString (GLenum name) { + const char* result = ""; + switch(name) { + case GL_EXTENSIONS: + result = ""; + break; + case GL_VERSION: + result = "OpenGL ES-CL 1.1"; + break; + case GL_RENDERER: + result = "XGU"; + break; + case GL_VENDOR: + result = "Jannik Vogel"; + break; + default: + unimplemented("%d", name); + assert(false); + break; + } + return (GLubyte*)result; +} + + +// Clearing +GL_API void GL_APIENTRY glClear (GLbitfield mask) { + + XguClearSurface flags = 0; + if (mask & GL_COLOR_BUFFER_BIT) { flags |= XGU_CLEAR_COLOR; } + if (mask & GL_DEPTH_BUFFER_BIT) { flags |= XGU_CLEAR_Z; } + if (mask & GL_STENCIL_BUFFER_BIT) { flags |= XGU_CLEAR_STENCIL; } + + pb_print("Clearing\n"); + + uint32_t* p = pb_begin(); + //FIXME: Set clear region + p = xgu_clear_surface(p, flags); + pb_end(p); + + //FIXME: Store size we used to init + int width = pb_back_buffer_width(); + int height = pb_back_buffer_height(); + + //FIXME: Remove this hack! + pb_erase_depth_stencil_buffer(0, 0, width, height); //FIXME: Do in XGU + pb_fill(0, 0, width, height, 0x80808080); //FIXME: Do in XGU + +} + +GL_API void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { + + uint32_t color = 0; + //FIXME: Verify order + color |= f_to_u8(red) << 0; + color |= f_to_u8(green) << 8; + color |= f_to_u8(blue) << 16; + color |= f_to_u8(alpha) << 24; + + uint32_t* p = pb_begin(); + p = xgu_set_color_clear_value(p, color); + pb_end(p); +} + + +// Buffers +GL_API void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers) { + Buffer buffer = DEFAULT_BUFFER(); + gen_objects(n, buffers, &buffer, sizeof(Buffer)); +} + +GL_API void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer) { + GLuint* bound_buffer_store = get_bound_buffer_store(target); + *bound_buffer_store = buffer; +} + +GL_API void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage) { + Buffer* buffer = objects[*get_bound_buffer_store(target)-1].data; + if (buffer->data != NULL) { + //FIXME: Re-use existing buffer if it's a good fit? + //FIXME: Assert that this memory is no longer used + MmFreeContiguousMemory(buffer->data); + } + buffer->data = MmAllocateContiguousMemory(size); + buffer->size = size; + assert(buffer->data != NULL); + if (data != NULL) { + memcpy(buffer->data, data, size); + } else { + memset(buffer->data, 0x00, size); + } +} + +GL_API void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data) { + Buffer* buffer = objects[*get_bound_buffer_store(target)-1].data; + assert(buffer->data != NULL); + assert(buffer->size >= (offset + size)); + assert(data != NULL); + memcpy(&buffer->data[offset], data, size); +} + +GL_API void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers) { + for(int i = 0; i < n; i++) { + + //FIXME: Also ignore non-existing names + if (buffers[i] == 0) { + continue; + } + + Buffer* buffer = objects[buffers[i]-1].data; + if (buffer->data != NULL) { + //FIXME: Assert that the data is no longer used + MmFreeContiguousMemory(buffer->data); + } + } + del_objects(n, buffers); +} + +static void store_attrib_pointer(Attrib* attrib, GLenum gl_type, unsigned int size, size_t stride, const void* pointer) { + uintptr_t base; + if (gl_array_buffer == 0) { + base = 0; + } else { + Buffer* buffer = objects[gl_array_buffer-1].data; + base = (uintptr_t)buffer->data; + } + attrib->array.gl_type = gl_type; + attrib->array.size = size; + attrib->array.stride = stride; + attrib->array.data = (const void*)(base + (uintptr_t)pointer); +} + +// Vertex buffers +GL_API void GL_APIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const void *pointer) { + store_attrib_pointer(&state.texture_coord_array[client_active_texture], type, size, stride, pointer); +} + +GL_API void GL_APIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const void *pointer) { + store_attrib_pointer(&state.color_array, type, size, stride, pointer); +} + +GL_API void GL_APIENTRY glNormalPointer (GLenum type, GLsizei stride, const void *pointer) { + store_attrib_pointer(&state.normal_array, type, 3, stride, pointer); +} + +GL_API void GL_APIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const void *pointer) { + store_attrib_pointer(&state.vertex_array, type, size, stride, pointer); +} + + +// Draw calls +GL_API void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count) { + prepare_drawing(); + xgux_draw_arrays(gl_to_xgu_primitive_type(mode), first, count); +} + +GL_API void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices) { + prepare_drawing(); + + uintptr_t base; + if (gl_element_array_buffer == 0) { + base = 0; + } else { + Buffer* buffer = objects[gl_element_array_buffer-1].data; + base = (uintptr_t)buffer->data; + } + + // This function only handles the 16 bit variant for now + switch(type) { + case GL_UNSIGNED_SHORT: { + xgux_draw_elements16(gl_to_xgu_primitive_type(mode), (const uint16_t*)(base + (uintptr_t)indices), count); + break; + } +#if 0 + //FIXME: Not declared in gl.h + untested + case GL_UNSIGNED_INT: + xgux_draw_elements32(gl_to_xgu_primitive_type(mode), (const uint32_t*)(base + (uintptr_t)indices), count); + break; +#endif + default: + unimplemented("%d", type); + assert(false); + break; + } +} + + +// Matrix functions +GL_API void GL_APIENTRY glMatrixMode (GLenum mode) { + assert(!isinf(matrix[1])); //FIXME: Remove sanity check + + switch(mode) { + case GL_PROJECTION: + matrix = &matrix_p[0]; + matrix_slot = &matrix_p_slot; + break; + case GL_MODELVIEW: + matrix = &matrix_mv[0]; + matrix_slot = &matrix_mv_slot; + break; + case GL_TEXTURE: + matrix = &matrix_t[client_active_texture][0]; + matrix_slot = &matrix_t_slot[client_active_texture]; + break; + default: + unimplemented("%d", mode); + assert(false); + break; + } + + // Go to the current slot + matrix = &matrix[*matrix_slot * 4*4]; + + assert(!isinf(matrix[1])); //FIXME: Remove sanity check +} + +GL_API void GL_APIENTRY glLoadIdentity (void) { + matrix_identity(matrix); + + assert(!isinf(matrix[1])); +} + +GL_API void GL_APIENTRY glMultMatrixf (const GLfloat *m) { + + //FIXME: Remove sanity checks + for(int i = 0; i < 4*4; i++) { + debugPrint("0x%08X ", *(uint32_t*)&matrix[i]); + assert(!isinf(matrix[i])); + } + debugPrint("= x\n"); + for(int i = 0; i < 4*4; i++) { + debugPrint("0x%08X ", *(uint32_t*)&m[i]); + assert(!isinf(m[i])); + } + debugPrint("= m\n"); + + float t[4 * 4]; + matmul4(t, matrix, m); + memcpy(matrix, t, sizeof(t)); + + for(int i = 0; i < 4*4; i++) { + debugPrint("0x%08X ", *(uint32_t*)&matrix[i]); + assert(!isinf(matrix[i])); + } + debugPrint("= r\n"); + assert(!isinf(matrix[1])); +} + +GL_API void GL_APIENTRY glOrthof (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) { + float m[4*4]; + ortho(m, l, r, b, t, n, f); + assert(!isinf(m[0])); //FIXME: Remove sanity check + glMultMatrixf(m); + + assert(!isinf(matrix[1])); //FIXME: Remove sanity check +} + +GL_API void GL_APIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z) { + float m[4*4]; + matrix_identity(m); + _math_matrix_translate(m, x, y, z); + assert(!isinf(m[0])); //FIXME: Remove sanity check + glMultMatrixf(m); + + assert(!isinf(matrix[1])); //FIXME: Remove sanity check +} + +GL_API void GL_APIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { + float m[4*4]; + matrix_identity(m); + _math_matrix_rotate(m, angle, x, y, z); + assert(!isinf(m[0])); //FIXME: Remove sanity check + glMultMatrixf(m); + + assert(!isinf(matrix[1])); //FIXME: Remove sanity check +} + +GL_API void GL_APIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z) { + float m[4*4]; + matrix_identity(m); + _math_matrix_scale(m, x, y, z); + assert(!isinf(m[0])); //FIXME: Remove sanity check + glMultMatrixf(m); + + assert(!isinf(matrix[1])); //FIXME: Remove sanity check +} + +GL_API void GL_APIENTRY glPopMatrix (void) { + assert(*matrix_slot > 0); + matrix -= 4*4; + *matrix_slot -= 1; + + assert(!isinf(matrix[1])); //FIXME: Remove sanity check +} + +GL_API void GL_APIENTRY glPushMatrix (void) { + assert(!isinf(matrix[1])); //FIXME: Remove sanity check + + float* new_matrix = matrix; + new_matrix += 4*4; + memcpy(new_matrix, matrix, 4*4*sizeof(float)); + matrix = new_matrix; + *matrix_slot += 1; + assert(*matrix_slot < 16); +} + + +// Framebuffer setup +GL_API void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height) { + //FIXME: Switch to xgu variant to avoid side-effects + debugPrint("%d %d %d %d\n", x, y, width, height); + assert(x == 0); + assert(y == 0); + assert(width == 640); //FIXME: Set up game correctly + assert(height == 480); //FIXME: Set up game correctly + if (width > 640) { width = 640; } //FIXME: Remove! + if (height > 480) { height = 480; } //FIXME: Remove! + pb_set_viewport(x, y, width, height, 0.0f, 1.0f); +} + + +// Textures +GL_API void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures) { + Texture texture = DEFAULT_TEXTURE(); + gen_objects(n, textures, &texture, sizeof(Texture)); +} + +GL_API void GL_APIENTRY glBindTexture (GLenum target, GLuint texture) { + assert(target == GL_TEXTURE_2D); + state.texture_binding_2d[active_texture] = texture; +} + +GL_API void GL_APIENTRY glActiveTexture (GLenum texture) { + active_texture = texture - GL_TEXTURE0; +} + +GL_API void GL_APIENTRY glClientActiveTexture (GLenum texture) { + client_active_texture = texture - GL_TEXTURE0; +} + +GL_API void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures) { + del_objects(n, textures); +} + + +GL_API void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) { + assert(target == GL_TEXTURE_2D); + assert(border == 0); + + Texture* tx = get_bound_texture(active_texture); + + if (level > 0) { + unimplemented(); + return; + } + + unsigned int bpp; + + switch(internalformat) { + case GL_LUMINANCE: + assert(format == GL_LUMINANCE); + assert(type == GL_UNSIGNED_BYTE); + tx->internal_base_format = GL_LUMINANCE; + bpp = 1*8; + break; + case GL_LUMINANCE_ALPHA: + assert(format == GL_LUMINANCE_ALPHA); + assert(type == GL_UNSIGNED_BYTE); + tx->internal_base_format = GL_LUMINANCE_ALPHA; + bpp = 2*8; + break; + case GL_RGB: + assert(format == GL_RGB); + assert(type == GL_UNSIGNED_BYTE); + tx->internal_base_format = GL_RGB; + bpp = 4*8; // 3*8 in GL, but we have to pad this + break; + case GL_RGBA: + assert(format == GL_RGBA); + assert(type == GL_UNSIGNED_BYTE); + tx->internal_base_format = GL_RGBA; + bpp = 4*8; + break; + default: + tx->internal_base_format = -1; + bpp = 0; + unimplemented("%d", internalformat); + assert(false); + return; + } + + tx->width = width; + tx->height = height; + tx->pitch = width * bpp / 8; + size_t size = tx->pitch * tx->height; + if (tx->data != NULL) { + //FIXME: Re-use existing buffer if it's a good fit? + //FIXME: Assert that this memory is no longer used + MmFreeContiguousMemory(tx->data); + } + tx->data = MmAllocateContiguousMemory(size); + + // Copy pixels + //FIXME: Respect GL pixel packing stuff + //FIXME: Swizzle + assert(pixels != NULL); + if (tx->internal_base_format == GL_RGB) { + assert(format == GL_RGB); + assert(type == GL_UNSIGNED_BYTE); + const uint8_t* src = pixels; + uint8_t* dst = tx->data; + assert(tx->pitch == tx->width * 4); + for(int y = 0; y < tx->height; y++) { + for(int x = 0; x < tx->height; x++) { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = 0xFF; + dst += 4; + src += 3; + } + } + } else { + memcpy(tx->data, pixels, size); + } +} + +GL_API void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param) { + assert(target == GL_TEXTURE_2D); + + Texture* tx = get_bound_texture(active_texture); + + switch(pname) { + case GL_TEXTURE_MIN_FILTER: + tx->min_filter = param; + break; + case GL_TEXTURE_MAG_FILTER: + tx->mag_filter = param; + break; + case GL_TEXTURE_WRAP_S: + tx->wrap_s = param; + break; + case GL_TEXTURE_WRAP_T: + tx->wrap_t = param; + break; + default: + unimplemented("%d", pname); + assert(false); + return; + } +} + + +// Renderstates +GL_API void GL_APIENTRY glAlphaFunc (GLenum func, GLfloat ref) { +#if 0 + //FIXME: https://github.com/dracc/nxdk/pull/4/files#r357990989 + // https://github.com/dracc/nxdk/pull/4/files#r357990961 + uint32_t* p = pb_begin(); + p = xgu_set_alpha_func(p, gl_to_xgu_alpha_func(func)); + p = xgu_set_alpha_ref(p, f_to_u8(ref)); + pb_end(p); +#endif +} + +GL_API void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor) { + uint32_t* p = pb_begin(); + p = xgu_set_blend_func_sfactor(p, gl_to_xgu_blend_factor(sfactor)); + p = xgu_set_blend_func_dfactor(p, gl_to_xgu_blend_factor(dfactor)); + pb_end(p); +} + +GL_API void GL_APIENTRY glClipPlanef (GLenum p, const GLfloat *eqn) { + //FIXME: Use a free texture stage and set it to cull mode + GLuint index = p - GL_CLIP_PLANE0; + assert(index < ARRAY_SIZE(clip_planes)); + + ClipPlane* clip_plane = &clip_planes[index]; + + float v[4]; + float m[4*4]; + bool ret = invert(m, &matrix_mv[matrix_mv_slot * 4*4]); + unimplemented(); //FIXME: Multiply eqn by m to get the v + + clip_plane->x = v[0]; + clip_plane->y = v[1]; + clip_plane->z = v[2]; + clip_plane->w = v[3]; +} + +GL_API void GL_APIENTRY glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) { + //FIXME: Could save bandwidth using other commands; however, this is currently easier to maintain + //FIXME: Won't work between begin/end + state.color_array.value[0] = red / 255.0f; + state.color_array.value[1] = green / 255.0f; + state.color_array.value[2] = blue / 255.0f; + state.color_array.value[3] = alpha / 255.0f; +} + +GL_API void GL_APIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { + //FIXME: Won't work between begin/end + state.color_array.value[0] = red; + state.color_array.value[1] = green; + state.color_array.value[2] = blue; + state.color_array.value[3] = alpha; +} + +GL_API void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { + + XguColorMask mask = 0; + if (red != GL_FALSE) { mask |= XGU_RED; } + if (green != GL_FALSE) { mask |= XGU_GREEN; } + if (blue != GL_FALSE) { mask |= XGU_BLUE; } + if (alpha != GL_FALSE) { mask |= XGU_ALPHA; } + + uint32_t* p = pb_begin(); + p = xgu_set_color_mask(p, mask); + pb_end(p); +} + +GL_API void GL_APIENTRY glDepthFunc (GLenum func) { + unimplemented(); //FIXME: Missing from XGU +} + +GL_API void GL_APIENTRY glDepthMask (GLboolean flag) { + unimplemented(); //FIXME: Missing from XGU +} + +GL_API void GL_APIENTRY glEnable (GLenum cap) { + uint32_t* p = pb_begin(); + p = set_enabled(p, cap, true); + pb_end(p); +} + +GL_API void GL_APIENTRY glDisable (GLenum cap) { + uint32_t* p = pb_begin(); + p = set_enabled(p, cap, false); + pb_end(p); +} + +GL_API void GL_APIENTRY glEnableClientState (GLenum array) { + set_client_state_enabled(array, true); +} + +GL_API void GL_APIENTRY glDisableClientState (GLenum array) { + set_client_state_enabled(array, false); +} + +GL_API void GL_APIENTRY glCullFace (GLenum mode) { + uint32_t* p = pb_begin(); + p = xgu_set_cull_face(p, gl_to_xgu_cull_face(mode)); + pb_end(p); +} + +GL_API void GL_APIENTRY glFrontFace (GLenum mode) { + uint32_t* p = pb_begin(); + p = xgu_set_front_face(p, gl_to_xgu_front_face(mode)); + pb_end(p); +} + + +// Stencil actions +GL_API void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask) { + unimplemented(); //FIXME: Missing from XGU +} + +GL_API void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass) { + uint32_t* p = pb_begin(); + p = xgu_set_stencil_op_fail(p, gl_to_xgu_stencil_op(fail)); + p = xgu_set_stencil_op_zfail(p, gl_to_xgu_stencil_op(zfail)); + p = xgu_set_stencil_op_zpass(p, gl_to_xgu_stencil_op(zpass)); + pb_end(p); +} + + +// Misc. +GL_API void GL_APIENTRY glPointParameterf (GLenum pname, GLfloat param) { + unimplemented(); //FIXME: Bad in XGU +} + +GL_API void GL_APIENTRY glPointParameterfv (GLenum pname, const GLfloat *params) { + unimplemented(); //FIXME: Bad in XGU +} + +GL_API void GL_APIENTRY glPointSize (GLfloat size) { + unimplemented(); //FIXME: Bad in XGU +} + +GL_API void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units) { + unimplemented(); //FIXME: Missing from XGU +} + + +// TexEnv +GL_API void GL_APIENTRY glTexEnvi (GLenum target, GLenum pname, GLint param) { + + // Deal with the weird pointsprite target first + if (target == GL_POINT_SPRITE) { + assert(pname == GL_COORD_REPLACE); + unimplemented(); //FIXME: !!! Supported on Xbox?! + return; + } + + // Deal with actual texenv stuff now + + assert(target == GL_TEXTURE_ENV); + + TexEnv* t = &texenvs[active_texture]; + + switch(pname) { + + case GL_TEXTURE_ENV_MODE: + t->env_mode = param; + break; + + case GL_COMBINE_RGB: + t->combine_rgb = param; + break; + case GL_COMBINE_ALPHA: + t->combine_alpha = param; + break; + + case GL_SRC0_RGB: + t->src_rgb[0] = param; + break; + case GL_SRC1_RGB: + t->src_rgb[1] = param; + break; + case GL_SRC2_RGB: + t->src_rgb[2] = param; + break; + + case GL_SRC0_ALPHA: + t->src_alpha[0] = param; + break; + + case GL_OPERAND0_RGB: + t->src_operand_rgb[0] = param; + break; + + case GL_OPERAND1_RGB: + t->src_operand_rgb[1] = param; + break; + + case GL_OPERAND2_RGB: + t->src_operand_rgb[2] = param; + break; + + case GL_OPERAND0_ALPHA: + t->src_operand_alpha[0] = param; + break; + + default: + unimplemented("%d", pname); + assert(false); + return; + } +} + + +// Pixel readback +GL_API void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) { + // Not implemented, only used in screenshots + unimplemented(); +} + + +// Lighting +GL_API void GL_APIENTRY glLightModelf (GLenum pname, GLfloat param) { + switch(pname) { + default: + unimplemented("%d", pname); + assert(false); + return; + } +} + +GL_API void GL_APIENTRY glLightModelfv (GLenum pname, const GLfloat *params) { + switch(pname) { + case GL_LIGHT_MODEL_AMBIENT: + unimplemented("%d", pname); //FIXME: !!! + break; +//#define GL_LIGHT_MODEL_TWO_SIDE 10032: + default: + unimplemented("%d", pname); + assert(false); + return; + } +} + +GL_API void GL_APIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params) { + assert(light >= GL_LIGHT0); + unsigned int light_index = light - GL_LIGHT0; + assert(light_index < 4); //FIXME: Not sure how many lights Xbox has; there's probably some constant we can use + switch(pname) { + case GL_POSITION: + unimplemented("%d", pname); //FIXME: !!! + break; + case GL_AMBIENT: + unimplemented("%d", pname); //FIXME: !!! + break; + case GL_DIFFUSE: + unimplemented("%d", pname); //FIXME: !!! + break; + case GL_SPECULAR: + unimplemented("%d", pname); //FIXME: !!! + break; + default: + unimplemented("%d", pname); + assert(false); + return; + } +} + + +// Materials +GL_API void GL_APIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params) { + + if (face == GL_FRONT_AND_BACK) { + glMaterialfv(GL_FRONT, pname, params); + glMaterialfv(GL_BACK, pname, params); + return; + } + + assert(face == GL_FRONT || face == GL_BACK); + switch(pname) { + case GL_SHININESS: + unimplemented("%d", pname); //FIXME: !!! + break; + case GL_EMISSION: + unimplemented("%d", pname); //FIXME: !!! + break; + case GL_AMBIENT: + unimplemented("%d", pname); //FIXME: !!! + break; + case GL_DIFFUSE: + unimplemented("%d", pname); //FIXME: !!! + break; + case GL_SPECULAR: + unimplemented("%d", pname); //FIXME: !!! + break; + default: + unimplemented("%d", pname); + assert(false); + return; + } +} + + +// Pixel pushing +GL_API void GL_APIENTRY glPixelStorei (GLenum pname, GLint param) { + switch(pname) { + case GL_PACK_ALIGNMENT: + assert(param == 1); + break; + case GL_UNPACK_ALIGNMENT: + assert(param == 1); + break; + default: + unimplemented("%d", pname); + assert(false); + break; + } +} + + + + + +// SDL GL hooks via EGL + +#include + +#if 1 +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface) { + + debugPrint("Going to swap buffers\n"); + + /* Draw some text on the screen */ + static int frame = 0; + frame++; + pb_print("Neverball (frame %d)\n", frame); + pb_draw_text_screen(); + + while(pb_busy()) { + /* Wait for completion... */ + } + + /* Swap buffers (if we can) */ + while (pb_finished()) { + /* Not ready to swap yet */ + } + + + + + // Prepare next frame + + pb_wait_for_vbl(); + pb_reset(); + pb_target_back_buffer(); + + pb_erase_text_screen(); + + while(pb_busy()) { + /* Wait for completion... */ + } + + return EGL_TRUE; +} +#endif + + + + +//FIXME: Use stuff like `ptr = MmAllocateContiguousMemoryEx(size, 0, 0x3ffb000, 0, 0x404);` to alloc buffer / tex + +// Initialization + +#include +#include +#include +#include + +__attribute__((destructor)) static void exit_xbox(void) { + assert(false); +} + +static HAL_SHUTDOWN_REGISTRATION shutdown_registration; +static NTAPI VOID shutdown_notification_routine (PHAL_SHUTDOWN_REGISTRATION ShutdownRegistration) { + exit_xbox(); +} + +__attribute__((constructor)) static void setup_xbox(void) { + + // Open log file + freopen("log.txt", "wb", stdout); + + // Register shutdown routine to catch errors + shutdown_registration.NotificationRoutine = shutdown_notification_routine; + shutdown_registration.Priority = 0; + HalRegisterShutdownNotification(&shutdown_registration, TRUE); + + // Set up display mode + XVideoSetMode(640, 480, 32, REFRESH_DEFAULT); + //FIXME: Re-enable + //pb_set_color_format(NV097_SET_SURFACE_FORMAT_COLOR_LE_X8R8G8B8, false); + +#if 1 + // We consume a lot of memory, so we need to claim the framebuffer + size_t fb_size = 640 * 480 * 4; + extern uint8_t* _fb; + _fb = (uint8_t*)MmAllocateContiguousMemoryEx(fb_size, 0, 0xFFFFFFFF, 0x1000, PAGE_READWRITE | PAGE_WRITECOMBINE); + memset(_fb, 0x00, fb_size); +#define _PCRTC_START 0xFD600800 + *(unsigned int*)(_PCRTC_START) = (unsigned int)_fb & 0x03FFFFFF; + debugPrint("FB: 0x%X\n", _fb); +#endif + + // Initialize pbkit + int err = pb_init(); + if (err) { + debugPrint("pb_init Error %d\n", err); + //XSleep(2000); + //XReboot(); + return; + } + + // Show framebuffer, not debug-screen +#if 0 + pb_show_front_screen(); +#else + pb_show_debug_screen(); +#endif + + //debugPrint("\n\n\n\n"); + + //FIXME: Bump GPU in right state? + +} From 24a544b1c78e357b9b77be201684006fb048932a Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Wed, 18 Dec 2019 01:27:47 +0100 Subject: [PATCH 07/93] REMOVEME annotate draw calls via stdout --- share/gui.c | 5 +++-- share/solid_draw.c | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/share/gui.c b/share/gui.c index 5a660003f..d915ffec9 100644 --- a/share/gui.c +++ b/share/gui.c @@ -207,8 +207,9 @@ static void draw_enable(GLboolean c, GLboolean u, GLboolean p) static void draw_rect(int id) { - glDrawElements(GL_TRIANGLE_STRIP, RECT_ELEM, GL_UNSIGNED_SHORT, - (const GLvoid *) (id * WIDGET_ELEM * sizeof (GLushort))); +printf("Tried to draw %d\n", RECT_ELEM); + glDrawElements(GL_TRIANGLE_STRIP, RECT_ELEM, GL_UNSIGNED_SHORT, + (const GLvoid *) (id * WIDGET_ELEM * sizeof (GLushort))); } static void draw_text(int id) diff --git a/share/solid_draw.c b/share/solid_draw.c index a60aff2c7..bb79c2637 100644 --- a/share/solid_draw.c +++ b/share/solid_draw.c @@ -424,8 +424,10 @@ void sol_draw_mesh(const struct d_mesh *mp, struct s_rend *rend, int p) if (rend->curr_mtrl.base.fl & M_PARTICLE) glDrawArrays(GL_POINTS, 0, mp->vbc); - else - glDrawElements(GL_TRIANGLES, mp->ebc, GL_UNSIGNED_SHORT, 0); + else { +printf("Tried to draw %d (solid)\n", mp->ebc); + glDrawElements(GL_TRIANGLES, mp->ebc, GL_UNSIGNED_SHORT, 0); +} } } From f6e11af951b67a73f345dbbaaaa4276b67a625b1 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 16 Dec 2019 13:13:28 +0100 Subject: [PATCH 08/93] REMOVEME neverball log to hal/debug.h --- ball/main.c | 15 +++++++++++---- ball/st_conf.c | 3 ++- ball/st_title.c | 3 ++- share/common.c | 1 + share/dir.c | 20 +++++++++++++++++++- share/fs_stdio.c | 13 ++++++++++++- share/gui.c | 12 +++++++++--- share/log.c | 10 ++++++++++ share/state.c | 5 ++--- share/theme.c | 3 +-- share/video.c | 6 +++--- 11 files changed, 72 insertions(+), 19 deletions(-) diff --git a/ball/main.c b/ball/main.c index e7725e040..4a91f6f23 100644 --- a/ball/main.c +++ b/ball/main.c @@ -523,7 +523,7 @@ static void make_dirs_and_migrate(void) fs_mkdir("Screenshots"); } - +#include /*---------------------------------------------------------------------------*/ int main(int argc, char *argv[]) @@ -571,8 +571,10 @@ int main(int argc, char *argv[]) /* Initialize video. */ - if (!video_init()) + if (!video_init()) { +assert(0); return 1; +} /* Material system. */ @@ -623,11 +625,14 @@ int main(int argc, char *argv[]) /* Run the main game loop. */ t0 = SDL_GetTicks(); - +//assert(0); while (loop()) { +//debugPrint("%d > %d?\n", t1, t0); +//assert(0); if ((t1 = SDL_GetTicks()) > t0) { +//assert(0); /* Step the game state. */ st_timer(0.001f * (t1 - t0)); @@ -637,7 +642,9 @@ int main(int argc, char *argv[]) /* Render. */ hmd_step(); +//assert(0); st_paint(0.001f * t0); +//assert(0); video_swap(); if (config_get_d(CONFIG_NICE)) @@ -653,7 +660,7 @@ int main(int argc, char *argv[]) hmd_free(); joy_quit(); SDL_Quit(); - +assert(0); return 0; } diff --git a/ball/st_conf.c b/ball/st_conf.c index dfe1b41a6..8e9e7678f 100644 --- a/ball/st_conf.c +++ b/ball/st_conf.c @@ -218,7 +218,7 @@ static int null_enter(struct state *st, struct state *prev) return 0; } - +#include static void null_leave(struct state *st, struct state *next, int id) { mtrl_load_objects(); @@ -228,6 +228,7 @@ static void null_leave(struct state *st, struct state *next, int id) geom_init(); gui_init(); hud_init(); +//assert(0); } /*---------------------------------------------------------------------------*/ diff --git a/ball/st_title.c b/ball/st_title.c index c90c83ff5..2ffa6ee20 100644 --- a/ball/st_title.c +++ b/ball/st_title.c @@ -200,9 +200,10 @@ static int filter_cmd(const union cmd *cmd) { return (cmd ? cmd->type != CMD_SOUND : 1); } - +#include static int title_enter(struct state *st, struct state *prev) { +//assert(0); game_proxy_filter(filter_cmd); /* Start the title screen music. */ diff --git a/share/common.c b/share/common.c index 0c629f0be..7ed761668 100644 --- a/share/common.c +++ b/share/common.c @@ -160,6 +160,7 @@ const char *date_to_str(time_t i) return str; } +#include int file_exists(const char *path) { return (access(path, F_OK) == 0); diff --git a/share/dir.c b/share/dir.c index 3a434422e..9aa424d6b 100644 --- a/share/dir.c +++ b/share/dir.c @@ -12,6 +12,10 @@ * General Public License for more details. */ +#ifdef NXDK +#include +#endif + #ifndef _WIN32 #include #else @@ -25,11 +29,16 @@ #include "dir.h" #include "common.h" +#ifdef NXDK +#include +#include <_windows.h> +#endif + List dir_list_files(const char *path) { List files = NULL; - #ifndef _WIN32 +assert(0); DIR *dir; if ((dir = opendir(path))) @@ -47,6 +56,10 @@ List dir_list_files(const char *path) closedir(dir); } #else +#ifndef NXDK + debugPrint("Asking for files in '%s'\n", path); +#endif + HANDLE hFind; WIN32_FIND_DATA FindFileData; @@ -59,6 +72,10 @@ List dir_list_files(const char *path) //FIXME: Handle wide strings? files = list_cons(strdup(FindFileData.cFileName), files); +#ifndef NXDK + debugPrint("Found '%s'\n", FindFileData.cFileName); +#endif + FindNextFile(hFind, &FindFileData); } FindClose(hFind); @@ -141,6 +158,7 @@ void dir_free(Array items) int dir_exists(const char *path) { #ifndef _WIN32 + assert(0); DIR *dir; if ((dir = opendir(path))) diff --git a/share/fs_stdio.c b/share/fs_stdio.c index f2a27c4c3..bb899f71b 100644 --- a/share/fs_stdio.c +++ b/share/fs_stdio.c @@ -12,6 +12,11 @@ * General Public License for more details. */ +#ifdef NXDK +#include +#endif +#include + #include #include #include @@ -195,7 +200,7 @@ void fs_dir_free(Array items) } /*---------------------------------------------------------------------------*/ - +#include static char *real_path(const char *path) { char *real = NULL; @@ -227,6 +232,9 @@ fs_file fs_open_read(const char *path) if ((real = real_path(path))) { +#ifdef NXDK +debugPrint("Trying to open '%s' (read)\n", real); +#endif fh->handle = fopen(real, "rb"); free(real); } @@ -252,6 +260,9 @@ static fs_file fs_open_write_flags(const char *path, int append) if ((real = path_join(fs_dir_write, path))) { +#ifdef NXDK +debugPrint("Trying to open '%s' (write)\n", real); +#endif fh->handle = fopen(real, append ? "ab" : "wb"); free(real); } diff --git a/share/gui.c b/share/gui.c index d915ffec9..a31ece8d0 100644 --- a/share/gui.c +++ b/share/gui.c @@ -12,6 +12,8 @@ * General Public License for more details. */ +#include + #include #include #include @@ -215,11 +217,13 @@ printf("Tried to draw %d\n", RECT_ELEM); static void draw_text(int id) { glDrawArrays(GL_TRIANGLE_STRIP, id * WIDGET_VERT + RECT_VERT, TEXT_VERT); +assert(0); } static void draw_image(int id) { glDrawArrays(GL_TRIANGLE_STRIP, id * WIDGET_VERT + RECT_VERT, IMAGE_VERT); +assert(0); } static void draw_disable(void) @@ -491,6 +495,8 @@ static void gui_theme_quit(void) theme_free(&curr_theme); } +#include + static void gui_theme_init(void) { gui_theme_quit(); @@ -516,11 +522,9 @@ void gui_init(void) borders[i] = padding; /* Initialize font rendering. */ - gui_font_init(); /* Initialize GUI theme. */ - gui_theme_init(); /* Initialize the VBOs. */ @@ -531,9 +535,11 @@ void gui_init(void) glBindBuffer_(GL_ARRAY_BUFFER, vert_vbo); glBufferData_(GL_ARRAY_BUFFER, sizeof (vert_buf), vert_buf, GL_STATIC_DRAW); glBindBuffer_(GL_ARRAY_BUFFER, 0); - +//assert(0); glGenBuffers_(1, &vert_ebo); +//assert(0); glBindBuffer_(GL_ELEMENT_ARRAY_BUFFER, vert_ebo); +//assert(0); glBufferData_(GL_ELEMENT_ARRAY_BUFFER, WIDGET_MAX * WIDGET_ELEM * sizeof (GLushort), NULL, GL_STATIC_DRAW); diff --git a/share/log.c b/share/log.c index ecf5a9405..f3642a9c7 100644 --- a/share/log.c +++ b/share/log.c @@ -12,6 +12,11 @@ * General Public License for more details. */ +#ifdef NXDK +#include +#include +#endif + #include #include @@ -42,6 +47,11 @@ void log_printf(const char *fmt, ...) vsnprintf(str, len, fmt, ap); va_end(ap); +#ifdef NXDK +debugPrint("%s\n", str); +//Sleep(100); +#endif + fputs(str, stderr); fflush(stderr); diff --git a/share/state.c b/share/state.c index d0c2dcd4d..6d603809f 100644 --- a/share/state.c +++ b/share/state.c @@ -120,14 +120,13 @@ void init_state(struct state *st) { state = st; } - +#include int goto_state(struct state *st) { struct state *prev = state; - if (state && state->leave) state->leave(state, st, state->gui_id); - +//assert(0); state = st; state_time = 0; state_drawn = 0; diff --git a/share/theme.c b/share/theme.c index 9b5231043..70c7b78bd 100644 --- a/share/theme.c +++ b/share/theme.c @@ -86,7 +86,7 @@ static const char *theme_path(const char *name, const char *file) } return ""; } - +#include int theme_load(struct theme *theme, const char *name) { char buff[MAXSTR]; @@ -101,7 +101,6 @@ int theme_load(struct theme *theme, const char *name) memset(theme, 0, sizeof (*theme)); /* Load description. */ - if ((fp = fs_open_read(theme_path(name, "theme.txt")))) { while ((fs_gets(buff, sizeof (buff), fp))) diff --git a/share/video.c b/share/video.c index 61748ea17..41951e097 100644 --- a/share/video.c +++ b/share/video.c @@ -354,7 +354,7 @@ int video_perf(void) { return fps; } - +#include void video_swap(void) { int dt; @@ -365,9 +365,9 @@ void video_swap(void) /* Take a screenshot of the complete back buffer and swap it. */ snapshot_take(); - +//assert(0); SDL_GL_SwapWindow(window); - +//assert(0); /* Accumulate time passed and frames rendered. */ dt = (int) SDL_GetTicks() - last; From 3f717860689219ee60bd4e4673994a7d136c7b90 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Wed, 18 Dec 2019 01:30:27 +0100 Subject: [PATCH 09/93] REMOVEME only allow certain files to miss --- share/fs_stdio.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/share/fs_stdio.c b/share/fs_stdio.c index bb899f71b..44599fe67 100644 --- a/share/fs_stdio.c +++ b/share/fs_stdio.c @@ -236,6 +236,12 @@ fs_file fs_open_read(const char *path) debugPrint("Trying to open '%s' (read)\n", real); #endif fh->handle = fopen(real, "rb"); + +assert(fh->handle +|| !strcmp(real, "./Neverball/neverballrc") +|| !strcmp(real, "./Neverball/lang/.txt") +); + free(real); } @@ -264,6 +270,12 @@ static fs_file fs_open_write_flags(const char *path, int append) debugPrint("Trying to open '%s' (write)\n", real); #endif fh->handle = fopen(real, append ? "ab" : "wb"); + +assert(fh->handle +|| !strcmp(real, "./Neverball/neverball.log") +|| !strcmp(real, "./Neverball/Replays/Last.nbr") +); + free(real); } From 7e63c28096d0849a3a7b520778d5cd2c316d999b Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 19 Dec 2019 15:53:38 +0100 Subject: [PATCH 10/93] REMOVEME workaround for pdclib scanf bug --- share/config.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/share/config.c b/share/config.c index b58dfedab..6d7508af9 100644 --- a/share/config.c +++ b/share/config.c @@ -319,7 +319,15 @@ static int scan_key_and_value(char **dst_key, char **dst_val, char *line) ke = -1; vs = -1; - sscanf(line, " %n%*s%n %n", &ks, &ke, &vs); +#ifdef NXDK +debugPrint("'%s'\n", line); +char foo[1024]; +#endif + sscanf(line, " %n%*s%n %n", &ks, +#ifdef NXDK +&foo, +#endif +&ke, &vs); if (ks < 0 || ke < 0 || vs < 0) return 0; From 82797b92ce7416e6672c0617f540cb7cdc22782b Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 21 Dec 2019 00:23:12 +0100 Subject: [PATCH 11/93] REMOVEME touch asserts and more debug print --- ball/main.c | 4 ++-- share/dir.c | 2 -- share/font.c | 3 +++ share/gui.c | 13 ++++++++++--- share/lang.c | 27 +++++++++++++++++++++++++-- 5 files changed, 40 insertions(+), 9 deletions(-) diff --git a/ball/main.c b/ball/main.c index 4a91f6f23..95e1b218a 100644 --- a/ball/main.c +++ b/ball/main.c @@ -565,7 +565,7 @@ int main(int argc, char *argv[]) lang_init(); /* Initialize audio. */ - +//assert(0); audio_init(); tilt_init(); @@ -583,7 +583,7 @@ assert(0); /* Screen states. */ init_state(&st_null); - +//assert(0); /* Initialize demo playback or load the level. */ if (opt_replay && diff --git a/share/dir.c b/share/dir.c index 9aa424d6b..ad52203a5 100644 --- a/share/dir.c +++ b/share/dir.c @@ -38,7 +38,6 @@ List dir_list_files(const char *path) { List files = NULL; #ifndef _WIN32 -assert(0); DIR *dir; if ((dir = opendir(path))) @@ -158,7 +157,6 @@ void dir_free(Array items) int dir_exists(const char *path) { #ifndef _WIN32 - assert(0); DIR *dir; if ((dir = opendir(path))) diff --git a/share/font.c b/share/font.c index d6807a7d7..9bd0e3c97 100644 --- a/share/font.c +++ b/share/font.c @@ -12,6 +12,8 @@ * General Public License for more details. */ +#include + #include #include @@ -46,6 +48,7 @@ int font_load(struct font *ft, const char *path, int sizes[3]) return 1; } } +assert(0); return 0; } diff --git a/share/gui.c b/share/gui.c index a31ece8d0..112806146 100644 --- a/share/gui.c +++ b/share/gui.c @@ -217,7 +217,7 @@ printf("Tried to draw %d\n", RECT_ELEM); static void draw_text(int id) { glDrawArrays(GL_TRIANGLE_STRIP, id * WIDGET_VERT + RECT_VERT, TEXT_VERT); -assert(0); +//assert(0); } static void draw_image(int id) @@ -771,6 +771,7 @@ void gui_set_image(int id, const char *file) glDeleteTextures(1, &widget[id].image); widget[id].image = make_image_from_file(file, IF_MIPMAP); +assert(widget[id].image != 0); } void gui_set_label(int id, const char *text) @@ -790,6 +791,7 @@ void gui_set_label(int id, const char *text) &widget[id].text_w, &widget[id].text_h, str, ttf, 0); +assert(widget[id].image != 0); w = widget[id].text_w; h = widget[id].text_h; @@ -917,6 +919,7 @@ int gui_image(int pd, const char *file, int w, int h) if ((id = gui_widget(pd, GUI_IMAGE))) { widget[id].image = make_image_from_file(file, IF_MIPMAP); +assert(widget[id].image != 0); widget[id].w = w; widget[id].h = h; widget[id].flags |= GUI_RECT; @@ -948,6 +951,7 @@ int gui_state(int pd, const char *text, int size, int token, int value) &widget[id].text_w, &widget[id].text_h, text, ttf, 0); +assert(widget[id].image != 0); widget[id].w = widget[id].text_w; widget[id].h = widget[id].text_h; widget[id].size = size; @@ -965,11 +969,12 @@ int gui_label(int pd, const char *text, int size, const GLubyte *c0, if ((id = gui_widget(pd, GUI_LABEL))) { TTF_Font *ttf = fonts[widget[id].font].ttf[size]; - +assert(ttf != NULL); widget[id].image = make_image_from_font(NULL, NULL, &widget[id].text_w, &widget[id].text_h, text, ttf, 0); +assert(widget[id].image != 0); widget[id].w = widget[id].text_w; widget[id].h = widget[id].text_h; widget[id].size = size; @@ -1674,8 +1679,10 @@ static void gui_paint_label(int id) { /* Short-circuit empty labels. */ - if (widget[id].image == 0) + if (widget[id].image == 0) { + assert(0); return; + } /* Draw the widget text box, textured using the glyph. */ diff --git a/share/lang.c b/share/lang.c index dc12c2ad1..3178ac360 100644 --- a/share/lang.c +++ b/share/lang.c @@ -13,6 +13,13 @@ * General Public License for more details. */ +#ifdef NXDK +#include +#endif + + +#include + #include #include #include @@ -132,16 +139,27 @@ int lang_load(struct lang_desc *desc, const char *path) fs_file fp; memset(desc, 0, sizeof (*desc)); - +#ifndef NXDK +printf("lang '%s'\n", path); +#else +debugPrint("lang '%s'\n", path); +#endif if ((fp = fs_open_read(path))) { +#ifndef NXDK +printf("lang loaded '%s'\n", path); +#else +debugPrint("lang loaded '%s'\n", path); +#endif char buf[MAXSTR]; SAFECPY(desc->code, base_name_sans(path, ".txt")); while (fs_gets(buf, sizeof (buf), fp)) { +assert(0); strip_newline(buf); +assert(0); if (str_starts_with(buf, "name1 ")) SAFECPY(desc->name1, buf + 6); @@ -153,10 +171,13 @@ int lang_load(struct lang_desc *desc, const char *path) fs_close(fp); - if (*desc->name1) + if (*desc->name1) { + assert(0); return 1; + } } } +//assert(0); return 0; } @@ -231,8 +252,10 @@ static int lang_status; void lang_init(void) { +//assert(0); lang_quit(); lang_load(&curr_lang, lang_path(config_get_s(CONFIG_LANGUAGE))); +//assert(0); gt_init("neverball", curr_lang.code); lang_status = 1; } From 35628ef4b04c3bc0cf07cdfef33dff78735eb064 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 21 Dec 2019 00:24:05 +0100 Subject: [PATCH 12/93] REMOVEME more file related debug messages --- share/dir.c | 4 ++-- share/fs_stdio.c | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/share/dir.c b/share/dir.c index ad52203a5..6669944c4 100644 --- a/share/dir.c +++ b/share/dir.c @@ -48,7 +48,7 @@ List dir_list_files(const char *path) { if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue; - +printf("-- '%s'\n", ent->d_name); files = list_cons(strdup(ent->d_name), files); } @@ -72,7 +72,7 @@ List dir_list_files(const char *path) files = list_cons(strdup(FindFileData.cFileName), files); #ifndef NXDK - debugPrint("Found '%s'\n", FindFileData.cFileName); + printf("-- '%s'\n", FindFileData.cFileName); #endif FindNextFile(hFind, &FindFileData); diff --git a/share/fs_stdio.c b/share/fs_stdio.c index 44599fe67..e676e4847 100644 --- a/share/fs_stdio.c +++ b/share/fs_stdio.c @@ -210,8 +210,14 @@ static char *real_path(const char *path) { real = path_join(p->data, path); - if (file_exists(real)) + if (file_exists(real)) { +#ifdef NXDK +debugPrint("found '%s'\n", real); +#else +printf("found '%s'\n", real); +#endif break; + } free(real); real = NULL; @@ -230,6 +236,9 @@ fs_file fs_open_read(const char *path) { char *real; +#ifdef NXDK +debugPrint("Path: %s\n", path); +#endif if ((real = real_path(path))) { #ifdef NXDK From b15786cd87295796d6ada3407876e2f17671b2fa Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 21 Dec 2019 02:59:52 +0100 Subject: [PATCH 13/93] hax --- xbox/xbox.c | 509 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 454 insertions(+), 55 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index e9b58a24b..54d0cda28 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -5,6 +5,30 @@ #include #include +#include + +static unsigned int frame = 0; //FIXME: Remove +static SDL_GameController* g = NULL; + +static void debugPrintFloat(float f) { +#if 0 + //FIXME: pdclib can't do this + debugPrint("%f", f); +#endif +#if 0 + debugPrint("0x%08X", *(uint32_t*)&f); +#endif +#if 1 + bool sign = f < 0.0f; + if (sign) { f = -f; } + unsigned int value = (unsigned int)(f * 10000); + unsigned int mantissa = value % 10000; + value /= 10000; + debugPrint("%s%u.%04u", sign ? "-" : "", value, mantissa); +#endif +} + + static void _unimplemented(const char* fmt, ...) { char buf[1024]; va_list va; @@ -118,6 +142,15 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) { //#include +static void* AllocateResourceMemory(size_t size) { +#define MAXRAM 0x03FFAFFF + return MmAllocateContiguousMemoryEx(size, 0, MAXRAM, 0, PAGE_READWRITE | PAGE_WRITECOMBINE); +} + +static void FreeResourceMemory(void* ptr) { + MmFreeContiguousMemory(ptr); +} + typedef struct { void* data; } Object; @@ -367,8 +400,8 @@ static XguFrontFace gl_to_xgu_front_face(GLenum mode) { static XguVertexArrayType gl_to_xgu_vertex_array_type(GLenum mode) { switch(mode) { - case GL_FLOAT: return XGU_FLOAT; - case GL_SHORT: return NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_S32K; //FIXME: NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_S1; for normals? + case GL_FLOAT: return XGU_FLOAT; + case GL_SHORT: return NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_S32K; //FIXME: NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_S1; for normals? case GL_UNSIGNED_BYTE: return NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_UB_OGL; //FIXME XGU_U8_XYZW ? default: unimplemented("%d", mode); @@ -496,22 +529,22 @@ static bool is_texenv_src_inverted(TexEnv* t, int texture, bool rgb, int arg) { static uint32_t* setup_texenv_src(uint32_t* p, TexEnv* t, unsigned int texture, unsigned int stage, bool rgb, - unsigned int x_a, bool a_alpha, bool a_invert, - unsigned int x_b, bool b_alpha, bool b_invert, - unsigned int x_c, bool c_alpha, bool c_invert, - unsigned int x_d, bool d_alpha, bool d_invert) { + unsigned int x_a, bool a_rgb, bool a_invert, + unsigned int x_b, bool b_rgb, bool b_invert, + unsigned int x_c, bool c_rgb, bool c_invert, + unsigned int x_d, bool d_rgb, bool d_invert) { if (rgb) { p = pb_push1(p, NV097_SET_COMBINER_COLOR_ICW + stage * 4, - MASK(NV097_SET_COMBINER_COLOR_ICW_A_SOURCE, x_a) | MASK(NV097_SET_COMBINER_COLOR_ICW_A_ALPHA, a_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_COLOR_ICW_A_MAP, a_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) - | MASK(NV097_SET_COMBINER_COLOR_ICW_B_SOURCE, x_b) | MASK(NV097_SET_COMBINER_COLOR_ICW_B_ALPHA, b_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_COLOR_ICW_B_MAP, b_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) - | MASK(NV097_SET_COMBINER_COLOR_ICW_C_SOURCE, x_c) | MASK(NV097_SET_COMBINER_COLOR_ICW_C_ALPHA, c_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_COLOR_ICW_C_MAP, c_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) - | MASK(NV097_SET_COMBINER_COLOR_ICW_D_SOURCE, x_d) | MASK(NV097_SET_COMBINER_COLOR_ICW_D_ALPHA, d_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_COLOR_ICW_D_MAP, d_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED)); + MASK(NV097_SET_COMBINER_COLOR_ICW_A_SOURCE, x_a) | MASK(NV097_SET_COMBINER_COLOR_ICW_A_ALPHA, a_rgb ? 0 : 1) | MASK(NV097_SET_COMBINER_COLOR_ICW_A_MAP, a_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) + | MASK(NV097_SET_COMBINER_COLOR_ICW_B_SOURCE, x_b) | MASK(NV097_SET_COMBINER_COLOR_ICW_B_ALPHA, b_rgb ? 0 : 1) | MASK(NV097_SET_COMBINER_COLOR_ICW_B_MAP, b_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) + | MASK(NV097_SET_COMBINER_COLOR_ICW_C_SOURCE, x_c) | MASK(NV097_SET_COMBINER_COLOR_ICW_C_ALPHA, c_rgb ? 0 : 1) | MASK(NV097_SET_COMBINER_COLOR_ICW_C_MAP, c_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) + | MASK(NV097_SET_COMBINER_COLOR_ICW_D_SOURCE, x_d) | MASK(NV097_SET_COMBINER_COLOR_ICW_D_ALPHA, d_rgb ? 0 : 1) | MASK(NV097_SET_COMBINER_COLOR_ICW_D_MAP, d_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED)); } else { p = pb_push1(p, NV097_SET_COMBINER_ALPHA_ICW + stage * 4, - MASK(NV097_SET_COMBINER_ALPHA_ICW_A_SOURCE, x_a) | MASK(NV097_SET_COMBINER_ALPHA_ICW_A_ALPHA, a_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_ALPHA_ICW_A_MAP, a_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) - | MASK(NV097_SET_COMBINER_ALPHA_ICW_B_SOURCE, x_b) | MASK(NV097_SET_COMBINER_ALPHA_ICW_B_ALPHA, b_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_ALPHA_ICW_B_MAP, b_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) - | MASK(NV097_SET_COMBINER_ALPHA_ICW_C_SOURCE, x_c) | MASK(NV097_SET_COMBINER_ALPHA_ICW_C_ALPHA, c_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_ALPHA_ICW_C_MAP, c_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) - | MASK(NV097_SET_COMBINER_ALPHA_ICW_D_SOURCE, x_d) | MASK(NV097_SET_COMBINER_ALPHA_ICW_D_ALPHA, d_alpha ? 1 : 0) | MASK(NV097_SET_COMBINER_ALPHA_ICW_D_MAP, d_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED)); + MASK(NV097_SET_COMBINER_ALPHA_ICW_A_SOURCE, x_a) | MASK(NV097_SET_COMBINER_ALPHA_ICW_A_ALPHA, a_rgb ? 0 : 1) | MASK(NV097_SET_COMBINER_ALPHA_ICW_A_MAP, a_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) + | MASK(NV097_SET_COMBINER_ALPHA_ICW_B_SOURCE, x_b) | MASK(NV097_SET_COMBINER_ALPHA_ICW_B_ALPHA, b_rgb ? 0 : 1) | MASK(NV097_SET_COMBINER_ALPHA_ICW_B_MAP, b_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) + | MASK(NV097_SET_COMBINER_ALPHA_ICW_C_SOURCE, x_c) | MASK(NV097_SET_COMBINER_ALPHA_ICW_C_ALPHA, c_rgb ? 0 : 1) | MASK(NV097_SET_COMBINER_ALPHA_ICW_C_MAP, c_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED) + | MASK(NV097_SET_COMBINER_ALPHA_ICW_D_SOURCE, x_d) | MASK(NV097_SET_COMBINER_ALPHA_ICW_D_ALPHA, d_rgb ? 0 : 1) | MASK(NV097_SET_COMBINER_ALPHA_ICW_D_MAP, d_invert ? _RC_UNSIGNED_INVERT : _RC_UNSIGNED)); } return p; } @@ -716,6 +749,7 @@ static void setup_texenv() { pb_end(p); } + static GLuint gl_array_buffer = 0; static GLuint gl_element_array_buffer = 0; @@ -768,6 +802,44 @@ typedef struct { static ClipPlane clip_planes[3]; //FIXME: No more needed for neverball +static void print_attrib(XguVertexArray array, Attrib* attrib, unsigned int start, unsigned int count, bool submit) { + unsigned int end = start + count; + if (!attrib->array.enabled) { + debugPrint("\narray %d disabled\n", array, attrib->array.stride, attrib->array.data); + return; + } + if (attrib->array.gl_type == GL_SHORT) { + debugPrint("\narray %d as GL_SHORT, stride %d at %p\n", array, attrib->array.stride, attrib->array.data); + for(int i = start; i < end; i++) { + int16_t* v = i * attrib->array.stride + (uintptr_t)attrib->array.data; + debugPrint("[%d]:", i); + for(int j = 0; j < attrib->array.size; j++) { + debugPrint(" %d", (int)v[j]); + } + debugPrint("\n"); + if (submit) { + assert(array == XGU_VERTEX_ARRAY); + assert(attrib->array.size == 2); + uint32_t* p = pb_begin(); + p = xgu_vertex4f(p, v[0], v[1], 1.0f, 1.0f); + pb_end(p); + } + } + } else if (attrib->array.gl_type == GL_FLOAT) { + debugPrint("\narray %d as GL_FLOAT, stride %d at %p\n", array, attrib->array.stride, attrib->array.data); + for(int i = start; i < end; i++) { + float* v = i * attrib->array.stride + (uintptr_t)attrib->array.data; + debugPrint("[%d]:", i); + for(int j = 0; j < attrib->array.size; j++) { + debugPrint(" "); + debugPrintFloat(v[j]); + } + debugPrint("\n"); + assert(!submit); + } + } +} + static void setup_attrib(XguVertexArray array, Attrib* attrib) { if (!attrib->array.enabled) { uint32_t* p = pb_begin(); @@ -778,6 +850,7 @@ static void setup_attrib(XguVertexArray array, Attrib* attrib) { return; } assert(attrib->array.size > 0); + assert(attrib->array.stride > 0); xgux_set_attrib_pointer(array, gl_to_xgu_vertex_array_type(attrib->array.gl_type), attrib->array.size, attrib->array.stride, attrib->array.data); } @@ -790,10 +863,10 @@ static bool is_texture_complete(Texture* tx) { static unsigned int gl_to_xgu_texture_format(GLenum internalformat) { switch(internalformat) { - case GL_LUMINANCE: return NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_Y8; - case GL_LUMINANCE_ALPHA: return NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_AY8; - case GL_RGB: return NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_X8R8G8B8; - case GL_RGBA: return NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_A8R8G8B8; + case GL_LUMINANCE: return XGU_TEXTURE_FORMAT_Y8; + case GL_LUMINANCE_ALPHA: return XGU_TEXTURE_FORMAT_A8Y8; + case GL_RGB: return XGU_TEXTURE_FORMAT_X8R8G8B8; + case GL_RGBA: return XGU_TEXTURE_FORMAT_A8R8G8B8; default: unimplemented("%d", internalformat); assert(false); @@ -846,13 +919,17 @@ static void setup_textures() { const ClipPlane* clip_plane = &clip_planes[clip_plane_index]; // Set vertex attributes for the texture coordinates + //FIXME: This is wrong? It has to inherit the vertex position + // Should be using texgen probably Attrib attrib = { .array = { .enabled = false }, .value = { clip_plane->x, clip_plane->y, clip_plane->z, clip_plane->w } }; - setup_attrib(XGU_TEXCOORD0_ARRAY+i, &attrib); + setup_attrib(9 /*FIXME: XGU_TEXCOORD0_ARRAY*/+i, &attrib); // Setup shader + //FIXME: Can use 4 clip planes per texture unit by using texture-matrix? + //FIXME: Also disable texture matrix?! unimplemented(); //FIXME: This should be NV097_SET_SHADER_STAGE_PROGRAM_STAGE0_CLIP_PLANE shaders[i] = NV097_SET_SHADER_STAGE_PROGRAM_STAGE0_PROGRAM_NONE; @@ -885,6 +962,21 @@ static void setup_textures() { p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_ENABLE(i),0x4003ffc0); //set stage 0 texture enable flags unimplemented("Setup min and mag"); //FIXME: !!! p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_FILTER(i),0x04074000); //set stage 0 texture filters (AA!) + + p = xgu_set_texgen_s(p, i, XGU_TEXGEN_DISABLE); + p = xgu_set_texgen_t(p, i, XGU_TEXGEN_DISABLE); + p = xgu_set_texgen_r(p, i, XGU_TEXGEN_DISABLE); + p = xgu_set_texgen_q(p, i, XGU_TEXGEN_DISABLE); + p = xgu_set_texture_matrix_enable(p, i, true); + //FIXME: Not hitting pixel centers yet! + const float m[4*4] = { + tx->width, 0.0f, 0.0f, 0.0f, + 0.0f, tx->height, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + p = xgu_set_texture_matrix(p, i, m); + pb_end(p); // Setup texture shader @@ -918,11 +1010,7 @@ static void setup_matrices() { //FIXME: p = xgu_set_normalization(p, false); //FIXME: p = xgu_set_lighting_enable(p, false); - for(int i = 0; i < XGU_TEXTURE_COUNT; i++) { - //FIXME: p = xgu_set_texgen(p, XGU_TEXGEN_OFF); - //p = xgu_set_texture_matrix_enable(p, i, false); // FIXME: Set these to matrix_t[i] - //uint32_t* xgu_set_texture_matrix(uint32_t* p, uint32_t slot, const float m[4*4]) { - } + pb_end(p); @@ -939,41 +1027,137 @@ static void setup_matrices() { const float* matrix_p_now = &matrix_p[matrix_p_slot * 4*4]; const float* matrix_mv_now = &matrix_mv[matrix_mv_slot * 4*4]; +#if 0 for(int i = 0; i < 4*4; i++) { debugPrint("%d %d [%d]\n", matrix_p_slot, matrix_mv_slot, i); assert(!isinf(matrix_p_now[i])); assert(!isinf(matrix_mv_now[i])); } +#endif + +#define PRINT_MATRIX(_m) \ + { \ + const float* __m = _m; \ + for(int i = 0; i < 4; i++) { \ + for(int j = 0; j < 4; j++) { \ + debugPrint(" "); \ + debugPrintFloat(__m[i*4+j]); \ + assert(!isinf(__m[i*4+j])); \ + } \ + debugPrint("\n"); \ + } \ + } + +debugPrint("\ndraw:\n"); + PRINT_MATRIX(matrix_p_now); #if 1 { + static float m[4*4]; + memcpy(m, matrix_mv_now, sizeof(m)); + matrix_mv_now = m; + } { static float m[4*4]; memcpy(m, matrix_p_now, sizeof(m)); matrix_p_now = m; } + + + + + +float f = 6000.0f; + if (true) { float m[4*4]; matrix_identity(m); - _math_matrix_scale(m, 1.0f/640.0f, 1.0f/480.0f, 1.0f); +static float dx = 320.0f; +static float dy = -240.0f; +if (g != NULL) { + float xx = SDL_GameControllerGetAxis(g, SDL_CONTROLLER_AXIS_RIGHTX); + if (fabsf(xx) > 1000) { dx += xx/f; } + float xy = SDL_GameControllerGetAxis(g, SDL_CONTROLLER_AXIS_RIGHTY); + if (fabsf(xy) > 1000) { dy += xy/f; } +} +pb_print("%d %d scale\n", (int)(1000*dx), (int)(1000*dy)); + _math_matrix_scale(m, dx, dy, -(float)0xFFFF); float t[4*4]; memcpy(t, matrix_p_now, sizeof(t)); matmul4(matrix_p_now, t, m); } + + if (true) { float m[4*4]; matrix_identity(m); - _math_matrix_translate(m, 0.0f, 0.0f, 0.0f); +static float dx = 0.0f; +static float dy = -480.0f; +if (g != NULL) { + float xx = SDL_GameControllerGetAxis(g, SDL_CONTROLLER_AXIS_LEFTX); + if (fabsf(xx) > 1000) { dx += xx/f; } + float xy = SDL_GameControllerGetAxis(g, SDL_CONTROLLER_AXIS_LEFTY); + if (fabsf(xy) > 1000) { dy += xy/f; } +} +pb_print("%d %d trans\n", (int)(1000*dx), (int)(1000*dy)); + _math_matrix_translate(m, dx, dy, 0.0f); float t[4*4]; memcpy(t, matrix_p_now, sizeof(t)); matmul4(matrix_p_now, t, m); } + + + +// matrix_identity(matrix_mv_now); + //matrix_identity(matrix_p_now); + +debugPrint("\ndraw (xbox):\n"); + PRINT_MATRIX(matrix_p_now); + +//Sleep(100); +#endif + +#if 0 + float m_viewport[4*4] = { + 0.5 * width/2.0f, 0.0f, 0.0f, width/2.0f, + 0.0f, 0.5*-height/2.0f, 0.0f, height/2.0f, + 0.0f, 0.0f, (float)0x7FFF, 0x7FFF, + 0.0f, 0.0f, 0.0f, 1.0f + }; +memcpy(matrix_mv_now, m_viewport, sizeof(m_viewport)); +memcpy(matrix_p_now, m_identity, sizeof(m_identity)); #endif +// Transpose +#define TRANSPOSE(__m) \ + { \ + float* m_old = __m; \ + float m_new[4*4]; \ + for(int i = 0; i < 4; i++) { \ + for(int j = 0; j < 4; j++) { \ + m_new[i+4*j] = m_old[i*4+j]; \ + } \ + } \ + memcpy(m_old, m_new, sizeof(m_new)); \ + } +TRANSPOSE(matrix_p_now) +TRANSPOSE(matrix_mv_now) + + //FIXME: Could be wrong float matrix_c_now[4*4]; +bool flip = false; +if (g != NULL) { + flip = SDL_GameControllerGetButton(g, SDL_CONTROLLER_BUTTON_BACK); +} +if (flip) { + matmul4(matrix_c_now, matrix_p_now, matrix_mv_now); +pb_print("p*mv\n"); +} else { matmul4(matrix_c_now, matrix_mv_now, matrix_p_now); +pb_print("mv*p\n"); +} for(int i = 0; i < 4*4; i++) { assert(!isinf(matrix_p_now[i])); @@ -981,10 +1165,13 @@ static void setup_matrices() { assert(!isinf(matrix_c_now[i])); } + +#if 0 for(int i = 0; i < XGU_WEIGHT_COUNT; i++) { - p = xgu_set_model_view_matrix(p, i, matrix_mv_now); //FIXME: Not sure when used? + p = xgu_set_model_view_matrix(p, i, m_identity); //FIXME: Not sure when used? p = xgu_set_inverse_model_view_matrix(p, i, m_identity); //FIXME: Not sure when used? } +#endif /* Set up all states for hardware vertex pipeline */ @@ -1012,7 +1199,10 @@ static void prepare_drawing() { setup_attrib(XGU_VERTEX_ARRAY, &state.vertex_array); setup_attrib(XGU_COLOR_ARRAY, &state.color_array); setup_attrib(XGU_NORMAL_ARRAY, &state.normal_array); - setup_attrib(XGU_TEXCOORD0_ARRAY, &state.texture_coord_array[0]); + setup_attrib( 9 /*FIXME:XGU_TEXCOORD0_ARRAY*/, &state.texture_coord_array[0]); + setup_attrib(10 /*FIXME:XGU_TEXCOORD1_ARRAY*/, &state.texture_coord_array[1]); + setup_attrib(11 /*FIXME:XGU_TEXCOORD2_ARRAY*/, &state.texture_coord_array[2]); + setup_attrib(12 /*FIXME:XGU_TEXCOORD3_ARRAY*/, &state.texture_coord_array[3]); // Set up all matrices etc. setup_matrices(); @@ -1024,15 +1214,54 @@ static void prepare_drawing() { setup_texenv(); #if 1 - // Set some safe state - uint32_t* p = pb_begin(); - p = xgu_set_cull_face_enable(p, false); - p = xgu_set_depth_test_enable(p, false); - p = xgu_set_lighting_enable(p, false); + { + // Set some safe state + uint32_t* p = pb_begin(); + p = xgu_set_cull_face_enable(p, false); + p = xgu_set_depth_test_enable(p, false); + p = xgu_set_lighting_enable(p, false); + pb_end(p); + } +#endif - p = xgu_set_alpha_test_enable(p, false); - p = xgu_set_blend_enable(p, false); - pb_end(p); +#if 0 + { + // Set some safe alpha state + uint32_t* p = pb_begin(); + p = xgu_set_alpha_test_enable(p, false); + p = xgu_set_blend_enable(p, false); + pb_end(p); + } +#endif + +#if 0 + { + // Disco lighting + uint32_t* p = pb_begin(); + // The following isn't 0, 0, 0 to avoid assert in XQEMU; anything with 0, x, 0 should work + p = xgu_set_vertex_data_array_format(p, XGU_COLOR_ARRAY, 1, 0, 0); + p = xgu_set_vertex_data4ub(p, XGU_COLOR_ARRAY, rand() & 0xFF, rand() & 0xFF, rand() & 0xFF, rand() & 0xFF); + pb_end(p); + } +#endif + +#if 0 + { + // Output selector + unsigned int source = _RC_TEXTURE+0; + uint32_t* p = pb_begin(); + p = pb_push1(p, NV097_SET_COMBINER_SPECULAR_FOG_CW0, + MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_A_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_A_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_A_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_B_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_B_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_B_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_C_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_C_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_C_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_D_SOURCE, source) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_D_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_D_INVERSE, 0)); + p = pb_push1(p, NV097_SET_COMBINER_SPECULAR_FOG_CW1, + MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_E_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_E_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_E_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_F_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_F_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_F_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_G_SOURCE, source) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_G_ALPHA, 1) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_G_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_SPECULAR_CLAMP, 0)); + pb_end(p); + } #endif } @@ -1136,10 +1365,10 @@ GL_API void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void Buffer* buffer = objects[*get_bound_buffer_store(target)-1].data; if (buffer->data != NULL) { //FIXME: Re-use existing buffer if it's a good fit? - //FIXME: Assert that this memory is no longer used - MmFreeContiguousMemory(buffer->data); + assert(false); //FIXME: Assert that this memory is no longer used + FreeResourceMemory(buffer->data); } - buffer->data = MmAllocateContiguousMemory(size); + buffer->data = AllocateResourceMemory(size); buffer->size = size; assert(buffer->data != NULL); if (data != NULL) { @@ -1155,6 +1384,7 @@ GL_API void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizei assert(buffer->size >= (offset + size)); assert(data != NULL); memcpy(&buffer->data[offset], data, size); +debugPrint("Set %d bytes at %d in %p\n", size, offset, &buffer->data[offset]); } GL_API void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers) { @@ -1167,8 +1397,8 @@ GL_API void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers) { Buffer* buffer = objects[buffers[i]-1].data; if (buffer->data != NULL) { - //FIXME: Assert that the data is no longer used - MmFreeContiguousMemory(buffer->data); + assert(false); //FIXME: Assert that the data is no longer used + FreeResourceMemory(buffer->data); } } del_objects(n, buffers); @@ -1181,6 +1411,7 @@ static void store_attrib_pointer(Attrib* attrib, GLenum gl_type, unsigned int si } else { Buffer* buffer = objects[gl_array_buffer-1].data; base = (uintptr_t)buffer->data; + assert(base != 0); } attrib->array.gl_type = gl_type; attrib->array.size = size; @@ -1205,14 +1436,79 @@ GL_API void GL_APIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride store_attrib_pointer(&state.vertex_array, type, size, stride, pointer); } +static uint32_t* borders(uint32_t* p) { + + p = xgu_begin(p, XGU_LINE_STRIP); + p = xgux_set_color3f(p, 1.0f, 0.0f, 0.0f); + p = xgu_vertex4f(p, 10, 10, 1.0f, 1.0f); + p = xgu_vertex4f(p, 10, 470, 1.0f, 1.0f); + p = xgu_vertex4f(p, 630, 470, 1.0f, 1.0f); + p = xgu_vertex4f(p, 630, 10, 1.0f, 1.0f); + p = xgu_vertex4f(p, 10, 10, 1.0f, 1.0f); + p = xgu_end(p); + + p = xgu_begin(p, XGU_LINE_STRIP); + p = xgux_set_color3f(p, 0.0f, 0.0f, 1.0f); + p = xgu_vertex4f(p, -310, -230, 1.0f, 1.0f); + p = xgu_vertex4f(p, -310, 230, 1.0f, 1.0f); + p = xgu_vertex4f(p, 310, 230, 1.0f, 1.0f); + p = xgu_vertex4f(p, 310, -230, 1.0f, 1.0f); + p = xgu_vertex4f(p, -310, -230, 1.0f, 1.0f); + p = xgu_end(p); + +/* + p = xgu_begin(p, XGU_TRIANGLE_STRIP); + p = xgux_set_color3f(p, 1.0f, 1.0f, 1.0f); + for(int i = -1; i < 4; i++) + p = xgux_set_texcoord3f(p, i, 0.0f, 0.0f, 1.0f); p = xgu_vertex4f(p, -310, -230, 1.0f, 1.0f); + for(int i = -1; i < 4; i++) + p = xgux_set_texcoord3f(p, i, 32.0f, 0.0f, 1.0f); p = xgu_vertex4f(p, 310, -230, 1.0f, 1.0f); + for(int i = -1; i < 4; i++) + p = xgux_set_texcoord3f(p, i, 0.0f, 32.0f, 1.0f); p = xgu_vertex4f(p, -310, 230, 1.0f, 1.0f); + for(int i = -1; i < 4; i++) + p = xgux_set_texcoord3f(p, i, 32.0f, 32.0f, 1.0f); p = xgu_vertex4f(p, 310, 230, 1.0f, 1.0f); + p = xgu_end(p); +*/ + + return p; +} + // Draw calls GL_API void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count) { + + static unsigned int f = -1; + if (f == frame) { + //return; + } + f = frame; + prepare_drawing(); xgux_draw_arrays(gl_to_xgu_primitive_type(mode), first, count); +#if 1 + uint32_t* p = pb_begin(); +#if 0 + p = xgu_begin(p, XGU_LINE_STRIP); //gl_to_xgu_primitive_type(mode)); + pb_end(p); + print_attrib(XGU_VERTEX_ARRAY, &state.vertex_array, first, count, true); + p = pb_begin(); + p = xgu_end(p); +#endif +p = borders(p); + pb_end(p); +#endif } GL_API void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices) { + +//return; + + static unsigned int f = -1; + if (f == frame) { + //return; + } + f = frame; + prepare_drawing(); uintptr_t base; @@ -1221,19 +1517,38 @@ GL_API void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, } else { Buffer* buffer = objects[gl_element_array_buffer-1].data; base = (uintptr_t)buffer->data; + assert(base != 0); } // This function only handles the 16 bit variant for now switch(type) { case GL_UNSIGNED_SHORT: { - xgux_draw_elements16(gl_to_xgu_primitive_type(mode), (const uint16_t*)(base + (uintptr_t)indices), count); + const uint16_t* indices_ptr = (const uint16_t*)(base + (uintptr_t)indices); + xgux_draw_elements16(gl_to_xgu_primitive_type(mode), indices_ptr, count); +#if 1 + uint32_t* p = pb_begin(); +#if 0 + p = xgu_begin(p, XGU_LINE_STRIP); //gl_to_xgu_primitive_type(mode)); + p = xgu_vertex3f(p, 0, 0, 1); + pb_end(p); + for(unsigned int i = 0; i < count; i++) { + print_attrib(XGU_VERTEX_ARRAY, &state.vertex_array, indices_ptr[i], 1, true); + } + p = pb_begin(); + p = xgu_end(p); +#endif +p = borders(p); + pb_end(p); +#endif break; } #if 0 //FIXME: Not declared in gl.h + untested - case GL_UNSIGNED_INT: - xgux_draw_elements32(gl_to_xgu_primitive_type(mode), (const uint32_t*)(base + (uintptr_t)indices), count); + case GL_UNSIGNED_INT: { + const uint32_t* indices_ptr = (const uint32_t*)(base + (uintptr_t)indices); + xgux_draw_elements32(gl_to_xgu_primitive_type(mode), indices_ptr, count); break; + } #endif default: unimplemented("%d", type); @@ -1276,31 +1591,35 @@ GL_API void GL_APIENTRY glLoadIdentity (void) { matrix_identity(matrix); assert(!isinf(matrix[1])); + +debugPrint("\nident:\n"); +PRINT_MATRIX(matrix) + } GL_API void GL_APIENTRY glMultMatrixf (const GLfloat *m) { //FIXME: Remove sanity checks for(int i = 0; i < 4*4; i++) { - debugPrint("0x%08X ", *(uint32_t*)&matrix[i]); +// debugPrint("0x%08X ", *(uint32_t*)&matrix[i]); assert(!isinf(matrix[i])); } - debugPrint("= x\n"); +// debugPrint("= x\n"); for(int i = 0; i < 4*4; i++) { - debugPrint("0x%08X ", *(uint32_t*)&m[i]); +// debugPrint("0x%08X ", *(uint32_t*)&m[i]); assert(!isinf(m[i])); } - debugPrint("= m\n"); +// debugPrint("= m\n"); float t[4 * 4]; matmul4(t, matrix, m); memcpy(matrix, t, sizeof(t)); for(int i = 0; i < 4*4; i++) { - debugPrint("0x%08X ", *(uint32_t*)&matrix[i]); +// debugPrint("0x%08X ", *(uint32_t*)&matrix[i]); assert(!isinf(matrix[i])); } - debugPrint("= r\n"); +// debugPrint("= r\n"); assert(!isinf(matrix[1])); } @@ -1309,7 +1628,6 @@ GL_API void GL_APIENTRY glOrthof (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GL ortho(m, l, r, b, t, n, f); assert(!isinf(m[0])); //FIXME: Remove sanity check glMultMatrixf(m); - assert(!isinf(matrix[1])); //FIXME: Remove sanity check } @@ -1317,6 +1635,15 @@ GL_API void GL_APIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z) { float m[4*4]; matrix_identity(m); _math_matrix_translate(m, x, y, z); + +#if 0 +debugPrint("\ntrans: "); +debugPrintFloat(x); debugPrint(" "); +debugPrintFloat(y); debugPrint(" "); +debugPrintFloat(z); debugPrint("\n"); +PRINT_MATRIX(m); +#endif + assert(!isinf(m[0])); //FIXME: Remove sanity check glMultMatrixf(m); @@ -1338,8 +1665,16 @@ GL_API void GL_APIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z) { matrix_identity(m); _math_matrix_scale(m, x, y, z); assert(!isinf(m[0])); //FIXME: Remove sanity check - glMultMatrixf(m); +#if 0 +debugPrint("\nscale: "); +debugPrintFloat(x); debugPrint(" "); +debugPrintFloat(y); debugPrint(" "); +debugPrintFloat(z); debugPrint("\n"); +PRINT_MATRIX(m); +#endif + + glMultMatrixf(m); assert(!isinf(matrix[1])); //FIXME: Remove sanity check } @@ -1454,9 +1789,9 @@ GL_API void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internal if (tx->data != NULL) { //FIXME: Re-use existing buffer if it's a good fit? //FIXME: Assert that this memory is no longer used - MmFreeContiguousMemory(tx->data); + FreeResourceMemory(tx->data); } - tx->data = MmAllocateContiguousMemory(size); + tx->data = AllocateResourceMemory(size); // Copy pixels //FIXME: Respect GL pixel packing stuff @@ -1832,6 +2167,38 @@ GL_API void GL_APIENTRY glPixelStorei (GLenum pname, GLint param) { #if 1 EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface) { + + frame++; + +#if 1 + //FIXME: This doesn't work for some reason + static bool draw_debug = false; + SDL_GameControllerUpdate(); + if (g == NULL) { + g = SDL_GameControllerOpen(0); + if (g == NULL) { + debugPrint("failed to open gamepad\n"); + Sleep(100); + } + } + if (g != NULL) { + bool button = SDL_GameControllerGetButton(g, SDL_CONTROLLER_BUTTON_START); + if (button) { + draw_debug = !draw_debug; + + if (draw_debug) { + pb_show_front_screen(); + } else { + pb_show_debug_screen(); + } + + Sleep(200); + } + } +#endif + + + debugPrint("Going to swap buffers\n"); /* Draw some text on the screen */ @@ -1871,7 +2238,6 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface -//FIXME: Use stuff like `ptr = MmAllocateContiguousMemoryEx(size, 0, 0x3ffb000, 0, 0x404);` to alloc buffer / tex // Initialization @@ -1931,6 +2297,39 @@ __attribute__((constructor)) static void setup_xbox(void) { pb_show_debug_screen(); #endif + +#if 0 + // GL self-test (might leak some memory) + GLuint b; + glGenBuffers(1, &b); + glBindBuffer(GL_ARRAY_BUFFER, b); + uint8_t data[] = {0,-1,-1,3,4,5,6,7,8}; + glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, 0); + uint8_t subdata[] = {1,2}; + glBufferSubData(GL_ARRAY_BUFFER, 1, sizeof(subdata), subdata); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_SHORT, 4, (void*)0); + prepare_drawing(); + Sleep(2000); +#endif + +#if 1 + debugPrintFloat(0.01f); debugPrint(" "); + debugPrintFloat(0.001f); debugPrint(" "); + debugPrintFloat(0.0001f); debugPrint(" "); + debugPrintFloat(1.0f); debugPrint(" "); + debugPrintFloat(-1.0f); debugPrint(" "); + debugPrintFloat(123.456f); debugPrint(" "); + debugPrintFloat(123.4f); debugPrint(" "); + debugPrintFloat(123.44444f); debugPrint(" "); + debugPrintFloat(123.45555f); debugPrint(" "); + debugPrint("\n"); +#endif + + // Workaround for nxdk-sdl bug? + //FIXME: Why is this necessary? + SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); + //debugPrint("\n\n\n\n"); //FIXME: Bump GPU in right state? From 7c43bbe9cd93e3c8f924f7bfb0942bab503a26c8 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 23 Dec 2019 03:27:48 +0100 Subject: [PATCH 14/93] REMOVEME Disable some more asserts --- share/gui.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/share/gui.c b/share/gui.c index 112806146..ecc831ed3 100644 --- a/share/gui.c +++ b/share/gui.c @@ -223,7 +223,7 @@ static void draw_text(int id) static void draw_image(int id) { glDrawArrays(GL_TRIANGLE_STRIP, id * WIDGET_VERT + RECT_VERT, IMAGE_VERT); -assert(0); +//assert(0); } static void draw_disable(void) @@ -771,7 +771,7 @@ void gui_set_image(int id, const char *file) glDeleteTextures(1, &widget[id].image); widget[id].image = make_image_from_file(file, IF_MIPMAP); -assert(widget[id].image != 0); +//assert(widget[id].image != 0); } void gui_set_label(int id, const char *text) @@ -791,7 +791,7 @@ void gui_set_label(int id, const char *text) &widget[id].text_w, &widget[id].text_h, str, ttf, 0); -assert(widget[id].image != 0); +//assert(widget[id].image != 0); w = widget[id].text_w; h = widget[id].text_h; @@ -919,7 +919,7 @@ int gui_image(int pd, const char *file, int w, int h) if ((id = gui_widget(pd, GUI_IMAGE))) { widget[id].image = make_image_from_file(file, IF_MIPMAP); -assert(widget[id].image != 0); +//assert(widget[id].image != 0); widget[id].w = w; widget[id].h = h; widget[id].flags |= GUI_RECT; @@ -951,7 +951,7 @@ int gui_state(int pd, const char *text, int size, int token, int value) &widget[id].text_w, &widget[id].text_h, text, ttf, 0); -assert(widget[id].image != 0); +//assert(widget[id].image != 0); widget[id].w = widget[id].text_w; widget[id].h = widget[id].text_h; widget[id].size = size; @@ -974,7 +974,7 @@ assert(ttf != NULL); &widget[id].text_w, &widget[id].text_h, text, ttf, 0); -assert(widget[id].image != 0); +//assert(widget[id].image != 0); widget[id].w = widget[id].text_w; widget[id].h = widget[id].text_h; widget[id].size = size; @@ -1680,7 +1680,7 @@ static void gui_paint_label(int id) /* Short-circuit empty labels. */ if (widget[id].image == 0) { - assert(0); + //assert(0); return; } From 2114aacbeedcde36fba54c4a9dda5a3bde0d919d Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 23 Dec 2019 03:28:49 +0100 Subject: [PATCH 15/93] more win --- xbox/GLES/gl.h | 2 + xbox/xbox.c | 189 +++++++++++++++++++++++++++++-------------------- 2 files changed, 113 insertions(+), 78 deletions(-) diff --git a/xbox/GLES/gl.h b/xbox/GLES/gl.h index 55f43390a..b8ff920bf 100644 --- a/xbox/GLES/gl.h +++ b/xbox/GLES/gl.h @@ -153,6 +153,7 @@ typedef unsigned int GLbitfield; #define GL_INTERPOLATE 10082 #define GL_MODULATE 10083 + #define GL_NEAREST 10084 #define GL_OPERAND0_ALPHA 10085 @@ -256,6 +257,7 @@ GL_API void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, GL_API void GL_APIENTRY glMatrixMode (GLenum mode); GL_API void GL_APIENTRY glLoadIdentity (void); GL_API void GL_APIENTRY glMultMatrixf (const GLfloat *m); +//#define glMultMatrixf(m) { debugPrint("%s:%d\n", __FILE__, __LINE__); glMultMatrixf(m); } GL_API void GL_APIENTRY glOrthof (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); GL_API void GL_APIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z); GL_API void GL_APIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); diff --git a/xbox/xbox.c b/xbox/xbox.c index 54d0cda28..8c4342046 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -10,7 +10,7 @@ static unsigned int frame = 0; //FIXME: Remove static SDL_GameController* g = NULL; -static void debugPrintFloat(float f) { +void debugPrintFloat(float f) { #if 0 //FIXME: pdclib can't do this debugPrint("%f", f); @@ -366,6 +366,21 @@ static XguPrimitiveType gl_to_xgu_primitive_type(GLenum mode) { } } +#define XGU_TEXTURE_FILTER_LINEAR 4 //FIXME: Shitty workaround for XGU +#define XGU_TEXTURE_FILTER_NEAREST XGU_TEXTURE_FILTER_LINEAR //FIXME: Shitty workaround for XGU + +static XguStencilOp gl_to_xgu_texture_filter(GLenum filter) { + switch(filter) { + case GL_LINEAR: return XGU_TEXTURE_FILTER_LINEAR; + case GL_NEAREST: return XGU_TEXTURE_FILTER_NEAREST; + default: + unimplemented("%d", filter); + assert(false); + return -1; + } +} + + static XguStencilOp gl_to_xgu_stencil_op(GLenum op) { switch(op) { default: @@ -866,7 +881,7 @@ static unsigned int gl_to_xgu_texture_format(GLenum internalformat) { case GL_LUMINANCE: return XGU_TEXTURE_FORMAT_Y8; case GL_LUMINANCE_ALPHA: return XGU_TEXTURE_FORMAT_A8Y8; case GL_RGB: return XGU_TEXTURE_FORMAT_X8R8G8B8; - case GL_RGBA: return XGU_TEXTURE_FORMAT_A8R8G8B8; + case GL_RGBA: return XGU_TEXTURE_FORMAT_A8B8G8R8; default: unimplemented("%d", internalformat); assert(false); @@ -901,9 +916,8 @@ static void setup_textures() { // Disable texture p = pb_begin(); - p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_ENABLE(i),0x0003ffc0);//set stage 1 texture enable flags (bit30 disabled) - p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_WRAP(i),0x00030303);//set stage 1 texture modes (0x0W0V0U wrapping: 1=wrap 2=mirror 3=clamp 4=border 5=clamp to edge) - p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_FILTER(i),0x02022000);//set stage 1 texture filters (no AA, stage not even used) + p = xgu_set_texture_control0(p, i, false, 0, 0); + //FIXME: pbkit also sets wrap/addressing and filter stuff for disabled textures?! pb_end(p); // Find the next used clip plane @@ -953,28 +967,51 @@ static void setup_textures() { // Setup texture shaders[i] = NV097_SET_SHADER_STAGE_PROGRAM_STAGE0_2D_PROJECTIVE; p = pb_begin(); + + //FIXME: I'd rather have XGU_TEXTURE_2D and XGU_TEXTURE_CUBEMAP for these + bool cubemap_enable = false; + unsigned int dimensionality = 2; + + unsigned int context_dma = 0; //FIXME: Which one did pbkit use? + bool border = false; + p = xgu_set_texture_offset(p, i, (uintptr_t)tx->data & 0x03ffffff); + p = xgu_set_texture_format(p, i, context_dma, cubemap_enable, border, dimensionality, + gl_to_xgu_texture_format(tx->internal_base_format), 1, + 0,0,0); + unimplemented("Setup wrap"); //FIXME: !!! + p = xgu_set_texture_address(p, i, 0x00030303); //FIXME: Shitty workaround for XGU + p = xgu_set_texture_control0(p, i, true, 0, 0); + p = xgu_set_texture_control1(p, i, tx->pitch); + p = xgu_set_texture_filter(p, i, 0, gl_to_xgu_texture_filter(tx->min_filter), + gl_to_xgu_texture_filter(tx->mag_filter), + false, false, false, false); + p = xgu_set_texture_image_rect(p, i, tx->width, tx->height); + +#if 0 //FIXME: Use NV097_SET_TEXTURE_FORMAT and friends p = pb_push2(p,NV20_TCL_PRIMITIVE_3D_TX_OFFSET(i), (uintptr_t)tx->data & 0x03ffffff, 0x0001002A | (gl_to_xgu_texture_format(tx->internal_base_format) << 8)); //set stage 0 texture address & format p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_NPOT_PITCH(i), tx->pitch<<16); //set stage 0 texture pitch (pitch<<16) p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_NPOT_SIZE(i), (tx->width<<16) | tx->height); //set stage 0 texture width & height ((witdh<<16)|height) - unimplemented("Setup wrap"); //FIXME: !!! + p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_WRAP(i),0x00030303);//set stage 0 texture modes (0x0W0V0U wrapping: 1=wrap 2=mirror 3=clamp 4=border 5=clamp to edge) p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_ENABLE(i),0x4003ffc0); //set stage 0 texture enable flags - unimplemented("Setup min and mag"); //FIXME: !!! + p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_FILTER(i),0x04074000); //set stage 0 texture filters (AA!) +#endif p = xgu_set_texgen_s(p, i, XGU_TEXGEN_DISABLE); p = xgu_set_texgen_t(p, i, XGU_TEXGEN_DISABLE); p = xgu_set_texgen_r(p, i, XGU_TEXGEN_DISABLE); p = xgu_set_texgen_q(p, i, XGU_TEXGEN_DISABLE); p = xgu_set_texture_matrix_enable(p, i, true); - //FIXME: Not hitting pixel centers yet! + unimplemented(); //FIXME: Not hitting pixel centers yet! const float m[4*4] = { tx->width, 0.0f, 0.0f, 0.0f, 0.0f, tx->height, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; + unimplemented(); //FIXME: Also respect matrix_t p = xgu_set_texture_matrix(p, i, m); pb_end(p); @@ -1027,29 +1064,35 @@ static void setup_matrices() { const float* matrix_p_now = &matrix_p[matrix_p_slot * 4*4]; const float* matrix_mv_now = &matrix_mv[matrix_mv_slot * 4*4]; -#if 0 - for(int i = 0; i < 4*4; i++) { - debugPrint("%d %d [%d]\n", matrix_p_slot, matrix_mv_slot, i); - assert(!isinf(matrix_p_now[i])); - assert(!isinf(matrix_mv_now[i])); - } -#endif #define PRINT_MATRIX(_m) \ - { \ + if (0) { \ const float* __m = _m; \ for(int i = 0; i < 4; i++) { \ for(int j = 0; j < 4; j++) { \ debugPrint(" "); \ debugPrintFloat(__m[i*4+j]); \ - assert(!isinf(__m[i*4+j])); \ } \ debugPrint("\n"); \ } \ + CHECK_MATRIX(__m); \ + } + +#define CHECK_MATRIX(_mc) \ + if (1) { \ + /*debugPrint(":%d (%s)\n", __LINE__, __FUNCTION__); */ \ + const float* __mc = _mc; \ + for(int i = 0; i < 4; i++) { \ + for(int j = 0; j < 4; j++) { \ + assert(!isinf(__mc[i*4+j])); \ + } \ + } \ } +#if 0 debugPrint("\ndraw:\n"); PRINT_MATRIX(matrix_p_now); +#endif #if 1 { @@ -1074,6 +1117,7 @@ float f = 6000.0f; matrix_identity(m); static float dx = 320.0f; static float dy = -240.0f; +#if 0 if (g != NULL) { float xx = SDL_GameControllerGetAxis(g, SDL_CONTROLLER_AXIS_RIGHTX); if (fabsf(xx) > 1000) { dx += xx/f; } @@ -1081,6 +1125,7 @@ if (g != NULL) { if (fabsf(xy) > 1000) { dy += xy/f; } } pb_print("%d %d scale\n", (int)(1000*dx), (int)(1000*dy)); +#endif _math_matrix_scale(m, dx, dy, -(float)0xFFFF); float t[4*4]; memcpy(t, matrix_p_now, sizeof(t)); @@ -1093,6 +1138,7 @@ pb_print("%d %d scale\n", (int)(1000*dx), (int)(1000*dy)); matrix_identity(m); static float dx = 0.0f; static float dy = -480.0f; +#if 0 if (g != NULL) { float xx = SDL_GameControllerGetAxis(g, SDL_CONTROLLER_AXIS_LEFTX); if (fabsf(xx) > 1000) { dx += xx/f; } @@ -1100,6 +1146,7 @@ if (g != NULL) { if (fabsf(xy) > 1000) { dy += xy/f; } } pb_print("%d %d trans\n", (int)(1000*dx), (int)(1000*dy)); +#endif _math_matrix_translate(m, dx, dy, 0.0f); float t[4*4]; memcpy(t, matrix_p_now, sizeof(t)); @@ -1111,8 +1158,10 @@ pb_print("%d %d trans\n", (int)(1000*dx), (int)(1000*dy)); // matrix_identity(matrix_mv_now); //matrix_identity(matrix_p_now); +#if 0 debugPrint("\ndraw (xbox):\n"); PRINT_MATRIX(matrix_p_now); +#endif //Sleep(100); #endif @@ -1147,23 +1196,11 @@ TRANSPOSE(matrix_mv_now) //FIXME: Could be wrong float matrix_c_now[4*4]; -bool flip = false; -if (g != NULL) { - flip = SDL_GameControllerGetButton(g, SDL_CONTROLLER_BUTTON_BACK); -} -if (flip) { - matmul4(matrix_c_now, matrix_p_now, matrix_mv_now); -pb_print("p*mv\n"); -} else { matmul4(matrix_c_now, matrix_mv_now, matrix_p_now); -pb_print("mv*p\n"); -} - for(int i = 0; i < 4*4; i++) { - assert(!isinf(matrix_p_now[i])); - assert(!isinf(matrix_mv_now[i])); - assert(!isinf(matrix_c_now[i])); - } + CHECK_MATRIX(matrix_p_now); + CHECK_MATRIX(matrix_mv_now); + CHECK_MATRIX(matrix_c_now); #if 0 @@ -1330,8 +1367,8 @@ GL_API void GL_APIENTRY glClear (GLbitfield mask) { int height = pb_back_buffer_height(); //FIXME: Remove this hack! - pb_erase_depth_stencil_buffer(0, 0, width, height); //FIXME: Do in XGU - pb_fill(0, 0, width, height, 0x80808080); //FIXME: Do in XGU + pb_erase_depth_stencil_buffer(0, 0, width/2, height/4); //FIXME: Do in XGU + pb_fill(0, 0, width/2, height/4, 0x80808080); //FIXME: Do in XGU } @@ -1397,7 +1434,7 @@ GL_API void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers) { Buffer* buffer = objects[buffers[i]-1].data; if (buffer->data != NULL) { - assert(false); //FIXME: Assert that the data is no longer used + unimplemented(); //FIXME: Assert that the data is no longer used FreeResourceMemory(buffer->data); } } @@ -1438,6 +1475,7 @@ GL_API void GL_APIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride static uint32_t* borders(uint32_t* p) { +/* p = xgu_begin(p, XGU_LINE_STRIP); p = xgux_set_color3f(p, 1.0f, 0.0f, 0.0f); p = xgu_vertex4f(p, 10, 10, 1.0f, 1.0f); @@ -1455,6 +1493,7 @@ static uint32_t* borders(uint32_t* p) { p = xgu_vertex4f(p, 310, -230, 1.0f, 1.0f); p = xgu_vertex4f(p, -310, -230, 1.0f, 1.0f); p = xgu_end(p); +*/ /* p = xgu_begin(p, XGU_TRIANGLE_STRIP); @@ -1560,7 +1599,7 @@ p = borders(p); // Matrix functions GL_API void GL_APIENTRY glMatrixMode (GLenum mode) { - assert(!isinf(matrix[1])); //FIXME: Remove sanity check + CHECK_MATRIX(matrix); switch(mode) { case GL_PROJECTION: @@ -1584,51 +1623,39 @@ GL_API void GL_APIENTRY glMatrixMode (GLenum mode) { // Go to the current slot matrix = &matrix[*matrix_slot * 4*4]; - assert(!isinf(matrix[1])); //FIXME: Remove sanity check + CHECK_MATRIX(matrix); } GL_API void GL_APIENTRY glLoadIdentity (void) { matrix_identity(matrix); - assert(!isinf(matrix[1])); - -debugPrint("\nident:\n"); -PRINT_MATRIX(matrix) - + CHECK_MATRIX(matrix); } -GL_API void GL_APIENTRY glMultMatrixf (const GLfloat *m) { +#undef glMultMatrixf - //FIXME: Remove sanity checks - for(int i = 0; i < 4*4; i++) { -// debugPrint("0x%08X ", *(uint32_t*)&matrix[i]); - assert(!isinf(matrix[i])); - } -// debugPrint("= x\n"); - for(int i = 0; i < 4*4; i++) { -// debugPrint("0x%08X ", *(uint32_t*)&m[i]); - assert(!isinf(m[i])); - } -// debugPrint("= m\n"); +static void _glMultMatrixf (const GLfloat *m) { + + CHECK_MATRIX(matrix); + PRINT_MATRIX(m); float t[4 * 4]; matmul4(t, matrix, m); memcpy(matrix, t, sizeof(t)); - for(int i = 0; i < 4*4; i++) { -// debugPrint("0x%08X ", *(uint32_t*)&matrix[i]); - assert(!isinf(matrix[i])); - } -// debugPrint("= r\n"); - assert(!isinf(matrix[1])); + CHECK_MATRIX(matrix); +} + +GL_API void GL_APIENTRY glMultMatrixf (const GLfloat *m) { + _glMultMatrixf(m); } GL_API void GL_APIENTRY glOrthof (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) { float m[4*4]; ortho(m, l, r, b, t, n, f); - assert(!isinf(m[0])); //FIXME: Remove sanity check - glMultMatrixf(m); - assert(!isinf(matrix[1])); //FIXME: Remove sanity check + CHECK_MATRIX(m); + _glMultMatrixf(m); + CHECK_MATRIX(matrix); } GL_API void GL_APIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z) { @@ -1644,27 +1671,27 @@ debugPrintFloat(z); debugPrint("\n"); PRINT_MATRIX(m); #endif - assert(!isinf(m[0])); //FIXME: Remove sanity check - glMultMatrixf(m); + CHECK_MATRIX(m); + _glMultMatrixf(m); - assert(!isinf(matrix[1])); //FIXME: Remove sanity check + CHECK_MATRIX(matrix); } GL_API void GL_APIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { float m[4*4]; matrix_identity(m); _math_matrix_rotate(m, angle, x, y, z); - assert(!isinf(m[0])); //FIXME: Remove sanity check - glMultMatrixf(m); + CHECK_MATRIX(m); + _glMultMatrixf(m); - assert(!isinf(matrix[1])); //FIXME: Remove sanity check + CHECK_MATRIX(matrix); } GL_API void GL_APIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z) { float m[4*4]; matrix_identity(m); _math_matrix_scale(m, x, y, z); - assert(!isinf(m[0])); //FIXME: Remove sanity check + CHECK_MATRIX(m); #if 0 debugPrint("\nscale: "); @@ -1674,8 +1701,8 @@ debugPrintFloat(z); debugPrint("\n"); PRINT_MATRIX(m); #endif - glMultMatrixf(m); - assert(!isinf(matrix[1])); //FIXME: Remove sanity check + _glMultMatrixf(m); + CHECK_MATRIX(matrix); } GL_API void GL_APIENTRY glPopMatrix (void) { @@ -1683,11 +1710,11 @@ GL_API void GL_APIENTRY glPopMatrix (void) { matrix -= 4*4; *matrix_slot -= 1; - assert(!isinf(matrix[1])); //FIXME: Remove sanity check + CHECK_MATRIX(matrix); } GL_API void GL_APIENTRY glPushMatrix (void) { - assert(!isinf(matrix[1])); //FIXME: Remove sanity check + CHECK_MATRIX(matrix); float* new_matrix = matrix; new_matrix += 4*4; @@ -1805,9 +1832,10 @@ GL_API void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internal assert(tx->pitch == tx->width * 4); for(int y = 0; y < tx->height; y++) { for(int x = 0; x < tx->height; x++) { - dst[0] = src[0]; + //FIXME: Can also use different texture format instead probably + dst[0] = src[2]; dst[1] = src[1]; - dst[2] = src[2]; + dst[2] = src[0]; dst[3] = 0xFF; dst += 4; src += 3; @@ -2313,7 +2341,7 @@ __attribute__((constructor)) static void setup_xbox(void) { Sleep(2000); #endif -#if 1 +#if 0 debugPrintFloat(0.01f); debugPrint(" "); debugPrintFloat(0.001f); debugPrint(" "); debugPrintFloat(0.0001f); debugPrint(" "); @@ -2330,7 +2358,12 @@ __attribute__((constructor)) static void setup_xbox(void) { //FIXME: Why is this necessary? SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); - //debugPrint("\n\n\n\n"); + debugPrint("\n\n\n\n"); + debugPrint("\n\n\n\n"); + debugPrint("\n\n\n\n"); + debugPrint("\n\n\n\n"); + debugPrint("\n\n\n\n"); + debugPrint("\n\n\n\n"); //FIXME: Bump GPU in right state? From 0e1cb49615af9456327904be8dbcfe9c323adcea Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Tue, 24 Dec 2019 04:28:08 +0100 Subject: [PATCH 16/93] REMOVEME: Disable shadows in default config --- xbox/neverballrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbox/neverballrc b/xbox/neverballrc index 64465ec36..02305b121 100644 --- a/xbox/neverballrc +++ b/xbox/neverballrc @@ -10,7 +10,7 @@ multisample 8 mipmap 1 aniso 8 background 1 -shadow 1 +shadow 0 audio_buff 2048 mouse_sense 300 mouse_response 50 From bf57c7e4bd52ca19ec0bb9c5e981a71533d45550 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Tue, 24 Dec 2019 04:29:16 +0100 Subject: [PATCH 17/93] more-xbox-hax --- xbox/xbox.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 8c4342046..cf14592cd 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1061,12 +1061,13 @@ static void setup_matrices() { // Update matrices //FIXME: Keep dirty bits - const float* matrix_p_now = &matrix_p[matrix_p_slot * 4*4]; +unimplemented(); //FIXME: const +float* matrix_p_now = &matrix_p[matrix_p_slot * 4*4]; const float* matrix_mv_now = &matrix_mv[matrix_mv_slot * 4*4]; #define PRINT_MATRIX(_m) \ - if (0) { \ + if (1) { \ const float* __m = _m; \ for(int i = 0; i < 4; i++) { \ for(int j = 0; j < 4; j++) { \ @@ -1155,10 +1156,11 @@ pb_print("%d %d trans\n", (int)(1000*dx), (int)(1000*dy)); + // matrix_identity(matrix_mv_now); //matrix_identity(matrix_p_now); -#if 0 +#if 1 debugPrint("\ndraw (xbox):\n"); PRINT_MATRIX(matrix_p_now); #endif @@ -1194,6 +1196,7 @@ TRANSPOSE(matrix_p_now) TRANSPOSE(matrix_mv_now) + //FIXME: Could be wrong float matrix_c_now[4*4]; matmul4(matrix_c_now, matrix_mv_now, matrix_p_now); @@ -1647,7 +1650,13 @@ static void _glMultMatrixf (const GLfloat *m) { } GL_API void GL_APIENTRY glMultMatrixf (const GLfloat *m) { - _glMultMatrixf(m); + + float t[4 * 4]; + memcpy(t, m, sizeof(t)); + +//TRANSPOSE(t); + + _glMultMatrixf(t); } GL_API void GL_APIENTRY glOrthof (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) { From 336b6a075b04f817358b81a4c8e56c6da0775a7a Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 27 Dec 2019 01:33:22 +0100 Subject: [PATCH 18/93] neverball: Disable some log header (crashes Xbox port) - needs investigation --- share/log.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/share/log.c b/share/log.c index f3642a9c7..e3a926ffa 100644 --- a/share/log.c +++ b/share/log.c @@ -83,10 +83,15 @@ void log_init(const char *name, const char *path) if ((log_fp = fs_open_append(path))) { /* Printed on first message. */ - +#if 0 +#error this will crash probably sprintf(log_header, "%s - %s %s", date_to_str(time(NULL)), name, VERSION); +#endif +#ifdef NXDK +debugPrint("log_init...\n"); +#endif } else { From aed0a5ad8d7fda14fa12485a4f8ef7e599c3ebb6 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 27 Dec 2019 01:35:47 +0100 Subject: [PATCH 19/93] fixupxbox --- Makefile.nxdk | 2 +- xbox/GLES/gl.h | 8 +++ xbox/matrix.h | 40 ++++++++++++- xbox/xbox.c | 154 ++++++++++++++++++++++++++++++++++--------------- 4 files changed, 152 insertions(+), 52 deletions(-) diff --git a/Makefile.nxdk b/Makefile.nxdk index bf1bb2928..37a20defe 100644 --- a/Makefile.nxdk +++ b/Makefile.nxdk @@ -108,7 +108,7 @@ include $(CURDIR)/xbox/Makefile-zlib.xbox include $(CURDIR)/xbox/Makefile-libpng.xbox # XGU -CFLAGS += -I$(CURDIR)/xbox/nxdk/lib +CFLAGS += -idirafter$(CURDIR)/xbox/nxdk/lib all: $(OUTPUT_DIR)/default.xbe data $(GEN_XISO) diff --git a/xbox/GLES/gl.h b/xbox/GLES/gl.h index b8ff920bf..324f68610 100644 --- a/xbox/GLES/gl.h +++ b/xbox/GLES/gl.h @@ -181,6 +181,12 @@ typedef unsigned int GLbitfield; +// Not used in neverball, only for debugging +#define GL_MATRIX_MODE 30000 +#define GL_MODELVIEW_MATRIX 30001 +#define GL_PROJECTION_MATRIX 30002 + + @@ -320,3 +326,5 @@ GL_API void GL_APIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat * // Pixel pushing GL_API void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); +// Not used in neverball, only for debugging +GL_API void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data); diff --git a/xbox/matrix.h b/xbox/matrix.h index 374b91f8f..3692c1c9a 100644 --- a/xbox/matrix.h +++ b/xbox/matrix.h @@ -2,6 +2,40 @@ // These might have come from https://github.com/intel/external-mesa/blob/master/src/mesa/math/m_matrix.c ? //FIXME: Verify that these are conforming to GL spec +#include + +#ifndef NXDK +#define debugPrint(...) printf(__VA_ARGS__) +#define debugPrintFloat(f) printf("%.4f", f) +#else +#include +void debugPrintFloat(float); +#endif + +#define PRINT_MATRIX(_m) \ + if (1) { \ + const float* __m = _m; \ + for(int i = 0; i < 4; i++) { \ + for(int j = 0; j < 4; j++) { \ + debugPrint(" "); \ + debugPrintFloat(__m[i*4+j]); \ + } \ + debugPrint("\n"); \ + } \ + CHECK_MATRIX(__m); \ + } + +#define CHECK_MATRIX(_mc) \ + if (1) { \ + /*debugPrint(":%d (%s)\n", __LINE__, __FUNCTION__); */ \ + const float* __mc = _mc; \ + for(int i = 0; i < 4; i++) { \ + for(int j = 0; j < 4; j++) { \ + assert(!isinf(__mc[i*4+j])); \ + } \ + } \ + } + #define _USE_MATH_DEFINES #include @@ -29,7 +63,7 @@ static void _math_matrix_scale(GLfloat *m, GLfloat x, GLfloat y, GLfloat z ) { } -bool invert(float invOut[16], const float m[16]) +static bool invert(float invOut[16], const float m[16]) { float inv[16], det; int i; @@ -177,7 +211,7 @@ static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b ) #undef B #undef P -void ortho(float* r, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearval, GLdouble farval) { +static void ortho(float* r, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearval, GLdouble farval) { //FIXME: Multiply this onto the existing stack - don't overwrite GLfloat m[16]; @@ -207,7 +241,7 @@ void ortho(float* r, GLdouble left, GLdouble right, GLdouble bottom, GLdouble to memcpy(r, m, sizeof(m)); } -void _math_matrix_rotate( GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z ) +static void _math_matrix_rotate( GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z ) { GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c; diff --git a/xbox/xbox.c b/xbox/xbox.c index cf14592cd..cbaea795e 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -805,7 +805,7 @@ static unsigned int matrix_t_slot[4] = { 0, 0, 0, 0 }; //FIXME: This code assumes that matrix_mv_slot is 0 static unsigned int* matrix_slot = &matrix_mv_slot; static float* matrix = &matrix_mv[0]; - +static GLenum matrix_mode = GL_MODELVIEW; typedef struct { bool enabled; @@ -836,7 +836,7 @@ static void print_attrib(XguVertexArray array, Attrib* attrib, unsigned int star assert(array == XGU_VERTEX_ARRAY); assert(attrib->array.size == 2); uint32_t* p = pb_begin(); - p = xgu_vertex4f(p, v[0], v[1], 1.0f, 1.0f); + p = xgu_vertex4f(p, v[0], v[1], 0.0f, 1.0f); pb_end(p); } } @@ -850,7 +850,18 @@ static void print_attrib(XguVertexArray array, Attrib* attrib, unsigned int star debugPrintFloat(v[j]); } debugPrint("\n"); - assert(!submit); + if (submit) { + assert(array == XGU_VERTEX_ARRAY); + uint32_t* p = pb_begin(); + if (attrib->array.size == 2){ + p = xgu_vertex4f(p, v[0], v[1], 0.0f, 1.0f); + } else if (attrib->array.size == 3){ + p = xgu_vertex4f(p, v[0], v[1], v[2], 1.0f); + } else { + assert(false); + } + pb_end(p); + } } } } @@ -858,8 +869,8 @@ static void print_attrib(XguVertexArray array, Attrib* attrib, unsigned int star static void setup_attrib(XguVertexArray array, Attrib* attrib) { if (!attrib->array.enabled) { uint32_t* p = pb_begin(); - // The following isn't 0, 0, 0 to avoid assert in XQEMU; anything with 0, x, 0 should work - p = xgu_set_vertex_data_array_format(p, array, 1, 0, 0); + //FIXME: Somehow XGU should check for XGU_FLOAT if size is 0? type=FLOAT + size=0 means disabled + p = xgu_set_vertex_data_array_format(p, array, XGU_FLOAT, 0, 0); p = xgu_set_vertex_data4f(p, array, attrib->value[0], attrib->value[1], attrib->value[2], attrib->value[3]); pb_end(p); return; @@ -972,7 +983,7 @@ static void setup_textures() { bool cubemap_enable = false; unsigned int dimensionality = 2; - unsigned int context_dma = 0; //FIXME: Which one did pbkit use? + unsigned int context_dma = 2; //FIXME: Which one did pbkit use? bool border = false; p = xgu_set_texture_offset(p, i, (uintptr_t)tx->data & 0x03ffffff); p = xgu_set_texture_format(p, i, context_dma, cubemap_enable, border, dimensionality, @@ -1066,30 +1077,6 @@ float* matrix_p_now = &matrix_p[matrix_p_slot * 4*4]; const float* matrix_mv_now = &matrix_mv[matrix_mv_slot * 4*4]; -#define PRINT_MATRIX(_m) \ - if (1) { \ - const float* __m = _m; \ - for(int i = 0; i < 4; i++) { \ - for(int j = 0; j < 4; j++) { \ - debugPrint(" "); \ - debugPrintFloat(__m[i*4+j]); \ - } \ - debugPrint("\n"); \ - } \ - CHECK_MATRIX(__m); \ - } - -#define CHECK_MATRIX(_mc) \ - if (1) { \ - /*debugPrint(":%d (%s)\n", __LINE__, __FUNCTION__); */ \ - const float* __mc = _mc; \ - for(int i = 0; i < 4; i++) { \ - for(int j = 0; j < 4; j++) { \ - assert(!isinf(__mc[i*4+j])); \ - } \ - } \ - } - #if 0 debugPrint("\ndraw:\n"); PRINT_MATRIX(matrix_p_now); @@ -1127,7 +1114,7 @@ if (g != NULL) { } pb_print("%d %d scale\n", (int)(1000*dx), (int)(1000*dy)); #endif - _math_matrix_scale(m, dx, dy, -(float)0xFFFF); + _math_matrix_scale(m, dx, dy, (float)0xFFFF); float t[4*4]; memcpy(t, matrix_p_now, sizeof(t)); matmul4(matrix_p_now, t, m); @@ -1154,8 +1141,30 @@ pb_print("%d %d trans\n", (int)(1000*dx), (int)(1000*dy)); matmul4(matrix_p_now, t, m); } +#if 0 +matrix_p_now[4*3+0] = 0.0f; +matrix_p_now[4*3+1] = 0.14f; +matrix_p_now[4*3+2] = -0.99f; +matrix_p_now[4*3+3] = 501.0f; +#endif - +#if 0 +matrix_p_now[4*0+3] = 320.0f; +matrix_p_now[4*1+3] = 240.0f; +#endif +#if 0 +matrix_p_now[4*2+0] = 10.0f; +matrix_p_now[4*2+1] = 10.0f; +matrix_p_now[4*2+3] = 0.0f; +#endif +#if 0 +matrix_p_now[4*3+0] = 10.0f; +matrix_p_now[4*3+1] = 10.0f; +matrix_p_now[4*3+2] = 0.0f; +#endif +#if 0 +matrix_p_now[4*3+3] = 10.0f; +#endif // matrix_identity(matrix_mv_now); //matrix_identity(matrix_p_now); @@ -1170,13 +1179,28 @@ debugPrint("\ndraw (xbox):\n"); #if 0 float m_viewport[4*4] = { - 0.5 * width/2.0f, 0.0f, 0.0f, width/2.0f, + 320.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -240.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0xFFFF, 0, + 0.0f, 480.0f, 0, 1 + }; +//memcpy(matrix_mv_now, m_viewport, sizeof(m_viewport)); +//memcpy(matrix_p_now, m_identity, sizeof(m_identity)); + +matmul4(matrix_p_now,matrix_p_now,m_viewport); +#endif + +#if 0 + float m_viewport[4*4] = { + 0.5 * width/2.0f, 0.0f, 0.0f, width/2.0f, 0.0f, 0.5*-height/2.0f, 0.0f, height/2.0f, 0.0f, 0.0f, (float)0x7FFF, 0x7FFF, 0.0f, 0.0f, 0.0f, 1.0f }; -memcpy(matrix_mv_now, m_viewport, sizeof(m_viewport)); -memcpy(matrix_p_now, m_identity, sizeof(m_identity)); +//memcpy(matrix_mv_now, m_viewport, sizeof(m_viewport)); +//memcpy(matrix_p_now, m_identity, sizeof(m_identity)); + +matmul4(matrix_p_now,m_viewport,matrix_p_now); #endif @@ -1236,6 +1260,13 @@ static void prepare_drawing() { //FIXME: This uses a mask: p = xgu_set_light_enable(p, ); // Setup attributes +#if 1 + uint32_t* p = pb_begin(); + for(int i = 0; i < 16; i++) { + p = xgu_set_vertex_data_array_format(p, i, XGU_FLOAT, 0, 0); + } + pb_end(p); +#endif setup_attrib(XGU_VERTEX_ARRAY, &state.vertex_array); setup_attrib(XGU_COLOR_ARRAY, &state.color_array); setup_attrib(XGU_NORMAL_ARRAY, &state.normal_array); @@ -1278,8 +1309,7 @@ static void prepare_drawing() { { // Disco lighting uint32_t* p = pb_begin(); - // The following isn't 0, 0, 0 to avoid assert in XQEMU; anything with 0, x, 0 should work - p = xgu_set_vertex_data_array_format(p, XGU_COLOR_ARRAY, 1, 0, 0); + p = xgu_set_vertex_data_array_format(p, XGU_COLOR_ARRAY, XGU_FLOAT, 0, 0); p = xgu_set_vertex_data4ub(p, XGU_COLOR_ARRAY, rand() & 0xFF, rand() & 0xFF, rand() & 0xFF, rand() & 0xFF); pb_end(p); } @@ -1309,8 +1339,6 @@ static void prepare_drawing() { - - GL_API void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data) { switch(pname) { case GL_MAX_TEXTURE_SIZE: @@ -1319,6 +1347,24 @@ GL_API void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data) { case GL_MAX_TEXTURE_UNITS: data[0] = 4; break; + case GL_MATRIX_MODE: + data[0] = matrix_mode; + break; + default: + unimplemented("%d", pname); + assert(false); + break; + } +} + +GL_API void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data) { + switch(pname) { + case GL_MODELVIEW_MATRIX: + memcpy(data, &matrix_mv[matrix_mv_slot * 16], 16 * sizeof(GLfloat)); + break; + case GL_PROJECTION_MATRIX: + memcpy(data, &matrix_p[matrix_p_slot * 16], 16 * sizeof(GLfloat)); + break; default: unimplemented("%d", pname); assert(false); @@ -1326,6 +1372,7 @@ GL_API void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data) { } } + GL_API const GLubyte *GL_APIENTRY glGetString (GLenum name) { const char* result = ""; switch(name) { @@ -1370,8 +1417,8 @@ GL_API void GL_APIENTRY glClear (GLbitfield mask) { int height = pb_back_buffer_height(); //FIXME: Remove this hack! - pb_erase_depth_stencil_buffer(0, 0, width/2, height/4); //FIXME: Do in XGU - pb_fill(0, 0, width/2, height/4, 0x80808080); //FIXME: Do in XGU + pb_erase_depth_stencil_buffer(0, 0, width, height); //FIXME: Do in XGU + pb_fill(0, 0, width, height, 0x80808080); //FIXME: Do in XGU } @@ -1519,6 +1566,9 @@ static uint32_t* borders(uint32_t* p) { // Draw calls GL_API void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count) { +unimplemented("disabled due to errors on physical hardware"); +return; //FIXME: !!! + static unsigned int f = -1; if (f == frame) { //return; @@ -1526,7 +1576,9 @@ GL_API void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count) { f = frame; prepare_drawing(); + xgux_draw_arrays(gl_to_xgu_primitive_type(mode), first, count); + #if 1 uint32_t* p = pb_begin(); #if 0 @@ -1604,6 +1656,9 @@ p = borders(p); GL_API void GL_APIENTRY glMatrixMode (GLenum mode) { CHECK_MATRIX(matrix); + // Remember mode + matrix_mode = mode; + switch(mode) { case GL_PROJECTION: matrix = &matrix_p[0]; @@ -1639,7 +1694,9 @@ GL_API void GL_APIENTRY glLoadIdentity (void) { static void _glMultMatrixf (const GLfloat *m) { +debugPrint("_glMultMatrixf:\n"); CHECK_MATRIX(matrix); +//PRINT_MATRIX(matrix); PRINT_MATRIX(m); float t[4 * 4]; @@ -2367,13 +2424,14 @@ __attribute__((constructor)) static void setup_xbox(void) { //FIXME: Why is this necessary? SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); - debugPrint("\n\n\n\n"); - debugPrint("\n\n\n\n"); - debugPrint("\n\n\n\n"); - debugPrint("\n\n\n\n"); - debugPrint("\n\n\n\n"); - debugPrint("\n\n\n\n"); - + debugPrint("\n\n"); + debugPrint("\n\n"); + debugPrint("\n\n"); + debugPrint("\n\n"); + debugPrint("\n\n"); + debugPrint("\n\n"); + debugPrint("\n\n"); + debugPrint("\n\n"); //FIXME: Bump GPU in right state? } From 2622ee424dae2214c18d38ba01b2a3d6ea80977b Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 7 May 2020 22:23:42 +0200 Subject: [PATCH 20/93] use libs from modern nxdk (untested) --- Makefile.nxdk | 7 --- xbox/Makefile-libjpeg-turbo.xbox | 74 -------------------------------- xbox/Makefile-libpng.xbox | 25 ----------- xbox/Makefile-zlib.xbox | 18 -------- xbox/xbox.c | 10 ----- 5 files changed, 134 deletions(-) delete mode 100644 xbox/Makefile-libjpeg-turbo.xbox delete mode 100644 xbox/Makefile-libpng.xbox delete mode 100644 xbox/Makefile-zlib.xbox diff --git a/Makefile.nxdk b/Makefile.nxdk index 37a20defe..df4c8f405 100644 --- a/Makefile.nxdk +++ b/Makefile.nxdk @@ -100,13 +100,6 @@ NXDK_SDL = y include $(CURDIR)/xbox/Makefile-vorbis.xbox include $(CURDIR)/xbox/Makefile-ogg.xbox -# Add libjpeg -include $(CURDIR)/xbox/Makefile-libjpeg-turbo.xbox - -# Add libpng (depends on zlib) -include $(CURDIR)/xbox/Makefile-zlib.xbox -include $(CURDIR)/xbox/Makefile-libpng.xbox - # XGU CFLAGS += -idirafter$(CURDIR)/xbox/nxdk/lib diff --git a/xbox/Makefile-libjpeg-turbo.xbox b/xbox/Makefile-libjpeg-turbo.xbox deleted file mode 100644 index 9b5563ca2..000000000 --- a/xbox/Makefile-libjpeg-turbo.xbox +++ /dev/null @@ -1,74 +0,0 @@ -#FIXME: Depends on jconfig.h being fixed up; modify: -# //#define NEED_SYS_TYPES_H 1 -# //#define NEED_BSD_STRINGS 1 -# // #define __CHAR_UNSIGNED__ 1 -#FIXME: Depends on jconfigint.h being fixed up; modify: -# #define SIZEOF_SIZE_T 4 //@SIZE_T@ -# //#cmakedefine HAVE_BUILTIN_CTZL -# //#cmakedefine HAVE_INTRIN_H -#FIXME: Extend `#if !defined(__MINGW32__) && !defined(NXDK)` in tjutil.h - -#LIBJPEG_TURBO_DIR = $(NXDK_DIR)/lib/libjpeg-turbo -LIBJPEG_TURBO_DIR = $(CURDIR)/xbox/nxdk-libjpeg-turbo - -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcapimin.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcapistd.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jccoefct.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jccolor.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcdctmgr.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jchuff.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcicc.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcinit.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcmainct.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcmarker.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcmaster.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcomapi.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcparam.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcphuff.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcprepct.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcsample.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jctrans.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdapimin.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdapistd.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdatadst.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdatasrc.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdcoefct.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdcolor.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jddctmgr.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdhuff.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdicc.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdinput.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdmainct.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdmarker.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdmaster.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdmerge.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdphuff.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdpostct.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdsample.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdtrans.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jerror.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jfdctflt.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jfdctfst.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jfdctint.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jidctflt.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jidctfst.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jidctint.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jidctred.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jquant1.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jquant2.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jutils.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jmemmgr.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jmemnobs.c) - -#FIXME: Support simd/i386/*-mmx.asm and simd/i386/*-sse.asm -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jsimd_none.c) - -#FIXME: These 3 are optional, not sure why we require them right now -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jaricom.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jcarith.c) -LIBJPEG_TURBO_SRCS += $(wildcard $(LIBJPEG_TURBO_DIR)/jdarith.c) - -SRCS += $(LIBJPEG_TURBO_SRCS) -CFLAGS += -isystem $(LIBJPEG_TURBO_DIR) -# Ideally we'd use -D__MINGW32__ here, so we can compile this lib without -# changes, but that won't work with global CFLAGS diff --git a/xbox/Makefile-libpng.xbox b/xbox/Makefile-libpng.xbox deleted file mode 100644 index d5ec84f08..000000000 --- a/xbox/Makefile-libpng.xbox +++ /dev/null @@ -1,25 +0,0 @@ -#FIXME: Needs to copy $(LIBPNG_DIR)/scripts/pnglibconf.h.prebuilt to $(LIBPNG_DIR)/pnglibconf.h; modify: -# //#define PNG_FLOATING_ARITHMETIC_SUPPORTED -# //#define PNG_FLOATING_POINT_SUPPORTED - -#LIBPNG_DIR = $(NXDK_DIR)/lib/libpng -LIBPNG_DIR = $(CURDIR)/xbox/nxdk-libpng - -LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/png.c) -LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngerror.c) -LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngget.c) -LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngmem.c) -LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngpread.c) -LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngread.c) -LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngrio.c) -LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngrtran.c) -LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngrutil.c) -LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngset.c) -LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngtrans.c) -LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngwio.c) -LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngwrite.c) -LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngwtran.c) -LIBPNG_SRCS += $(wildcard $(LIBPNG_DIR)/pngwutil.c) - -SRCS += $(LIBPNG_SRCS) -CFLAGS += -isystem $(LIBPNG_DIR) diff --git a/xbox/Makefile-zlib.xbox b/xbox/Makefile-zlib.xbox deleted file mode 100644 index 5dca0d4b9..000000000 --- a/xbox/Makefile-zlib.xbox +++ /dev/null @@ -1,18 +0,0 @@ -#ZLIB_DIR = $(NXDK_DIR)/lib/zlib -ZLIB_DIR = $(CURDIR)/xbox/nxdk-zlib - -ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/adler32.c) -ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/crc32.c) -ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/deflate.c) -ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/infback.c) -ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/inffast.c) -ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/inflate.c) -ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/inftrees.c) -ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/trees.c) -ZLIB_SRCS += $(wildcard $(ZLIB_DIR)/zutil.c) - -#FIXME: gzip support - -SRCS += $(ZLIB_SRCS) -CFLAGS += -isystem $(ZLIB_DIR) \ - -DZ_SOLO diff --git a/xbox/xbox.c b/xbox/xbox.c index cbaea795e..4c40b62c1 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -76,16 +76,6 @@ int closedir(DIR *__dirp) { } #endif -// Some windows garbage - -#include - -DWORD GetFileAttributesA( - LPCSTR lpFileName -) { - debugPrint("GetFileAttributes '%s'\n", lpFileName); - return FILE_ATTRIBUTE_DIRECTORY; -} // sys/stat.h #include "sys/stat.h" From 9d45a82c8615bece18e0ee87c65f8329bb15742a Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 7 May 2020 22:23:58 +0200 Subject: [PATCH 21/93] update to planned XGU (untested) --- xbox/xbox.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 4c40b62c1..73a26e45a 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -356,10 +356,11 @@ static XguPrimitiveType gl_to_xgu_primitive_type(GLenum mode) { } } +typedef unsigned int XguTextureFilter; #define XGU_TEXTURE_FILTER_LINEAR 4 //FIXME: Shitty workaround for XGU #define XGU_TEXTURE_FILTER_NEAREST XGU_TEXTURE_FILTER_LINEAR //FIXME: Shitty workaround for XGU -static XguStencilOp gl_to_xgu_texture_filter(GLenum filter) { +static XguTextureFilter gl_to_xgu_texture_filter(GLenum filter) { switch(filter) { case GL_LINEAR: return XGU_TEXTURE_FILTER_LINEAR; case GL_NEAREST: return XGU_TEXTURE_FILTER_NEAREST; @@ -983,7 +984,8 @@ static void setup_textures() { p = xgu_set_texture_address(p, i, 0x00030303); //FIXME: Shitty workaround for XGU p = xgu_set_texture_control0(p, i, true, 0, 0); p = xgu_set_texture_control1(p, i, tx->pitch); - p = xgu_set_texture_filter(p, i, 0, gl_to_xgu_texture_filter(tx->min_filter), + p = xgu_set_texture_filter(p, i, 0, XGU_TEXTURE_CONVOLUTION_QUINCUNX, + gl_to_xgu_texture_filter(tx->min_filter), gl_to_xgu_texture_filter(tx->mag_filter), false, false, false, false); p = xgu_set_texture_image_rect(p, i, tx->width, tx->height); From e8cc6db6f90e80ff745463f61bc8e29530538442 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 7 May 2020 22:24:10 +0200 Subject: [PATCH 22/93] fix FFP on hw (untested) --- xbox/xbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 73a26e45a..e7d76bdc8 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1233,7 +1233,7 @@ TRANSPOSE(matrix_mv_now) /* Set up all states for hardware vertex pipeline */ //FIXME: Might need inverse or some additional transform p = pb_begin(); - p = xgu_set_transform_execution_mode(p, XGU_FIXED, XGU_RANGE_MODE_USER); + p = xgu_set_transform_execution_mode(p, XGU_FIXED, XGU_RANGE_MODE_PRIVATE); //FIXME: p = xgu_set_fog_enable(p, false); p = xgu_set_projection_matrix(p, matrix_p_now); //FIXME: Unused in XQEMU p = xgu_set_composite_matrix(p, matrix_c_now); //FIXME: Always used in XQEMU? From 505fc05e19df142a03629df5824e24b3e400620b Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 7 May 2020 23:06:33 +0200 Subject: [PATCH 23/93] use paths for modern nxdk compatibility --- Makefile.nxdk | 6 +++--- share/base_config.c | 8 ++++++-- share/base_config.h | 10 ++++++++-- share/fs_stdio.c | 4 ++++ 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Makefile.nxdk b/Makefile.nxdk index df4c8f405..babeb98dd 100644 --- a/Makefile.nxdk +++ b/Makefile.nxdk @@ -9,9 +9,9 @@ CFLAGS = CFLAGS += -ferror-limit=0 CFLAGS += -DENABLE_OPENGLES=1 -#CFLAGS += -DCONFIG_USER=\"$(USERDIR)\" \ -#CFLAGS += -DCONFIG_DATA=\"$(DATADIR)\" \ -#CFLAGS += -DCONFIG_LOCALE=\"$(LOCALEDIR)\" +CFLAGS += -DCONFIG_USER=\"E:\\\\UDATA\\\\Neverball\" +CFLAGS += -DCONFIG_DATA=\"D:\\\\Neverball\\\\data\" +CFLAGS += -DCONFIG_LOCALE=\"D:\\\\Neverball\\\\locale\" CFLAGS += -I$(CURDIR)/share/ -I$(CURDIR)/xbox/ -D_CRTIMP= BALL_SRCS := \ diff --git a/share/base_config.c b/share/base_config.c index 858f3fe20..9bffc4e19 100644 --- a/share/base_config.c +++ b/share/base_config.c @@ -45,7 +45,7 @@ static const char *pick_data_path(const char *arg_data_path) return CONFIG_DATA; SAFECPY(dir, fs_base_dir()); - SAFECAT(dir, "/"); + SAFECAT(dir, SEP); SAFECAT(dir, CONFIG_DATA); return dir; @@ -103,7 +103,11 @@ void config_paths(const char *arg_data_path) /* User directory. */ home = pick_home_path(); - user = concat_string(home, "/", CONFIG_USER, NULL); +#ifdef NXDK + user = concat_string("", "", CONFIG_USER, NULL); +#else + user = concat_string(home, SEP, CONFIG_USER, NULL); +#endif /* Set up directory for writing, create if needed. */ diff --git a/share/base_config.h b/share/base_config.h index df4860df6..7e73e7039 100644 --- a/share/base_config.h +++ b/share/base_config.h @@ -30,12 +30,18 @@ #define VERSION "unknown" #endif +#ifdef _WIN32 +#define SEP "\\" +#else +#define SEP "/" +#endif + #ifndef CONFIG_DATA -#define CONFIG_DATA "./data" /* Game data directory */ +#define CONFIG_DATA "." SEP "data" /* Game data directory */ #endif #ifndef CONFIG_LOCALE -#define CONFIG_LOCALE "./locale" /* Game localisation */ +#define CONFIG_LOCALE "." SEP "locale" /* Game localisation */ #endif /* User config directory */ diff --git a/share/fs_stdio.c b/share/fs_stdio.c index e676e4847..0e2f9a1e9 100644 --- a/share/fs_stdio.c +++ b/share/fs_stdio.c @@ -47,7 +47,11 @@ static List fs_path; int fs_init(const char *argv0) { +#ifdef NXDK + fs_dir_base = ""; +#else fs_dir_base = strdup(argv0 && *argv0 ? dir_name(argv0) : "."); +#endif fs_dir_write = NULL; fs_path = NULL; From 0d22bc591a57cf1b2ce0149579741fb409b0ba8d Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 7 May 2020 23:06:54 +0200 Subject: [PATCH 24/93] Remove hacky _windows.h for modern nxdk --- share/dir.c | 1 - xbox/_windows.h | 11 ----------- xbox/xbox.c | 2 ++ 3 files changed, 2 insertions(+), 12 deletions(-) delete mode 100644 xbox/_windows.h diff --git a/share/dir.c b/share/dir.c index 6669944c4..8c597acc4 100644 --- a/share/dir.c +++ b/share/dir.c @@ -31,7 +31,6 @@ #ifdef NXDK #include -#include <_windows.h> #endif List dir_list_files(const char *path) diff --git a/xbox/_windows.h b/xbox/_windows.h deleted file mode 100644 index 1032f7266..000000000 --- a/xbox/_windows.h +++ /dev/null @@ -1,11 +0,0 @@ -// fileapi - -#include - -#define INVALID_FILE_ATTRIBUTES -1 - -DWORD GetFileAttributesA( - LPCSTR lpFileName -); - -#define GetFileAttributes(...) GetFileAttributesA(__VA_ARGS__) diff --git a/xbox/xbox.c b/xbox/xbox.c index e7d76bdc8..9e3cd3fd5 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -7,6 +7,8 @@ #include +#include + static unsigned int frame = 0; //FIXME: Remove static SDL_GameController* g = NULL; From 9c3260be956d222c354794d05981ce99e8678daf Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 7 May 2020 23:07:07 +0200 Subject: [PATCH 25/93] debug print where I assume problems --- share/dir.c | 1 + 1 file changed, 1 insertion(+) diff --git a/share/dir.c b/share/dir.c index 8c597acc4..4891117fb 100644 --- a/share/dir.c +++ b/share/dir.c @@ -166,6 +166,7 @@ int dir_exists(const char *path) return 0; #else DWORD dwAttrib = GetFileAttributes(path); + debugPrint("Path '%s': 0x%08X\n", path, dwAttrib); return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) ? 1 : 0; From c4cd351e2b6d8f20d297e717d423200b8bf84a81 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 7 May 2020 23:08:15 +0200 Subject: [PATCH 26/93] remove stupid X suffix --- Makefile.nxdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.nxdk b/Makefile.nxdk index babeb98dd..2979fb6c4 100644 --- a/Makefile.nxdk +++ b/Makefile.nxdk @@ -1,6 +1,6 @@ NXDK_DIR = $(CURDIR)/../XboxDev/nxdk -XBE_TITLE = NeverballX +XBE_TITLE = Neverball OUTPUT_DIR = bin GEN_XISO = $(XBE_TITLE).iso From 770cf65f327f57957710a539857781f68a2a88ad Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 7 May 2020 23:09:56 +0200 Subject: [PATCH 27/93] Force user to configure their nxdk --- Makefile.nxdk | 2 -- 1 file changed, 2 deletions(-) diff --git a/Makefile.nxdk b/Makefile.nxdk index 2979fb6c4..386aae629 100644 --- a/Makefile.nxdk +++ b/Makefile.nxdk @@ -1,5 +1,3 @@ -NXDK_DIR = $(CURDIR)/../XboxDev/nxdk - XBE_TITLE = Neverball OUTPUT_DIR = bin GEN_XISO = $(XBE_TITLE).iso From 65c914630e50c357c0a90669db93c4a102bbd822 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 7 May 2020 23:11:10 +0200 Subject: [PATCH 28/93] remove redundant include --- share/dir.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/share/dir.c b/share/dir.c index 4891117fb..4bba27195 100644 --- a/share/dir.c +++ b/share/dir.c @@ -29,10 +29,6 @@ #include "dir.h" #include "common.h" -#ifdef NXDK -#include -#endif - List dir_list_files(const char *path) { List files = NULL; From 3b56097e7319a6f7b229e861c9778b61f17d5f8a Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 7 May 2020 23:29:44 +0200 Subject: [PATCH 29/93] critical bugfix in win32 filesearch for neverball --- share/dir.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/share/dir.c b/share/dir.c index 4bba27195..9c066ac54 100644 --- a/share/dir.c +++ b/share/dir.c @@ -50,7 +50,7 @@ printf("-- '%s'\n", ent->d_name); closedir(dir); } #else -#ifndef NXDK +#ifdef NXDK debugPrint("Asking for files in '%s'\n", path); #endif @@ -68,9 +68,11 @@ printf("-- '%s'\n", ent->d_name); #ifndef NXDK printf("-- '%s'\n", FindFileData.cFileName); +#else + debugPrint("-- '%s'\n", FindFileData.cFileName); #endif - FindNextFile(hFind, &FindFileData); + status = FindNextFile(hFind, &FindFileData); } FindClose(hFind); } From fabc89ac3e3bc910d658587faf41ef1a733aea84 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 7 May 2020 23:30:11 +0200 Subject: [PATCH 30/93] REMOVEME: many debug prints --- ball/main.c | 31 ++++++++++++++++++++----------- share/base_config.c | 41 ++++++++++++++++++++++++++++++----------- share/config.c | 6 ++++++ share/dir.c | 3 +++ share/fs_common.c | 10 +++++++++- share/fs_stdio.c | 11 ++++++++++- share/log.c | 3 +++ xbox/xbox.c | 5 +---- 8 files changed, 82 insertions(+), 28 deletions(-) diff --git a/ball/main.c b/ball/main.c index 95e1b218a..54dfdb086 100644 --- a/ball/main.c +++ b/ball/main.c @@ -43,6 +43,12 @@ #include "st_level.h" #include "st_pause.h" +#ifdef NXDK +#include +#else +#define debugPrint(...) +#endif + const char TITLE[] = "Neverball " VERSION; const char ICON[] = "icon/neverball.png"; @@ -529,57 +535,60 @@ static void make_dirs_and_migrate(void) int main(int argc, char *argv[]) { int t1, t0; - +debugPrint("%s:%d\n", __FILE__, __LINE__); if (!fs_init(argc > 0 ? argv[0] : NULL)) { fprintf(stderr, "Failure to initialize virtual file system (%s)\n", fs_error()); return 1; } - +debugPrint("%s:%d\n", __FILE__, __LINE__); opt_parse(argc, argv); - +debugPrint("%s:%d\n", __FILE__, __LINE__); config_paths(opt_data); +debugPrint("%s:%d\n", __FILE__, __LINE__); log_init("Neverball", "neverball.log"); +debugPrint("%s:%d\n", __FILE__, __LINE__); make_dirs_and_migrate(); /* Initialize SDL. */ - +debugPrint("%s:%d\n", __FILE__, __LINE__); if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) == -1) { log_printf("Failure to initialize SDL (%s)\n", SDL_GetError()); return 1; } - +debugPrint("%s:%d\n", __FILE__, __LINE__); /* Enable joystick events. */ - +debugPrint("%s:%d\n", __FILE__, __LINE__); joy_init(); /* Intitialize configuration. */ - +debugPrint("%s:%d\n", __FILE__, __LINE__); config_init(); config_load(); - +debugPrint("%s:%d\n", __FILE__, __LINE__); /* Initialize localization. */ lang_init(); - +debugPrint("%s:%d\n", __FILE__, __LINE__); /* Initialize audio. */ //assert(0); audio_init(); tilt_init(); - +debugPrint("%s:%d\n", __FILE__, __LINE__); /* Initialize video. */ if (!video_init()) { assert(0); return 1; } +debugPrint("%s:%d\n", __FILE__, __LINE__); /* Material system. */ mtrl_init(); - +debugPrint("%s:%d\n", __FILE__, __LINE__); /* Screen states. */ init_state(&st_null); diff --git a/share/base_config.c b/share/base_config.c index 9bffc4e19..f3cafc8ce 100644 --- a/share/base_config.c +++ b/share/base_config.c @@ -28,6 +28,12 @@ #endif #endif +#ifdef NXDK +#include +#else +#define debugPrint(...) +#endif + /*---------------------------------------------------------------------------*/ static const char *pick_data_path(const char *arg_data_path) @@ -95,14 +101,15 @@ void config_paths(const char *arg_data_path) */ /* Data directory. */ - +debugPrint("%s:%d\n", __FILE__, __LINE__); data = pick_data_path(arg_data_path); - +debugPrint("%s:%d\n", __FILE__, __LINE__); fs_add_path_with_archives(data); - +debugPrint("%s:%d\n", __FILE__, __LINE__); /* User directory. */ home = pick_home_path(); +debugPrint("%s:%d\n", __FILE__, __LINE__); #ifdef NXDK user = concat_string("", "", CONFIG_USER, NULL); #else @@ -110,32 +117,44 @@ void config_paths(const char *arg_data_path) #endif /* Set up directory for writing, create if needed. */ - +debugPrint("%s:%d\n", __FILE__, __LINE__); if (!fs_set_write_dir(user)) { +debugPrint("%s:%d\n", __FILE__, __LINE__); int success = 0; log_printf("Failure to establish write directory. First run?\n"); - - if (fs_set_write_dir(home)) - if (fs_mkdir(CONFIG_USER)) - if (fs_set_write_dir(user)) +debugPrint("%s:%d\n", __FILE__, __LINE__); + if (fs_set_write_dir(home)) { + debugPrint("%s:%d\n", __FILE__, __LINE__); + if (fs_mkdir(CONFIG_USER)) { +debugPrint("%s:%d\n", __FILE__, __LINE__); + if (fs_set_write_dir(user)) { +debugPrint("%s:%d\n", __FILE__, __LINE__); success = 1; - + } + } + } +debugPrint("%s:%d\n", __FILE__, __LINE__); if (success) { +debugPrint("%s:%d\n", __FILE__, __LINE__); log_printf("Write directory established at %s\n", user); } else { +debugPrint("%s:%d\n", __FILE__, __LINE__); log_printf("Write directory not established at %s\n", user); fs_set_write_dir(NULL); +debugPrint("%s:%d\n", __FILE__, __LINE__); } +debugPrint("%s:%d\n", __FILE__, __LINE__); } - +debugPrint("%s:%d\n", __FILE__, __LINE__); fs_add_path_with_archives(user); - +debugPrint("%s:%d\n", __FILE__, __LINE__); free((void *) user); +debugPrint("%s:%d\n", __FILE__, __LINE__); } /*---------------------------------------------------------------------------*/ diff --git a/share/config.c b/share/config.c index 6d7508af9..ac996dcf8 100644 --- a/share/config.c +++ b/share/config.c @@ -23,6 +23,12 @@ #include "common.h" #include "fs.h" +#ifdef NXDK +#include +#else +#define debugPrint(...) +#endif + /*---------------------------------------------------------------------------*/ /* Integer options. */ diff --git a/share/dir.c b/share/dir.c index 9c066ac54..f39da1c8b 100644 --- a/share/dir.c +++ b/share/dir.c @@ -66,10 +66,12 @@ printf("-- '%s'\n", ent->d_name); //FIXME: Handle wide strings? files = list_cons(strdup(FindFileData.cFileName), files); +#if 0 #ifndef NXDK printf("-- '%s'\n", FindFileData.cFileName); #else debugPrint("-- '%s'\n", FindFileData.cFileName); +#endif #endif status = FindNextFile(hFind, &FindFileData); @@ -164,6 +166,7 @@ int dir_exists(const char *path) return 0; #else DWORD dwAttrib = GetFileAttributes(path); + printf("Path '%s': 0x%08X\n", path, dwAttrib); debugPrint("Path '%s': 0x%08X\n", path, dwAttrib); return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && diff --git a/share/fs_common.c b/share/fs_common.c index 060b35bfb..ac7396ea2 100644 --- a/share/fs_common.c +++ b/share/fs_common.c @@ -22,6 +22,12 @@ #include "array.h" #include "common.h" +#ifdef NXDK +#include +#else +#define debugPrint(...) +#endif + /* * This file implements the high-level virtual file system layer * routines. @@ -45,9 +51,10 @@ static void add_archives(const char *path) { Array archives; int i; - +debugPrint("scanning '%s'\n", path); if ((archives = dir_scan(path, is_archive, NULL, NULL))) { +debugPrint("scanning '%s' ??\n", path); array_sort(archives, cmp_dir_items); for (i = 0; i < array_len(archives); i++) @@ -55,6 +62,7 @@ static void add_archives(const char *path) dir_free(archives); } +debugPrint("scanning '%s' !!\n", path); } int fs_add_path_with_archives(const char *path) diff --git a/share/fs_stdio.c b/share/fs_stdio.c index 0e2f9a1e9..c30f20fce 100644 --- a/share/fs_stdio.c +++ b/share/fs_stdio.c @@ -107,15 +107,21 @@ int fs_add_path(const char *path) int fs_set_write_dir(const char *path) { +debugPrint("%s:%d\n", __FILE__, __LINE__); if (dir_exists(path)) { +debugPrint("%s:%d\n", __FILE__, __LINE__); if (fs_dir_write) { +debugPrint("%s:%d\n", __FILE__, __LINE__); free(fs_dir_write); +debugPrint("%s:%d\n", __FILE__, __LINE__); fs_dir_write = NULL; +debugPrint("%s:%d\n", __FILE__, __LINE__); } - +debugPrint("%s:%d\n", __FILE__, __LINE__); fs_dir_write = strdup(path); +debugPrint("%s:%d\n", __FILE__, __LINE__); return 1; } return 0; @@ -309,6 +315,9 @@ fs_file fs_open_write(const char *path) fs_file fs_open_append(const char *path) { +#ifdef NXDK +debugPrint("Trying to open '%s' (append)\n", path); +#endif return fs_open_write_flags(path, 1); } diff --git a/share/log.c b/share/log.c index e3a926ffa..b38e616d1 100644 --- a/share/log.c +++ b/share/log.c @@ -78,6 +78,9 @@ debugPrint("%s\n", str); void log_init(const char *name, const char *path) { +#ifdef NXDK +debugPrint("log_init('%s', '%s')\n", name, path); +#endif if (!log_fp) { if ((log_fp = fs_open_append(path))) diff --git a/xbox/xbox.c b/xbox/xbox.c index 9e3cd3fd5..0646466c7 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -2422,10 +2422,7 @@ __attribute__((constructor)) static void setup_xbox(void) { debugPrint("\n\n"); debugPrint("\n\n"); debugPrint("\n\n"); - debugPrint("\n\n"); - debugPrint("\n\n"); - debugPrint("\n\n"); - debugPrint("\n\n"); + //FIXME: Bump GPU in right state? } From e6d8b6e69398d275da11f5905baba4c50e9f8212 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 7 May 2020 23:30:24 +0200 Subject: [PATCH 31/93] move log for modern nxdk and add entry message --- xbox/xbox.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 0646466c7..f1a0713ef 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -2346,7 +2346,8 @@ static NTAPI VOID shutdown_notification_routine (PHAL_SHUTDOWN_REGISTRATION Shut __attribute__((constructor)) static void setup_xbox(void) { // Open log file - freopen("log.txt", "wb", stdout); + freopen("D:\\log.txt", "wb", stdout); + printf("Log started\n"); // Register shutdown routine to catch errors shutdown_registration.NotificationRoutine = shutdown_notification_routine; From e4b72714760ed0efa3cd99b3adb8ae0cd8f17bd7 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 7 May 2020 23:37:59 +0200 Subject: [PATCH 32/93] critical nxdk win32 filelist bugfix HACKY --- share/dir.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/share/dir.c b/share/dir.c index f39da1c8b..3eb31c949 100644 --- a/share/dir.c +++ b/share/dir.c @@ -57,7 +57,9 @@ printf("-- '%s'\n", ent->d_name); HANDLE hFind; WIN32_FIND_DATA FindFileData; - hFind = FindFirstFile(path, &FindFileData); + char buf[1024]; + sprintf(buf, "%s\\*", path); + hFind = FindFirstFile(buf, &FindFileData); if (hFind != INVALID_HANDLE_VALUE) { BOOL status = TRUE; From 8fcffa54c6bce3866d6c5112e383170a32df2604 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 7 May 2020 23:38:22 +0200 Subject: [PATCH 33/93] split debugmessage in dir related func --- share/dir.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/share/dir.c b/share/dir.c index 3eb31c949..ae2cd65ad 100644 --- a/share/dir.c +++ b/share/dir.c @@ -167,9 +167,11 @@ int dir_exists(const char *path) } return 0; #else + printf("Path '%s':", path); + debugPrint("Path '%s':", path); DWORD dwAttrib = GetFileAttributes(path); - printf("Path '%s': 0x%08X\n", path, dwAttrib); - debugPrint("Path '%s': 0x%08X\n", path, dwAttrib); + printf(" 0x%08X\n", path, dwAttrib); + debugPrint(" 0x%08X\n", path, dwAttrib); return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) ? 1 : 0; From fb2c86f77bd974a682d5239ec12be40eb68adc22 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 7 May 2020 23:43:03 +0200 Subject: [PATCH 34/93] force ascii in win32 filelist neverball code --- share/dir.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/share/dir.c b/share/dir.c index ae2cd65ad..9d6b6eb52 100644 --- a/share/dir.c +++ b/share/dir.c @@ -55,11 +55,11 @@ printf("-- '%s'\n", ent->d_name); #endif HANDLE hFind; - WIN32_FIND_DATA FindFileData; + WIN32_FIND_DATAA FindFileData; char buf[1024]; sprintf(buf, "%s\\*", path); - hFind = FindFirstFile(buf, &FindFileData); + hFind = FindFirstFileA(buf, &FindFileData); if (hFind != INVALID_HANDLE_VALUE) { BOOL status = TRUE; @@ -76,7 +76,7 @@ printf("-- '%s'\n", ent->d_name); #endif #endif - status = FindNextFile(hFind, &FindFileData); + status = FindNextFileA(hFind, &FindFileData); } FindClose(hFind); } @@ -169,7 +169,7 @@ int dir_exists(const char *path) #else printf("Path '%s':", path); debugPrint("Path '%s':", path); - DWORD dwAttrib = GetFileAttributes(path); + DWORD dwAttrib = GetFileAttributesA(path); printf(" 0x%08X\n", path, dwAttrib); debugPrint(" 0x%08X\n", path, dwAttrib); From bb95c31b082e339f34122f0083cb932ef0c55ed4 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 8 May 2020 00:00:16 +0200 Subject: [PATCH 35/93] add nxdk workarounds in build-system --- Makefile.nxdk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile.nxdk b/Makefile.nxdk index 386aae629..151b9ba8b 100644 --- a/Makefile.nxdk +++ b/Makefile.nxdk @@ -114,3 +114,7 @@ data: force force: include $(NXDK_DIR)/Makefile + +# nxdk workarounds +NXDK_CFLAGS := $(CFLAGS) $(NXDK_CFLAGS) +CFLAGS := -Wno-deprecated-declarations From 0c3603ba79ef736613f27399c35b52a4f92b628b Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 8 May 2020 00:19:34 +0200 Subject: [PATCH 36/93] fix path for modern nxdk --- share/common.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/share/common.c b/share/common.c index 7ed761668..9b76b097f 100644 --- a/share/common.c +++ b/share/common.c @@ -218,7 +218,11 @@ int path_is_abs(const char *path) char *path_join(const char *head, const char *tail) { +#ifdef _WIN32 + return *head ? concat_string(head, "\\", tail, NULL) : strdup(tail); +#else return *head ? concat_string(head, "/", tail, NULL) : strdup(tail); +#endif } const char *path_last_sep(const char *path) From 168413017fc8e66346eaefa1057e6f1ca6dfd386 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 8 May 2020 00:19:53 +0200 Subject: [PATCH 37/93] hack for stack-corruption crash avoidance --- share/dir.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/share/dir.c b/share/dir.c index 9d6b6eb52..7ad543f38 100644 --- a/share/dir.c +++ b/share/dir.c @@ -167,11 +167,14 @@ int dir_exists(const char *path) } return 0; #else +return 1; +debugPrint("%s:%d\n", __FILE__, __LINE__); printf("Path '%s':", path); debugPrint("Path '%s':", path); DWORD dwAttrib = GetFileAttributesA(path); printf(" 0x%08X\n", path, dwAttrib); debugPrint(" 0x%08X\n", path, dwAttrib); +debugPrint("%s:%d\n", __FILE__, __LINE__); return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) ? 1 : 0; From 58bde6d7f2ed58f59cc83a34a80e49b8ef589a0d Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 8 May 2020 00:20:25 +0200 Subject: [PATCH 38/93] fix paths for new nxdk in asserts --- share/fs_stdio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/share/fs_stdio.c b/share/fs_stdio.c index c30f20fce..d1e2e0949 100644 --- a/share/fs_stdio.c +++ b/share/fs_stdio.c @@ -257,8 +257,8 @@ debugPrint("Trying to open '%s' (read)\n", real); fh->handle = fopen(real, "rb"); assert(fh->handle -|| !strcmp(real, "./Neverball/neverballrc") -|| !strcmp(real, "./Neverball/lang/.txt") +|| !strcmp(real, "D:\\Neverball\\neverballrc") +|| !strcmp(real, "D:\\Neverball\\lang.txt") ); free(real); @@ -291,8 +291,8 @@ debugPrint("Trying to open '%s' (write)\n", real); fh->handle = fopen(real, append ? "ab" : "wb"); assert(fh->handle -|| !strcmp(real, "./Neverball/neverball.log") -|| !strcmp(real, "./Neverball/Replays/Last.nbr") +|| !strcmp(real, "E:\\UDATA\\Neverball\\neverball.log") +|| !strcmp(real, "E:\\UDATA\\Neverball\\Replays\\Last.nbr") ); free(real); From a805ff934a3f85d1c01e96b2f086a94ee7bae620 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 8 May 2020 00:41:42 +0200 Subject: [PATCH 39/93] change config path so it finds default video mode --- Makefile.nxdk | 3 ++- share/fs_stdio.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile.nxdk b/Makefile.nxdk index 151b9ba8b..4b327971b 100644 --- a/Makefile.nxdk +++ b/Makefile.nxdk @@ -7,7 +7,8 @@ CFLAGS = CFLAGS += -ferror-limit=0 CFLAGS += -DENABLE_OPENGLES=1 -CFLAGS += -DCONFIG_USER=\"E:\\\\UDATA\\\\Neverball\" +#CFLAGS += -DCONFIG_USER=\"E:\\\\UDATA\\\\Neverball\" +CFLAGS += -DCONFIG_USER=\"D:\\\\Neverball\" CFLAGS += -DCONFIG_DATA=\"D:\\\\Neverball\\\\data\" CFLAGS += -DCONFIG_LOCALE=\"D:\\\\Neverball\\\\locale\" CFLAGS += -I$(CURDIR)/share/ -I$(CURDIR)/xbox/ -D_CRTIMP= diff --git a/share/fs_stdio.c b/share/fs_stdio.c index d1e2e0949..5b11c5551 100644 --- a/share/fs_stdio.c +++ b/share/fs_stdio.c @@ -291,6 +291,8 @@ debugPrint("Trying to open '%s' (write)\n", real); fh->handle = fopen(real, append ? "ab" : "wb"); assert(fh->handle +|| !strcmp(real, "D:\\Neverball\\neverball.log") +|| !strcmp(real, "D:\\Neverball\\Replays\\Last.nbr") || !strcmp(real, "E:\\UDATA\\Neverball\\neverball.log") || !strcmp(real, "E:\\UDATA\\Neverball\\Replays\\Last.nbr") ); From f7daf423e577da9104b5ac8a82ddb511509f32ce Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 8 May 2020 00:41:58 +0200 Subject: [PATCH 40/93] hacks for windows path --- share/common.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/share/common.c b/share/common.c index 9b76b097f..326f24b73 100644 --- a/share/common.c +++ b/share/common.c @@ -266,7 +266,11 @@ char *path_normalize(char *path) char *sep = path; while ((sep = (char *) path_next_sep(sep))) +#ifdef _WIN32 + *sep++ = '\\'; +#else *sep++ = '/'; +#endif return path; } @@ -315,7 +319,11 @@ const char *dir_name(const char *name) if ((sep = (char *) path_last_sep(buff))) { if (sep == buff) +#ifdef _WIN32 + return "\\"; +#else return "/"; +#endif *sep = '\0'; From 4acbc5d469f4b3dca8e09b3dcd3668b506b5859d Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 8 May 2020 00:42:08 +0200 Subject: [PATCH 41/93] critical fix to make path work on Xbox --- share/fs_stdio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/share/fs_stdio.c b/share/fs_stdio.c index 5b11c5551..d9989c55d 100644 --- a/share/fs_stdio.c +++ b/share/fs_stdio.c @@ -219,6 +219,7 @@ static char *real_path(const char *path) for (p = fs_path; p; p = p->next) { real = path_join(p->data, path); + path_normalize(real); if (file_exists(real)) { #ifdef NXDK From 478fb30c98a7ef9ded8ddcf0c45f82449c58de53 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 8 May 2020 00:44:55 +0200 Subject: [PATCH 42/93] show graphics --- xbox/xbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index f1a0713ef..f96817feb 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -2380,7 +2380,7 @@ __attribute__((constructor)) static void setup_xbox(void) { } // Show framebuffer, not debug-screen -#if 0 +#if 1 pb_show_front_screen(); #else pb_show_debug_screen(); From 0e912a040ae923a186ae463415095dbbdf04f079 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 14 May 2020 02:43:06 +0200 Subject: [PATCH 43/93] Remove some debug prints --- share/fs_stdio.c | 2 ++ xbox/matrix.h | 4 ++++ xbox/xbox.c | 11 ++++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/share/fs_stdio.c b/share/fs_stdio.c index d9989c55d..6799f5282 100644 --- a/share/fs_stdio.c +++ b/share/fs_stdio.c @@ -14,6 +14,8 @@ #ifdef NXDK #include +#else +#define debugPrint(...) 0 #endif #include diff --git a/xbox/matrix.h b/xbox/matrix.h index 3692c1c9a..18a20d133 100644 --- a/xbox/matrix.h +++ b/xbox/matrix.h @@ -8,9 +8,13 @@ #define debugPrint(...) printf(__VA_ARGS__) #define debugPrintFloat(f) printf("%.4f", f) #else +#ifndef debugPrint #include +#endif +#ifndef debugPrintFloat void debugPrintFloat(float); #endif +#endif #define PRINT_MATRIX(_m) \ if (1) { \ diff --git a/xbox/xbox.c b/xbox/xbox.c index f96817feb..cfa808e7e 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1,4 +1,3 @@ -#include #include #include @@ -12,6 +11,9 @@ static unsigned int frame = 0; //FIXME: Remove static SDL_GameController* g = NULL; +#if 0 +#include + void debugPrintFloat(float f) { #if 0 //FIXME: pdclib can't do this @@ -41,6 +43,13 @@ static void _unimplemented(const char* fmt, ...) { } #define unimplemented(fmt, ...) _unimplemented("%s (%s:%d) " fmt "\n", __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) +#else +void debugPrintFloat(float f) {} +#define debugPrintFloat(f) 0 +#define debugPrint(...) 0 +#define unimplemented(fmt, ...) 0 +#endif + // stdlib.h #include From 3b76d17b50d728221d141ef522434d08999efa5c Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 14 May 2020 02:43:23 +0200 Subject: [PATCH 44/93] partial normalize support --- xbox/xbox.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index cfa808e7e..7dab42f5f 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -295,7 +295,8 @@ static uint32_t* set_enabled(uint32_t* p, GLenum cap, bool enabled) { p = xgu_set_alpha_test_enable(p, enabled); break; case GL_NORMALIZE: - unimplemented("GL_NORMALIZE"); //FIXME: Missing from XGU + //FIXME: Needs more changes to matrices? + p = xgu_set_normalization_enable(p, enabled); break; case GL_CULL_FACE: p = xgu_set_cull_face_enable(p, enabled); From 2abd9f86b456336db74fa370174498a9d82eb79a Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 14 May 2020 02:43:45 +0200 Subject: [PATCH 45/93] depth func support --- xbox/xbox.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 7dab42f5f..2eed29363 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -393,6 +393,16 @@ static XguStencilOp gl_to_xgu_stencil_op(GLenum op) { } } +static XguFuncType gl_to_xgu_func_type(GLenum func) { + switch(func) { + case GL_LESS: return XGU_FUNC_LESS; + default: + unimplemented("%d", func); + assert(false); + return -1; + } +} + static XguCullFace gl_to_xgu_cull_face(GLenum mode) { switch(mode) { case GL_FRONT: return XGU_CULL_FRONT; @@ -2010,7 +2020,9 @@ GL_API void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean b } GL_API void GL_APIENTRY glDepthFunc (GLenum func) { - unimplemented(); //FIXME: Missing from XGU + uint32_t* p = pb_begin(); +// p = xgu_set_depth_func(p, gl_to_xgu_func_type(func)); + pb_end(p); } GL_API void GL_APIENTRY glDepthMask (GLboolean flag) { From 747bdad9f3b06f2b64451573212d0f39c11aedb9 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 14 May 2020 02:44:11 +0200 Subject: [PATCH 46/93] invert front face mode for Xbox (WHY?) --- xbox/xbox.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 2eed29363..f4fab234e 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -417,8 +417,9 @@ static XguCullFace gl_to_xgu_cull_face(GLenum mode) { static XguFrontFace gl_to_xgu_front_face(GLenum mode) { switch(mode) { - case GL_CW: return XGU_FRONT_CW; - case GL_CCW: return XGU_FRONT_CCW; + //FIXME: Why do I have to invert this?! + case GL_CW: return XGU_FRONT_CCW; + case GL_CCW: return XGU_FRONT_CW; default: unimplemented("%d", mode); assert(false); @@ -2448,4 +2449,6 @@ __attribute__((constructor)) static void setup_xbox(void) { //FIXME: Bump GPU in right state? + glFrontFace(GL_CW); + } From 9da918dffab2d84d03233ff4ce54b2405d347674 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 14 May 2020 02:44:33 +0200 Subject: [PATCH 47/93] undo texcoord bug workaround --- xbox/xbox.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index f4fab234e..dd248c58d 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -964,7 +964,7 @@ static void setup_textures() { .array = { .enabled = false }, .value = { clip_plane->x, clip_plane->y, clip_plane->z, clip_plane->w } }; - setup_attrib(9 /*FIXME: XGU_TEXCOORD0_ARRAY*/+i, &attrib); + setup_attrib(XGU_TEXCOORD0_ARRAY+i, &attrib); // Setup shader //FIXME: Can use 4 clip planes per texture unit by using texture-matrix? @@ -1285,10 +1285,10 @@ static void prepare_drawing() { setup_attrib(XGU_VERTEX_ARRAY, &state.vertex_array); setup_attrib(XGU_COLOR_ARRAY, &state.color_array); setup_attrib(XGU_NORMAL_ARRAY, &state.normal_array); - setup_attrib( 9 /*FIXME:XGU_TEXCOORD0_ARRAY*/, &state.texture_coord_array[0]); - setup_attrib(10 /*FIXME:XGU_TEXCOORD1_ARRAY*/, &state.texture_coord_array[1]); - setup_attrib(11 /*FIXME:XGU_TEXCOORD2_ARRAY*/, &state.texture_coord_array[2]); - setup_attrib(12 /*FIXME:XGU_TEXCOORD3_ARRAY*/, &state.texture_coord_array[3]); + setup_attrib(XGU_TEXCOORD0_ARRAY, &state.texture_coord_array[0]); + setup_attrib(XGU_TEXCOORD1_ARRAY, &state.texture_coord_array[1]); + setup_attrib(XGU_TEXCOORD2_ARRAY, &state.texture_coord_array[2]); + setup_attrib(XGU_TEXCOORD3_ARRAY, &state.texture_coord_array[3]); // Set up all matrices etc. setup_matrices(); From b69672826c41d1e9cbb832a1896f0517b77f5116 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 14 May 2020 02:44:47 +0200 Subject: [PATCH 48/93] use newer xgu_set_texture_address --- xbox/xbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index dd248c58d..32c2a75d5 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1004,7 +1004,7 @@ static void setup_textures() { gl_to_xgu_texture_format(tx->internal_base_format), 1, 0,0,0); unimplemented("Setup wrap"); //FIXME: !!! - p = xgu_set_texture_address(p, i, 0x00030303); //FIXME: Shitty workaround for XGU + p = xgu_set_texture_address(p, i, 3, false, 3, false, 3, false, false); //FIXME: Shitty workaround for XGU p = xgu_set_texture_control0(p, i, true, 0, 0); p = xgu_set_texture_control1(p, i, tx->pitch); p = xgu_set_texture_filter(p, i, 0, XGU_TEXTURE_CONVOLUTION_QUINCUNX, From 40a8b89e0f6f3d720c304b9b3698f8db069ac903 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 14 May 2020 02:45:37 +0200 Subject: [PATCH 49/93] add hacky states in setup_matrice --- xbox/xbox.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 32c2a75d5..b732ca9f3 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1069,9 +1069,9 @@ static void setup_matrices() { /* A generic identity matrix */ const float m_identity[4*4] = DEFAULT_MATRIX(); - //FIXME: p = xgu_set_skinning(p, XGU_SKINNING_OFF); - //FIXME: p = xgu_set_normalization(p, false); - //FIXME: p = xgu_set_lighting_enable(p, false); + p = xgu_set_skin_mode(p, XGU_SKIN_MODE_OFF); + p = xgu_set_normalization_enable(p, false); + p = xgu_set_lighting_enable(p, false); From 29c9e14596c385be9a9945571176ccd1d9f4c1c5 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 14 May 2020 02:45:59 +0200 Subject: [PATCH 50/93] fix transforms (2D and 3D work now) --- xbox/xbox.c | 102 +++++----------------------------------------------- 1 file changed, 9 insertions(+), 93 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index b732ca9f3..297ae69d4 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1112,77 +1112,19 @@ debugPrint("\ndraw:\n"); - -float f = 6000.0f; - if (true) { - float m[4*4]; - matrix_identity(m); -static float dx = 320.0f; -static float dy = -240.0f; -#if 0 -if (g != NULL) { - float xx = SDL_GameControllerGetAxis(g, SDL_CONTROLLER_AXIS_RIGHTX); - if (fabsf(xx) > 1000) { dx += xx/f; } - float xy = SDL_GameControllerGetAxis(g, SDL_CONTROLLER_AXIS_RIGHTY); - if (fabsf(xy) > 1000) { dy += xy/f; } -} -pb_print("%d %d scale\n", (int)(1000*dx), (int)(1000*dy)); -#endif - _math_matrix_scale(m, dx, dy, (float)0xFFFF); - float t[4*4]; - memcpy(t, matrix_p_now, sizeof(t)); - matmul4(matrix_p_now, t, m); - } - - - if (true) { - float m[4*4]; - matrix_identity(m); -static float dx = 0.0f; -static float dy = -480.0f; -#if 0 -if (g != NULL) { - float xx = SDL_GameControllerGetAxis(g, SDL_CONTROLLER_AXIS_LEFTX); - if (fabsf(xx) > 1000) { dx += xx/f; } - float xy = SDL_GameControllerGetAxis(g, SDL_CONTROLLER_AXIS_LEFTY); - if (fabsf(xy) > 1000) { dy += xy/f; } -} -pb_print("%d %d trans\n", (int)(1000*dx), (int)(1000*dy)); -#endif - _math_matrix_translate(m, dx, dy, 0.0f); + float max_z = 0xFFFFFF; + float m[4*4] = { + 320.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -240.0f, 0.0f, 0.0f, + 0.0f, 0.0f, max_z / 2.0f, 0.0f, + 320.0f, 240.0f, max_z / 2.0f, 1.0f + }; float t[4*4]; memcpy(t, matrix_p_now, sizeof(t)); - matmul4(matrix_p_now, t, m); + matmul4(matrix_p_now, m, t); } -#if 0 -matrix_p_now[4*3+0] = 0.0f; -matrix_p_now[4*3+1] = 0.14f; -matrix_p_now[4*3+2] = -0.99f; -matrix_p_now[4*3+3] = 501.0f; -#endif - -#if 0 -matrix_p_now[4*0+3] = 320.0f; -matrix_p_now[4*1+3] = 240.0f; -#endif -#if 0 -matrix_p_now[4*2+0] = 10.0f; -matrix_p_now[4*2+1] = 10.0f; -matrix_p_now[4*2+3] = 0.0f; -#endif -#if 0 -matrix_p_now[4*3+0] = 10.0f; -matrix_p_now[4*3+1] = 10.0f; -matrix_p_now[4*3+2] = 0.0f; -#endif -#if 0 -matrix_p_now[4*3+3] = 10.0f; -#endif - -// matrix_identity(matrix_mv_now); - //matrix_identity(matrix_p_now); #if 1 debugPrint("\ndraw (xbox):\n"); @@ -1192,32 +1134,6 @@ debugPrint("\ndraw (xbox):\n"); //Sleep(100); #endif -#if 0 - float m_viewport[4*4] = { - 320.0f, 0.0f, 0.0f, 0.0f, - 0.0f, -240.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0xFFFF, 0, - 0.0f, 480.0f, 0, 1 - }; -//memcpy(matrix_mv_now, m_viewport, sizeof(m_viewport)); -//memcpy(matrix_p_now, m_identity, sizeof(m_identity)); - -matmul4(matrix_p_now,matrix_p_now,m_viewport); -#endif - -#if 0 - float m_viewport[4*4] = { - 0.5 * width/2.0f, 0.0f, 0.0f, width/2.0f, - 0.0f, 0.5*-height/2.0f, 0.0f, height/2.0f, - 0.0f, 0.0f, (float)0x7FFF, 0x7FFF, - 0.0f, 0.0f, 0.0f, 1.0f - }; -//memcpy(matrix_mv_now, m_viewport, sizeof(m_viewport)); -//memcpy(matrix_p_now, m_identity, sizeof(m_identity)); - -matmul4(matrix_p_now,m_viewport,matrix_p_now); -#endif - // Transpose #define TRANSPOSE(__m) \ @@ -1261,7 +1177,7 @@ TRANSPOSE(matrix_mv_now) p = xgu_set_projection_matrix(p, matrix_p_now); //FIXME: Unused in XQEMU p = xgu_set_composite_matrix(p, matrix_c_now); //FIXME: Always used in XQEMU? p = xgu_set_viewport_offset(p, 0.0f, 0.0f, 0.0f, 0.0f); - p = xgu_set_viewport_scale(p, 1.0f / width, 1.0f / height, 1.0f / (float)0xFFFF, 1.0f); //FIXME: Ignored?! + p = xgu_set_viewport_scale(p, 1.0f, 1.0f, 1.0f, 1.0f); //FIXME: Ignored?! pb_end(p); } From e014593aa32962896d61f6e3a7a44c8e5f8e1522 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 14 May 2020 02:46:22 +0200 Subject: [PATCH 51/93] add workaround for safety (no longer needed with inverted front-face) --- xbox/xbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 297ae69d4..32c9821f3 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1215,7 +1215,7 @@ static void prepare_drawing() { // Set the register combiner setup_texenv(); -#if 1 +#if 0 { // Set some safe state uint32_t* p = pb_begin(); From f03ccf0082d058b2adb3a5a8d73146ce55f46cd8 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 14 May 2020 02:46:36 +0200 Subject: [PATCH 52/93] clear using XGU functions --- xbox/xbox.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 32c9821f3..c33246570 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1338,18 +1338,22 @@ GL_API void GL_APIENTRY glClear (GLbitfield mask) { pb_print("Clearing\n"); + //FIXME: Store size we used to init + int width = pb_back_buffer_width(); + int height = pb_back_buffer_height(); + uint32_t* p = pb_begin(); - //FIXME: Set clear region + p = xgu_set_clear_rect_horizontal(p, 0, width); + p = xgu_set_clear_rect_vertical(p, 0, height); + p = xgu_set_zstencil_clear_value(p, 0xFFFFFF00); //FIXME: This assumes Z24S8 p = xgu_clear_surface(p, flags); pb_end(p); - //FIXME: Store size we used to init - int width = pb_back_buffer_width(); - int height = pb_back_buffer_height(); + //FIXME: Remove this hack! - pb_erase_depth_stencil_buffer(0, 0, width, height); //FIXME: Do in XGU - pb_fill(0, 0, width, height, 0x80808080); //FIXME: Do in XGU + //pb_erase_depth_stencil_buffer(0, 0, width, height); //FIXME: Do in XGU + //pb_fill(0, 0, width, height, 0x80808080); //FIXME: Do in XGU } From 5c928edb994a419e28396f2c26a0ac434f4f0317 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 14 May 2020 02:46:49 +0200 Subject: [PATCH 53/93] re-enable glDrawArrays --- xbox/xbox.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xbox/xbox.c b/xbox/xbox.c index c33246570..a39526cc7 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1501,8 +1501,10 @@ static uint32_t* borders(uint32_t* p) { // Draw calls GL_API void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count) { +#if 0 unimplemented("disabled due to errors on physical hardware"); return; //FIXME: !!! +#endif static unsigned int f = -1; if (f == frame) { From 4c90155f878d7a02d22bcb86a1adc790aa93070f Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 14 May 2020 02:51:09 +0200 Subject: [PATCH 54/93] fix bug in base game where path wasn't normalized --- share/fs_stdio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/share/fs_stdio.c b/share/fs_stdio.c index 6799f5282..366b83826 100644 --- a/share/fs_stdio.c +++ b/share/fs_stdio.c @@ -288,6 +288,7 @@ static fs_file fs_open_write_flags(const char *path, int append) if ((real = path_join(fs_dir_write, path))) { + path_normalize(real); #ifdef NXDK debugPrint("Trying to open '%s' (write)\n", real); #endif From b356d4f29b9f311ae17e2fae0a00111e2ff84b20 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 14 May 2020 02:51:25 +0200 Subject: [PATCH 55/93] attempt to fix clear-color --- xbox/xbox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index a39526cc7..7dbcd9574 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1361,9 +1361,9 @@ GL_API void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, uint32_t color = 0; //FIXME: Verify order - color |= f_to_u8(red) << 0; + color |= f_to_u8(red) << 16; color |= f_to_u8(green) << 8; - color |= f_to_u8(blue) << 16; + color |= f_to_u8(blue) << 0; color |= f_to_u8(alpha) << 24; uint32_t* p = pb_begin(); From 2c1661015f478df0caf8d12cb4865351c0e6515b Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 14 May 2020 14:24:35 +0200 Subject: [PATCH 56/93] add texture swizzling and wrapmodes --- Makefile.nxdk | 2 +- xbox/swizzle.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++ xbox/swizzle.h | 63 +++++++++++++++++++ xbox/xbox.c | 63 +++++++++++++++---- 4 files changed, 276 insertions(+), 14 deletions(-) create mode 100644 xbox/swizzle.c create mode 100644 xbox/swizzle.h diff --git a/Makefile.nxdk b/Makefile.nxdk index 4b327971b..60d3f0060 100644 --- a/Makefile.nxdk +++ b/Makefile.nxdk @@ -89,7 +89,7 @@ BALL_SRCS += share/fs_stdio.c BALL_SRCS += share/tilt_null.c BALL_SRCS += share/hmd_null.c -SRCS = $(BALL_SRCS) xbox/xbox.c +SRCS = $(BALL_SRCS) xbox/xbox.c xbox/swizzle.c #SHADER_OBJS = ps.inl vs.inl # Add SDL diff --git a/xbox/swizzle.c b/xbox/swizzle.c new file mode 100644 index 000000000..5c6ba72a3 --- /dev/null +++ b/xbox/swizzle.c @@ -0,0 +1,162 @@ +/* + * QEMU texture swizzling routines + * + * Copyright (c) 2015 Jannik Vogel + * Copyright (c) 2013 espes + * Copyright (c) 2007-2010 The Nouveau Project. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include +#include + +#include "swizzle.h" + +/* This should be pretty straightforward. + * It creates a bit pattern like ..zyxzyxzyx from ..xxx, ..yyy and ..zzz + * If there are no bits left from any component it will pack the other masks + * more tighly (Example: zzxzxzyx = Fewer x than z and even fewer y) + */ +static void generate_swizzle_masks(unsigned int width, + unsigned int height, + unsigned int depth, + uint32_t* mask_x, + uint32_t* mask_y, + uint32_t* mask_z) +{ + uint32_t x = 0, y = 0, z = 0; + uint32_t bit = 1; + uint32_t mask_bit = 1; + bool done; + do { + done = true; + if (bit < width) { x |= mask_bit; mask_bit <<= 1; done = false; } + if (bit < height) { y |= mask_bit; mask_bit <<= 1; done = false; } + if (bit < depth) { z |= mask_bit; mask_bit <<= 1; done = false; } + bit <<= 1; + } while(!done); + assert(x ^ y ^ z == (mask_bit - 1)); + *mask_x = x; + *mask_y = y; + *mask_z = z; +} + +/* This fills a pattern with a value if your value has bits abcd and your + * pattern is 11010100100 this will return: 0a0b0c00d00 + */ +static uint32_t fill_pattern(uint32_t pattern, uint32_t value) +{ + uint32_t result = 0; + uint32_t bit = 1; + while(value) { + if (pattern & bit) { + /* Copy bit to result */ + result |= value & 1 ? bit : 0; + value >>= 1; + } + bit <<= 1; + } + return result; +} + +static unsigned int get_swizzled_offset( + unsigned int x, unsigned int y, unsigned int z, + uint32_t mask_x, uint32_t mask_y, uint32_t mask_z, + unsigned int bytes_per_pixel) +{ + return bytes_per_pixel * (fill_pattern(mask_x, x) + | fill_pattern(mask_y, y) + | fill_pattern(mask_z, z)); +} + +void swizzle_box( + const uint8_t *src_buf, + unsigned int width, + unsigned int height, + unsigned int depth, + uint8_t *dst_buf, + unsigned int row_pitch, + unsigned int slice_pitch, + unsigned int bytes_per_pixel) +{ + uint32_t mask_x, mask_y, mask_z; + generate_swizzle_masks(width, height, depth, &mask_x, &mask_y, &mask_z); + + int x, y, z; + for (z = 0; z < depth; z++) { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + const uint8_t *src = src_buf + + y * row_pitch + x * bytes_per_pixel; + uint8_t *dst = dst_buf + get_swizzled_offset(x, y, 0, + mask_x, mask_y, 0, + bytes_per_pixel); + memcpy(dst, src, bytes_per_pixel); + } + } + src_buf += slice_pitch; + } +} + +void unswizzle_box( + const uint8_t *src_buf, + unsigned int width, + unsigned int height, + unsigned int depth, + uint8_t *dst_buf, + unsigned int row_pitch, + unsigned int slice_pitch, + unsigned int bytes_per_pixel) +{ + uint32_t mask_x, mask_y, mask_z; + generate_swizzle_masks(width, height, depth, &mask_x, &mask_y, &mask_z); + + int x, y, z; + for (z = 0; z < depth; z++) { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + const uint8_t *src = src_buf + + get_swizzled_offset(x, y, z, mask_x, mask_y, mask_z, + bytes_per_pixel); + uint8_t *dst = dst_buf + y * row_pitch + x * bytes_per_pixel; + memcpy(dst, src, bytes_per_pixel); + } + } + dst_buf += slice_pitch; + } +} + +void unswizzle_rect( + const uint8_t *src_buf, + unsigned int width, + unsigned int height, + uint8_t *dst_buf, + unsigned int pitch, + unsigned int bytes_per_pixel) +{ + unswizzle_box(src_buf, width, height, 1, dst_buf, pitch, 0, bytes_per_pixel); +} + +void swizzle_rect( + const uint8_t *src_buf, + unsigned int width, + unsigned int height, + uint8_t *dst_buf, + unsigned int pitch, + unsigned int bytes_per_pixel) +{ + swizzle_box(src_buf, width, height, 1, dst_buf, pitch, 0, bytes_per_pixel); +} diff --git a/xbox/swizzle.h b/xbox/swizzle.h new file mode 100644 index 000000000..41e9c94c3 --- /dev/null +++ b/xbox/swizzle.h @@ -0,0 +1,63 @@ +/* + * QEMU texture swizzling routines + * + * Copyright (c) 2015 Jannik Vogel + * Copyright (c) 2013 espes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef HW_XBOX_SWIZZLE_H +#define HW_XBOX_SWIZZLE_H + +#include +#include + +void swizzle_box( + const uint8_t *src_buf, + unsigned int width, + unsigned int height, + unsigned int depth, + uint8_t *dst_buf, + unsigned int row_pitch, + unsigned int slice_pitch, + unsigned int bytes_per_pixel); + +void unswizzle_box( + const uint8_t *src_buf, + unsigned int width, + unsigned int height, + unsigned int depth, + uint8_t *dst_buf, + unsigned int row_pitch, + unsigned int slice_pitch, + unsigned int bytes_per_pixel); + +void unswizzle_rect( + const uint8_t *src_buf, + unsigned int width, + unsigned int height, + uint8_t *dst_buf, + unsigned int pitch, + unsigned int bytes_per_pixel); + +void swizzle_rect( + const uint8_t *src_buf, + unsigned int width, + unsigned int height, + uint8_t *dst_buf, + unsigned int pitch, + unsigned int bytes_per_pixel); + +#endif diff --git a/xbox/xbox.c b/xbox/xbox.c index 7dbcd9574..4683ab4c2 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -8,6 +8,8 @@ #include +#include "swizzle.h" + static unsigned int frame = 0; //FIXME: Remove static SDL_GameController* g = NULL; @@ -168,7 +170,9 @@ typedef struct { typedef struct { GLsizei width; + unsigned int width_shift; GLsizei height; + unsigned int height_shift; size_t pitch; void* data; GLint min_filter; @@ -901,12 +905,28 @@ static bool is_texture_complete(Texture* tx) { return true; } + +static unsigned int gl_to_xgu_texture_address(GLenum wrap) { + switch(wrap) { + case GL_REPEAT: return XGU_WRAP; +// case GL_MIRROR_REPEAT: return XGU_MIRROR; + case GL_CLAMP_TO_EDGE: return XGU_CLAMP_TO_EDGE; +// case GL_CLAMP_TO_BORDER: return XGU_CLAMP_TO_BORDER; +// case GL_CLAMP: return XGU_CLAMP; + default: + unimplemented("%d", wrap); + assert(false); + break; + } + return -1; +} + static unsigned int gl_to_xgu_texture_format(GLenum internalformat) { switch(internalformat) { - case GL_LUMINANCE: return XGU_TEXTURE_FORMAT_Y8; - case GL_LUMINANCE_ALPHA: return XGU_TEXTURE_FORMAT_A8Y8; - case GL_RGB: return XGU_TEXTURE_FORMAT_X8R8G8B8; - case GL_RGBA: return XGU_TEXTURE_FORMAT_A8B8G8R8; + case GL_LUMINANCE: return XGU_TEXTURE_FORMAT_Y8_SWIZZLED; + case GL_LUMINANCE_ALPHA: return XGU_TEXTURE_FORMAT_A8Y8_SWIZZLED; + case GL_RGB: return XGU_TEXTURE_FORMAT_X8R8G8B8_SWIZZLED; + case GL_RGBA: return XGU_TEXTURE_FORMAT_A8B8G8R8_SWIZZLED; default: unimplemented("%d", internalformat); assert(false); @@ -1002,9 +1022,11 @@ static void setup_textures() { p = xgu_set_texture_offset(p, i, (uintptr_t)tx->data & 0x03ffffff); p = xgu_set_texture_format(p, i, context_dma, cubemap_enable, border, dimensionality, gl_to_xgu_texture_format(tx->internal_base_format), 1, - 0,0,0); - unimplemented("Setup wrap"); //FIXME: !!! - p = xgu_set_texture_address(p, i, 3, false, 3, false, 3, false, false); //FIXME: Shitty workaround for XGU + tx->width_shift,tx->height_shift,0); + p = xgu_set_texture_address(p, i, gl_to_xgu_texture_address(tx->wrap_s), false, + gl_to_xgu_texture_address(tx->wrap_t), false, + XGU_CLAMP_TO_EDGE, false, + false); p = xgu_set_texture_control0(p, i, true, 0, 0); p = xgu_set_texture_control1(p, i, tx->pitch); p = xgu_set_texture_filter(p, i, 0, XGU_TEXTURE_CONVOLUTION_QUINCUNX, @@ -1032,8 +1054,8 @@ static void setup_textures() { p = xgu_set_texture_matrix_enable(p, i, true); unimplemented(); //FIXME: Not hitting pixel centers yet! const float m[4*4] = { - tx->width, 0.0f, 0.0f, 0.0f, - 0.0f, tx->height, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; @@ -1812,6 +1834,13 @@ GL_API void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internal return; } + tx->width_shift = __builtin_ffs(width) - 1; + tx->height_shift = __builtin_ffs(height) - 1; + debugPrint("%d = %d [%d]\n", width, 1 << tx->width_shift, tx->width_shift); + debugPrint("%d = %d [%d]\n", height, 1 << tx->height_shift, tx->height_shift); + assert(width == (1 << tx->width_shift)); + assert(height == (1 << tx->height_shift)); + tx->width = width; tx->height = height; tx->pitch = width * bpp / 8; @@ -1825,16 +1854,17 @@ GL_API void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internal // Copy pixels //FIXME: Respect GL pixel packing stuff - //FIXME: Swizzle + debugPrint("swizzling\n"); assert(pixels != NULL); if (tx->internal_base_format == GL_RGB) { assert(format == GL_RGB); assert(type == GL_UNSIGNED_BYTE); + uint8_t* tmp = malloc(tx->width * tx->height * 4); const uint8_t* src = pixels; - uint8_t* dst = tx->data; + uint8_t* dst = tmp; assert(tx->pitch == tx->width * 4); for(int y = 0; y < tx->height; y++) { - for(int x = 0; x < tx->height; x++) { + for(int x = 0; x < tx->width; x++) { //FIXME: Can also use different texture format instead probably dst[0] = src[2]; dst[1] = src[1]; @@ -1844,9 +1874,16 @@ GL_API void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internal src += 3; } } + debugPrint("1 swizzling..\n"); + swizzle_rect(tmp, tx->width, tx->height, tx->data, tx->width * 4, 4); + debugPrint("1 okay?!\n"); + free(tmp); } else { - memcpy(tx->data, pixels, size); + debugPrint("2 swizzling..\n"); + swizzle_rect(pixels, tx->width, tx->height, tx->data, tx->pitch, bpp / 8); + debugPrint("2 okay?!\n"); } + debugPrint("swizzling done\n"); } GL_API void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param) { From f82cf03d7a992498695edfd9f5929d68ccb34442 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 15 May 2020 03:24:54 +0200 Subject: [PATCH 57/93] depthfunc --- xbox/xbox.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 4683ab4c2..5b219044d 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -399,7 +399,14 @@ static XguStencilOp gl_to_xgu_stencil_op(GLenum op) { static XguFuncType gl_to_xgu_func_type(GLenum func) { switch(func) { - case GL_LESS: return XGU_FUNC_LESS; + case GL_NEVER: return XGU_FUNC_NEVER; + case GL_LESS: return XGU_FUNC_LESS; + case GL_EQUAL: return XGU_FUNC_EQUAL; + case GL_LEQUAL: return XGU_FUNC_LESS_OR_EQUAL; + case GL_GREATER: return XGU_FUNC_GREATER; + case GL_NOTEQUAL: return XGU_FUNC_NOT_EQUAL; + case GL_GEQUAL: return XGU_FUNC_GREATER_OR_EQUAL; + case GL_ALWAYS: return XGU_FUNC_ALWAYS; default: unimplemented("%d", func); assert(false); @@ -1981,7 +1988,7 @@ GL_API void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean b GL_API void GL_APIENTRY glDepthFunc (GLenum func) { uint32_t* p = pb_begin(); -// p = xgu_set_depth_func(p, gl_to_xgu_func_type(func)); + p = xgu_set_depth_func(p, gl_to_xgu_func_type(func)); pb_end(p); } From 5793c578b2e3e76eda691db2753bd8534b2b3c7d Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 15 May 2020 03:26:44 +0200 Subject: [PATCH 58/93] texture matrices --- xbox/xbox.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 5b219044d..66958a741 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1059,15 +1059,8 @@ static void setup_textures() { p = xgu_set_texgen_r(p, i, XGU_TEXGEN_DISABLE); p = xgu_set_texgen_q(p, i, XGU_TEXGEN_DISABLE); p = xgu_set_texture_matrix_enable(p, i, true); - unimplemented(); //FIXME: Not hitting pixel centers yet! - const float m[4*4] = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f - }; - unimplemented(); //FIXME: Also respect matrix_t - p = xgu_set_texture_matrix(p, i, m); + unimplemented(); //FIXME: Not hitting pixel centers yet?! + p = xgu_set_texture_matrix(p, i, &matrix_t[i][0]); pb_end(p); @@ -1788,6 +1781,7 @@ GL_API void GL_APIENTRY glActiveTexture (GLenum texture) { GL_API void GL_APIENTRY glClientActiveTexture (GLenum texture) { client_active_texture = texture - GL_TEXTURE0; + glMatrixMode(matrix_mode); // Necessary because the matrix pointers are cached } GL_API void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures) { From 6a01304e690a40932d4df3f482a4e897de39bc1a Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 15 May 2020 13:16:31 +0200 Subject: [PATCH 59/93] Support depth mask --- xbox/xbox.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 66958a741..3c1b9b893 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1987,7 +1987,9 @@ GL_API void GL_APIENTRY glDepthFunc (GLenum func) { } GL_API void GL_APIENTRY glDepthMask (GLboolean flag) { - unimplemented(); //FIXME: Missing from XGU + uint32_t* p = pb_begin(); + p = xgu_set_depth_mask(p, flag); + pb_end(p); } GL_API void GL_APIENTRY glEnable (GLenum cap) { From 51c729593314bd7ed2063c21df2134b0877bad3a Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 15 May 2020 13:16:41 +0200 Subject: [PATCH 60/93] Support stencil func --- xbox/xbox.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 3c1b9b893..e5f67f409 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -2027,7 +2027,11 @@ GL_API void GL_APIENTRY glFrontFace (GLenum mode) { // Stencil actions GL_API void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask) { - unimplemented(); //FIXME: Missing from XGU + uint32_t* p = pb_begin(); + p = xgu_set_stencil_func(p, gl_to_xgu_func_type(func)); + p = xgu_set_stencil_func_ref(p, ref); + p = xgu_set_stencil_func_mask(p, mask); + pb_end(p); } GL_API void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass) { From 8d13366ed9100f0f7d430ef941ac717896a92a0a Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 15 May 2020 14:39:55 +0200 Subject: [PATCH 61/93] Add texgen support (broken in XQEMU) --- share/solid_draw.c | 2 +- xbox/GLES/gl.h | 15 +++++++++++++++ xbox/xbox.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/share/solid_draw.c b/share/solid_draw.c index bb79c2637..0581106e7 100644 --- a/share/solid_draw.c +++ b/share/solid_draw.c @@ -899,7 +899,7 @@ void r_apply_mtrl(struct s_rend *rend, int mi) /* Environment mapping. */ -#if !ENABLE_OPENGLES +#if !ENABLE_OPENGLES || defined(NXDK) if ((mp_flags & M_ENVIRONMENT) ^ (mq_flags & M_ENVIRONMENT)) { if (mp_flags & M_ENVIRONMENT) diff --git a/xbox/GLES/gl.h b/xbox/GLES/gl.h index 324f68610..4699a909e 100644 --- a/xbox/GLES/gl.h +++ b/xbox/GLES/gl.h @@ -328,3 +328,18 @@ GL_API void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); // Not used in neverball, only for debugging GL_API void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data); + + + + + + + +// Not in GLES, but added for Xbox +#define GL_TEXTURE_GEN_MODE 40000 +#define GL_SPHERE_MAP 40001 +#define GL_S 40002 +#define GL_T 40003 +#define GL_TEXTURE_GEN_S 40004 +#define GL_TEXTURE_GEN_T 40005 +GL_API void GL_APIENTRY glTexGeni (GLenum coord, GLenum pname, GLint param); diff --git a/xbox/xbox.c b/xbox/xbox.c index e5f67f409..81fc3ed01 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -282,6 +282,10 @@ typedef struct { Attrib vertex_array; Attrib color_array; Attrib normal_array; + bool texgen_s_enabled[4]; + bool texgen_t_enabled[4]; + GLenum texgen_s[4]; + GLenum texgen_t[4]; bool texture_2d[4]; //FIXME: Move into a texture unit array GLuint texture_binding_2d[4]; Light light[3]; //FIXME: no more needed in neverball @@ -293,8 +297,15 @@ static State state = { #include "matrix.h" + static uint32_t* set_enabled(uint32_t* p, GLenum cap, bool enabled) { switch(cap) { + case GL_TEXTURE_GEN_S: + state.texgen_s_enabled[active_texture] = enabled; + break; + case GL_TEXTURE_GEN_T: + state.texgen_t_enabled[active_texture] = enabled; + break; case GL_ALPHA_TEST: p = xgu_set_alpha_test_enable(p, enabled); break; @@ -912,6 +923,16 @@ static bool is_texture_complete(Texture* tx) { return true; } +static unsigned int gl_to_xgu_texgen(GLenum texgen) { + switch(texgen) { + case GL_SPHERE_MAP: return XGU_TEXGEN_SPHERE_MAP; + default: + unimplemented("%d", texgen); + assert(false); + break; + } + return -1; +} static unsigned int gl_to_xgu_texture_address(GLenum wrap) { switch(wrap) { @@ -1054,8 +1075,10 @@ static void setup_textures() { p = pb_push1(p,NV20_TCL_PRIMITIVE_3D_TX_FILTER(i),0x04074000); //set stage 0 texture filters (AA!) #endif - p = xgu_set_texgen_s(p, i, XGU_TEXGEN_DISABLE); - p = xgu_set_texgen_t(p, i, XGU_TEXGEN_DISABLE); + p = xgu_set_texgen_s(p, i, state.texgen_s_enabled[i] ? gl_to_xgu_texgen(state.texgen_s[i]) + : XGU_TEXGEN_DISABLE); + p = xgu_set_texgen_t(p, i, state.texgen_t_enabled[i] ? gl_to_xgu_texgen(state.texgen_t[i]) + : XGU_TEXGEN_DISABLE); p = xgu_set_texgen_r(p, i, XGU_TEXGEN_DISABLE); p = xgu_set_texgen_q(p, i, XGU_TEXGEN_DISABLE); p = xgu_set_texture_matrix_enable(p, i, true); @@ -1289,6 +1312,21 @@ static void prepare_drawing() { } +GL_API void GL_APIENTRY glTexGeni (GLenum coord, GLenum pname, GLint param) { + assert(pname == GL_TEXTURE_GEN_MODE); + switch(coord) { + case GL_S: + state.texgen_s[active_texture] = param; + break; + case GL_T: + state.texgen_t[active_texture] = param; + break; + default: + unimplemented("%d", coord); + assert(false); + break; + } +} From d0ba3a5cc3aaa9da9c6b0ac3dde53b81ba77e773 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 15 May 2020 14:48:53 +0200 Subject: [PATCH 62/93] leave note about tex matrix perf --- xbox/xbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 81fc3ed01..7bc784b90 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1081,7 +1081,7 @@ static void setup_textures() { : XGU_TEXGEN_DISABLE); p = xgu_set_texgen_r(p, i, XGU_TEXGEN_DISABLE); p = xgu_set_texgen_q(p, i, XGU_TEXGEN_DISABLE); - p = xgu_set_texture_matrix_enable(p, i, true); + p = xgu_set_texture_matrix_enable(p, i, true); //FIXME: See if this makes a perf difference and only enable if not identity? unimplemented(); //FIXME: Not hitting pixel centers yet?! p = xgu_set_texture_matrix(p, i, &matrix_t[i][0]); From 36957a48ec505491199b4e31452657379811ba14 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 15 May 2020 20:59:00 +0200 Subject: [PATCH 63/93] backport nv2a-re changes --- xbox/GLES/gl.h | 32 ++- xbox/xbox.c | 574 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 561 insertions(+), 45 deletions(-) diff --git a/xbox/GLES/gl.h b/xbox/GLES/gl.h index 4699a909e..84f8ccc76 100644 --- a/xbox/GLES/gl.h +++ b/xbox/GLES/gl.h @@ -146,13 +146,12 @@ typedef unsigned int GLbitfield; #define GL_LIGHT0 10076 #define GL_LIGHT1 10077 #define GL_LIGHT2 10078 - -#define GL_COMBINE 10079 -#define GL_COMBINE_ALPHA 10080 -#define GL_COMBINE_RGB 10081 - -#define GL_INTERPOLATE 10082 -#define GL_MODULATE 10083 +#define GL_LIGHT3 10079 +#define GL_LIGHT4 10080 +#define GL_LIGHT5 10081 +#define GL_LIGHT6 10082 +#define GL_LIGHT7 10083 +//FIXME: This also needs to reserve many other slots until at least GL_LIGHT7 #define GL_NEAREST 10084 @@ -170,6 +169,13 @@ typedef unsigned int GLbitfield; #define GL_TEXTURE_ENV 10092 #define GL_TEXTURE_ENV_MODE 10093 +#define GL_COMBINE 10094 +#define GL_COMBINE_ALPHA 10095 +#define GL_COMBINE_RGB 10096 + +#define GL_INTERPOLATE 10097 +#define GL_MODULATE 10098 + // Not used in neverball, only for completeness @@ -343,3 +349,15 @@ GL_API void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data); #define GL_TEXTURE_GEN_S 40004 #define GL_TEXTURE_GEN_T 40005 GL_API void GL_APIENTRY glTexGeni (GLenum coord, GLenum pname, GLint param); + + + +// Backport from nv2a-re +#define GL_AMBIENT_AND_DIFFUSE 60 +#define GL_CONSTANT_ATTENUATION 100 +#define GL_LINEAR_ATTENUATION 110 +#define GL_QUADRATIC_ATTENUATION 120 +#define GL_SPOT_EXPONENT 130 +#define GL_SPOT_CUTOFF 140 +#define GL_SPOT_DIRECTION 150 +#define GL_LIGHT_MODEL_LOCAL_VIEWER 210 diff --git a/xbox/xbox.c b/xbox/xbox.c index 7bc784b90..33ad57f07 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -10,6 +10,51 @@ #include "swizzle.h" +static float viewport_matrix[4*4]; + +static float _max(float a, float b) { + return (a > b) ? a : b; +} + +static float _dot3(const float* a, const float* b) { + return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]; +} + +static float _dot4(const float* a, const float* b) { + return _dot3(a,b)+a[3]*b[3]; +} + +static void _normalize(float* v) { + float l = sqrtf(_dot3(v,v)); + v[0] /= l; + v[1] /= l; + v[2] /= l; +} + +static void transposeMatrix(float* out, const float* in) { + float t[4*4]; + for(int i = 0; i < 4; i++) { + for(int j = 0; j < 4; j++) { + t[i*4+j] = in[i+4*j]; + } + } + memcpy(out, t, sizeof(t)); +} + +static void mult_vec4_mat4(float* o, const float* m, const float* v) { + float t[4*4]; + //memcpy(t, m, sizeof(t)); + transposeMatrix(t, m); + //printf("%f\n", t[0*4+3]); + //printf("%f\n", t[1*4+3]); + //printf("%f\n", t[2*4+3]); + //printf("%f\n", t[3*4+3]); + o[0] = _dot4(&t[0*4], v); + o[1] = _dot4(&t[1*4], v); + o[2] = _dot4(&t[2*4], v); + o[3] = _dot4(&t[3*4], v); +} + static unsigned int frame = 0; //FIXME: Remove static SDL_GameController* g = NULL; @@ -274,9 +319,45 @@ TexEnv texenvs[4] = { typedef struct { bool enabled; - //FIXME: Store other attributes? + bool is_dir; + struct { + float x; + float y; + float z; + float w; + } position; + struct { + float x; + float y; + float z; + } spot_direction; + float spot_exponent; + float spot_cutoff; + struct { + float r; + float g; + float b; + float a; + } diffuse; + struct { + float r; + float g; + float b; + float a; + } specular; + struct { + float r; + float g; + float b; + float a; + } ambient; + float constant_attenuation; + float linear_attenuation; + float quadratic_attenuation; } Light; +#define GL_MAX_LIGHTS 8 + typedef struct { Attrib texture_coord_array[4]; Attrib vertex_array; @@ -288,7 +369,43 @@ typedef struct { GLenum texgen_t[4]; bool texture_2d[4]; //FIXME: Move into a texture unit array GLuint texture_binding_2d[4]; - Light light[3]; //FIXME: no more needed in neverball + Light lights[GL_MAX_LIGHTS]; //FIXME: no more needed in neverball + bool color_material_enabled; + GLenum color_material_front; + GLenum color_material_back; + struct { + float r; + float g; + float b; + float a; //FIXME: Unused?! + } light_model_ambient; + struct { + struct { + float r; + float g; + float b; + float a; //FIXME: Unused?! + } emission; + struct { + float r; + float g; + float b; + float a; //FIXME: Unused?! + } ambient; + struct { + float r; + float g; + float b; + float a; //FIXME: Unused?! + } diffuse; + struct { + float r; + float g; + float b; + float a; //FIXME: Unused?! + } specular; + float shininess; + } material[2]; } State; static State state = { .texture_2d = { false, false, false, false }, @@ -319,22 +436,23 @@ static uint32_t* set_enabled(uint32_t* p, GLenum cap, bool enabled) { case GL_DEPTH_TEST: p = xgu_set_depth_test_enable(p, enabled); break; + case GL_STENCIL_TEST: + p = xgu_set_stencil_test_enable(p, enabled); + break; case GL_TEXTURE_2D: state.texture_2d[active_texture] = enabled; break; case GL_BLEND: p = xgu_set_blend_enable(p, enabled); break; - case GL_LIGHT0: - case GL_LIGHT1: - case GL_LIGHT2: - state.light[cap - GL_LIGHT0].enabled = enabled; + case GL_LIGHT0 ... GL_LIGHT0+GL_MAX_LIGHTS-1: + state.lights[cap - GL_LIGHT0].enabled = enabled; break; case GL_LIGHTING: p = xgu_set_lighting_enable(p, enabled); break; case GL_COLOR_MATERIAL: - unimplemented(); //FIXME: !!! + state.color_material_enabled = enabled; break; case GL_POLYGON_OFFSET_FILL: unimplemented(); //FIXME: !!! @@ -401,6 +519,7 @@ static XguTextureFilter gl_to_xgu_texture_filter(GLenum filter) { static XguStencilOp gl_to_xgu_stencil_op(GLenum op) { switch(op) { + case GL_KEEP: return XGU_STENCIL_OP_KEEP; default: unimplemented("%d", op); assert(false); @@ -1116,7 +1235,6 @@ static void setup_matrices() { p = xgu_set_skin_mode(p, XGU_SKIN_MODE_OFF); p = xgu_set_normalization_enable(p, false); - p = xgu_set_lighting_enable(p, false); @@ -1132,9 +1250,8 @@ static void setup_matrices() { // Update matrices //FIXME: Keep dirty bits -unimplemented(); //FIXME: const -float* matrix_p_now = &matrix_p[matrix_p_slot * 4*4]; - const float* matrix_mv_now = &matrix_mv[matrix_mv_slot * 4*4]; + float* matrix_p_now = &matrix_p[matrix_p_slot * 4*4]; + float* matrix_mv_now = &matrix_mv[matrix_mv_slot * 4*4]; #if 0 @@ -1157,18 +1274,10 @@ debugPrint("\ndraw:\n"); - if (true) { - float max_z = 0xFFFFFF; - float m[4*4] = { - 320.0f, 0.0f, 0.0f, 0.0f, - 0.0f, -240.0f, 0.0f, 0.0f, - 0.0f, 0.0f, max_z / 2.0f, 0.0f, - 320.0f, 240.0f, max_z / 2.0f, 1.0f - }; - float t[4*4]; - memcpy(t, matrix_p_now, sizeof(t)); - matmul4(matrix_p_now, m, t); - } + float t[4*4]; + memcpy(t, matrix_p_now, sizeof(t)); + matmul4(matrix_p_now, viewport_matrix, t); + #if 1 @@ -1219,14 +1328,193 @@ TRANSPOSE(matrix_mv_now) p = pb_begin(); p = xgu_set_transform_execution_mode(p, XGU_FIXED, XGU_RANGE_MODE_PRIVATE); //FIXME: p = xgu_set_fog_enable(p, false); + + //FIXME: Probably should include the viewort matrix p = xgu_set_projection_matrix(p, matrix_p_now); //FIXME: Unused in XQEMU + p = xgu_set_composite_matrix(p, matrix_c_now); //FIXME: Always used in XQEMU? + + for(int i = 0; i < XGU_WEIGHT_COUNT; i++) { +#if 1 + // Only required if skinning is enabled? + transposeMatrix(t, matrix_mv_now); + p = xgu_set_model_view_matrix(p, i, t); //FIXME: Not sure when used? +#endif +#if 1 + // Required for lighting + + invert(t, matrix_mv_now); //FIXME: This is affected if we want to normalize normals + //transposeMatrix(t, t); + //FIXME: mesa only uploads a 4x3 / 3x4 matrix + p = xgu_set_inverse_model_view_matrix(p, i, t); //FIXME: Not sure when used? +#endif + } + p = xgu_set_viewport_offset(p, 0.0f, 0.0f, 0.0f, 0.0f); p = xgu_set_viewport_scale(p, 1.0f, 1.0f, 1.0f, 1.0f); //FIXME: Ignored?! pb_end(p); } +static void gl_to_xgu_material_source(GLenum mode, XguMaterialSource* emissive, XguMaterialSource* ambient, XguMaterialSource* diffuse, XguMaterialSource* specular) { + switch(mode) { + case GL_EMISSION: + *emissive = XGU_MATERIAL_SOURCE_VERTEX_DIFFUSE; + break; + case GL_AMBIENT: + *ambient = XGU_MATERIAL_SOURCE_VERTEX_DIFFUSE; + break; + case GL_DIFFUSE: + *diffuse = XGU_MATERIAL_SOURCE_VERTEX_DIFFUSE; + break; + case GL_SPECULAR: + *specular = XGU_MATERIAL_SOURCE_VERTEX_DIFFUSE; + break; + case GL_AMBIENT_AND_DIFFUSE: + *ambient = XGU_MATERIAL_SOURCE_VERTEX_DIFFUSE; + *diffuse = XGU_MATERIAL_SOURCE_VERTEX_DIFFUSE; + break; + default: + unimplemented("%d", mode); + assert(false); + break; + } +} + +static void setup_lighting() { + XguMaterialSource emissive[2] = { XGU_MATERIAL_SOURCE_DISABLE, XGU_MATERIAL_SOURCE_DISABLE }; + XguMaterialSource ambient[2] = { XGU_MATERIAL_SOURCE_DISABLE, XGU_MATERIAL_SOURCE_DISABLE }; + XguMaterialSource diffuse[2] = { XGU_MATERIAL_SOURCE_DISABLE, XGU_MATERIAL_SOURCE_DISABLE }; + XguMaterialSource specular[2] = { XGU_MATERIAL_SOURCE_DISABLE, XGU_MATERIAL_SOURCE_DISABLE }; + + if (state.color_material_enabled) { + gl_to_xgu_material_source(state.color_material_front, &emissive[0], &ambient[0], &diffuse[0], &specular[0]); + gl_to_xgu_material_source(state.color_material_back, &emissive[1], &ambient[1], &diffuse[1], &specular[1]); + } + + uint32_t* p = pb_begin(); + + // Note: I don't think GL can do two-sided for this one? + p = xgu_set_scene_ambient_color(p, state.light_model_ambient.r, state.light_model_ambient.g, state.light_model_ambient.b); + p = xgu_set_back_scene_ambient_color(p, state.light_model_ambient.r, state.light_model_ambient.g, state.light_model_ambient.b); + + // Note: This sets the color source, not the actual color + p = xgu_set_color_material(p, emissive[0], ambient[0], diffuse[0], specular[0], + emissive[1], ambient[1], diffuse[1], specular[1]); + + p = xgu_set_material_emission(p, state.material[0].emission.r, state.material[0].emission.g, state.material[0].emission.b); + p = xgu_set_back_material_emission(p, state.material[1].emission.r, state.material[1].emission.g, state.material[1].emission.b); + + unimplemented(); //FIXME: What about state.material[#].ambient + unimplemented(); //FIXME: What about state.material[#].diffuse + unimplemented(); //FIXME: What about state.material[#].specular + + //FIXME: How does this contribute? + float material_alpha[2] = { 1.0f, 1.0f }; + p = xgu_set_material_alpha(p, material_alpha[0]); + p = xgu_set_back_material_alpha(p, material_alpha[1]); + + //FIXME: When to do this? + bool specular_enabled = false; + p = xgu_set_specular_enable(p, specular_enabled); + + XguLightMask mask[8]; + for(int i = 0; i < 8; i++) { + mask[i] = XGU_LMASK_OFF; + } + assert(GL_MAX_LIGHTS <= 8); + for(int i = 0; i < GL_MAX_LIGHTS; i++) { + Light* l = &state.lights[i]; + if (!l->enabled) { + continue; + } + + if (l->is_dir) { + mask[i] = XGU_LMASK_INFINITE; + //printf("directional light\n"); + + XguVec3 v = { l->position.x, l->position.y, l->position.z }; + //printf("light-dir: %f %f %f\n", v.x, v.y, v.z); + p = xgu_set_light_infinite_direction(p, i, v); + + } else { + if (l->spot_cutoff == 180.0f) { + mask[i] = XGU_LMASK_LOCAL; + //printf("point light\n"); + } else { + mask[i] = XGU_LMASK_SPOT; + //printf("spot light\n"); + } + + { + XguVec3 v = { l->position.x, l->position.y, l->position.z }; + p = xgu_set_light_local_position(p, i, v); + } + + p = xgu_set_light_local_attenuation(p, i, l->constant_attenuation, l->linear_attenuation, l->quadratic_attenuation); + + pb_end(p); + + XguVec3 direction = { + l->spot_direction.x, + l->spot_direction.y, + l->spot_direction.z + }; + _normalize(&direction.x); +#if 0 + //FIXME: Do cos outside of function? + float theta = 0.0f; + float phi = l->spot_cutoff / 180.0f * M_PI; + float falloff = 1.0f; + // D3D direction is flipped + direction.x *= -1.0f; + direction.y *= -1.0f; + direction.z *= -1.0f; + xgux_set_light_spot_d3d(i, theta, phi, falloff, direction); +#else + //FIXME: Do cos inside the function? + float cutoff = l->spot_cutoff / 180.0f * M_PI; //FIXME: Accept values in degree to be closer to GL? + xgux_set_light_spot_gl(i, l->spot_exponent, cutoff, direction); +#endif + p = pb_begin(); + } + + p = xgu_set_light_diffuse_color(p, i, l->diffuse.r, l->diffuse.g, l->diffuse.b); + p = xgu_set_back_light_diffuse_color(p, i, l->diffuse.r, l->diffuse.g, l->diffuse.b); + + // We'd be incorrectly mixing colors in the shader, so it's too bright. + // Hence, we disable some lights for now. + //FIXME: Do proper mixing in shader. +#if 1 + p = xgu_set_light_ambient_color(p, i, l->ambient.r, l->ambient.g, l->ambient.b); + p = xgu_set_back_light_ambient_color(p, i, l->ambient.r, l->ambient.g, l->ambient.b); + + p = xgu_set_light_specular_color(p, i, l->specular.r, l->specular.g, l->specular.b); + p = xgu_set_back_light_specular_color(p, i, l->specular.r, l->specular.g, l->specular.b); +#else + p = xgu_set_light_ambient_color(p, i, 0,0,0); + p = xgu_set_back_light_ambient_color(p, i, 0,0,0); + + p = xgu_set_light_specular_color(p, i, 0,0,0); + p = xgu_set_back_light_specular_color(p, i, 0,0,0); +#endif + } + p = xgu_set_light_enable_mask(p, mask[0], + mask[1], + mask[2], + mask[3], + mask[4], + mask[5], + mask[6], + mask[7]); + + pb_end(p); + + // Set material + xgux_set_specular_gl(state.material[0].shininess); + xgux_set_back_specular_gl(state.material[1].shininess); +} + static void prepare_drawing() { debugPrint("Preparing to draw\n"); @@ -1254,6 +1542,17 @@ static void prepare_drawing() { // Set up all matrices etc. setup_matrices(); + // Setup lighting +#if 1 + setup_lighting(); +#else + { + uint32_t* p = pb_begin(); + p = xgu_set_lighting_enable(p, false); + pb_end(p); + } +#endif + // Setup textures setup_textures(); @@ -2176,6 +2475,18 @@ GL_API void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei h // Lighting GL_API void GL_APIENTRY glLightModelf (GLenum pname, GLfloat param) { switch(pname) { + case GL_LIGHT_MODEL_TWO_SIDE: + //FIXME: Why is this never called by neverball? + uint32_t* p = pb_begin(); + p = xgu_set_two_side_light_enable(p, (bool)param); + pb_end(p); + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + unimplemented(); //FIXME: Not provided by XGU yet + //uint32_t* p = pb_begin(); + //p = xgu_set_local_viewer_enable(p, (bool)param); + //pb_end(p); + break; default: unimplemented("%d", pname); assert(false); @@ -2186,9 +2497,11 @@ GL_API void GL_APIENTRY glLightModelf (GLenum pname, GLfloat param) { GL_API void GL_APIENTRY glLightModelfv (GLenum pname, const GLfloat *params) { switch(pname) { case GL_LIGHT_MODEL_AMBIENT: - unimplemented("%d", pname); //FIXME: !!! + state.light_model_ambient.r = params[0]; + state.light_model_ambient.g = params[1]; + state.light_model_ambient.b = params[2]; + state.light_model_ambient.a = params[3]; break; -//#define GL_LIGHT_MODEL_TWO_SIDE 10032: default: unimplemented("%d", pname); assert(false); @@ -2197,21 +2510,62 @@ GL_API void GL_APIENTRY glLightModelfv (GLenum pname, const GLfloat *params) { } GL_API void GL_APIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params) { - assert(light >= GL_LIGHT0); unsigned int light_index = light - GL_LIGHT0; - assert(light_index < 4); //FIXME: Not sure how many lights Xbox has; there's probably some constant we can use + assert(light_index < GL_MAX_LIGHTS); //FIXME: Not sure how many lights Xbox has; there's probably some constant we can use + Light* l = &state.lights[light_index]; + const float* modelViewMatrix = &matrix_mv[matrix_mv_slot * 4*4]; switch(pname) { case GL_POSITION: - unimplemented("%d", pname); //FIXME: !!! + mult_vec4_mat4(&l->position.x, modelViewMatrix, params); + l->is_dir = (params[3] == 0.0f); + //memcpy(&l->position.x, param, sizeof(l->position)); break; case GL_AMBIENT: - unimplemented("%d", pname); //FIXME: !!! + l->ambient.r = params[0]; + l->ambient.g = params[1]; + l->ambient.b = params[2]; + l->ambient.a = params[3]; + break; + case GL_SPECULAR: + l->specular.r = params[0]; + l->specular.g = params[1]; + l->specular.b = params[2]; + l->specular.a = params[3]; break; case GL_DIFFUSE: - unimplemented("%d", pname); //FIXME: !!! + l->diffuse.r = params[0]; + l->diffuse.g = params[1]; + l->diffuse.b = params[2]; + l->diffuse.a = params[3]; + break; + case GL_SPOT_DIRECTION: { + float t[4] = { + params[0], + params[1], + params[2], + 0.0f + }; + float f[4]; + mult_vec4_mat4(f, modelViewMatrix, t); + l->spot_direction.x = f[0]; + l->spot_direction.y = f[1]; + l->spot_direction.z = f[2]; break; - case GL_SPECULAR: - unimplemented("%d", pname); //FIXME: !!! + } + case GL_SPOT_CUTOFF: + l->spot_cutoff = params[0]; + break; + case GL_SPOT_EXPONENT: + l->spot_exponent = params[0]; + break; + case GL_CONSTANT_ATTENUATION: + l->constant_attenuation = params[0]; + break; + case GL_LINEAR_ATTENUATION: + l->linear_attenuation = params[0]; + break; + case GL_QUADRATIC_ATTENUATION: + l->quadratic_attenuation = params[0]; break; default: unimplemented("%d", pname); @@ -2222,6 +2576,30 @@ GL_API void GL_APIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *pa // Materials + +GL_API void GL_APIENTRY glColorMaterial (GLenum face, GLenum mode) { + + if (face == GL_FRONT_AND_BACK) { + glColorMaterial(GL_FRONT, mode); + glColorMaterial(GL_BACK, mode); + return; + } + + assert(face == GL_FRONT || face == GL_BACK); + switch(face) { + case GL_FRONT: + state.color_material_front = mode; + break; + case GL_BACK: + state.color_material_back = mode; + break; + default: + unimplemented("%d", face); + assert(false); + return; + } +} + GL_API void GL_APIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params) { if (face == GL_FRONT_AND_BACK) { @@ -2230,22 +2608,41 @@ GL_API void GL_APIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat * return; } + if (pname == GL_AMBIENT_AND_DIFFUSE) { + glMaterialfv(face, GL_AMBIENT, params); + glMaterialfv(face, GL_DIFFUSE, params); + return; + } + assert(face == GL_FRONT || face == GL_BACK); + unsigned int face_index = (face == GL_FRONT) ? 0 : 1; switch(pname) { case GL_SHININESS: - unimplemented("%d", pname); //FIXME: !!! + state.material[face_index].shininess = params[0]; break; case GL_EMISSION: - unimplemented("%d", pname); //FIXME: !!! + state.material[face_index].emission.r = params[0]; + state.material[face_index].emission.g = params[1]; + state.material[face_index].emission.b = params[2]; + state.material[face_index].emission.a = params[3]; break; case GL_AMBIENT: - unimplemented("%d", pname); //FIXME: !!! + state.material[face_index].ambient.r = params[0]; + state.material[face_index].ambient.g = params[1]; + state.material[face_index].ambient.b = params[2]; + state.material[face_index].ambient.a = params[3]; break; case GL_DIFFUSE: - unimplemented("%d", pname); //FIXME: !!! + state.material[face_index].diffuse.r = params[0]; + state.material[face_index].diffuse.g = params[1]; + state.material[face_index].diffuse.b = params[2]; + state.material[face_index].diffuse.a = params[3]; break; case GL_SPECULAR: - unimplemented("%d", pname); //FIXME: !!! + state.material[face_index].specular.r = params[0]; + state.material[face_index].specular.g = params[1]; + state.material[face_index].specular.b = params[2]; + state.material[face_index].specular.a = params[3]; break; default: unimplemented("%d", pname); @@ -2407,7 +2804,7 @@ __attribute__((constructor)) static void setup_xbox(void) { } // Show framebuffer, not debug-screen -#if 1 +#if 0 pb_show_front_screen(); #else pb_show_debug_screen(); @@ -2446,13 +2843,114 @@ __attribute__((constructor)) static void setup_xbox(void) { //FIXME: Why is this necessary? SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); + debugPrint("\n\n"); + debugPrint("\n\n"); + debugPrint("\n\n"); + debugPrint("\n\n"); debugPrint("\n\n"); debugPrint("\n\n"); debugPrint("\n\n"); debugPrint("\n\n"); //FIXME: Bump GPU in right state? + uint32_t* p = pb_begin(); + uint32_t control0 = 0; +#define NV097_SET_CONTROL0_TEXTUREPERSPECTIVE 0x100000 + control0 |= NV097_SET_CONTROL0_TEXTUREPERSPECTIVE; + control0 |= NV097_SET_CONTROL0_STENCIL_WRITE_ENABLE; + + float max_z = 0xFFFFFF; +#if 0 + // W-buffer + p=pb_push1(p,NV097_SET_ZMIN_MAX_CONTROL,0); //CULL_NEAR_FAR_EN_FALSE | ZCLAMP_EN_CULL | CULL_IGNORE_W_FALSE + + float w_far = 1.0f; + float f = max_z / w_far; + + //FIXME: Does not work yet + + float tmp[4*4] = { + 320.0f*f, 0.0f, 0.0f, 0.0f, + 0.0f, -240.0f*f, 0.0f, 0.0f, + 0.0f, 0.0f, max_z / 2.0f*f, 0.0f, + 320.0f*f, 240.0f*f, max_z / 2.0f*f, f, + }; + + control0 |= NV097_SET_CONTROL0_Z_PERSPECTIVE_ENABLE; + +#else + // Z-buffer + p=pb_push1(p,NV097_SET_ZMIN_MAX_CONTROL,1); //CULL_NEAR_FAR_EN_TRUE | ZCLAMP_EN_CULL | CULL_IGNORE_W_FALSE + + float tmp[4*4] = { + 320.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -240.0f, 0.0f, 0.0f, + 0.0f, 0.0f, max_z / 2.0f, 0.0f, + 320.0f, 240.0f, max_z / 2.0f, 1.0f, + }; + memcpy(viewport_matrix, tmp, sizeof(tmp)); + +#endif + //control0 |= NV097_SET_CONTROL0_Z_FORMAT; // Float if present; fixed otherwise + p = pb_push1(p, NV097_SET_CONTROL0, control0); + pb_end(p); + + + // Set up some defaults + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + //FIXME: backport these from nv2a-re: + //glClearDepth(1.0); + //glClearStencil(0); + + glDisable(GL_STENCIL_TEST); + //FIXME: backport this from nv2a-re: + //glStencilMask(~0); + glStencilFunc(GL_ALWAYS, 0, ~0); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + glDisable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + glDisable(GL_NORMALIZE); + + glMatrixMode(GL_MODELVIEW); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + glDisable(GL_LIGHTING); + { float f[] = { 0.2f, 0.2f, 0.2f, 1.0f }; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, f); } + + { float f[] = { 0.2f, 0.2f, 0.2f, 1.0f }; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, f); } + { float f[] = { 0.8f, 0.8f, 0.8f, 1.0f }; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, f); } + { float f[] = { 0.0f, 0.0f, 0.0f, 1.0f }; glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, f); } + { float f[] = { 0.0f, 0.0f, 0.0f, 1.0f }; glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, f); } + { float f[] = { 0.0f }; glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, f); } + + glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, 0); + glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 0); + + for(int i = 0; i < GL_MAX_LIGHTS; i++) { + glDisable(GL_LIGHT0 + i); + { float f[] = {0,0,0,1}; glLightfv(GL_LIGHT0 + i, GL_AMBIENT, f); } + if (i == 0) { + { float f[] = {1,1,1,1}; glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, f); } + { float f[] = {1,1,1,1}; glLightfv(GL_LIGHT0 + i, GL_SPECULAR, f); } + } else { + { float f[] = {0,0,0,1}; glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, f); } + { float f[] = {0,0,0,1}; glLightfv(GL_LIGHT0 + i, GL_SPECULAR, f); } + } + { float f[] = {0,0,1,0}; glLightfv(GL_LIGHT0 + i, GL_POSITION, f); } + { float f[] = {0,0,-1}; glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, f); } + { float f[] = {180}; glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, f); } + { float f[] = {0}; glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, f); } + { float f[] = {1}; glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, f); } + { float f[] = {0}; glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, f); } + { float f[] = {0}; glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, f); } + } glFrontFace(GL_CW); + glDisable(GL_COLOR_MATERIAL); + + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); } From 09319de71381f40c1426bcbb578adb9e9144914a Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 15 May 2020 21:05:56 +0200 Subject: [PATCH 64/93] Expect XGU in system nxdk --- Makefile.nxdk | 3 --- 1 file changed, 3 deletions(-) diff --git a/Makefile.nxdk b/Makefile.nxdk index 60d3f0060..debe40121 100644 --- a/Makefile.nxdk +++ b/Makefile.nxdk @@ -99,9 +99,6 @@ NXDK_SDL = y include $(CURDIR)/xbox/Makefile-vorbis.xbox include $(CURDIR)/xbox/Makefile-ogg.xbox -# XGU -CFLAGS += -idirafter$(CURDIR)/xbox/nxdk/lib - all: $(OUTPUT_DIR)/default.xbe data $(GEN_XISO) # Add data to XISO From edf68d918ad7f9f39193ae9e1e52cf62582a7a50 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 15 May 2020 23:02:44 +0200 Subject: [PATCH 65/93] Fix critical bug in setup_textures --- xbox/xbox.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 33ad57f07..6cfa5e54f 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1205,17 +1205,17 @@ static void setup_textures() { p = xgu_set_texture_matrix(p, i, &matrix_t[i][0]); pb_end(p); - - // Setup texture shader - p = pb_begin(); - p = pb_push1(p, NV097_SET_SHADER_STAGE_PROGRAM, - MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE0, shaders[0]) - | MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE1, shaders[1]) - | MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE2, shaders[2]) - | MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE3, shaders[3])); - pb_end(p); } + // Setup texture shader + p = pb_begin(); + p = pb_push1(p, NV097_SET_SHADER_STAGE_PROGRAM, + MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE0, shaders[0]) + | MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE1, shaders[1]) + | MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE2, shaders[2]) + | MASK(NV097_SET_SHADER_STAGE_PROGRAM_STAGE3, shaders[3])); + pb_end(p); + // Assert that we handled all clip planes while(clip_plane_index < ARRAY_SIZE(clip_planes)) { From d3d915ca81d863d0bbae2db73441d3e9cb9a7c74 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 16 May 2020 01:22:34 +0200 Subject: [PATCH 66/93] fixup xbox makefile copying wrong files --- Makefile.nxdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.nxdk b/Makefile.nxdk index debe40121..119905f24 100644 --- a/Makefile.nxdk +++ b/Makefile.nxdk @@ -105,7 +105,7 @@ all: $(OUTPUT_DIR)/default.xbe data $(GEN_XISO) #FIXME: Copy files to $(OUTPUT_DIR) data: force @echo "Updating data" - @cp -r $(CURDIR)/data $(OUTPUT_DIR)/Neverball + @cp -r $(CURDIR)/data/. $(OUTPUT_DIR)/Neverball @echo "Updating config" @cp -r $(CURDIR)/xbox/neverballrc $(OUTPUT_DIR)/Neverball #FIXME: Buggy From 365e7aaff7a73e3505e2ed6cfd3612f4d782f154 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 18 May 2020 19:35:43 +0200 Subject: [PATCH 67/93] fixup data move --- Makefile.nxdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.nxdk b/Makefile.nxdk index 119905f24..932aad742 100644 --- a/Makefile.nxdk +++ b/Makefile.nxdk @@ -9,7 +9,7 @@ CFLAGS += -ferror-limit=0 CFLAGS += -DENABLE_OPENGLES=1 #CFLAGS += -DCONFIG_USER=\"E:\\\\UDATA\\\\Neverball\" CFLAGS += -DCONFIG_USER=\"D:\\\\Neverball\" -CFLAGS += -DCONFIG_DATA=\"D:\\\\Neverball\\\\data\" +CFLAGS += -DCONFIG_DATA=\"D:\\\\Neverball\" CFLAGS += -DCONFIG_LOCALE=\"D:\\\\Neverball\\\\locale\" CFLAGS += -I$(CURDIR)/share/ -I$(CURDIR)/xbox/ -D_CRTIMP= From 2710f4d47559fc736f056ecf7b6b632a723bf477 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 18 May 2020 19:36:10 +0200 Subject: [PATCH 68/93] implement materials properly (?) --- xbox/xbox.c | 194 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 164 insertions(+), 30 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 6cfa5e54f..3166ac068 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -16,6 +16,12 @@ static float _max(float a, float b) { return (a > b) ? a : b; } +static void _mul3(float* v, const float* a, const float* b) { + v[0] = a[0]*b[0]; + v[1] = a[1]*b[1]; + v[2] = a[2]*b[2]; +} + static float _dot3(const float* a, const float* b) { return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]; } @@ -1360,19 +1366,33 @@ static void gl_to_xgu_material_source(GLenum mode, XguMaterialSource* emissive, switch(mode) { case GL_EMISSION: *emissive = XGU_MATERIAL_SOURCE_VERTEX_DIFFUSE; + *ambient = XGU_MATERIAL_SOURCE_DISABLE; + *diffuse = XGU_MATERIAL_SOURCE_DISABLE; + *specular = XGU_MATERIAL_SOURCE_DISABLE; break; case GL_AMBIENT: + *emissive = XGU_MATERIAL_SOURCE_DISABLE; *ambient = XGU_MATERIAL_SOURCE_VERTEX_DIFFUSE; + *diffuse = XGU_MATERIAL_SOURCE_DISABLE; + *specular = XGU_MATERIAL_SOURCE_DISABLE; break; case GL_DIFFUSE: + *emissive = XGU_MATERIAL_SOURCE_DISABLE; + *ambient = XGU_MATERIAL_SOURCE_DISABLE; *diffuse = XGU_MATERIAL_SOURCE_VERTEX_DIFFUSE; + *specular = XGU_MATERIAL_SOURCE_DISABLE; break; case GL_SPECULAR: + *emissive = XGU_MATERIAL_SOURCE_DISABLE; + *ambient = XGU_MATERIAL_SOURCE_DISABLE; + *diffuse = XGU_MATERIAL_SOURCE_DISABLE; *specular = XGU_MATERIAL_SOURCE_VERTEX_DIFFUSE; break; case GL_AMBIENT_AND_DIFFUSE: + *emissive = XGU_MATERIAL_SOURCE_DISABLE; *ambient = XGU_MATERIAL_SOURCE_VERTEX_DIFFUSE; *diffuse = XGU_MATERIAL_SOURCE_VERTEX_DIFFUSE; + *specular = XGU_MATERIAL_SOURCE_DISABLE; break; default: unimplemented("%d", mode); @@ -1382,42 +1402,123 @@ static void gl_to_xgu_material_source(GLenum mode, XguMaterialSource* emissive, } static void setup_lighting() { - XguMaterialSource emissive[2] = { XGU_MATERIAL_SOURCE_DISABLE, XGU_MATERIAL_SOURCE_DISABLE }; - XguMaterialSource ambient[2] = { XGU_MATERIAL_SOURCE_DISABLE, XGU_MATERIAL_SOURCE_DISABLE }; - XguMaterialSource diffuse[2] = { XGU_MATERIAL_SOURCE_DISABLE, XGU_MATERIAL_SOURCE_DISABLE }; - XguMaterialSource specular[2] = { XGU_MATERIAL_SOURCE_DISABLE, XGU_MATERIAL_SOURCE_DISABLE }; + XguMaterialSource emissive_source[2] = { XGU_MATERIAL_SOURCE_DISABLE, XGU_MATERIAL_SOURCE_DISABLE }; + XguMaterialSource ambient_source[2] = { XGU_MATERIAL_SOURCE_DISABLE, XGU_MATERIAL_SOURCE_DISABLE }; + XguMaterialSource diffuse_source[2] = { XGU_MATERIAL_SOURCE_DISABLE, XGU_MATERIAL_SOURCE_DISABLE }; + XguMaterialSource specular_source[2] = { XGU_MATERIAL_SOURCE_DISABLE, XGU_MATERIAL_SOURCE_DISABLE }; if (state.color_material_enabled) { - gl_to_xgu_material_source(state.color_material_front, &emissive[0], &ambient[0], &diffuse[0], &specular[0]); - gl_to_xgu_material_source(state.color_material_back, &emissive[1], &ambient[1], &diffuse[1], &specular[1]); + gl_to_xgu_material_source(state.color_material_front, &emissive_source[0], &ambient_source[0], &diffuse_source[0], &specular_source[0]); + gl_to_xgu_material_source(state.color_material_back, &emissive_source[1], &ambient_source[1], &diffuse_source[1], &specular_source[1]); } uint32_t* p = pb_begin(); - // Note: I don't think GL can do two-sided for this one? - p = xgu_set_scene_ambient_color(p, state.light_model_ambient.r, state.light_model_ambient.g, state.light_model_ambient.b); - p = xgu_set_back_scene_ambient_color(p, state.light_model_ambient.r, state.light_model_ambient.g, state.light_model_ambient.b); - + //FIXME: What if only one-sided lighting is enabled? Will it still use [1]? // Note: This sets the color source, not the actual color - p = xgu_set_color_material(p, emissive[0], ambient[0], diffuse[0], specular[0], - emissive[1], ambient[1], diffuse[1], specular[1]); + p = xgu_set_color_material(p, emissive_source[0], ambient_source[0], diffuse_source[0], specular_source[0], + emissive_source[1], ambient_source[1], diffuse_source[1], specular_source[1]); + + int sides = 2; + + // Reverse engineered from Futurama PAL + for(int side = 0; side < sides; side++) { + float f1[3]; + float f2[3]; + if (ambient_source[side] != XGU_MATERIAL_SOURCE_DISABLE) { + // Ambient = Vertex + // Emission = ??? + + f1[0] = state.material[side].emission.r; + f1[1] = state.material[side].emission.g; + f1[2] = state.material[side].emission.b; + + // Note: I don't think GL can do two-sided for this one? + f2[0] = state.light_model_ambient.r; + f2[1] = state.light_model_ambient.g; + f2[2] = state.light_model_ambient.b; + + if (emissive_source[side] != XGU_MATERIAL_SOURCE_DISABLE) { + // Ambient = Vertex + // Emission = Vertex + + //FIXME: = f1 + f2 * vertex ??? + // = material.emission + light_model.ambient * vertex + + //FIXME: What about replacing the emission? + // Shouldn't this be something like: + // = vertex + light_model.ambient * vertex ? + // Will the GPU automatically use vertex instead of f1? + // Is this an invalid GPU state? (GL API makes this impossible) + assert(false); + + } else { + // Ambient = Vertex + // Emission = Material + + // Confusingly: + // - f1 = SCENE_AMBIENT_COLOR [but used for material.emission here] + // - f2 = MATERIAL_EMISSION [but used for light_model.ambient here] - p = xgu_set_material_emission(p, state.material[0].emission.r, state.material[0].emission.g, state.material[0].emission.b); - p = xgu_set_back_material_emission(p, state.material[1].emission.r, state.material[1].emission.g, state.material[1].emission.b); + //FIXME: = f1 + f2 * vertex ??? + // = material.emission + light_model.ambient * vertex + } + } else if (emissive_source[side] != XGU_MATERIAL_SOURCE_DISABLE) { + assert(ambient_source[side] == XGU_MATERIAL_SOURCE_DISABLE); + // Ambient = Material + // Emission = Vertex + + f1[0] = state.light_model_ambient.r * state.material[side].ambient.r; + f1[1] = state.light_model_ambient.g * state.material[side].ambient.g; + f1[2] = state.light_model_ambient.b * state.material[side].ambient.b; + + f2[0] = 1.0f; + f2[1] = 1.0f; + f2[2] = 1.0f; + + //FIXME: = f1 + f2 * vertex ??? + // = (light_model.ambient * material.ambient) + vertex ??? + } else { + assert(ambient_source[side] == XGU_MATERIAL_SOURCE_DISABLE); + assert(emissive_source[side] == XGU_MATERIAL_SOURCE_DISABLE); + // Ambient = Material + // Emission = Material - unimplemented(); //FIXME: What about state.material[#].ambient - unimplemented(); //FIXME: What about state.material[#].diffuse - unimplemented(); //FIXME: What about state.material[#].specular + f1[0] = state.light_model_ambient.r * state.material[side].ambient.r + state.material[side].emission.r; + f1[1] = state.light_model_ambient.g * state.material[side].ambient.g + state.material[side].emission.g; + f1[2] = state.light_model_ambient.b * state.material[side].ambient.b + state.material[side].emission.b; + + f2[0] = 0.0f; + f2[1] = 0.0f; + f2[2] = 0.0f; + + //FIXME: = f1 + f2 * vertex ??? + // = (light_model.ambient * material.ambient + material.emission) + 0 ??? + } + if (side == 0) { + p = xgu_set_scene_ambient_color(p, f1[0], f1[1], f1[2]); + p = xgu_set_material_emission(p, f2[0], f2[1], f2[2]); + } else { + p = xgu_set_back_scene_ambient_color(p, f1[0], f1[1], f1[2]); + p = xgu_set_back_material_emission(p, f2[0], f2[1], f2[2]); + } + } //FIXME: How does this contribute? - float material_alpha[2] = { 1.0f, 1.0f }; - p = xgu_set_material_alpha(p, material_alpha[0]); - p = xgu_set_back_material_alpha(p, material_alpha[1]); + p = xgu_set_material_alpha(p, state.material[0].diffuse.a); + p = xgu_set_back_material_alpha(p, state.material[1].diffuse.a); //FIXME: When to do this? bool specular_enabled = false; p = xgu_set_specular_enable(p, specular_enabled); + bool separate_specular = false; //FIXME: Respect GL + bool localeye = false; //FIXME: Respect GL + XguSout sout = XGU_SOUT_ZERO_OUT; //FIXME: What is this? + // - D3D VP always uses PASSTHROUGH? + // - D3D FFP always uses ZERO_OUT? + p = xgu_set_light_control(p, separate_specular, localeye, sout); + XguLightMask mask[8]; for(int i = 0; i < 8; i++) { mask[i] = XGU_LMASK_OFF; @@ -1479,19 +1580,52 @@ static void setup_lighting() { p = pb_begin(); } - p = xgu_set_light_diffuse_color(p, i, l->diffuse.r, l->diffuse.g, l->diffuse.b); - p = xgu_set_back_light_diffuse_color(p, i, l->diffuse.r, l->diffuse.g, l->diffuse.b); - // We'd be incorrectly mixing colors in the shader, so it's too bright. - // Hence, we disable some lights for now. - //FIXME: Do proper mixing in shader. + + for(int side = 0; side < sides; side++) { + float f[3]; + + if (diffuse_source[side] == XGU_MATERIAL_SOURCE_DISABLE) { + _mul3(f, &l->diffuse, &state.material[side].diffuse); + } else { + memcpy(f, &l->diffuse, sizeof(f)); + } + if (side == 0) { + p = xgu_set_light_diffuse_color(p, i, f[0], f[1], f[2]); + } else { + p = xgu_set_back_light_diffuse_color(p, i, f[0], f[1], f[2]); + } + + // We'd be incorrectly mixing colors in the shader, so it's too bright? + // Hence, we disable some lights for now. + //FIXME: Do proper mixing in shader. #if 1 - p = xgu_set_light_ambient_color(p, i, l->ambient.r, l->ambient.g, l->ambient.b); - p = xgu_set_back_light_ambient_color(p, i, l->ambient.r, l->ambient.g, l->ambient.b); + if (ambient_source[side] == XGU_MATERIAL_SOURCE_DISABLE) { + _mul3(f, &l->ambient, &state.material[side].ambient); + } else { + memcpy(f, &l->ambient, sizeof(f)); + } + if (side == 0) { + p = xgu_set_light_ambient_color(p, i, f[0], f[1], f[2]); + } else { + p = xgu_set_back_light_ambient_color(p, i, f[0], f[1], f[2]); + } + + if (specular_source[side] == XGU_MATERIAL_SOURCE_DISABLE) { + _mul3(f, &l->specular, &state.material[side].specular); + } else { + memcpy(f, &l->specular, sizeof(f)); + } + if (side == 0) { + p = xgu_set_light_specular_color(p, i, f[0], f[1], f[2]); + } else { + p = xgu_set_back_light_specular_color(p, i, f[0], f[1], f[2]); + } + } - p = xgu_set_light_specular_color(p, i, l->specular.r, l->specular.g, l->specular.b); - p = xgu_set_back_light_specular_color(p, i, l->specular.r, l->specular.g, l->specular.b); #else + } + p = xgu_set_light_ambient_color(p, i, 0,0,0); p = xgu_set_back_light_ambient_color(p, i, 0,0,0); @@ -2949,8 +3083,8 @@ __attribute__((constructor)) static void setup_xbox(void) { } glFrontFace(GL_CW); - glDisable(GL_COLOR_MATERIAL); + glDisable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); } From 5ec0a4e6cdf9aeee365922bd651274e31c5a9728 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 18 May 2020 19:36:19 +0200 Subject: [PATCH 69/93] check memory allocations --- xbox/xbox.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 3166ac068..3e8b34aab 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -198,7 +198,9 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) { static void* AllocateResourceMemory(size_t size) { #define MAXRAM 0x03FFAFFF - return MmAllocateContiguousMemoryEx(size, 0, MAXRAM, 0, PAGE_READWRITE | PAGE_WRITECOMBINE); + void* addr = MmAllocateContiguousMemoryEx(size, 0, MAXRAM, 0, PAGE_READWRITE | PAGE_WRITECOMBINE); + assert(addr != NULL); + return addr; } static void FreeResourceMemory(void* ptr) { From 62a17ede36ec4450898e48babd03a1f93309cc96 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 18 May 2020 19:36:27 +0200 Subject: [PATCH 70/93] fix typo --- xbox/xbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 3e8b34aab..688c1b881 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -732,7 +732,7 @@ static void setup_texenv() { uint32_t* p = pb_begin(); //FIXME: This is an assumption on how this should be handled - // The GL ES 1.1 Full spec claism that only texture 0 uses Cp=Cf. + // The GL ES 1.1 Full spec claims that only texture 0 uses Cp=Cf. // However, what if unit 0 is inactive? Cp=Cf? Cp=undefined? // Couldn't find an answer when skimming over spec. GLuint rc_previous = _RC_PRIMARY_COLOR; From 5d18ff13908dc8604e11552610bb5675c89df4fd Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 18 May 2020 20:12:00 +0200 Subject: [PATCH 71/93] Use correct values for texfilter --- xbox/xbox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 688c1b881..358ae9175 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -510,8 +510,8 @@ static XguPrimitiveType gl_to_xgu_primitive_type(GLenum mode) { } typedef unsigned int XguTextureFilter; -#define XGU_TEXTURE_FILTER_LINEAR 4 //FIXME: Shitty workaround for XGU -#define XGU_TEXTURE_FILTER_NEAREST XGU_TEXTURE_FILTER_LINEAR //FIXME: Shitty workaround for XGU +#define XGU_TEXTURE_FILTER_LINEAR 2 //FIXME: Shitty workaround for XGU +#define XGU_TEXTURE_FILTER_NEAREST 1 //FIXME: Shitty workaround for XGU static XguTextureFilter gl_to_xgu_texture_filter(GLenum filter) { switch(filter) { From 45ad85a4c826e8eeaeda0de8dbd1680a4dc9d948 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 18 May 2020 20:12:08 +0200 Subject: [PATCH 72/93] Avoid debugging to disk --- share/gui.c | 2 +- share/solid_draw.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/share/gui.c b/share/gui.c index ecc831ed3..686073d66 100644 --- a/share/gui.c +++ b/share/gui.c @@ -209,7 +209,7 @@ static void draw_enable(GLboolean c, GLboolean u, GLboolean p) static void draw_rect(int id) { -printf("Tried to draw %d\n", RECT_ELEM); +//printf("Tried to draw %d\n", RECT_ELEM); glDrawElements(GL_TRIANGLE_STRIP, RECT_ELEM, GL_UNSIGNED_SHORT, (const GLvoid *) (id * WIDGET_ELEM * sizeof (GLushort))); } diff --git a/share/solid_draw.c b/share/solid_draw.c index 0581106e7..a0de76a88 100644 --- a/share/solid_draw.c +++ b/share/solid_draw.c @@ -425,7 +425,7 @@ void sol_draw_mesh(const struct d_mesh *mp, struct s_rend *rend, int p) if (rend->curr_mtrl.base.fl & M_PARTICLE) glDrawArrays(GL_POINTS, 0, mp->vbc); else { -printf("Tried to draw %d (solid)\n", mp->ebc); +//printf("Tried to draw %d (solid)\n", mp->ebc); glDrawElements(GL_TRIANGLES, mp->ebc, GL_UNSIGNED_SHORT, 0); } } From d97f3936b1afda1a9d72945fd94decea07b254ea Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 18 May 2020 20:12:23 +0200 Subject: [PATCH 73/93] Improve debug button (move from start to back) --- xbox/xbox.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 358ae9175..920ea3fac 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -2830,8 +2830,9 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface } } if (g != NULL) { - bool button = SDL_GameControllerGetButton(g, SDL_CONTROLLER_BUTTON_START); - if (button) { + static bool pressed = true; + bool button = SDL_GameControllerGetButton(g, SDL_CONTROLLER_BUTTON_BACK); + if (button && !pressed) { draw_debug = !draw_debug; if (draw_debug) { @@ -2840,8 +2841,8 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface pb_show_debug_screen(); } - Sleep(200); } + pressed = button; } #endif From 6583711c858837e4e113a72d33ba4e4939e28d00 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 18 May 2020 20:33:04 +0200 Subject: [PATCH 74/93] Improve logging of unimplemented things --- xbox/xbox.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 920ea3fac..599a3d11c 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -64,9 +64,26 @@ static void mult_vec4_mat4(float* o, const float* m, const float* v) { static unsigned int frame = 0; //FIXME: Remove static SDL_GameController* g = NULL; -#if 0 #include +static void _unimplemented(const char* fmt, ...) { + char buf[1024]; + va_list va; + va_start(va, fmt); + vsprintf(buf, fmt, va); + va_end(va); + printf(buf); // Log to disk + debugPrint(buf); // Log to display +} +#define unimplemented(fmt, ...) { \ + static bool encountered = false; \ + if (!encountered) { \ + _unimplemented("%s (%s:%d) " fmt "\n", __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); \ + encountered = true; \ + } \ +} + +#if 0 void debugPrintFloat(float f) { #if 0 //FIXME: pdclib can't do this @@ -85,22 +102,10 @@ void debugPrintFloat(float f) { #endif } - -static void _unimplemented(const char* fmt, ...) { - char buf[1024]; - va_list va; - va_start(va, fmt); - vsprintf(buf, fmt, va); - va_end(va); - debugPrint(buf); -} -#define unimplemented(fmt, ...) _unimplemented("%s (%s:%d) " fmt "\n", __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) - #else void debugPrintFloat(float f) {} #define debugPrintFloat(f) 0 #define debugPrint(...) 0 -#define unimplemented(fmt, ...) 0 #endif // stdlib.h From 7b43ac9f649ab887bbc2a4422e1890b46dce0a66 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 18 May 2020 20:33:26 +0200 Subject: [PATCH 75/93] Continue clipplane support --- xbox/xbox.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 599a3d11c..1199c9604 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -425,11 +425,23 @@ static State state = { .texture_binding_2d = { 0, 0, 0, 0 } }; +typedef struct { + bool enabled; + float x; + float y; + float z; + float w; +} ClipPlane; +static ClipPlane clip_planes[3]; //FIXME: No more needed for neverball + #include "matrix.h" static uint32_t* set_enabled(uint32_t* p, GLenum cap, bool enabled) { switch(cap) { + case GL_CLIP_PLANE0 ... GL_CLIP_PLANE0+3-1: //FIXME: Find right GL constant + clip_planes[cap - GL_CLIP_PLANE0].enabled = enabled; + break; case GL_TEXTURE_GEN_S: state.texgen_s_enabled[active_texture] = enabled; break; @@ -975,14 +987,7 @@ static unsigned int* matrix_slot = &matrix_mv_slot; static float* matrix = &matrix_mv[0]; static GLenum matrix_mode = GL_MODELVIEW; -typedef struct { - bool enabled; - float x; - float y; - float z; - float w; -} ClipPlane; -static ClipPlane clip_planes[3]; //FIXME: No more needed for neverball + static void print_attrib(XguVertexArray array, Attrib* attrib, unsigned int start, unsigned int count, bool submit) { @@ -2420,7 +2425,7 @@ GL_API void GL_APIENTRY glClipPlanef (GLenum p, const GLfloat *eqn) { float v[4]; float m[4*4]; bool ret = invert(m, &matrix_mv[matrix_mv_slot * 4*4]); - unimplemented(); //FIXME: Multiply eqn by m to get the v + mult_vec4_mat4(v, m, eqn); //FIXME: Multiply eqn by m to get the v clip_plane->x = v[0]; clip_plane->y = v[1]; From f5972f29392d2f06b248b99c5c244955e6906639 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 18 May 2020 20:33:33 +0200 Subject: [PATCH 76/93] more stencil ops --- xbox/xbox.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xbox/xbox.c b/xbox/xbox.c index 1199c9604..75dc7c720 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -545,6 +545,9 @@ static XguTextureFilter gl_to_xgu_texture_filter(GLenum filter) { static XguStencilOp gl_to_xgu_stencil_op(GLenum op) { switch(op) { case GL_KEEP: return XGU_STENCIL_OP_KEEP; + case GL_REPLACE: return XGU_STENCIL_OP_REPLACE; +//FIXME: case GL_INCR: return XGU_STENCIL_OP_INCR; +//FIXME: case GL_DECR: return XGU_STENCIL_OP_DECR; default: unimplemented("%d", op); assert(false); From 8f22f7da1f2349f109fcf827740a166ef8c51f8a Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 18 May 2020 20:33:44 +0200 Subject: [PATCH 77/93] set clipping during init --- xbox/xbox.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xbox/xbox.c b/xbox/xbox.c index 75dc7c720..241424f2e 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -3043,6 +3043,8 @@ __attribute__((constructor)) static void setup_xbox(void) { #endif //control0 |= NV097_SET_CONTROL0_Z_FORMAT; // Float if present; fixed otherwise p = pb_push1(p, NV097_SET_CONTROL0, control0); + p = xgu_set_clip_min(p, (float)0x000000); + p = xgu_set_clip_max(p, (float)0xFFFFFF); pb_end(p); From 5c0560d3f990bc406accd5b9d0c7476f3535f4f0 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 18 May 2020 21:02:48 +0200 Subject: [PATCH 78/93] fix textures --- xbox/xbox.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 241424f2e..ac38dc50d 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1186,18 +1186,24 @@ static void setup_textures() { unsigned int dimensionality = 2; unsigned int context_dma = 2; //FIXME: Which one did pbkit use? - bool border = false; + XguBorderSrc border = XGU_SOURCE_COLOR; + + unsigned int mipmap_levels = 1; + unsigned int min_lod = 0; + unsigned int max_lod = 0; + unsigned int lod_bias = 0; + p = xgu_set_texture_offset(p, i, (uintptr_t)tx->data & 0x03ffffff); p = xgu_set_texture_format(p, i, context_dma, cubemap_enable, border, dimensionality, - gl_to_xgu_texture_format(tx->internal_base_format), 1, + gl_to_xgu_texture_format(tx->internal_base_format), mipmap_levels, tx->width_shift,tx->height_shift,0); p = xgu_set_texture_address(p, i, gl_to_xgu_texture_address(tx->wrap_s), false, gl_to_xgu_texture_address(tx->wrap_t), false, XGU_CLAMP_TO_EDGE, false, false); - p = xgu_set_texture_control0(p, i, true, 0, 0); + p = xgu_set_texture_control0(p, i, true, min_lod, max_lod); p = xgu_set_texture_control1(p, i, tx->pitch); - p = xgu_set_texture_filter(p, i, 0, XGU_TEXTURE_CONVOLUTION_QUINCUNX, + p = xgu_set_texture_filter(p, i, lod_bias, XGU_TEXTURE_CONVOLUTION_QUINCUNX, gl_to_xgu_texture_filter(tx->min_filter), gl_to_xgu_texture_filter(tx->mag_filter), false, false, false, false); From 769888d13b9933a5a71c3f494d84bbab6433cb79 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 18 May 2020 21:04:57 +0200 Subject: [PATCH 79/93] remove printing on clear --- xbox/xbox.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index ac38dc50d..944de7955 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1850,8 +1850,6 @@ GL_API void GL_APIENTRY glClear (GLbitfield mask) { if (mask & GL_DEPTH_BUFFER_BIT) { flags |= XGU_CLEAR_Z; } if (mask & GL_STENCIL_BUFFER_BIT) { flags |= XGU_CLEAR_STENCIL; } - pb_print("Clearing\n"); - //FIXME: Store size we used to init int width = pb_back_buffer_width(); int height = pb_back_buffer_height(); @@ -2872,7 +2870,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface /* Draw some text on the screen */ static int frame = 0; frame++; - pb_print("Neverball (frame %d)\n", frame); + pb_print("Frame %d\n", frame); pb_draw_text_screen(); while(pb_busy()) { From ca72bdb6e20b70e000a8516b23b3d57285f30e02 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 21 May 2020 15:24:54 +0200 Subject: [PATCH 80/93] add an unconditional debugPrint (broken) --- xbox/xbox.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 944de7955..b082eddb1 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -82,6 +82,7 @@ static void _unimplemented(const char* fmt, ...) { } \ } +#define _debugPrint(...) debugPrint(__VA_ARGS__) #if 0 void debugPrintFloat(float f) { @@ -2997,14 +2998,14 @@ __attribute__((constructor)) static void setup_xbox(void) { //FIXME: Why is this necessary? SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); - debugPrint("\n\n"); - debugPrint("\n\n"); - debugPrint("\n\n"); - debugPrint("\n\n"); - debugPrint("\n\n"); - debugPrint("\n\n"); - debugPrint("\n\n"); - debugPrint("\n\n"); + _debugPrint("\n\n"); + _debugPrint("\n\n"); + _debugPrint("\n\n"); + _debugPrint("\n\n"); + _debugPrint("\n\n"); +// debugPrint("\n\n"); +// debugPrint("\n\n"); +// debugPrint("\n\n"); //FIXME: Bump GPU in right state? uint32_t* p = pb_begin(); From 6abfd16a4373b0a2f65d979387e008772c04e33d Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 21 May 2020 15:25:04 +0200 Subject: [PATCH 81/93] attempt to fix lighting matrix --- xbox/xbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index b082eddb1..3a4cd5547 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1372,7 +1372,7 @@ TRANSPOSE(matrix_mv_now) // Required for lighting invert(t, matrix_mv_now); //FIXME: This is affected if we want to normalize normals - //transposeMatrix(t, t); + transposeMatrix(t, t); //FIXME: mesa only uploads a 4x3 / 3x4 matrix p = xgu_set_inverse_model_view_matrix(p, i, t); //FIXME: Not sure when used? #endif From eb7ca40aa37cae393e59bc0f11a1160383049787 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 21 May 2020 15:25:31 +0200 Subject: [PATCH 82/93] display memory information every frame --- xbox/xbox.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 3a4cd5547..f47e55000 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -2870,8 +2870,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface /* Draw some text on the screen */ static int frame = 0; - frame++; - pb_print("Frame %d\n", frame); + frame++; + MM_STATISTICS mem_stats; + mem_stats.Length = sizeof(mem_stats); + MmQueryStatistics(&mem_stats); + pb_print("Frame %d; memory: %dMiB / %dMiB\n", frame, ((mem_stats.TotalPhysicalPages - mem_stats.AvailablePages) * 4) / 1024, (mem_stats.TotalPhysicalPages * 4) / 1024); pb_draw_text_screen(); while(pb_busy()) { From 97646a817eff28c379de6d6ab7b9d3dd7ec3a275 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 21 May 2020 15:26:00 +0200 Subject: [PATCH 83/93] remove useless synchronization with GPU --- xbox/xbox.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index f47e55000..85224a610 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -2891,16 +2891,12 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface // Prepare next frame - pb_wait_for_vbl(); + //pb_wait_for_vbl(); pb_reset(); pb_target_back_buffer(); pb_erase_text_screen(); - while(pb_busy()) { - /* Wait for completion... */ - } - return EGL_TRUE; } #endif From e7141436669c8c4206b635e522531e0f305659f2 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Thu, 21 May 2020 15:26:18 +0200 Subject: [PATCH 84/93] Attempt to enable zbuffer compression (if not already active) --- xbox/xbox.c | 1 + 1 file changed, 1 insertion(+) diff --git a/xbox/xbox.c b/xbox/xbox.c index 85224a610..c42b1861a 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -3049,6 +3049,7 @@ __attribute__((constructor)) static void setup_xbox(void) { p = pb_push1(p, NV097_SET_CONTROL0, control0); p = xgu_set_clip_min(p, (float)0x000000); p = xgu_set_clip_max(p, (float)0xFFFFFF); + p = pb_push1(p,NV097_SET_COMPRESS_ZBUFFER_EN,1); //FIXME: Does this work? pb_end(p); From 72d319d3b7d414bde17d61478b970c3af90caa30 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 23 May 2020 01:02:24 +0200 Subject: [PATCH 85/93] free textures on deletion --- xbox/xbox.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/xbox/xbox.c b/xbox/xbox.c index c42b1861a..c0b3ca211 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -2276,6 +2276,19 @@ GL_API void GL_APIENTRY glClientActiveTexture (GLenum texture) { } GL_API void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures) { + for(int i = 0; i < n; i++) { + + //FIXME: Also ignore non-existing names + if (textures[i] == 0) { + continue; + } + + Texture* texture = objects[textures[i]-1].data; + if (texture->data != NULL) { + unimplemented(); //FIXME: Assert that the data is no longer used + FreeResourceMemory(texture->data); + } + } del_objects(n, textures); } From 972ecd2a4d81c54011204693391f2b4e3a6e741f Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 23 May 2020 01:02:40 +0200 Subject: [PATCH 86/93] reset GPU command list pointer more often --- xbox/xbox.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xbox/xbox.c b/xbox/xbox.c index c0b3ca211..4654eae33 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1672,6 +1672,12 @@ static void setup_lighting() { } static void prepare_drawing() { + + unimplemented(); //FIXME: Measure length of buffer and resize so we can handle large levels + // `pb_busy` and `pb_reset` are too expensive. + while(pb_busy()); + pb_reset(); + debugPrint("Preparing to draw\n"); //FIXME: Track dirty bits From e742f31f4a5cfd722b0e6323f8ec724d2022feb2 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 23 May 2020 01:03:17 +0200 Subject: [PATCH 87/93] generate mipmaps (unconditionally for now) --- xbox/xbox.c | 77 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 12 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 4654eae33..7202c94d7 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -12,6 +12,8 @@ static float viewport_matrix[4*4]; +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + static float _max(float a, float b) { return (a > b) ? a : b; } @@ -2298,6 +2300,14 @@ GL_API void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures) { del_objects(n, textures); } +static void blend_2x2_bytes(unsigned int channels, const uint8_t* src_pixels, uint8_t* dst_pixels, unsigned int x, unsigned int y, size_t src_pitch, size_t dst_pitch) { + for(int channel = 0; channel < channels; channel++) { + dst_pixels[y * dst_pitch + x*channels + channel] = (src_pixels[(y*2+0) * src_pitch + (x*2+0)*channels + channel] + + src_pixels[(y*2+0) * src_pitch + (x*2+1)*channels + channel] + + src_pixels[(y*2+1) * src_pitch + (x*2+0)*channels + channel] + + src_pixels[(y*2+1) * src_pitch + (x*2+1)*channels + channel]) / 4; + } +} GL_API void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) { assert(target == GL_TEXTURE_2D); @@ -2355,28 +2365,39 @@ GL_API void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internal tx->width = width; tx->height = height; tx->pitch = width * bpp / 8; - size_t size = tx->pitch * tx->height; if (tx->data != NULL) { //FIXME: Re-use existing buffer if it's a good fit? //FIXME: Assert that this memory is no longer used FreeResourceMemory(tx->data); } + + // Calculate required size for mipmaps + unsigned int mip_levels = MAX(tx->width_shift, tx->height_shift) + 1; + unsigned int width_shift = tx->width_shift; + unsigned int height_shift = tx->height_shift; + size_t size = 0; + for(unsigned int mip_level = 0; mip_level < mip_levels; mip_level++) { + debugPrint("%d %d %d\n", mip_level, width_shift, height_shift); + size += (1 << (width_shift + height_shift)) * (bpp / 8); + if (width_shift > 0) { width_shift--; } + if (height_shift > 0) { height_shift--; } + } tx->data = AllocateResourceMemory(size); + // Allocate temporary space for generating mipmaps and swizzling source + uint8_t* tmp = malloc(tx->width * tx->height * (bpp / 8)); + // Copy pixels //FIXME: Respect GL pixel packing stuff - debugPrint("swizzling\n"); assert(pixels != NULL); if (tx->internal_base_format == GL_RGB) { assert(format == GL_RGB); assert(type == GL_UNSIGNED_BYTE); - uint8_t* tmp = malloc(tx->width * tx->height * 4); const uint8_t* src = pixels; uint8_t* dst = tmp; assert(tx->pitch == tx->width * 4); for(int y = 0; y < tx->height; y++) { for(int x = 0; x < tx->width; x++) { - //FIXME: Can also use different texture format instead probably dst[0] = src[2]; dst[1] = src[1]; dst[2] = src[0]; @@ -2385,16 +2406,48 @@ GL_API void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internal src += 3; } } - debugPrint("1 swizzling..\n"); - swizzle_rect(tmp, tx->width, tx->height, tx->data, tx->width * 4, 4); - debugPrint("1 okay?!\n"); - free(tmp); } else { - debugPrint("2 swizzling..\n"); - swizzle_rect(pixels, tx->width, tx->height, tx->data, tx->pitch, bpp / 8); - debugPrint("2 okay?!\n"); + memcpy(tmp, pixels, tx->width * tx->height * (bpp / 8)); } - debugPrint("swizzling done\n"); + + // Generate mipmaps + uint8_t* swizzled_pixels = (uint8_t*)tx->data; + unsigned int w = 1 << tx->width_shift; + unsigned int h = 1 << tx->height_shift; + size_t pitch = w * (bpp / 8); + unsigned int mip_level = 0; + while(true) { + + // Swizzle data + _debugPrint("Swizzling %dx%d [pitch %d, %dbpp] (%d / %d)\n", w, h, pitch, bpp, mip_level, mip_levels); + swizzle_rect(tmp, w, h, swizzled_pixels, pitch, bpp / 8); + + // Check if there is another mipmap level + mip_level++; + if (mip_level >= mip_levels) { + _debugPrint("Generated all levels!\n"); + break; + } + + // Calculate offset and size of next mipmap level + swizzled_pixels += pitch * h; + size_t src_pitch = pitch; + if (w > 1) { w /= 2; pitch /= 2; } + if (h > 1) { h /= 2; } + + // We can run the downscale in place + _debugPrint("Downscaling to %dx%d\n", w, h); + for(unsigned int y = 0; y < h; y++) { + for(unsigned int x = 0; x < w; x++) { + blend_2x2_bytes(bpp / 8, tmp, tmp, x, y, src_pitch, pitch); + } + } + + + + } + + free(tmp); } GL_API void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param) { From 8a636596dc733fa56c3b0b0ff9a60dedd9848871 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 23 May 2020 01:03:34 +0200 Subject: [PATCH 88/93] avoid setting some texture registers (errros on hw - FIXME) --- xbox/xbox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 7202c94d7..b1efddb2c 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1205,12 +1205,12 @@ static void setup_textures() { XGU_CLAMP_TO_EDGE, false, false); p = xgu_set_texture_control0(p, i, true, min_lod, max_lod); - p = xgu_set_texture_control1(p, i, tx->pitch); +// p = xgu_set_texture_control1(p, i, 0x800000 /*tx->pitch*/); p = xgu_set_texture_filter(p, i, lod_bias, XGU_TEXTURE_CONVOLUTION_QUINCUNX, gl_to_xgu_texture_filter(tx->min_filter), gl_to_xgu_texture_filter(tx->mag_filter), false, false, false, false); - p = xgu_set_texture_image_rect(p, i, tx->width, tx->height); +// p = xgu_set_texture_image_rect(p, i, 0 /*tx->width*/, 0 /*tx->height*/); #if 0 //FIXME: Use NV097_SET_TEXTURE_FORMAT and friends From dbaf7c1b0f113bf69786ed3d17b3db12b8615246 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 23 May 2020 01:03:56 +0200 Subject: [PATCH 89/93] set mipmap level settings in texture units (FIXME: wrong values) --- xbox/xbox.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index b1efddb2c..2a98536e9 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1191,9 +1191,9 @@ static void setup_textures() { unsigned int context_dma = 2; //FIXME: Which one did pbkit use? XguBorderSrc border = XGU_SOURCE_COLOR; - unsigned int mipmap_levels = 1; - unsigned int min_lod = 0; - unsigned int max_lod = 0; + unsigned int mipmap_levels = MAX(tx->width_shift, tx->height_shift) + 1; + unsigned int min_lod = 2; + unsigned int max_lod = 2; unsigned int lod_bias = 0; p = xgu_set_texture_offset(p, i, (uintptr_t)tx->data & 0x03ffffff); From f0c9bea5ca51e62fd871d487196d4ad562364025 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 23 May 2020 01:04:27 +0200 Subject: [PATCH 90/93] debug hacks --- xbox/xbox.c | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index 2a98536e9..5f5625503 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1541,6 +1541,12 @@ static void setup_lighting() { XguSout sout = XGU_SOUT_ZERO_OUT; //FIXME: What is this? // - D3D VP always uses PASSTHROUGH? // - D3D FFP always uses ZERO_OUT? + if (SDL_GameControllerGetButton(g, SDL_CONTROLLER_BUTTON_DPAD_LEFT)) { + sout = XGU_SOUT_PASSTHROUGH; //FIXME: What is this? + pb_print("PT;"); + } else { + pb_print("ZO;"); + } p = xgu_set_light_control(p, separate_specular, localeye, sout); XguLightMask mask[8]; @@ -1707,10 +1713,11 @@ static void prepare_drawing() { setup_matrices(); // Setup lighting -#if 1 setup_lighting(); -#else - { + +#if 1 + if (SDL_GameControllerGetButton(g, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)) { + pb_print("Lighting disabled\n"); uint32_t* p = pb_begin(); p = xgu_set_lighting_enable(p, false); pb_end(p); @@ -1720,8 +1727,10 @@ static void prepare_drawing() { // Setup textures setup_textures(); +debugPrint("texenv setup"); // Set the register combiner setup_texenv(); +debugPrint("debug stuff"); #if 0 { @@ -1754,24 +1763,44 @@ static void prepare_drawing() { } #endif -#if 0 - { +#if 1 + if (SDL_GameControllerGetButton(g, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) { + pb_print("BLEND;\n"); + uint32_t* p = pb_begin(); + p = xgu_set_blend_func_sfactor(p, XGU_FACTOR_SRC_ALPHA); + p = xgu_set_blend_func_dfactor(p, XGU_FACTOR_ONE_MINUS_SRC_ALPHA); + p = xgu_set_alpha_test_enable(p, false); + p = xgu_set_blend_enable(p, true); + p = pb_push1(p, NV097_SET_COMBINER_SPECULAR_FOG_CW1, + MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_E_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_E_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_E_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_F_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_F_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_F_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_G_SOURCE, _RC_PRIMARY_COLOR) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_G_ALPHA, 1) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_G_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_SPECULAR_CLAMP, 0)); + pb_end(p); + } +#endif + +#if 1 + if (SDL_GameControllerGetButton(g, SDL_CONTROLLER_BUTTON_DPAD_UP) || SDL_GameControllerGetButton(g, SDL_CONTROLLER_BUTTON_DPAD_DOWN)) { // Output selector - unsigned int source = _RC_TEXTURE+0; + unsigned int source = _RC_PRIMARY_COLOR; //_RC_TEXTURE+0; + int alpha = SDL_GameControllerGetButton(g, SDL_CONTROLLER_BUTTON_DPAD_UP) ? 1 : 0; + pb_print("%s;", alpha ? "A" : "RGB"); uint32_t* p = pb_begin(); p = pb_push1(p, NV097_SET_COMBINER_SPECULAR_FOG_CW0, MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_A_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_A_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_A_INVERSE, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_B_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_B_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_B_INVERSE, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_C_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_C_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_C_INVERSE, 0) - | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_D_SOURCE, source) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_D_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_D_INVERSE, 0)); + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_D_SOURCE, source) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_D_ALPHA, alpha) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW0_D_INVERSE, 0)); p = pb_push1(p, NV097_SET_COMBINER_SPECULAR_FOG_CW1, MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_E_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_E_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_E_INVERSE, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_F_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_F_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_F_INVERSE, 0) - | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_G_SOURCE, source) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_G_ALPHA, 1) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_G_INVERSE, 0) + | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_G_SOURCE, _RC_ZERO) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_G_ALPHA, 0) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_G_INVERSE, 1) | MASK(NV097_SET_COMBINER_SPECULAR_FOG_CW1_SPECULAR_CLAMP, 0)); pb_end(p); } #endif +_debugPrint("gone"); } @@ -2035,6 +2064,7 @@ return; //FIXME: !!! prepare_drawing(); +debugPrint("drawarrays"); xgux_draw_arrays(gl_to_xgu_primitive_type(mode), first, count); #if 1 @@ -2062,6 +2092,7 @@ GL_API void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, f = frame; prepare_drawing(); +debugPrint("elements "); uintptr_t base; if (gl_element_array_buffer == 0) { From 4c7a18430aec03baee08f5f0a872197bcc20b37a Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 23 May 2020 02:55:09 +0200 Subject: [PATCH 91/93] Add GL_GENERATE_MIPMAP_SGIS to enable mipmaps in the game --- xbox/GLES/gl.h | 3 +++ xbox/xbox.c | 19 +++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/xbox/GLES/gl.h b/xbox/GLES/gl.h index 84f8ccc76..b4481fe08 100644 --- a/xbox/GLES/gl.h +++ b/xbox/GLES/gl.h @@ -194,6 +194,9 @@ typedef unsigned int GLbitfield; +// Used in neverball conditionally +#define GL_GENERATE_MIPMAP_SGIS 25000 +#define GL_LINEAR_MIPMAP_LINEAR 25001 diff --git a/xbox/xbox.c b/xbox/xbox.c index 5f5625503..cc0b56216 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -530,13 +530,20 @@ static XguPrimitiveType gl_to_xgu_primitive_type(GLenum mode) { } typedef unsigned int XguTextureFilter; -#define XGU_TEXTURE_FILTER_LINEAR 2 //FIXME: Shitty workaround for XGU -#define XGU_TEXTURE_FILTER_NEAREST 1 //FIXME: Shitty workaround for XGU + //FIXME: Shitty workaround for XGU +#define XGU_TEXTURE_FILTER_NEAREST 1 +#define XGU_TEXTURE_FILTER_LINEAR 2 +#define XGU_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST 3 +#define XGU_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST 4 +#define XGU_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR 5 +#define XGU_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR 6 static XguTextureFilter gl_to_xgu_texture_filter(GLenum filter) { switch(filter) { - case GL_LINEAR: return XGU_TEXTURE_FILTER_LINEAR; - case GL_NEAREST: return XGU_TEXTURE_FILTER_NEAREST; + case GL_NEAREST: return XGU_TEXTURE_FILTER_NEAREST; + case GL_LINEAR: return XGU_TEXTURE_FILTER_LINEAR; + case GL_NEAREST_MIPMAP_LINEAR: return XGU_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR; + case GL_LINEAR_MIPMAP_LINEAR: return XGU_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR; default: unimplemented("%d", filter); assert(false); @@ -2442,6 +2449,7 @@ GL_API void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internal } // Generate mipmaps + unimplemented(); //FIXME: Make dependent on GL_GENERATE_MIPMAP_SGIS uint8_t* swizzled_pixels = (uint8_t*)tx->data; unsigned int w = 1 << tx->width_shift; unsigned int h = 1 << tx->height_shift; @@ -2487,6 +2495,9 @@ GL_API void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint para Texture* tx = get_bound_texture(active_texture); switch(pname) { + case GL_GENERATE_MIPMAP_SGIS: + unimplemented(); //FIXME: Make this optional (currently assumed true) + break; case GL_TEXTURE_MIN_FILTER: tx->min_filter = param; break; From 746d8c8c730e6325ac16c3551d682714f06f55ce Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 23 May 2020 02:55:33 +0200 Subject: [PATCH 92/93] pick proper mipmap level (FIXME: Confirm if not off-by-one) --- xbox/xbox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index cc0b56216..e271adea8 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -1199,8 +1199,8 @@ static void setup_textures() { XguBorderSrc border = XGU_SOURCE_COLOR; unsigned int mipmap_levels = MAX(tx->width_shift, tx->height_shift) + 1; - unsigned int min_lod = 2; - unsigned int max_lod = 2; + unsigned int min_lod = 0; + unsigned int max_lod = mipmap_levels - 1; unsigned int lod_bias = 0; p = xgu_set_texture_offset(p, i, (uintptr_t)tx->data & 0x03ffffff); From 42a8be94970117c91c4ed9c54f80713256138e56 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 23 May 2020 03:18:22 +0200 Subject: [PATCH 93/93] Add forgotten alpha setter for setup_texenv_output --- xbox/xbox.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/xbox/xbox.c b/xbox/xbox.c index e271adea8..31efb5e3c 100644 --- a/xbox/xbox.c +++ b/xbox/xbox.c @@ -679,14 +679,23 @@ static Texture* get_bound_texture(GLuint stage) { static uint32_t* setup_texenv_output(uint32_t* p, TexEnv* t, unsigned int texture, unsigned int stage, bool rgb, bool ab, bool cd, bool sum) { - p = pb_push1(p, NV097_SET_COMBINER_COLOR_OCW + stage * 4, - MASK(NV097_SET_COMBINER_COLOR_OCW_AB_DST, ab ? _RC_SPARE0 : _RC_DISCARD) - | MASK(NV097_SET_COMBINER_COLOR_OCW_CD_DST, cd ? _RC_SPARE0 : _RC_DISCARD) - | MASK(NV097_SET_COMBINER_COLOR_OCW_SUM_DST, sum ? _RC_SPARE0 : _RC_DISCARD) - | MASK(NV097_SET_COMBINER_COLOR_OCW_MUX_ENABLE, 0) - | MASK(NV097_SET_COMBINER_COLOR_OCW_AB_DOT_ENABLE, 0) - | MASK(NV097_SET_COMBINER_COLOR_OCW_CD_DOT_ENABLE, 0) - | MASK(NV097_SET_COMBINER_COLOR_OCW_OP, NV097_SET_COMBINER_COLOR_OCW_OP_NOSHIFT)); + if (rgb) { + p = pb_push1(p, NV097_SET_COMBINER_COLOR_OCW + stage * 4, + MASK(NV097_SET_COMBINER_COLOR_OCW_AB_DST, ab ? _RC_SPARE0 : _RC_DISCARD) + | MASK(NV097_SET_COMBINER_COLOR_OCW_CD_DST, cd ? _RC_SPARE0 : _RC_DISCARD) + | MASK(NV097_SET_COMBINER_COLOR_OCW_SUM_DST, sum ? _RC_SPARE0 : _RC_DISCARD) + | MASK(NV097_SET_COMBINER_COLOR_OCW_MUX_ENABLE, 0) + | MASK(NV097_SET_COMBINER_COLOR_OCW_AB_DOT_ENABLE, 0) + | MASK(NV097_SET_COMBINER_COLOR_OCW_CD_DOT_ENABLE, 0) + | MASK(NV097_SET_COMBINER_COLOR_OCW_OP, NV097_SET_COMBINER_COLOR_OCW_OP_NOSHIFT)); + } else { + p = pb_push1(p, NV097_SET_COMBINER_ALPHA_OCW + stage * 4, + MASK(NV097_SET_COMBINER_ALPHA_OCW_AB_DST, ab ? _RC_SPARE0 : _RC_DISCARD) + | MASK(NV097_SET_COMBINER_ALPHA_OCW_CD_DST, cd ? _RC_SPARE0 : _RC_DISCARD) + | MASK(NV097_SET_COMBINER_ALPHA_OCW_SUM_DST, sum ? _RC_SPARE0 : _RC_DISCARD) + | MASK(NV097_SET_COMBINER_ALPHA_OCW_MUX_ENABLE, 0) + | MASK(NV097_SET_COMBINER_ALPHA_OCW_OP, NV097_SET_COMBINER_ALPHA_OCW_OP_NOSHIFT)); + } return p; }