diff --git a/.gitignore b/.gitignore index b3401fa0..740e98c6 100644 --- a/.gitignore +++ b/.gitignore @@ -25,5 +25,5 @@ TDR/* xmplayer/* game_rebuild/* src_rebuild/dependencies/* -src_rebuild/EMULATOR/* +# src_rebuild/EMULATOR/* src_rebuild/.vs/* \ No newline at end of file diff --git a/src_rebuild/EMULATOR/ABS.C b/src_rebuild/EMULATOR/ABS.C new file mode 100644 index 00000000..d31734a0 --- /dev/null +++ b/src_rebuild/EMULATOR/ABS.C @@ -0,0 +1,7 @@ +#include "ABS.H" + +/*int abs(int input) +{ + UNIMPLEMENTED(); + return 0; +}*/ diff --git a/src_rebuild/EMULATOR/ABS.H b/src_rebuild/EMULATOR/ABS.H new file mode 100644 index 00000000..62ed1458 --- /dev/null +++ b/src_rebuild/EMULATOR/ABS.H @@ -0,0 +1,10 @@ +/*#ifndef ABS_H +#define ABS_H + +#ifndef ABS +#define ABS(x) (((x)>=0)?(x):(-(x))) +#endif + +//extern int abs(int input); + +#endif*/ \ No newline at end of file diff --git a/src_rebuild/EMULATOR/ASM.H b/src_rebuild/EMULATOR/ASM.H new file mode 100644 index 00000000..66fec5a0 --- /dev/null +++ b/src_rebuild/EMULATOR/ASM.H @@ -0,0 +1,150 @@ +#ifndef ASM_H +#define ASM_H + +#define R0 $0 +#define R1 $1 +#define R2 $2 +#define R3 $3 +#define R4 $4 +#define R5 $5 +#define R6 $6 +#define R7 $7 +#define R8 $8 +#define R9 $9 +#define R10 $10 +#define R11 $11 +#define R12 $12 +#define R13 $13 +#define R14 $14 +#define R15 $15 +#define R16 $16 +#define R17 $17 +#define R18 $18 +#define R19 $19 +#define R20 $20 +#define R21 $21 +#define R22 $22 +#define R23 $23 +#define R24 $24 +#define R25 $25 +#define R26 $26 +#define R27 $27 +#define R28 $28 +#define R29 $29 +#define R30 $30 +#define R31 $31 + +#if defined(_LANGUAGE_C)||defined(LANGUAGE_C)||defined(_LANGUAGE_C_PLUS_PLUS)||defined(__cplusplus)||defined(c_plusplus) +#else +#define zero $0 /* wired zero */ +#define AT $1 /* assembler temp */ +#define v0 $2 /* return value */ +#define v1 $3 +#define a0 $4 /* argument registers */ +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 /* caller saved */ +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define s0 $16 /* callee saved */ +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 /* code generator */ +#define t9 $25 +#define k0 $26 /* kernel temporary */ +#define k1 $27 +#define gp $28 /* global pointer */ +#define sp $29 /* stack pointer */ +#define fp $30 /* frame pointer */ +#define ra $31 /* return address */ +#endif + + +/* register offset */ +#define R_R0 0 +#define R_R1 1 +#define R_R2 2 +#define R_R3 3 +#define R_R4 4 +#define R_R5 5 +#define R_R6 6 +#define R_R7 7 +#define R_R8 8 +#define R_R9 9 +#define R_R10 10 +#define R_R11 11 +#define R_R12 12 +#define R_R13 13 +#define R_R14 14 +#define R_R15 15 +#define R_R16 16 +#define R_R17 17 +#define R_R18 18 +#define R_R19 19 +#define R_R20 20 +#define R_R21 21 +#define R_R22 22 +#define R_R23 23 +#define R_R24 24 +#define R_R25 25 +#define R_R26 26 +#define R_R27 27 +#define R_R28 28 +#define R_R29 29 +#define R_R30 30 +#define R_R31 31 +#define R_EPC 32 +#define R_MDHI 33 +#define R_MDLO 34 +#define R_SR 35 +#define R_CAUSE 36 +#define NREGS 40 + +/* + * compiler defined bindings + */ +#define R_ZERO R_R0 +#define R_AT R_R1 +#define R_V0 R_R2 +#define R_V1 R_R3 +#define R_A0 R_R4 +#define R_A1 R_R5 +#define R_A2 R_R6 +#define R_A3 R_R7 +#define R_T0 R_R8 +#define R_T1 R_R9 +#define R_T2 R_R10 +#define R_T3 R_R11 +#define R_T4 R_R12 +#define R_T5 R_R13 +#define R_T6 R_R14 +#define R_T7 R_R15 +#define R_S0 R_R16 +#define R_S1 R_R17 +#define R_S2 R_R18 +#define R_S3 R_R19 +#define R_S4 R_R20 +#define R_S5 R_R21 +#define R_S6 R_R22 +#define R_S7 R_R23 +#define R_T8 R_R24 +#define R_T9 R_R25 +#define R_K0 R_R26 +#define R_K1 R_R27 +#define R_GP R_R28 +#define R_SP R_R29 +#define R_FP R_R30 +#define R_RA R_R31 + +#endif diff --git a/src_rebuild/EMULATOR/CMakeLists.txt b/src_rebuild/EMULATOR/CMakeLists.txt new file mode 100644 index 00000000..ad2a64f6 --- /dev/null +++ b/src_rebuild/EMULATOR/CMakeLists.txt @@ -0,0 +1,48 @@ +cmake_minimum_required (VERSION 3.0) + +project (Emulator_${TARGET_ARCH}) + +set(OPT_DEFINITIONS "") + +#Extract current source folder name. +get_filename_component(PLATFORM_SPECIFIC_FOLDER_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) + +#Enable NTSC mode +OPTIONAL_DEFINE(NTSC_VERSION "Enable/Disable NTSC Mode" ON) + +#Enable 32-bit address for tag +OPTIONAL_DEFINE(USE_32_BIT_ADDR "Enable/Disable 32-bit address for tag" ON) + +#Setup platform specific / game code include folder +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +#Recursively locate the source files for SPEC_PSX. +file(GLOB_RECURSE EMULATOR_SPECIFIC_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/*.C ${CMAKE_CURRENT_SOURCE_DIR}/*.S ${CMAKE_CURRENT_SOURCE_DIR}/*.H ${CMAKE_CURRENT_SOURCE_DIR}/*.CUR ${CMAKE_CURRENT_SOURCE_DIR}/*.RC) + +#Group solution source files to correct folders. +source_group(${PLATFORM_SPECIFIC_FOLDER_NAME} FILES ${EMULATOR_SPECIFIC_SRCS}) + +if(NOT ANDROID) +add_library( +${PROJECT_NAME} +STATIC +${EMULATOR_SPECIFIC_SRCS} +) +endif() + +#Include all platform specific cmake files. +include("PLATFORM/Windows.cmake") +include("PLATFORM/Mingw.cmake") +include("PLATFORM/Linux.cmake") +include("PLATFORM/Emscripten.cmake") +include("PLATFORM/Android.cmake") + +if (NOT ANDROID) +BuildPreProcessorDefinitions() +target_compile_definitions(${PROJECT_NAME} PRIVATE GLEW_STATIC) + +set_target_properties( +${PROJECT_NAME} PROPERTIES OUTPUT_NAME "PSX" +${PROJECT_NAME} PROPERTIES FOLDER "Libs" +) +endif() diff --git a/src_rebuild/EMULATOR/CRASHHANDLER.C b/src_rebuild/EMULATOR/CRASHHANDLER.C new file mode 100644 index 00000000..3bb4605c --- /dev/null +++ b/src_rebuild/EMULATOR/CRASHHANDLER.C @@ -0,0 +1,30 @@ +#ifdef _WINDOWS + +#include +#include +#include + +typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); + +void CreateMiniDump(struct _EXCEPTION_POINTERS* exceptionInfo) +{ + HMODULE mhLib = LoadLibrary(_T("dbghelp.dll")); + MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress(mhLib, "MiniDumpWriteDump"); + HANDLE hFile = CreateFile(_T("CORE.DMP"), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + _MINIDUMP_EXCEPTION_INFORMATION ExInfo; + ExInfo.ThreadId = GetCurrentThreadId(); + ExInfo.ExceptionPointers = exceptionInfo; + ExInfo.ClientPointers = FALSE; + + pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL); + CloseHandle(hFile); +} + +LONG WINAPI unhandled_handler(struct _EXCEPTION_POINTERS* exceptionInfo) +{ + CreateMiniDump(exceptionInfo); + return EXCEPTION_CONTINUE_SEARCH; +} + +#endif \ No newline at end of file diff --git a/src_rebuild/EMULATOR/CRASHHANDLER.H b/src_rebuild/EMULATOR/CRASHHANDLER.H new file mode 100644 index 00000000..b0e97601 --- /dev/null +++ b/src_rebuild/EMULATOR/CRASHHANDLER.H @@ -0,0 +1,12 @@ +#ifndef CRASHHANDLER_H +#define CRASHHANDLER_H + +#if defined (_WINDOWS) +#include +#include +#include + +LONG WINAPI unhandled_handler(struct _EXCEPTION_POINTERS* apExceptionInfo); +#endif + +#endif \ No newline at end of file diff --git a/src_rebuild/EMULATOR/EMULATOR.C b/src_rebuild/EMULATOR/EMULATOR.C new file mode 100644 index 00000000..de083e04 --- /dev/null +++ b/src_rebuild/EMULATOR/EMULATOR.C @@ -0,0 +1,3163 @@ +#include "EMULATOR.H" + +#include "EMULATOR_VERSION.H" +#include "EMULATOR_GLOBALS.H" +#include "EMULATOR_PRIVATE.H" +#include "CRASHHANDLER.H" + +#include "EMULATOR_PLATFORM_SETUP.H" + +#include "LIBGPU.H" +#include "LIBETC.H" +#include "LIBPAD.H" + +//#include +//#include +#if !defined(__ANDROID__) +//#include +#endif +#include + +#define VERTEX_COLOUR_MULT (2) + +#if defined(NTSC_VERSION) +#define COUNTER_UPDATE_INTERVAL (263) +#else +#define COUNTER_UPDATE_INTERVAL (313) +#endif + +#include +#include +#include + +SDL_Window* g_window = NULL; + +#if defined(OGL) || defined(OGLES) +GLuint vramTexture; +GLuint vramFrameBuffer = 0; +GLuint vramRenderBuffer = 0; +GLuint nullWhiteTexture; +GLint g_defaultFBO; + +#elif defined(VK) + +struct FrameBuffer vramFrameBuffer; + +#define MAX_NUM_PHYSICAL_DEVICES (4) + +VkWin32SurfaceCreateInfoKHR surfaceCreateInfo = +{ + VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR +}; + +VkSurfaceKHR surface = VK_NULL_HANDLE; +VkInstance instance = VK_NULL_HANDLE; +VkPhysicalDeviceMemoryProperties deviceMemoryProperties; + +const char* enabledExtensionsDeviceCreateInfo[] = +{ + VK_KHR_SWAPCHAIN_EXTENSION_NAME +}; + +enum +{ + MAX_DEVICE_COUNT = 8, + MAX_QUEUE_COUNT = 4, + MAX_PRESENT_MODE_COUNT = 6, + MAX_SWAPCHAIN_IMAGES = 3, + FRAME_COUNT = 2, + PRESENT_MODE_MAILBOX_IMAGE_COUNT = 3, + PRESENT_MODE_DEFAULT_IMAGE_COUNT = 2, +}; + +VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; +uint32_t queueFamilyIndex; +VkQueue queue; +VkDevice device = VK_NULL_HANDLE; + +unsigned int vramTexture;///@TODO trim me +unsigned int vramRenderBuffer = 0; +unsigned int nullWhiteTexture; +int g_defaultFBO; + +const char* enabledExtensions[] = +{ + VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME +}; + +VkSwapchainKHR swapchain; +unsigned int swapchainImageCount; +VkImage swapchainImages[MAX_SWAPCHAIN_IMAGES]; +VkExtent2D swapchainExtent; +VkSurfaceFormatKHR surfaceFormat; +unsigned int frameIndex = 0; +VkCommandPool commandPool; +VkCommandBuffer commandBuffers[FRAME_COUNT]; +VkFence frameFences[FRAME_COUNT]; // Create with VK_FENCE_CREATE_SIGNALED_BIT. +VkSemaphore imageAvailableSemaphores[FRAME_COUNT]; +VkSemaphore renderFinishedSemaphores[FRAME_COUNT]; +#elif defined (D3D9) +SDL_Renderer* g_renderer; +IDirect3DDevice9* d3ddev; +IDirect3DTexture9* vramTexture = NULL; +IDirect3DSurface9* vramFrameBuffer = NULL; +IDirect3DVertexDeclaration9* g_vertexDecl = NULL; +unsigned int vramRenderBuffer = 0;///@FIXME delete unused? +IDirect3DTexture9* nullWhiteTexture = NULL; +IDirect3DSurface9* g_defaultFBO = NULL; +IDirect3DPixelShader9* g_defaultPixelShader = NULL; +IDirect3DVertexShader9* g_defaultVertexShader = NULL; +#else +unsigned int vramTexture; +unsigned int vramFrameBuffer = 0; +unsigned int vramRenderBuffer = 0; +unsigned int nullWhiteTexture; +int g_defaultFBO; +#endif + +int screenWidth = 0; +int screenHeight = 0; +int windowWidth = 0; +int windowHeight = 0; +char* pVirtualMemory = NULL; +SysCounter counters[3] = { 0 }; +#if !defined(__ANDROID__) +//std::thread counter_thread; +#endif +int g_hasHintedTextureAtlas = 0; +struct CachedTexture cachedTextures[MAX_NUM_CACHED_TEXTURES]; + +#if defined(D3D9) +static int Emulator_InitialiseD3D9Context(char* windowName) +{ + g_window = SDL_CreateWindow(windowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, 0); + if (g_window == NULL) + { + eprinterr("Failed to initialise SDL window!\n"); + return FALSE; + } + + g_renderer = SDL_CreateRenderer(g_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if (g_renderer == NULL) + { + eprinterr("Failed to initialise SDL renderer!\n"); + return FALSE; + } + + d3ddev = SDL_RenderGetD3D9Device(g_renderer); + if (g_renderer == NULL) + { + eprinterr("Failed to obtain D3D9 devicer!\n"); + return FALSE; + } + + return TRUE; +} +#endif + +#if defined(VK) +static int Emulator_InitialiseVKContext(char* windowName) +{ + VkApplicationInfo appInfo; + memset(&appInfo, 0, sizeof(VkApplicationInfo)); + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = windowName; + appInfo.applicationVersion = VK_MAKE_VERSION(EMULATOR_MAJOR_VERSION, EMULATOR_MINOR_VERSION, 0); + appInfo.pEngineName = EMULATOR_NAME; + appInfo.engineVersion = VK_MAKE_VERSION(EMULATOR_MAJOR_VERSION, EMULATOR_MINOR_VERSION, 0); + appInfo.apiVersion = VK_API_VERSION_1_0; + + VkInstanceCreateInfo createInfo; + memset(&createInfo, 0, sizeof(VkInstanceCreateInfo)); + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &appInfo; + createInfo.enabledExtensionCount = 2; + createInfo.ppEnabledExtensionNames = enabledExtensions; + createInfo.pNext = VK_NULL_HANDLE; + + //Create Vulkan Instance + if (vkCreateInstance(&createInfo, NULL, &instance) != VK_SUCCESS) + { + eprinterr("Failed to create Vulkan instance!"); + return FALSE; + } + + g_window = SDL_CreateWindow(windowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, SDL_WINDOW_VULKAN); + +#if defined(OGL) + SDL_GL_CreateContext(g_window); +#endif + + if (g_window == NULL) + { + eprinterr("Failed to initialise Vulkan context!\n"); + return FALSE; + } + + SDL_SysWMinfo sysInfo; + SDL_VERSION(&sysInfo.version); + SDL_GetWindowWMInfo(g_window, &sysInfo); + surfaceCreateInfo.hinstance = GetModuleHandle(0); + surfaceCreateInfo.hwnd = sysInfo.info.win.window; + + if (vkCreateWin32SurfaceKHR(instance, &surfaceCreateInfo, NULL, &surface) != VK_SUCCESS) + { + eprinterr("Failed to initialise Vulkan surface!\n"); + return FALSE; + } + + unsigned int physicalDeviceCount; + VkPhysicalDevice deviceHandles[MAX_DEVICE_COUNT]; + VkQueueFamilyProperties queueFamilyProperties[MAX_QUEUE_COUNT]; + VkPhysicalDeviceProperties deviceProperties; + VkPhysicalDeviceFeatures deviceFeatures; + + + vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, 0); + physicalDeviceCount = physicalDeviceCount > MAX_DEVICE_COUNT ? MAX_DEVICE_COUNT : physicalDeviceCount; + vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, deviceHandles); + + for (unsigned int i = 0; i < physicalDeviceCount; ++i)//Maybe 0 needs to be 1 + { + unsigned int queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties(deviceHandles[i], &queueFamilyCount, NULL); + queueFamilyCount = queueFamilyCount > MAX_QUEUE_COUNT ? MAX_QUEUE_COUNT : queueFamilyCount; + vkGetPhysicalDeviceQueueFamilyProperties(deviceHandles[i], &queueFamilyCount, queueFamilyProperties); + + vkGetPhysicalDeviceProperties(deviceHandles[i], &deviceProperties); + vkGetPhysicalDeviceFeatures(deviceHandles[i], &deviceFeatures); + vkGetPhysicalDeviceMemoryProperties(deviceHandles[i], &deviceMemoryProperties); + for (unsigned int j = 0; j < queueFamilyCount; ++j) { + + VkBool32 supportsPresent = VK_FALSE; + vkGetPhysicalDeviceSurfaceSupportKHR(deviceHandles[i], j, surface, &supportsPresent); + + if (supportsPresent && (queueFamilyProperties[j].queueFlags & VK_QUEUE_GRAPHICS_BIT)) + { + queueFamilyIndex = j; + physicalDevice = deviceHandles[i]; + break; + } + } + + if (physicalDevice) + { + break; + } + } + + VkDeviceCreateInfo deviceCreateInfo; + VkDeviceQueueCreateInfo deviceQueueCreateInfo; + memset(&deviceCreateInfo, 0, sizeof(VkDeviceCreateInfo)); + memset(&deviceQueueCreateInfo, 0, sizeof(VkDeviceQueueCreateInfo)); + + const float queuePriorities = { 1.0f }; + + deviceQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + deviceQueueCreateInfo.queueFamilyIndex = queueFamilyIndex; + deviceQueueCreateInfo.queueCount = 1; + deviceQueueCreateInfo.pQueuePriorities = &queuePriorities; + + deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + deviceCreateInfo.queueCreateInfoCount = 1; + deviceCreateInfo.pQueueCreateInfos = 0; + deviceCreateInfo.enabledLayerCount = 0; + deviceCreateInfo.ppEnabledLayerNames = 0; + deviceCreateInfo.enabledExtensionCount = 1; + deviceCreateInfo.ppEnabledExtensionNames = enabledExtensionsDeviceCreateInfo; + deviceCreateInfo.pEnabledFeatures = 0; + deviceCreateInfo.pQueueCreateInfos = &deviceQueueCreateInfo; + + if (vkCreateDevice(physicalDevice, &deviceCreateInfo, NULL, &device) != VK_SUCCESS) + { + eprinterr("Failed to create VK device!\n"); + return FALSE; + } + + vkGetDeviceQueue(device, queueFamilyIndex, 0, &queue); + + /* Initialise SwapChain */ + unsigned int formatCount = 1; + vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, 0); + vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, &surfaceFormat); + surfaceFormat.format = surfaceFormat.format == VK_FORMAT_UNDEFINED ? VK_FORMAT_B8G8R8A8_UNORM : surfaceFormat.format; + + unsigned int presentModeCount = 0; + vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, NULL); + VkPresentModeKHR presentModes[MAX_PRESENT_MODE_COUNT]; + presentModeCount = presentModeCount > MAX_PRESENT_MODE_COUNT ? MAX_PRESENT_MODE_COUNT : presentModeCount; + vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, presentModes); + + VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; + for (unsigned int i = 0; i < presentModeCount; ++i) + { + if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) + { + presentMode = VK_PRESENT_MODE_MAILBOX_KHR; + break; + } + } + swapchainImageCount = presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? PRESENT_MODE_MAILBOX_IMAGE_COUNT : PRESENT_MODE_DEFAULT_IMAGE_COUNT; + + VkSurfaceCapabilitiesKHR surfaceCapabilities; + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfaceCapabilities); + + swapchainExtent = surfaceCapabilities.currentExtent; + //if (swapchainExtent.width == UINT32_MAX) + //{ + // swapchainExtent.width = clamp_u32(width, surfaceCapabilities.minImageExtent.width, surfaceCapabilities.maxImageExtent.width); + // swapchainExtent.height = clamp_u32(height, surfaceCapabilities.minImageExtent.height, surfaceCapabilities.maxImageExtent.height); + //} + + VkSwapchainCreateInfoKHR swapChainCreateInfo; + memset(&swapChainCreateInfo, 0, sizeof(VkSwapchainCreateInfoKHR)); + swapChainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + swapChainCreateInfo.surface = surface; + swapChainCreateInfo.minImageCount = swapchainImageCount; + swapChainCreateInfo.imageFormat = surfaceFormat.format; + swapChainCreateInfo.imageColorSpace = surfaceFormat.colorSpace; + swapChainCreateInfo.imageExtent = swapchainExtent; + swapChainCreateInfo.imageArrayLayers = 1; // 2 for stereo + swapChainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapChainCreateInfo.preTransform = surfaceCapabilities.currentTransform; + swapChainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + swapChainCreateInfo.presentMode = presentMode; + swapChainCreateInfo.clipped = VK_TRUE; + + if (vkCreateSwapchainKHR(device, &swapChainCreateInfo, 0, &swapchain) != VK_SUCCESS) + { + eprinterr("Failed to create swap chain!\n"); + return FALSE; + } + + vkGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, NULL); + vkGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, swapchainImages); + + + VkCommandPoolCreateInfo commandPoolCreateInfo; + memset(&commandPoolCreateInfo, 0, sizeof(VkCommandPoolCreateInfo)); + commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex; + + vkCreateCommandPool(device, &commandPoolCreateInfo, 0, &commandPool); + + VkCommandBufferAllocateInfo commandBufferAllocInfo; + memset(&commandBufferAllocInfo, 0, sizeof(VkCommandBufferAllocateInfo)); + + commandBufferAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + commandBufferAllocInfo.commandPool = commandPool; + commandBufferAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + commandBufferAllocInfo.commandBufferCount = FRAME_COUNT; + + vkAllocateCommandBuffers(device, &commandBufferAllocInfo, commandBuffers); + + VkSemaphoreCreateInfo semaphoreCreateInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; + + vkCreateSemaphore(device, &semaphoreCreateInfo, 0, &imageAvailableSemaphores[0]); + vkCreateSemaphore(device, &semaphoreCreateInfo, 0, &imageAvailableSemaphores[1]); + vkCreateSemaphore(device, &semaphoreCreateInfo, 0, &renderFinishedSemaphores[0]); + vkCreateSemaphore(device, &semaphoreCreateInfo, 0, &renderFinishedSemaphores[1]); + + VkFenceCreateInfo fenceCreateInfo; + memset(&fenceCreateInfo, 0, sizeof(VkFenceCreateInfo)); + fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; + + vkCreateFence(device, &fenceCreateInfo, 0, &frameFences[0]); + vkCreateFence(device, &fenceCreateInfo, 0, &frameFences[1]); + + uint32_t index = (frameIndex++) % FRAME_COUNT; + vkWaitForFences(device, 1, &frameFences[index], VK_TRUE, UINT64_MAX); + vkResetFences(device, 1, &frameFences[index]); + + uint32_t imageIndex; + vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, imageAvailableSemaphores[index], VK_NULL_HANDLE, &imageIndex); + + VkCommandBufferBeginInfo beginInfo; + memset(&beginInfo, 0, sizeof(VkCommandBufferBeginInfo)); + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + vkBeginCommandBuffer(commandBuffers[index], &beginInfo); + + vkEndCommandBuffer(commandBuffers[index]); + + VkSubmitInfo submitInfo; + memset(&submitInfo, 0, sizeof(VkSubmitInfo)); + VkPipelineStageFlags writeDestStageMask = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; + + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.waitSemaphoreCount = 1; + submitInfo.pWaitSemaphores = &imageAvailableSemaphores[index]; + submitInfo.pWaitDstStageMask = &writeDestStageMask; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffers[index]; + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = &renderFinishedSemaphores[index]; + vkQueueSubmit(queue, 1, &submitInfo, frameFences[index]); + + VkPresentInfoKHR presentInfo; + memset(&presentInfo, 0, sizeof(VkPresentInfoKHR)); + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.waitSemaphoreCount = 1; + presentInfo.pWaitSemaphores = &renderFinishedSemaphores[index]; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &swapchain; + presentInfo.pImageIndices = &imageIndex; + + vkQueuePresentKHR(queue, &presentInfo); + + return TRUE; +} +#endif + +static int Emulator_InitialiseGLContext(char* windowName) +{ + g_window = SDL_CreateWindow(windowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, SDL_WINDOW_OPENGL); + +#if defined(OGL) + SDL_GL_CreateContext(g_window); +#endif + + if (g_window == NULL) + { + eprinterr("Failed to initialise SDL window or GL context!\n"); + return FALSE; + } + + return TRUE; +} + +#if defined(OGLES) +EGLint majorVersion = 0, minorVersion = 0; +EGLContext eglContext = NULL; +EGLSurface eglSurface = NULL; +EGLConfig eglConfig = NULL; +EGLDisplay eglDisplay = NULL; +int numConfigs = 0; + +const EGLint config16bpp[] = +{ +#if OGLES_VERSION == 2 + EGL_RENDERABLE_TYPE,EGL_OPENGL_ES2_BIT, +#elif OGLES_VERSION == 3 + EGL_RENDERABLE_TYPE,EGL_OPENGL_ES3_BIT, +#endif + EGL_BUFFER_SIZE,24, + EGL_RED_SIZE,8, + EGL_GREEN_SIZE,8, + EGL_BLUE_SIZE,8, + EGL_ALPHA_SIZE,0, + EGL_DEPTH_SIZE,24, + EGL_STENCIL_SIZE,0, + EGL_SAMPLE_BUFFERS,1, + EGL_SAMPLES,4, + EGL_NONE +}; + +static int Emulator_InitialiseGLESContext(char* windowName) +{ + unsigned int windowFlags = SDL_WINDOW_OPENGL; + +#if defined(__ANDROID__) + windowFlags |= SDL_WINDOW_FULLSCREEN; +#endif + + eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + g_window = SDL_CreateWindow(windowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, windowFlags); + + if(g_window == NULL) + { + eprinterr("Failed to create SDL window!\n"); + } + + if (!eglInitialize(eglDisplay, &majorVersion, &minorVersion)) + { + eprinterr("eglInitialize failure! Error: %x\n", eglGetError()); + return FALSE; + } + + eglBindAPI(EGL_OPENGL_ES_API); + + if (!eglChooseConfig(eglDisplay, config16bpp, &eglConfig, 1, &numConfigs)) + { + printf("eglChooseConfig failed\n"); + if (eglContext == 0) + { + printf("Error code: %d\n", eglGetError()); + } + } + + SDL_SysWMinfo systemInfo; + SDL_VERSION(&systemInfo.version); + SDL_GetWindowWMInfo(g_window, &systemInfo); +#if defined(__EMSCRIPTEN__) + EGLNativeWindowType dummyWindow; + eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, (EGLNativeWindowType)dummyWindow, NULL); +#elif defined(__ANDROID__) + eglSurface = systemInfo.info.android.surface; +#else + eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, (EGLNativeWindowType)systemInfo.info.win.window, NULL); +#endif + if (eglSurface == EGL_NO_SURFACE) + { + eprinterr("eglSurface failure! Error: %x\n", eglGetError()); + return FALSE; + } + + EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, OGLES_VERSION, EGL_NONE }; + eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, contextAttribs); + + if (eglContext == EGL_NO_CONTEXT) { + eprinterr("eglContext failure! Error: %x\n", eglGetError()); + return FALSE; + } + + eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); + + return TRUE; +} + +#endif + +static int Emulator_InitialiseSDL(char* windowName, int screenWidth, int screenHeight) +{ + screenWidth = screenWidth; + screenHeight = screenHeight; + windowWidth = screenWidth; + windowHeight = screenHeight; + + //Initialise SDL2 + if (SDL_Init(SDL_INIT_VIDEO) == 0) + { +#if !defined(RO_DOUBLE_BUFFERED) + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0); +#endif + +#if defined(OGLES) + +#if defined(__ANDROID__) + //Override to full screen. + SDL_DisplayMode displayMode; + if(SDL_GetCurrentDisplayMode(0, &displayMode) == 0) + { + screenWidth = displayMode.w; + windowWidth = displayMode.w; + screenHeight = displayMode.h; + windowHeight = displayMode.h; + } +#endif + //SDL_GL_SetAttribute(SDL_GL_CONTEXT_EGL, 1); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, OGLES_VERSION); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); +#elif defined(OGL) + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); +#endif + } + else + { + eprinterr("Error: Failed to initialise SDL\n"); + return FALSE; + } + +#if defined(OGL) + if (Emulator_InitialiseGLContext(windowName) == FALSE) + { + eprinterr("Failed to Initialise GL Context!\n"); + return FALSE; + } +#elif defined(OGLES) + if (Emulator_InitialiseGLESContext(windowName) == FALSE) + { + eprinterr("Failed to Initialise GLES Context!\n"); + return FALSE; + } +#elif defined(VK) + if (Emulator_InitialiseVKContext(windowName) == FALSE) + { + eprinterr("Failed to Initialise VK Context!\n"); + return FALSE; + } +#elif defined(D3D9) + if (Emulator_InitialiseD3D9Context(windowName) == FALSE) + { + eprinterr("Failed to Initialise D3D9 Context!\n"); + return FALSE; + } +#endif + +#if defined(OGL) + SDL_GL_SetSwapInterval(1); +#elif defined(OGLES) + eglSwapInterval(eglDisplay, 1); +#endif + + return TRUE; +} + +static int Emulator_InitialiseGLEW() +{ +#if defined(GLEW) + glewExperimental = GL_TRUE; + + GLenum err = glewInit(); + + if (err != GLEW_OK) + { + return FALSE; + } +#endif + return TRUE; +} + +static int Emulator_InitialiseCore() +{ + //Initialise texture cache +#if defined(OGL) || defined(OGLES) + SDL_memset(&cachedTextures[0], -1, MAX_NUM_CACHED_TEXTURES * sizeof(struct CachedTexture)); +#elif defined(D3D9) + SDL_memset(&cachedTextures[0], 0, MAX_NUM_CACHED_TEXTURES * sizeof(struct CachedTexture)); +#endif + return TRUE; +} + +void Emulator_Initialise(char* windowName, int screenWidth, int screenHeight) +{ + eprintf("Initialising Emulator.\n"); + eprintf("VERSION: %d.%d\n", EMULATOR_MAJOR_VERSION, EMULATOR_MINOR_VERSION); + eprintf("Compile Date: %s Time: %s\n", EMULATOR_COMPILE_DATE, EMULATOR_COMPILE_TIME); + + if (Emulator_InitialiseSDL(windowName, screenWidth, screenHeight) == FALSE) + { + eprinterr("Failed to Intialise SDL\n"); + Emulator_ShutDown(); + } + +#if defined(GLEW) + if (Emulator_InitialiseGLEW() == FALSE) + { + eprinterr("Failed to Intialise GLEW\n"); + Emulator_ShutDown(); + } +#endif + + if (Emulator_InitialiseCore() == FALSE) + { + eprinterr("Failed to Intialise Emulator Core.\n"); + Emulator_ShutDown(); + } + +#if defined(OGL) || defined(OGLES) + if (Emulator_InitialiseGL() == FALSE) + { + eprinterr("Failed to Intialise GL.\n"); + Emulator_ShutDown(); + } +#elif defined(D3D9) + if (Emulator_InitialiseD3D() == FALSE) + { + eprinterr("Failed to Intialise D3D.\n"); + Emulator_ShutDown(); + } +#endif + + //counter_thread = std::thread(Emulator_CounterLoop); +} + +void Emulator_CounterLoop() +{ + static int numUpdates = 0; + int last_time = 0; + + while (TRUE) + { + int now = SDL_GetTicks(); + + if (now > last_time + 1000) + { + numUpdates = 0; + last_time = now; + } + + if (numUpdates++ <= 60) + { + for (int i = 0; i < 3; i++) + { + //if (!counters[i].IsStopped) + { + counters[i].cycle += COUNTER_UPDATE_INTERVAL; + if (counters[i].target > 0) + { + counters[i].cycle %= counters[i].target; + } + } + } + } + } +} + +void Emulator_GenerateLineArray(struct Vertex* vertex, short* p0, short* p1, short* p2, short* p3) +{ + //Copy over position + if (p0 != NULL) + { + vertex[0].x = (float)p0[0]; + vertex[0].y = (float)p0[1]; + } + + if (p1 != NULL) + { + vertex[1].x = (float)p1[0]; + vertex[1].y = (float)p1[1]; + } +} + +void Emulator_GenerateVertexArrayQuad(struct Vertex* vertex, short* p0, short* p1, short* p2, short* p3, short w, short h) +{ +#if defined(PGXP) + PGXPVertex* pgxp_vertex_0 = NULL; + PGXPVertex* pgxp_vertex_1 = NULL; + PGXPVertex* pgxp_vertex_2 = NULL; + PGXPVertex* pgxp_vertex_3 = NULL; + + //Locate each vertex based on SXY2 (very slow) + for (int i = 0; i < pgxp_vertex_index; i++) + { + if (p0 != NULL) + { + if (((unsigned int*)p0)[0] == pgxp_vertex_buffer[i].originalSXY2) + { + pgxp_vertex_0 = &pgxp_vertex_buffer[i]; + continue; + } + } + + if (p1 != NULL) + { + if (((unsigned int*)p1)[0] == pgxp_vertex_buffer[i].originalSXY2) + { + pgxp_vertex_1 = &pgxp_vertex_buffer[i]; + continue; + } + } + + if (p2 != NULL) + { + if (((unsigned int*)p2)[0] == pgxp_vertex_buffer[i].originalSXY2) + { + pgxp_vertex_2 = &pgxp_vertex_buffer[i]; + continue; + } + } + + if (p3 != NULL) + { + if (((unsigned int*)p3)[0] == pgxp_vertex_buffer[i].originalSXY2) + { + pgxp_vertex_3 = &pgxp_vertex_buffer[i]; + continue; + } + } + } +#endif + + //Copy over position + if (p0 != NULL) + { +#if defined(PGXP) + if (pgxp_vertex_0 != NULL) + { + vertex[0].x = pgxp_vertex_0->x; + vertex[0].y = pgxp_vertex_0->y; + } + else + { + vertex[0].x = (float)p0[0]; + vertex[0].y = (float)p0[1]; + } +#else + vertex[0].x = (float)p0[0]; + vertex[0].y = (float)p0[1]; +#endif + } + + if (p1 != NULL) + { +#if defined(PGXP) + if (pgxp_vertex_1 != NULL) + { + vertex[1].x = pgxp_vertex_1->x; + vertex[1].y = pgxp_vertex_1->y; + } + else + { + vertex[1].x = (float)p1[0]; + vertex[1].y = (float)p1[1]; + } +#else + vertex[1].x = (float)p1[0]; + vertex[1].y = (float)p1[1]; +#endif + } + else + { + if (p0 != NULL && w != -1 && h != -1) + { + vertex[1].x = (float)p0[0]; + vertex[1].y = (float)p0[1] + h; + } + } + + if (p2 != NULL) + { +#if defined(PGXP) + if (pgxp_vertex_2 != NULL) + { + vertex[2].x = pgxp_vertex_2->x; + vertex[2].y = pgxp_vertex_2->y; + } + else + { + vertex[2].x = (float)p2[0]; + vertex[2].y = (float)p2[1]; + } +#else + vertex[2].x = (float)p2[0]; + vertex[2].y = (float)p2[1]; +#endif + } + else + { + if (p0 != NULL && w != -1 && h != -1) + { + vertex[2].x = (float)p0[0] + w; + vertex[2].y = (float)p0[1] + h; + } + } + + if (p3 != NULL) + { +#if defined(PGXP) + if (pgxp_vertex_3 != NULL) + { + vertex[3].x = pgxp_vertex_3->x; + vertex[3].y = pgxp_vertex_3->y; + } + else + { + vertex[3].x = (float)p3[0]; + vertex[3].y = (float)p3[1]; + } +#else + vertex[3].x = (float)p3[0]; + vertex[3].y = (float)p3[1]; +#endif + } + else + { + if (p0 != NULL && w != -1 && h != -1) + { + vertex[3].x = (float)p0[0] + w; + vertex[3].y = (float)p0[1]; + } + } + return; +} + + +void Emulator_GenerateTexcoordArrayQuad(struct Vertex* vertex, unsigned char* uv0, unsigned char* uv1, unsigned char* uv2, unsigned char* uv3, short w, short h) +{ +#if defined(PGXP) && 0 + /* + Locate polygon in ztable + */ + + PGXPPolygon* z0 = NULL; + PGXPPolygon* z1 = NULL; + PGXPPolygon* z2 = NULL; + PGXPPolygon* z3 = NULL; + + //Can speed this up by storing last index found and using as start iter + for (int i = pgxp_polgon_table_index; i > -1; i--) + { + if (uv0 != NULL) + { + if (((unsigned int*)uv0)[0] == pgxp_polygons[i].originalSXY) + { + z0 = &pgxp_polygons[i]; + //z0->bUsed = TRUE; + } + } + + if (uv1 != NULL) + { + if (((unsigned int*)uv1)[0] == pgxp_polygons[i].originalSXY) + { + z1 = &pgxp_polygons[i]; + //z1->bUsed = TRUE; + } + } + + if (uv2 != NULL) + { + if (((unsigned int*)uv2)[0] == pgxp_polygons[i].originalSXY) + { + z2 = &pgxp_polygons[i]; + //z2->bUsed = TRUE; + } + } + + if (uv3 != NULL) + { + if (((unsigned int*)uv3)[0] == pgxp_polygons[i].originalSXY) + { + z3 = &pgxp_polygons[i]; + //z3->bUsed = TRUE; + } + } + + if ((z0 != NULL || uv0 == NULL) && (z1 != NULL || uv1 == NULL) && (z2 != NULL || uv2 == NULL) && (z3 != NULL || uv3 == NULL)) + break; + } + + //Copy over uvs + if (uv0 != NULL) + { + if (z0 != NULL) + { + vertex[0].u0 = z0->x; + vertex[0].v0 = z0->y; + } + else + { + vertex[0].u0 = ((float)uv0[0]) / TPAGE_WIDTH; + vertex[0].v0 = ((float)uv0[1]) / TPAGE_HEIGHT; + } + } + + if (uv1 != NULL) + { + if (z1 != NULL) + { + vertex[1].u0 = z1->x; + vertex[1].v0 = z1->y; + } + else + { + vertex[1].u0 = ((float)uv1[0]) / TPAGE_WIDTH; + vertex[1].v0 = ((float)uv1[1]) / TPAGE_HEIGHT; + } + } + else + { + if (w != -1 && h != -1) + { + vertex[1].u0 = ((float)uv0[0]) / TPAGE_WIDTH; + vertex[1].v0 = ((float)uv0[1] + h) / TPAGE_HEIGHT; + } + } + + if (uv2 != NULL) + { + if (z2 != NULL) + { + vertex[2].u0 = z2->x; + vertex[2].v0 = z2->y; + } + else + { + vertex[2].u0 = ((float)uv2[0]) / TPAGE_WIDTH; + vertex[2].v0 = ((float)uv2[1]) / TPAGE_HEIGHT; + } + } + else + { + if (w != -1 && h != -1) + { + vertex[2].u0 = ((float)uv0[0] + w) / TPAGE_WIDTH; + vertex[2].v0 = ((float)uv0[1] + h) / TPAGE_HEIGHT; + } + } + + if (uv3 != NULL) + { + if (z3 != NULL) + { + vertex[3].u0 = z3->x; + vertex[3].v0 = z3->y; + } + else + { + vertex[3].u0 = ((float)uv3[0]) / TPAGE_WIDTH; + vertex[3].v0 = ((float)uv3[1]) / TPAGE_HEIGHT; + } + } + else + { + if (w != -1 && h != -1) + { + vertex[3].u0 = ((float)uv0[0] + w) / TPAGE_WIDTH; + vertex[3].v0 = ((float)uv0[1]) / TPAGE_HEIGHT; + } + } + +#else + //Copy over uvs + if (uv0 != NULL) + { + vertex[0].u0 = ((float)uv0[0]) / TPAGE_WIDTH; + vertex[0].v0 = ((float)uv0[1]) / TPAGE_HEIGHT; + } + + if (uv1 != NULL) + { + vertex[1].u0 = ((float)uv1[0]) / TPAGE_WIDTH; + vertex[1].v0 = ((float)uv1[1]) / TPAGE_HEIGHT; + } + else + { + if (uv0 != NULL && w != -1 && h != -1) + { + vertex[1].u0 = ((float)uv0[0]) / TPAGE_WIDTH; + vertex[1].v0 = ((float)uv0[1] + h) / TPAGE_HEIGHT; + } + } + + if (uv2 != NULL) + { + vertex[2].u0 = ((float)uv2[0]) / TPAGE_WIDTH; + vertex[2].v0 = ((float)uv2[1]) / TPAGE_HEIGHT; + } + else + { + if (w != -1 && h != -1) + { + vertex[2].u0 = ((float)uv0[0] + w) / TPAGE_WIDTH; + vertex[2].v0 = ((float)uv0[1] + h) / TPAGE_HEIGHT; + } + } + + if (uv3 != NULL) + { + vertex[3].u0 = ((float)uv3[0]) / TPAGE_WIDTH; + vertex[3].v0 = ((float)uv3[1]) / TPAGE_HEIGHT; + } + else + { + if (w != -1 && h != -1) + { + vertex[3].u0 = ((float)uv0[0] + w) / TPAGE_WIDTH; + vertex[3].v0 = ((float)uv0[1]) / TPAGE_HEIGHT; + } + } +#endif + return; +} + +void Emulator_GenerateColourArrayQuad(struct Vertex* vertex, unsigned char* col0, unsigned char* col1, unsigned char* col2, unsigned char* col3, int bMultiplyColour) +{ + //Copy over rgb vertex colours + if (col0 != NULL) + { + if (bMultiplyColour) + { +#if defined(OGL) || defined(OGLES) + vertex[0].col[0] = ((1.0f / 255.0f) * col0[0]) * VERTEX_COLOUR_MULT; + vertex[0].col[1] = ((1.0f / 255.0f) * col0[1]) * VERTEX_COLOUR_MULT; + vertex[0].col[2] = ((1.0f / 255.0f) * col0[2]) * VERTEX_COLOUR_MULT; + vertex[0].col[3] = (1.0f / 255.0f) * 255; +#elif defined(D3D9) + vertex[0].col = D3DCOLOR_RGBA(col0[2], col0[1], col0[0], 255); +#endif + } + else + { +#if defined(OGL) || defined(OGLES) + vertex[0].col[0] = (1.0f / 255.0f) * col0[0]; + vertex[0].col[1] = (1.0f / 255.0f) * col0[1]; + vertex[0].col[2] = (1.0f / 255.0f) * col0[2]; + vertex[0].col[3] = (1.0f / 255.0f) * 255; +#elif defined(D3D9) + vertex[0].col = D3DCOLOR_RGBA(col0[2], col0[1], col0[0], 255); +#endif + } + } + + if (col1 != NULL) + { + if (bMultiplyColour) + { +#if defined(OGL) || defined(OGLES) + vertex[1].col[0] = ((1.0f / 255.0f) * col1[0]) * VERTEX_COLOUR_MULT; + vertex[1].col[1] = ((1.0f / 255.0f) * col1[1]) * VERTEX_COLOUR_MULT; + vertex[1].col[2] = ((1.0f / 255.0f) * col1[2]) * VERTEX_COLOUR_MULT; + vertex[1].col[3] = (1.0f / 255.0f) * 255; +#elif defined(D3D9) + vertex[1].col = D3DCOLOR_RGBA(col1[2], col1[1], col1[0], 255); +#endif + } + else + { +#if defined(OGL) || defined(OGLES) + vertex[1].col[0] = (1.0f / 255.0f) * col1[0]; + vertex[1].col[1] = (1.0f / 255.0f) * col1[1]; + vertex[1].col[2] = (1.0f / 255.0f) * col1[2]; + vertex[1].col[3] = (1.0f / 255.0f) * 255; +#elif defined(D3D9) + vertex[1].col = D3DCOLOR_RGBA(col1[2], col1[1], col1[0], 255); +#endif +} + } + else + { + if (bMultiplyColour) + { +#if defined(OGL) || defined(OGLES) + vertex[1].col[0] = ((1.0f / 255.0f) * col0[0]) * VERTEX_COLOUR_MULT; + vertex[1].col[1] = ((1.0f / 255.0f) * col0[1]) * VERTEX_COLOUR_MULT; + vertex[1].col[2] = ((1.0f / 255.0f) * col0[2]) * VERTEX_COLOUR_MULT; + vertex[1].col[3] = (1.0f / 255.0f) * 255; +#elif defined(D3D9) + vertex[1].col = D3DCOLOR_RGBA(col0[2], col0[1], col0[0], 255); +#endif + } + else + { +#if defined(OGL) || defined(OGLES) + vertex[1].col[0] = (1.0f / 255.0f) * col0[0]; + vertex[1].col[1] = (1.0f / 255.0f) * col0[1]; + vertex[1].col[2] = (1.0f / 255.0f) * col0[2]; + vertex[1].col[3] = (1.0f / 255.0f) * 255; +#elif defined(D3D9) + vertex[1].col = D3DCOLOR_RGBA(col0[2], col0[1], col0[0], 255); +#endif + } + } + + if (col2 != NULL) + { + if (bMultiplyColour) + { +#if defined(OGL) || defined(OGLES) + vertex[2].col[0] = ((1.0f / 255.0f) * col2[0]) * VERTEX_COLOUR_MULT; + vertex[2].col[1] = ((1.0f / 255.0f) * col2[1]) * VERTEX_COLOUR_MULT; + vertex[2].col[2] = ((1.0f / 255.0f) * col2[2]) * VERTEX_COLOUR_MULT; + vertex[2].col[3] = (1.0f / 255.0f) * 255; +#elif defined(D3D9) + vertex[2].col = D3DCOLOR_RGBA(col2[2], col2[1], col2[0], 255); +#endif + } + else + { +#if defined(OGL) || defined(OGLES) + vertex[2].col[0] = (1.0f / 255.0f) * col2[0]; + vertex[2].col[1] = (1.0f / 255.0f) * col2[1]; + vertex[2].col[2] = (1.0f / 255.0f) * col2[2]; + vertex[2].col[3] = (1.0f / 255.0f) * 255; +#elif defined(D3D9) + vertex[2].col = D3DCOLOR_RGBA(col2[2], col2[1], col2[0], 255); +#endif + } + } + else + { + if (bMultiplyColour) + { +#if defined(OGL) || defined(OGLES) + vertex[2].col[0] = ((1.0f / 255.0f) * col0[0]) * VERTEX_COLOUR_MULT; + vertex[2].col[1] = ((1.0f / 255.0f) * col0[1]) * VERTEX_COLOUR_MULT; + vertex[2].col[2] = ((1.0f / 255.0f) * col0[2]) * VERTEX_COLOUR_MULT; + vertex[2].col[3] = (1.0f / 255.0f) * 255; +#elif defined(D3D9) + vertex[2].col = D3DCOLOR_RGBA(col0[2], col0[1], col0[0], 255); +#endif + } + else + { +#if defined(OGL) || defined(OGLES) + vertex[2].col[0] = (1.0f / 255.0f) * col0[0]; + vertex[2].col[1] = (1.0f / 255.0f) * col0[1]; + vertex[2].col[2] = (1.0f / 255.0f) * col0[2]; + vertex[2].col[3] = (1.0f / 255.0f) * 255; +#elif defined(D3D9) + vertex[2].col = D3DCOLOR_RGBA(col0[2], col0[1], col0[0], 255); +#endif + } + } + + if (col3 != NULL) + { + if (bMultiplyColour) + { +#if defined(OGL) || defined(OGLES) + vertex[3].col[0] = ((1.0f / 255.0f) * col3[0]) * VERTEX_COLOUR_MULT; + vertex[3].col[1] = ((1.0f / 255.0f) * col3[1]) * VERTEX_COLOUR_MULT; + vertex[3].col[2] = ((1.0f / 255.0f) * col3[2]) * VERTEX_COLOUR_MULT; + vertex[3].col[3] = (1.0f / 255.0f) * 255; +#elif defined(D3D9) + vertex[3].col = D3DCOLOR_RGBA(col3[2], col3[1], col3[0], 255); +#endif + } + else + { +#if defined(OGL) || defined(OGLES) + vertex[3].col[0] = (1.0f / 255.0f) * col3[0]; + vertex[3].col[1] = (1.0f / 255.0f) * col3[1]; + vertex[3].col[2] = (1.0f / 255.0f) * col3[2]; + vertex[3].col[3] = (1.0f / 255.0f) * 255; +#elif defined(D3D9) + vertex[3].col = D3DCOLOR_RGBA(col3[2], col3[1], col3[0], 255); +#endif + } + } + else + { + if (bMultiplyColour) + { +#if defined(OGL) || defined(OGLES) + vertex[3].col[0] = ((1.0f / 255.0f) * col0[0]) * VERTEX_COLOUR_MULT; + vertex[3].col[1] = ((1.0f / 255.0f) * col0[1]) * VERTEX_COLOUR_MULT; + vertex[3].col[2] = ((1.0f / 255.0f) * col0[2]) * VERTEX_COLOUR_MULT; + vertex[3].col[3] = (1.0f / 255.0f) * 255; +#elif defined(D3D9) + vertex[3].col = D3DCOLOR_RGBA(col0[2], col0[1], col0[0], 255); +#endif + } + else + { +#if defined(OGL) || defined(OGLES) + vertex[3].col[0] = (1.0f / 255.0f) * col0[0]; + vertex[3].col[1] = (1.0f / 255.0f) * col0[1]; + vertex[3].col[2] = (1.0f / 255.0f) * col0[2]; + vertex[3].col[3] = (1.0f / 255.0f) * 255; +#elif defined(D3D9) + vertex[3].col = D3DCOLOR_RGBA(col0[2], col0[1], col0[0], 255); +#endif + } + } + + return; +} + +#if defined(OGLES) || defined(OGL) +GLuint g_defaultShaderProgram; +#endif + +void Emulator_CreateGlobalShaders() +{ +#if defined(ES2_SHADERS) + const char* vertexShaderSource = "attribute vec4 a_position; attribute vec2 a_texcoord; varying vec2 v_texcoord; attribute vec4 a_colour; varying vec4 v_colour; uniform mat4 Projection; void main() { v_texcoord = a_texcoord; v_colour = a_colour; gl_Position = Projection*a_position; }"; +#elif defined(ES3_SHADERS) + const char* vertexShaderSource = "#version 300 es\n in vec4 a_position; in vec2 a_texcoord; out vec2 v_texcoord; in vec4 a_colour; out vec4 v_colour; uniform mat4 Projection; void main() { v_texcoord = a_texcoord; v_colour = a_colour; gl_Position = Projection*a_position; }"; +#elif defined(OGL) + const char* vertexShaderSource = "#version 330 core\n in vec4 a_position; in vec2 a_texcoord; out vec2 v_texcoord; in vec4 a_colour; out vec4 v_colour; uniform mat4 Projection; uniform mat4 Scale; void main() { v_texcoord = a_texcoord; v_colour = a_colour; gl_Position = Projection*(a_position*Scale); }"; +#elif defined(D3D9) + const char* vertexShaderSource = "struct VS_IN { float3 pos : POSITION; float2 texcoord : TEXCOORD0; float4 col : COLOR0; }; struct VS_OUT { float4 pos : POSITION; float2 texcoord : TEXCOORD0; float4 col : COLOR0; }; VS_OUT main(VS_IN input) { VS_OUT output; output.pos = float4(input.pos.xyz,1); output.texcoord = input.texcoord; output.col = input.col; return output; }"; +#endif + +#if defined(OGL) || defined(OGLES) + GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); + glCompileShader(vertexShader); +#elif defined(D3D9) + LPD3DXBUFFER vOutErrors = NULL; + LPD3DXBUFFER vertexShaderObject = NULL; + + if FAILED(D3DXCompileShader(vertexShaderSource, strlen(vertexShaderSource), NULL, NULL, "main", "vs_3_0", 0, &vertexShaderObject, &vOutErrors, NULL)) + { + eprinterr("Failed to compile vertex shader!\n") + } + + if FAILED(d3ddev->CreateVertexShader((DWORD*)vertexShaderObject->GetBufferPointer(), &g_defaultVertexShader)) + { + eprinterr("Failed to create vertex shader!\n"); + } +#endif + +#if defined(ES2_SHADERS) + const char* fragmentShaderSource = "precision mediump float; varying vec2 v_texcoord; varying vec4 v_colour; uniform bool bDiscardBlack; uniform sampler2D s_texture; void main() { gl_FragColor = texture2D(s_texture, v_texcoord); if (gl_FragColor.a == 0.0 && bDiscardBlack) { discard; } gl_FragColor *= v_colour; }"; +#elif defined(ES3_SHADERS) + const char* fragmentShaderSource = "#version 300 es\n precision mediump float; in vec2 v_texcoord; in vec4 v_colour; uniform sampler2D s_texture; out vec4 fragColour; void main() { fragColour = texture(s_texture, v_texcoord) * v_colour; }"; +#elif defined(OGL) + const char* fragmentShaderSource = "#version 330 core\n precision mediump float; in vec2 v_texcoord; in vec4 v_colour; uniform bool bDiscardBlack; uniform sampler2D s_texture; out vec4 fragColour; void main() { fragColour = texture(s_texture, v_texcoord); if (fragColour.a == 0.0 && bDiscardBlack) { discard; } fragColour *= v_colour; }"; +#elif defined(D3D9) + const char* fragmentShaderSource = "sampler tex : register(s0); bool bDiscardBlack = true; float4 main(in float2 texcoord : TEXCOORD0) : COLOR0 { float4 color = tex2D(tex, texcoord); float r = color.r; color.r = color.b; color.b = r; if(color.r == 0.0f && color.g == 0.0f && color.b == 0x0f) { discard; } return color; }"; +#endif + +#if defined(OGL) || defined(OGLES) + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); + glCompileShader(fragmentShader); +#elif defined(D3D9) + LPD3DXBUFFER pOutErrors = NULL; + LPD3DXBUFFER pixelShaderObject = NULL; + + if FAILED(D3DXCompileShader(fragmentShaderSource, strlen(fragmentShaderSource), NULL, NULL, "main", "ps_3_0", 0, &pixelShaderObject, &pOutErrors, NULL)) + { + eprinterr("Failed to compile pixel shader!\n") + } + + if FAILED(d3ddev->CreatePixelShader((DWORD*)pixelShaderObject->GetBufferPointer(), &g_defaultPixelShader)) + { + eprinterr("Failed to create pixel shader!\n"); + } +#endif + +#if defined(_DEBUG) && (defined(OGL) || defined(OGLES)) + char buff[1024]; + int maxLength = 1024; + glGetShaderInfoLog(fragmentShader, maxLength, &maxLength, &buff[0]); + + printf("%s", &buff[0]); + + maxLength = 1024; + glGetShaderInfoLog(vertexShader, maxLength, &maxLength, &buff[0]); + + printf("%s", &buff[0]); +#endif + +#if defined(OGL) || defined(OGLES) + /* Default */ + g_defaultShaderProgram = glCreateProgram(); + glAttachShader(g_defaultShaderProgram, vertexShader); + glAttachShader(g_defaultShaderProgram, fragmentShader); + glLinkProgram(g_defaultShaderProgram); + glUseProgram(g_defaultShaderProgram); + GLint idx = glGetUniformLocation(g_defaultShaderProgram, "s_texture"); + GLint sampler = 0; + glUniform1iv(idx, 1, &sampler); + glActiveTexture(GL_TEXTURE0 + sampler); +#endif +} + +unsigned short vram[VRAM_WIDTH * VRAM_HEIGHT]; + +int Emulator_InitialiseGL() +{ +#if defined(OGL) || defined(OGLES) + glEnable(GL_BLEND); + + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &g_defaultFBO); +#endif + + /* Initialise VRAM */ + SDL_memset(vram, 0, VRAM_WIDTH * VRAM_HEIGHT * sizeof(unsigned short)); + + /* Generate NULL white texture */ + Emulator_GenerateAndBindNullWhite(); + +#if defined(OGL) || defined(OGLES) + glDepthFunc(GL_LEQUAL); + glEnable(GL_SCISSOR_TEST); + glBlendColor(0.25f, 0.25f, 0.25f, 0.5f); + glGenTextures(1, &vramTexture); + + Emulator_BindTexture(vramTexture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +#endif + +#if defined(OGLES) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, VRAM_WIDTH, VRAM_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, &vram[0]); +#elif defined(OGL) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, VRAM_WIDTH, VRAM_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, &vram[0]); +#endif +#if defined(OGL) || defined(OGLES) + /* Generate VRAM Frame Buffer */ + glGenFramebuffers(1, &vramFrameBuffer); + glBindFramebuffer(GL_FRAMEBUFFER, vramFrameBuffer); +#endif + + /* Bind VRAM texture to vram framebuffer */ +#if defined (OGLES) + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, vramTexture, 0); +#elif defined(OGL) + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, vramTexture, 0); +#endif + +#if defined(OGL) || defined(OGLES) + while (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + { + eprinterr("Frame buffer error: %x\n", glGetError()); + eprinterr("Frame buffer status : %d\n", glCheckFramebufferStatus(GL_FRAMEBUFFER)); + exit(0); + } +#endif + +#if defined(OGL) || defined(OGLES) + glLineWidth(RESOLUTION_SCALE); +#endif + +#if defined(OGL) + glEnable(GL_DEPTH_TEST); +#endif + +#if defined(OGL) || defined(OGLES) + Emulator_CreateGlobalShaders(); + Emulator_BindTexture(0); + glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO); +#endif + return TRUE; +} + +#if defined(D3D9) +int Emulator_InitialiseD3D() +{ + d3ddev->GetRenderTarget(0, &g_defaultFBO); + d3ddev->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); + d3ddev->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(64, 64, 64, 128)); + d3ddev->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); + + /* Initialise VRAM */ + SDL_memset(vram, 0, VRAM_WIDTH * VRAM_HEIGHT * sizeof(unsigned short)); + + /* Generate NULL white texture */ + //Emulator_GenerateAndBindNullWhite();///@TODO + +#if defined(D3D9) + D3DVERTEXELEMENT9 vertexDecl[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + {0, 20, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + + if FAILED(d3ddev->CreateVertexDeclaration(vertexDecl, &g_vertexDecl)) + { + eprinterr("Failed to create vertex declaration!\n"); + return FALSE; + } + + d3ddev->SetVertexDeclaration(g_vertexDecl); + + if FAILED(d3ddev->CreateTexture(VRAM_WIDTH, VRAM_HEIGHT, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &vramTexture, NULL)) + { + eprinterr("Failed to create render target texture!\n"); + return FALSE; + } + + vramTexture->GetSurfaceLevel(0, &vramFrameBuffer); + + if FAILED(d3ddev->CreateRenderTarget(VRAM_WIDTH, VRAM_HEIGHT, D3DFMT_A1R5G5B5, D3DMULTISAMPLE_NONE, 0, TRUE, &vramFrameBuffer, NULL)) + { + eprinterr("Failed to create render target!\n"); + return FALSE; + } + + d3ddev->SetRenderTarget(0, vramFrameBuffer); + + Emulator_CreateGlobalShaders(); + +#endif + + return TRUE; +} +#elif defined(VK) + +unsigned int getMemoryType(unsigned int typeBits, VkMemoryPropertyFlags properties, VkBool32* memTypeFound) +{ + memTypeFound = NULL; + + for (unsigned int i = 0; i < deviceMemoryProperties.memoryTypeCount; i++) + { + if ((typeBits & 1) == 1) + { + if ((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties) + { + if (memTypeFound) + { + *memTypeFound = true; + } + return i; + } + } + typeBits >>= 1; + } + + if (memTypeFound) + { + *memTypeFound = false; + return 0; + } + else + { + eprinterr("Could not find matching memory type!\n"); + assert(FALSE); + } +} + +int Emulator_InitialiseVK() +{ + //d3ddev->GetRenderTarget(0, &g_defaultRenderTarget); + //d3ddev->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); + //d3ddev->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(64, 64, 64, 128)); + //d3ddev->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); + + /* Initialise VRAM */ + SDL_memset(vram, 0, VRAM_WIDTH * VRAM_HEIGHT * sizeof(unsigned short)); + + /* Generate NULL white texture */ + //Emulator_GenerateAndBindNullWhite();///@TODO + + vramFrameBuffer.width = VRAM_WIDTH; + vramFrameBuffer.height = VRAM_HEIGHT; + + // Find a suitable depth format + VkFormat fbDepthFormat; + //VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat); + //assert(validDepthFormat); + + // Color attachment + VkImageCreateInfo imageCreateInfo; + memset(&imageCreateInfo, 0, sizeof(VkImageCreateInfo)); + + imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; + imageCreateInfo.format = VK_FORMAT_R5G5B5A1_UNORM_PACK16; + imageCreateInfo.extent.width = vramFrameBuffer.width; + imageCreateInfo.extent.height = vramFrameBuffer.height; + imageCreateInfo.extent.depth = 1; + imageCreateInfo.mipLevels = 1; + imageCreateInfo.arrayLayers = 1; + imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + + // We will sample directly from the color attachment + imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + + VkMemoryAllocateInfo memoryAllocateInfo; + memset(&memoryAllocateInfo, 0, sizeof(VkMemoryAllocateInfo)); + VkMemoryRequirements memReqs; + memset(&memReqs, 0, sizeof(VkMemoryRequirements)); + if (vkCreateImage(device, &imageCreateInfo, nullptr, &vramFrameBuffer.color.image) != VK_SUCCESS) + { + eprinterr("Failed to create vram image!\n"); + return FALSE; + } + + vkGetImageMemoryRequirements(device, vramFrameBuffer.color.image, &memReqs); + memoryAllocateInfo.allocationSize = memReqs.size; + memoryAllocateInfo.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, NULL); + if (vkAllocateMemory(device, &memoryAllocateInfo, nullptr, &vramFrameBuffer.color.mem) != VK_SUCCESS) + { + eprinterr("Failed to allocate vram image memory!\n"); + return FALSE; + } + + if (vkBindImageMemory(device, vramFrameBuffer.color.image, vramFrameBuffer.color.mem, 0) != VK_SUCCESS) + { + eprinterr("Failed to bind vram image memory!\n"); + return FALSE; + } + + VkImageViewCreateInfo colorImageView; + memset(&colorImageView, 0, sizeof(VkImageViewCreateInfo)); + + colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; + colorImageView.format = VK_FORMAT_R5G5B5A1_UNORM_PACK16; + colorImageView.subresourceRange = {}; + colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + colorImageView.subresourceRange.baseMipLevel = 0; + colorImageView.subresourceRange.levelCount = 1; + colorImageView.subresourceRange.baseArrayLayer = 0; + colorImageView.subresourceRange.layerCount = 1; + colorImageView.image = vramFrameBuffer.color.image; + + if (vkCreateImageView(device, &colorImageView, nullptr, &vramFrameBuffer.color.view) != VK_SUCCESS) + { + eprinterr("Failed to create vram view image!\n"); + return FALSE; + } + + // Create sampler to sample from the attachment in the fragment shader + VkSamplerCreateInfo samplerInfo; + memset(&samplerInfo, 0, sizeof(VkSamplerCreateInfo)); + + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeV = samplerInfo.addressModeU; + samplerInfo.addressModeW = samplerInfo.addressModeU; + samplerInfo.mipLodBias = 0.0f; + samplerInfo.maxAnisotropy = 1.0f; + samplerInfo.minLod = 0.0f; + samplerInfo.maxLod = 1.0f; + samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + if (vkCreateSampler(device, &samplerInfo, nullptr, &vramFrameBuffer.sampler) != VK_SUCCESS) + { + eprinterr("Failed to create vram sampler!\n"); + return FALSE; + } + + // Depth stencil attachment + imageCreateInfo.format = fbDepthFormat; + imageCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + if (vkCreateImage(device, &imageCreateInfo, nullptr, &vramFrameBuffer.depth.image) != VK_SUCCESS) + { + eprinterr("Failed to create depth image!\n"); + return FALSE; + } + vkGetImageMemoryRequirements(device, vramFrameBuffer.depth.image, &memReqs); + memoryAllocateInfo.allocationSize = memReqs.size; + memoryAllocateInfo.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, FALSE); + if (vkAllocateMemory(device, &memoryAllocateInfo, nullptr, &vramFrameBuffer.depth.mem) != VK_SUCCESS) + { + eprinterr("Failed to allocate depth image memory!\n"); + return FALSE; + } + if (vkBindImageMemory(device, vramFrameBuffer.depth.image, vramFrameBuffer.depth.mem, 0) != VK_SUCCESS) + { + eprinterr("Failed to allocate bind depth image memory!\n"); + return FALSE; + } + + VkImageViewCreateInfo depthStencilView; + memset(&depthStencilView, 0, sizeof(VkImageViewCreateInfo)); + + depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D; + depthStencilView.format = fbDepthFormat; + depthStencilView.flags = 0; + depthStencilView.subresourceRange = {}; + depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + depthStencilView.subresourceRange.baseMipLevel = 0; + depthStencilView.subresourceRange.levelCount = 1; + depthStencilView.subresourceRange.baseArrayLayer = 0; + depthStencilView.subresourceRange.layerCount = 1; + depthStencilView.image = vramFrameBuffer.depth.image; + + if (vkCreateImageView(device, &depthStencilView, nullptr, &vramFrameBuffer.depth.view) != VK_SUCCESS) + { + eprinterr("Failed to create depth image view!\n"); + return FALSE; + } + // Create a separate render pass for the offscreen rendering as it may differ from the one used for scene rendering + VkAttachmentDescription attchmentDescriptions[2]; + memset(&attchmentDescriptions[0], 0, sizeof(VkAttachmentDescription) * 2); + + // Color attachment + attchmentDescriptions[0].format = VK_FORMAT_R5G5B5A1_UNORM_PACK16; + attchmentDescriptions[0].samples = VK_SAMPLE_COUNT_1_BIT; + attchmentDescriptions[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attchmentDescriptions[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attchmentDescriptions[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attchmentDescriptions[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attchmentDescriptions[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attchmentDescriptions[0].finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + // Depth attachment + attchmentDescriptions[1].format = fbDepthFormat; + attchmentDescriptions[1].samples = VK_SAMPLE_COUNT_1_BIT; + attchmentDescriptions[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attchmentDescriptions[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attchmentDescriptions[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attchmentDescriptions[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attchmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attchmentDescriptions[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkAttachmentReference colorReference = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; + VkAttachmentReference depthReference = { 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL }; + + VkSubpassDescription subpassDescription = {}; + subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpassDescription.colorAttachmentCount = 1; + subpassDescription.pColorAttachments = &colorReference; + subpassDescription.pDepthStencilAttachment = &depthReference; + + // Use subpass dependencies for layout transitions + VkSubpassDependency subPassDependencies[2]; + memset(&subPassDependencies[0], 0, sizeof(VkSubpassDependency) * 2); + + subPassDependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + subPassDependencies[0].dstSubpass = 0; + subPassDependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + subPassDependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + subPassDependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + subPassDependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + subPassDependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + subPassDependencies[1].srcSubpass = 0; + subPassDependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; + subPassDependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + subPassDependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + subPassDependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + subPassDependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + subPassDependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + // Create the actual renderpass + VkRenderPassCreateInfo renderPassInfo = {}; + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + renderPassInfo.attachmentCount = 2; + renderPassInfo.pAttachments = &attchmentDescriptions[0]; + renderPassInfo.subpassCount = 1; + renderPassInfo.pSubpasses = &subpassDescription; + renderPassInfo.dependencyCount = 2; + renderPassInfo.pDependencies = &subPassDependencies[0]; + + if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &vramFrameBuffer.renderPass) != VK_SUCCESS) + { + eprinterr("Failed to create render pass!\n"); + return FALSE; + } + + VkImageView attachments[2]; + attachments[0] = vramFrameBuffer.color.view; + attachments[1] = vramFrameBuffer.depth.view; + + VkFramebufferCreateInfo fbufCreateInfo; + memset(&fbufCreateInfo, 0, sizeof(VkFramebufferCreateInfo)); + fbufCreateInfo.renderPass = vramFrameBuffer.renderPass; + fbufCreateInfo.attachmentCount = 2; + fbufCreateInfo.pAttachments = attachments; + fbufCreateInfo.width = vramFrameBuffer.width; + fbufCreateInfo.height = vramFrameBuffer.height; + fbufCreateInfo.layers = 1; + + if (vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &vramFrameBuffer.frameBuffer) != VK_SUCCESS) + { + eprinterr("Failed to create frame buffer!\n"); + return FALSE; + } + + // Fill a descriptor for later use in a descriptor set + vramFrameBuffer.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + vramFrameBuffer.descriptor.imageView = vramFrameBuffer.color.view; + vramFrameBuffer.descriptor.sampler = vramFrameBuffer.sampler; + + Emulator_CreateGlobalShaders(); + + return TRUE; +} +#endif + +unsigned int g_lastBoundTexture = -1; +#if defined(OGL) || defined(OGLES) || defined(VK) +void Emulator_BindTexture(unsigned int textureId) +#elif defined(D3D9) +void Emulator_BindTexture(IDirect3DTexture9* texture) +#endif +{ +#if !defined(__EMSCRIPTEN__) + //assert(textureId < 1000); +#endif +#if defined(OGL) || defined(OGLES) + if (g_lastBoundTexture != textureId) + { + glBindTexture(GL_TEXTURE_2D, textureId); + + g_lastBoundTexture = textureId; + } +#elif defined(D3D9) + d3ddev->SetTexture(0, texture); +#endif +} + +#if defined(OGL) || defined(OGLES) || defined(VK) +void Emulator_DestroyTextures(int numTextures, unsigned int* textures) +#elif defined(D3D9) +void Emulator_DestroyTextures(IDirect3DTexture9* texture) +#endif +{ +#if defined(OGL) || defined(OGLES) + for (int i = 0; i < numTextures; i++) + { + if (textures[i] == g_lastBoundTexture) + { + g_lastBoundTexture = -1; + } + } + glDeleteTextures(numTextures, textures); +#elif defined(D3D9) + texture->Release(); +#endif +} + +void Emulator_GenerateAndBindNullWhite() +{ + unsigned char pixelData[4]; + ((int*)&pixelData[0])[0] = 0x80808080; +#if defined(OGL) || defined(OGLES) + glGenTextures(1, &nullWhiteTexture); + Emulator_BindTexture(nullWhiteTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixelData[0]); +#endif +} + +void Emulator_CheckTextureIntersection(RECT16* rect)///@TODO internal upres +{ + for (int i = 0; i < MAX_NUM_CACHED_TEXTURES; i++) + { + //Unused texture +#if defined(OGL) || defined(OGLES) + if (cachedTextures[i].textureID == 0xFFFFFFFF) +#elif defined(D3D9) + if (cachedTextures[i].texture == NULL) +#endif + continue; + + unsigned short tpage = cachedTextures[i].tpage; + unsigned int tpageX = ((tpage << 6) & 0x7C0) % VRAM_WIDTH;///@TODO macro + unsigned int tpageY = (((tpage << 4) & 0x100) + ((tpage >> 2) & 0x200)) % VRAM_HEIGHT;///@TODO macro + + if (rect->x < tpageX + TPAGE_WIDTH && rect->x + rect->w > tpageX&& + rect->y > tpageY + TPAGE_WIDTH && rect->y + rect->h < tpageY) + { +#if defined(OGL) || defined(OGLES) + Emulator_DestroyTextures(1, &cachedTextures[i].textureID); + SDL_memset(&cachedTextures[i], -1, sizeof(struct CachedTexture)); +#elif defined(D3D9) + Emulator_DestroyTextures(cachedTextures[i].texture); + SDL_memset(&cachedTextures[i], 0, sizeof(struct CachedTexture)); +#endif + } + } +} +#define NOFILE 0 + +#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) +void Emulator_SaveVRAM(const char* outputFileName, int x, int y, int width, int height, int bReadFromFrameBuffer) +{ +#if NOFILE + return; +#endif + +#if defined(OGL) || defined(OGLES) + FILE* f = fopen(outputFileName, "wb"); + if (f == NULL) + { + return; + } + unsigned char TGAheader[12] = { 0,0,2,0,0,0,0,0,0,0,0,0 }; + unsigned char header[6]; + header[0] = (width % 256); + header[1] = (width / 256); + header[2] = (height % 256); + header[3] = (height / 256); + header[4] = 16; + header[5] = 0; + unsigned short* pixelData = new unsigned short[width * height]; + + if (bReadFromFrameBuffer) + { + glReadPixels(x, y, width, height, GL_BGRA, TEXTURE_FORMAT, &pixelData[0]); + } + else + { + + glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, TEXTURE_FORMAT, pixelData); + } + + fwrite(TGAheader, sizeof(unsigned char), 12, f); + fwrite(header, sizeof(unsigned char), 6, f); + + //512 const is hdd sector size + int numSectorsToWrite = (width * height * sizeof(unsigned short)) / 512; + int numRemainingSectorsToWrite = (width * height * sizeof(unsigned short)) % 512; + + for (int i = 0; i < numSectorsToWrite; i++) + { + fwrite(&pixelData[i * 512 / sizeof(unsigned short)], 512, 1, f); + } + + for (int i = 0; i < numRemainingSectorsToWrite; i++) + { + fwrite(&pixelData[numSectorsToWrite * 512 / sizeof(unsigned short)], numRemainingSectorsToWrite, 1, f); + } + + fclose(f); + delete[] pixelData; + +#elif defined(D3D9) + D3DXSaveSurfaceToFile(outputFileName, D3DXIFF_TGA, vramFrameBuffer, NULL, NULL); +#endif +} +#endif + +void Emulator_BeginScene() +{ +#if defined(D3D9) + d3ddev->BeginScene(); +#endif + + SDL_Event event; + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_JOYDEVICEADDED: + if (SDL_IsGameController(event.jbutton.which)) + { + padHandle[event.jbutton.which] = SDL_GameControllerOpen(event.jbutton.which); + } + break; + case SDL_JOYDEVICEREMOVED: + SDL_GameControllerClose(padHandle[event.jbutton.which]); + break; + case SDL_QUIT: + Emulator_ShutDown(); + break; + case SDL_WINDOWEVENT: + switch (event.window.event) + { + case SDL_WINDOWEVENT_CLOSE: + Emulator_ShutDown(); + break; + } + break; + } + } +} + +#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) +void Emulator_TakeScreenshot() +{ + unsigned char* pixels = new unsigned char[512 * RESOLUTION_SCALE * 240 * RESOLUTION_SCALE * 4]; +#if defined(OGL) || defined(OGLES) + glReadPixels(0, 0, 512 * RESOLUTION_SCALE, 240 * RESOLUTION_SCALE, GL_BGRA, GL_UNSIGNED_BYTE, pixels); +#endif + SDL_Surface* surface = SDL_CreateRGBSurfaceFrom(pixels, 512 * RESOLUTION_SCALE, 240 * RESOLUTION_SCALE, 8 * 4, 512 * RESOLUTION_SCALE * 4, 0, 0, 0, 0); + SDL_SaveBMP(surface, "SCREENSHOT.BMP"); + SDL_FreeSurface(surface); + + delete[] pixels; +} +#endif + +///@FIXME keyboardState only accessible if padInitDirect called! Let the emulator manage input not the sub library! +void Emulator_DoDebugKeys() +{ + static unsigned int currentTime; + static unsigned int lastTime; + + currentTime = SDL_GetTicks(); + + if (currentTime > lastTime + 60) + { + if (keyboardState[SDL_SCANCODE_BACKSPACE]) + { + if (g_swapInterval != 0) + { + SDL_GL_SetSwapInterval(0); + } + g_swapInterval = 0; + } + else + { + if (g_swapInterval != 1) + { + SDL_GL_SetSwapInterval(1); + } + g_swapInterval = 1; + } + + if (keyboardState[SDL_SCANCODE_1]) + { + g_wireframeMode ^= 1; + } + + if (keyboardState[SDL_SCANCODE_2]) + { + g_texturelessMode ^= 1; + } + +#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) + if (keyboardState[SDL_SCANCODE_3]) + { + Emulator_TakeScreenshot(); + } +#endif + + lastTime = currentTime; + } +} + +void Emulator_UpdateInput() +{ + //Update pad + if (SDL_NumJoysticks() > 0) + { + for (int i = 0; i < MAX_CONTROLLERS; i++) + { + if (padHandle[i] != NULL) + { + padData[i][0] = 0; + padData[i][1] = 0x41;//? + ((unsigned short*)padData[i])[1] = UpdateGameControllerInput(padHandle[i]); + } + } + } + else + { + //Update keyboard + if (padData[0] != NULL) + { + ((unsigned short*)padData[0])[1] = UpdateKeyboardInput(); + } + } + +#if defined(__ANDROID__) + ///@TODO SDL_NumJoysticks always reports > 0 for some reason on Android. + ((unsigned short*)padData[0])[1] = UpdateKeyboardInput(); +#endif + + Emulator_DoDebugKeys(); +} + +unsigned int Emulator_GetFPS() +{ +#define FPS_INTERVAL 1.0 + + static unsigned int lastTime = SDL_GetTicks(); + static unsigned int currentFps = 0; + static unsigned int passedFrames = 0; + + passedFrames++; + if (lastTime < SDL_GetTicks() - FPS_INTERVAL * 1000) + { + lastTime = SDL_GetTicks(); + currentFps = passedFrames; + passedFrames = 0; + } + + return currentFps; +} + +void Emulator_SwapWindow() +{ +#if defined(RO_DOUBLE_BUFFERED) +#if defined(OGL) + SDL_GL_SwapWindow(g_window); +#elif defined(OGLES) + eglSwapBuffers(eglDisplay, eglSurface); +#elif defined(D3D9) + d3ddev->Present(NULL, NULL, NULL, NULL); +#endif +#else + glFinish(); +#endif +} + +void Emulator_EndScene() +{ +#if defined(OGL) || defined(OGLES) + glDisable(GL_BLEND); + + glUniform1i(glGetUniformLocation(g_defaultShaderProgram, "bDiscardBlack"), FALSE); + //glBindFramebuffer(GL_FRAMEBUFFER, vramFrameBuffer);///@TOCHECK is this really required? +#endif + +#if defined(VK) + //Unimplemented + //assert(FALSE); +#else + Emulator_BindFrameBuffer(g_defaultFBO); +#endif + Emulator_SetScissorBox(0, 0, windowWidth * RESOLUTION_SCALE, windowHeight * RESOLUTION_SCALE); + +#if defined(D3D9) + d3ddev->SetRenderTarget(0, g_defaultFBO); + d3ddev->SetVertexShader(g_defaultVertexShader); + d3ddev->SetPixelShader(g_defaultPixelShader); +#endif + + float x = 1.0f / (VRAM_WIDTH / (float)(word_33BC.disp.x * RESOLUTION_SCALE)); + float y = 1.0f / (VRAM_HEIGHT / (float)(word_33BC.disp.y * RESOLUTION_SCALE)); + float h = 1.0f / (VRAM_HEIGHT / (float)(word_33BC.disp.h * RESOLUTION_SCALE)); + float w = 1.0f / (VRAM_WIDTH / (float)(word_33BC.disp.w * RESOLUTION_SCALE)); + +#if defined(OGL) || defined(OGLES) + float vertexBuffer[] = + { + 0.0f, (float)word_33BC.disp.h * RESOLUTION_SCALE, 0.0f, x, y, 1.0f, 1.0f, 1.0f, 1.0f, + 0.0f, 0.0f, 0.0f, x, y + h, 1.0f, 1.0f, 1.0f, 1.0f, + (float)word_33BC.disp.w * RESOLUTION_SCALE, 0.0f, 0.0f, x + w, y + h, 1.0f, 1.0f, 1.0f, 1.0f, + (float)word_33BC.disp.w * RESOLUTION_SCALE, (float)word_33BC.disp.h * RESOLUTION_SCALE, 0.0f, x + w, y, 1.0f, 1.0f, 1.0f, 1.0f, + (float)word_33BC.disp.w * RESOLUTION_SCALE, 0.0f, 0.0f, x + w, y + h, 1.0f, 1.0f, 1.0f, 1.0f, + 0.0f, (float)word_33BC.disp.h * RESOLUTION_SCALE, 0.0f, x, y, 1.0f, 1.0f, 1.0f, 1.0f, + }; +#elif defined(D3D9) + +#if 0 + struct Vertex vertexBuffer[] = + { + 0.0f, (float)word_33BC.disp.h * RESOLUTION_SCALE, 0.0f, x, y + h, D3DCOLOR_RGBA(255, 255, 255, 255), + (float)word_33BC.disp.w * RESOLUTION_SCALE, (float)word_33BC.disp.h* RESOLUTION_SCALE, 0.0f, x + w, y + h, D3DCOLOR_RGBA(255, 255, 255, 255), + 0.0f, 0.0f, 0.0f, x, y, D3DCOLOR_RGBA(255, 255, 255, 255), + + + (float)word_33BC.disp.w * RESOLUTION_SCALE, 0.0f, 0.0f, x + w, y, D3DCOLOR_RGBA(255, 255, 255, 255), + 0.0f, 0.0f, 0.0f, x, y, D3DCOLOR_RGBA(255, 255, 255, 255), + (float)word_33BC.disp.w * RESOLUTION_SCALE, (float)word_33BC.disp.h * RESOLUTION_SCALE, 0.0f, x + w, y + h, D3DCOLOR_RGBA(255, 255, 255, 255), + }; +#else + struct Vertex vertexBuffer[] = + { + //BL + -1.0f, -1.0f, 0.0f, x, y + h, D3DCOLOR_RGBA(255, 255, 255, 255), + //BR + 1.0f, -1.0f, 0.0f, x + w, y + h, D3DCOLOR_RGBA(255, 255, 255, 255), + //TL + -1.0f, 1.0f, 0.0f, x, y, D3DCOLOR_RGBA(255, 255, 255, 255), + + //TR + 1.0f, 1.0f, 0.0f, x + w, y, D3DCOLOR_RGBA(255, 255, 255, 255), + //TL + -1.0f, 1.0f, 0.0f, x, y, D3DCOLOR_RGBA(255, 255, 255, 255), + //BR + 1.0f, -1.0f, 0.0f, x + w, y + h, D3DCOLOR_RGBA(255, 255, 255, 255), + }; +#endif + +#endif + + +#if defined(OGLES) || defined (OGL) + GLuint vbo, ibo, vao; + GLuint indexBuffer[] = { 0,1,2,0,2,3 }; + +#if (defined OGL) || (defined(OGLES) && OGLES_VERSION == 3) + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); +#else + glGenVertexArraysOES(1, &vao); + glBindVertexArrayOES(vao); +#endif + + glGenBuffers(1, &ibo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * 6, indexBuffer, GL_STATIC_DRAW); + + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertexBuffer), &vertexBuffer[0], GL_STATIC_DRAW); + + GLint posAttrib = glGetAttribLocation(g_defaultShaderProgram, "a_position"); + GLint colAttrib = glGetAttribLocation(g_defaultShaderProgram, "a_colour"); + GLint texAttrib = glGetAttribLocation(g_defaultShaderProgram, "a_texcoord"); + glEnableVertexAttribArray(posAttrib); + glEnableVertexAttribArray(colAttrib); + glEnableVertexAttribArray(texAttrib); + glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 9, 0); + glVertexAttribPointer(colAttrib, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 9, (GLvoid*)20); + glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 9, (GLvoid*)12); +#elif defined (D3D9) + LPDIRECT3DVERTEXBUFFER9 vertexBufferObject = NULL; + d3ddev->CreateVertexBuffer(sizeof(struct Vertex) * 6, 0, (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX0), D3DPOOL_MANAGED, &vertexBufferObject, NULL); + VOID* pVertexData; + vertexBufferObject->Lock(0, 0, (void**)&pVertexData, 0); + memcpy(pVertexData, &vertexBuffer[0], sizeof(struct Vertex) * 6); + vertexBufferObject->Unlock(); + d3ddev->SetStreamSource(0, vertexBufferObject, 0, sizeof(struct Vertex)); + + /* Nasty, make texture from render target*/ + IDirect3DSurface9* surface = NULL; + vramTexture->GetSurfaceLevel(0, &surface); + d3ddev->StretchRect(vramFrameBuffer, NULL, surface, NULL, D3DTEXF_LINEAR); + d3ddev->SetTexture(0, vramTexture); +#endif + Emulator_Ortho2D(0.0f, word_33BC.disp.w * RESOLUTION_SCALE, 0.0f, word_33BC.disp.h * RESOLUTION_SCALE, 0.0f, 1.0f); + Emulator_Scalef(1.0f, 1.0f, 1.0f); + +#if defined(OGLES) || defined (OGL) + Emulator_BindTexture(vramTexture); + + //Delete buffers + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL); +#elif defined(D3D9) + d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 6); +#endif + +#if defined(OGLES) || defined (OGL) + glDisableVertexAttribArray(posAttrib); + glDisableVertexAttribArray(colAttrib); + glDisableVertexAttribArray(texAttrib); + + glDeleteBuffers(1, &ibo); + glDeleteBuffers(1, &vbo); +#if (defined OGL) || (defined(OGLES) && OGLES_VERSION == 3) + glDeleteVertexArrays(1, &vao); +#else + glDeleteVertexArraysOES(1, &vao); +#endif +#endif + +#if _DEBUG && 0 + glBindFramebuffer(GL_READ_FRAMEBUFFER, vramFrameBuffer); + Emulator_SaveVRAM("VRAM.TGA", 0, 0, VRAM_WIDTH, VRAM_HEIGHT, TRUE); +#else + //Emulator_SaveVRAM("VRAM.TGA", 0, 0, VRAM_WIDTH, VRAM_HEIGHT, TRUE); +#endif + +#if defined(D3D9) + //texture->Release(); + d3ddev->SetVertexShader(NULL); + d3ddev->SetPixelShader(NULL); + d3ddev->EndScene(); +#endif + + Emulator_SwapWindow(); +#if defined(OGL) || defined(OGLES) + glUseProgram(g_defaultShaderProgram); +#endif +} + +void Emulator_ShutDown() +{ +#if defined(OGL) || defined(OGLES) + Emulator_DestroyFrameBuffer(&vramFrameBuffer); + Emulator_DestroyTextures(1, &vramTexture); + Emulator_DestroyTextures(1, &nullWhiteTexture); +#endif + + SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); + + for (int i = 0; i < MAX_NUM_CACHED_TEXTURES; i++) + { +#if defined(OGL) || defined(OGLES) + if (cachedTextures[i].textureID != 0xFFFFFFFF) + { + Emulator_DestroyTextures(1, &cachedTextures[i].textureID); + } +#elif defined(D3D9) + if (cachedTextures[i].texture != NULL) + { + Emulator_DestroyTextures(cachedTextures[i].texture); + } +#endif + } + +#if defined(VK) + vkDestroySurfaceKHR(instance, surface, 0); + vkDestroyInstance(instance, NULL); +#elif defined(D3D9) + if (g_defaultVertexShader != NULL) + { + g_defaultVertexShader->Release(); + } + + if (g_defaultPixelShader != NULL) + { + g_defaultPixelShader->Release(); + } + + SDL_DestroyRenderer(g_renderer); +#endif + + SDL_DestroyWindow(g_window); + SDL_Quit(); + exit(0); +} + +void Emulator_GenerateFrameBuffer(unsigned int* fbo) +{ +#if defined(OGL) || defined(OGLES) + glGenFramebuffers(1, fbo); + glBindFramebuffer(GL_FRAMEBUFFER, *fbo); +#endif +} + +struct CachedTexture* Emulator_FindTextureInCache(unsigned short tpage, unsigned short clut) +{ + if (g_hasHintedTextureAtlas) + { + for (int i = 0; i < MAX_NUM_CACHED_TEXTURES; i++) + { + if (cachedTextures[i].tpage == tpage) + { + cachedTextures[i].lastAccess = SDL_GetTicks(); + return &cachedTextures[i]; + } + } + } + else + { + for (int i = 0; i < MAX_NUM_CACHED_TEXTURES; i++) + { + if (cachedTextures[i].tpage == tpage && cachedTextures[i].clut == clut) + { + cachedTextures[i].lastAccess = SDL_GetTicks(); + return &cachedTextures[i]; + } + } + } + + return NULL; +} + +struct CachedTexture* Emulator_GetFreeCachedTexture() +{ + for (int i = 0; i < MAX_NUM_CACHED_TEXTURES; i++) + { +#if defined(OGL) || defined(OGLES) + if (cachedTextures[i].textureID == 0xFFFFFFFF) +#elif defined(D3D9) + if (cachedTextures[i].texture == NULL) +#endif + { + + return &cachedTextures[i]; + } + } + + //Cache is full, this should never happen + assert(0); + + return NULL; +} + +#if defined(OGL) || defined(OGLES) || defined(VK) +unsigned int Emulator_GenerateTpage(unsigned short tpage, unsigned short clut) +#elif defined(D3D9) +IDirect3DTexture9* Emulator_GenerateTpage(unsigned short tpage, unsigned short clut) +#endif +{ + unsigned int textureType = GET_TPAGE_TYPE(tpage); + unsigned int tpageX = GET_TPAGE_X(tpage); + unsigned int tpageY = GET_TPAGE_Y(tpage) + unsigned int clutX = GET_CLUT_X(clut); + unsigned int clutY = GET_CLUT_Y(clut); + +#if RESOLUTION_SCALE > 1 + if (tpageX >= 256) + { + tpageX += ((VRAM_WIDTH - (VRAM_WIDTH / RESOLUTION_SCALE)) / 2); + } + + if (tpageY >= 256) + { + tpageY += ((VRAM_HEIGHT - (VRAM_HEIGHT / RESOLUTION_SCALE)) / 2); + } + if (clutX >= 256) + { + clutX += ((VRAM_WIDTH - (VRAM_WIDTH / RESOLUTION_SCALE)) / 2); + } + if (clutY >= 256) + { + clutY += ((VRAM_HEIGHT - (VRAM_HEIGHT / RESOLUTION_SCALE)) / 2); + } +#endif + + struct CachedTexture* tpageTexture = Emulator_FindTextureInCache(tpage, clut); + int bMustAddTexture = (tpageTexture == NULL) ? 1 : 0; + + if (bMustAddTexture) + { + tpageTexture = Emulator_GetFreeCachedTexture(); + tpageTexture->tpage = tpage; + tpageTexture->clut = clut; +#if defined(OGL) || defined(OGLES) + glGenTextures(1, &tpageTexture->textureID); +#endif +#if !defined(__EMSCRIPTEN__) && !defined(VK) && !defined(D3D9) + assert(tpageTexture->textureID < 1000); +#endif +#if defined(OGL) || defined(OGLES) + Emulator_BindTexture(tpageTexture->textureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +#endif + } + else + { +#if defined(OGL) || defined(OGLES) + return tpageTexture->textureID; +#elif defined(D3D9) + return tpageTexture->texture; +#endif + } + + enum + { + TP_4BIT, + TP_8BIT, + TP_16BIT + }; + + switch (textureType) + { + case TP_16BIT: + { + unsigned short* tpage = (unsigned short*)SDL_malloc(TPAGE_WIDTH * TPAGE_HEIGHT * sizeof(unsigned short)); +#if defined(OGL) || defined(OGLES) + glReadPixels(tpageX, tpageY, TPAGE_WIDTH, TPAGE_HEIGHT, GL_RGBA, TEXTURE_FORMAT, tpage); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, TEXTURE_FORMAT, tpage); +#endif +#if defined(_DEBUG) && 0 + char buff[64]; + sprintf(&buff[0], "TPAGE_%d_%d.TGA", tpage, clut); + FILE* f = fopen(buff, "wb"); + unsigned char TGAheader[12] = { 0,0,2,0,0,0,0,0,0,0,0,0 }; + unsigned char header[6] = { 256 % 256, 256 / 256, 256 % 256, 256 / 256,16,0 }; + fwrite(TGAheader, sizeof(unsigned char), 12, f); + fwrite(header, sizeof(unsigned char), 6, f); + fwrite(tpage, sizeof(char), 256 * 256 * 2, f); + fclose(f); +#endif + + SDL_free(tpage); + break; + } + case TP_8BIT: + { + unsigned short* tpage = (unsigned short*)SDL_malloc(TPAGE_WIDTH * TPAGE_HEIGHT * sizeof(unsigned short)); +#if defined(OGL) || defined(OGLES) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, &tpage[0]); +#endif + SDL_free(tpage); +#if defined(_DEBUG) && 0 + char buff[64]; + sprintf(&buff[0], "TPAGE_%d_%d.TGA", tpage, clut); + FILE* f = fopen(buff, "wb"); + unsigned char TGAheader[12] = { 0,0,2,0,0,0,0,0,0,0,0,0 }; + unsigned char header[6] = { 256 % 256, 256 / 256, 256 % 256, 256 / 256,16,0 }; + fwrite(TGAheader, sizeof(unsigned char), 12, f); + fwrite(header, sizeof(unsigned char), 6, f); + fwrite(&tpage[0], sizeof(char), 256 * 256 * 2, f); + fclose(f); +#endif + break; + } + case TP_4BIT: + { + unsigned short clut[CLUT_WIDTH * CLUT_HEIGHT]; + + //Read CLUT +#if defined(OGL) || defined(OGLES) + glReadPixels(clutX, clutY, CLUT_WIDTH, CLUT_HEIGHT, GL_RGBA, TEXTURE_FORMAT, &clut[0]); +#elif defined(D3D9) + D3DLOCKED_RECT lockedRect; + RECT convertedRect; + convertedRect.top = clutY; + convertedRect.bottom = clutY + CLUT_HEIGHT; + convertedRect.left = clutX; + convertedRect.right = clutX + CLUT_WIDTH; + vramFrameBuffer->LockRect(&lockedRect, &convertedRect, D3DLOCK_READONLY); + + unsigned short* src = (unsigned short*)lockedRect.pBits; + unsigned short* dest = clut; + + for (int y = 0; y < CLUT_HEIGHT; y++) + { + for (int x = 0; x < CLUT_WIDTH; x++) + { + dest[x] = src[x]; + } + + src += lockedRect.Pitch / sizeof(unsigned short); + dest += CLUT_WIDTH; + } + + vramFrameBuffer->UnlockRect(); +#endif + unsigned short* tpage = (unsigned short*)SDL_malloc(TPAGE_WIDTH / 4 * TPAGE_HEIGHT * sizeof(unsigned short)); + +#if defined(OGL) || defined(OGLES) + //Read texture data + glReadPixels(tpageX, tpageY, TPAGE_WIDTH / 4, TPAGE_HEIGHT, GL_RGBA, TEXTURE_FORMAT, &tpage[0]); +#elif defined(D3D9) + convertedRect.top = tpageY; + convertedRect.bottom = tpageY + TPAGE_HEIGHT; + convertedRect.left = tpageX; + convertedRect.right = tpageX + (TPAGE_WIDTH / 4); + vramFrameBuffer->LockRect(&lockedRect, &convertedRect, D3DLOCK_READONLY); + + src = (unsigned short*)lockedRect.pBits; + dest = tpage; + + for (int y = 0; y < TPAGE_HEIGHT; y++) + { + for (int x = 0; x < (TPAGE_WIDTH / 4); x++) + { + dest[x] = src[x]; + } + + src += lockedRect.Pitch / sizeof(unsigned short); + dest += (TPAGE_WIDTH / 4); + } + + vramFrameBuffer->UnlockRect(); +#endif + + unsigned short* convertedTpage = (unsigned short*)SDL_malloc(TPAGE_WIDTH * TPAGE_HEIGHT * sizeof(unsigned short)); + unsigned short* convertPixel = &convertedTpage[0]; + + for (int xy = 0; xy < TPAGE_WIDTH / 4 * TPAGE_HEIGHT; xy++) + { + *convertPixel++ = clut[(tpage[xy] & (0xF << 0 * 4)) >> (0 * 4)]; + *convertPixel++ = clut[(tpage[xy] & (0xF << 1 * 4)) >> (1 * 4)]; + *convertPixel++ = clut[(tpage[xy] & (0xF << 2 * 4)) >> (2 * 4)]; + *convertPixel++ = clut[(tpage[xy] & (0xF << 3 * 4)) >> (3 * 4)]; + } + +#if defined(OGLES) +#define ARGB1555toRGBA1555(x) ((x & 0x8000) >> 15) | ((x & 0x7FFF) << 1) +#pragma pack(push,1) + struct rgba5551 + { + unsigned short r : 5; + unsigned short g : 5; + unsigned short b : 5; + unsigned short a : 1; + }; + + struct abgr1555 + { + unsigned short a : 1; + unsigned short b : 5; + unsigned short g : 5; + unsigned short r : 5; + }; +#pragma pack(pop) + + for (int xy = 0; xy < TPAGE_WIDTH * TPAGE_HEIGHT; xy++) + { + struct rgba5551* pixel = (struct rgba5551*) & convertedTpage[xy]; + struct abgr1555* pixel2 = (struct abgr1555*) & convertedTpage[xy]; + + unsigned short r = pixel->r; + unsigned short g = pixel->g; + unsigned short b = pixel->b; + unsigned short a = pixel->a; + pixel2->a = a; + pixel2->r = r; + pixel2->g = g; + pixel2->b = b; + } + +#endif + +#if _DEBUG && 0 + char buff[64]; + sprintf(&buff[0], "TPAGE_%d_%d.TGA", tpage, clut); + FILE* f = fopen(buff, "wb"); + unsigned char TGAheader[12] = { 0,0,2,0,0,0,0,0,0,0,0,0 }; + unsigned char header[6] = { 256 % 256, 256 / 256, 256 % 256, 256 / 256,16,0 }; + fwrite(TGAheader, sizeof(unsigned char), 12, f); + fwrite(header, sizeof(unsigned char), 6, f); + fwrite(&convertedTpage[0], sizeof(char), 256 * 256 * 2, f); + fclose(f); +#endif +#if defined(OGL) || defined(OGLES) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TPAGE_WIDTH, TPAGE_HEIGHT, 0, GL_RGBA, TEXTURE_FORMAT, &convertedTpage[0]); +#elif defined(D3D9) + + if FAILED(d3ddev->CreateTexture(TPAGE_WIDTH, TPAGE_HEIGHT, 0, 0, D3DFMT_A1R5G5B5, D3DPOOL_MANAGED, &tpageTexture->texture, NULL)) + { + eprinterr("Failed to create tpage texture!\n"); + assert(FALSE);//Should never happen cannot continue anymore. + } + + tpageTexture->texture->LockRect(0, &lockedRect, NULL, D3DLOCK_DISCARD); + + src = convertedTpage; + dest = (unsigned short*)lockedRect.pBits; + + for (int y = 0; y < TPAGE_HEIGHT; y++) + { + for (int x = 0; x < TPAGE_WIDTH; x++) + { + dest[x] = src[x]; + } + + src += TPAGE_WIDTH; + dest += lockedRect.Pitch / sizeof(unsigned short); + } + + tpageTexture->texture->UnlockRect(0); + + //D3DXSaveTextureToFile("Debug.TGA", D3DXIFF_TGA, tpageTexture->texture, NULL); +#endif + SDL_free(tpage); + SDL_free(convertedTpage); + + break; + } + } + +#if defined(OGL) || defined(OGLES) + return tpageTexture->textureID; +#elif defined(D3D9) + return tpageTexture->texture; +#elif defined(VK) + return NULL; +#endif +} + +void Emulator_DestroyFrameBuffer(unsigned int* fbo) +{ +#if defined(OGL) || defined(OGLES) + glDeleteFramebuffers(1, fbo); + glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO); +#endif +} + +static int g_PreviousBlendMode = -1; +static int g_PreviousSemiTrans = 0; + +void Emulator_SetBlendMode(int mode, int semiTransparent) +{ + if (semiTransparent) + { + //If previous wasn't semi trans, enable blend + if (g_PreviousSemiTrans == 0) + { +#if defined(OGL) || defined(OGLES) + glEnable(GL_BLEND); +#elif defined(D3D9) + d3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); +#endif + } + + if (g_PreviousBlendMode != mode) + { + switch (mode) + { + case BM_AVERAGE: +#if defined(OGL) || defined(OGLES) + glBlendFuncSeparate(GL_CONSTANT_ALPHA, GL_CONSTANT_ALPHA, GL_ONE, GL_ZERO); + glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); +#elif defined(D3D9) + d3ddev->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + d3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_BLENDFACTOR); + d3ddev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_BLENDFACTOR); + d3ddev->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE); + d3ddev->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO); + d3ddev->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); +#endif + break; + case BM_ADD: +#if defined(OGL) || defined(OGLES) + glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ZERO); + glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); +#elif defined(D3D9) + d3ddev->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + d3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); + d3ddev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + d3ddev->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE); + d3ddev->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO); + d3ddev->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); +#endif + break; + case BM_SUBTRACT: +#if defined(OGL) || defined(OGLES) + glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ZERO); + glBlendEquationSeparate(GL_FUNC_REVERSE_SUBTRACT, GL_FUNC_ADD); +#elif defined(D3D9) + d3ddev->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT); + d3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); + d3ddev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + d3ddev->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE); + d3ddev->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO); + d3ddev->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); +#endif + break; + case BM_ADD_QUATER_SOURCE: +#if defined(OGL) || defined(OGLES) + glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_ONE, GL_ONE, GL_ZERO); + glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); +#elif defined(D3D9) + d3ddev->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + d3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_BLENDFACTOR); + d3ddev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + d3ddev->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE); + d3ddev->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO); + d3ddev->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); +#endif + break; + default: +#if defined(OGL) || defined(OGLES) + glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); + glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); +#endif + break; + } + + g_PreviousBlendMode = mode; + } + } + else + { + //If previous was semi trans disable blend + if (g_PreviousSemiTrans) + { +#if defined(OGL) || defined(OGLES) + glDisable(GL_BLEND); +#elif defined(D3D9) + d3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); +#endif + } + } + + g_PreviousSemiTrans = semiTransparent; +} + +#if defined(OGLES) || defined(OGL) || defined(D3D9) || defined(VK) +void Emulator_Ortho2D(float left, float right, float bottom, float top, float znear, float zfar) +{ +#if defined(OGL) || defined(OGLES) + float a = 2.0f / (right - left); + float b = 2.0f / (top - bottom); + float c = -2.0f / (zfar - znear); + + float tx = -(right + left) / (right - left); + float ty = -(top + bottom) / (top - bottom); + float tz = -(zfar + znear) / (zfar - znear); + + float ortho[16] = + { + a, 0, 0, 0, + 0, b, 0, 0, + 0, 0, c, 0, + tx, ty, tz, 1 + }; + + GLint projectionUniform = glGetUniformLocation(g_defaultShaderProgram, "Projection"); + glUniformMatrix4fv(projectionUniform, 1, GL_FALSE, &ortho[0]); +#elif defined(D3D9) + D3DXMATRIX ortho; + D3DXMatrixOrthoOffCenterLH(&ortho, left, right, top, bottom, -1.0f, 1.0f); + d3ddev->SetTransform(D3DTS_PROJECTION, &ortho); +#endif +} + +void Emulator_Scalef(float sx, float sy, float sz) +{ +#if defined(OGL) || defined(OGLES) + float scale[16] = + { + sx, 0, 0, 0, + 0, sy, 0, 0, + 0, 0, sz, 0, + 0, 0, 0, 1 + }; + + GLint scaleUniform = glGetUniformLocation(g_defaultShaderProgram, "Scale"); + glUniformMatrix4fv(scaleUniform, 1, GL_FALSE, &scale[0]); +#endif + +} + +#endif + +void Emulator_GetTopLeftAndBottomLeftTextureCoordinate(int* x, int* y, int* w, int* h, unsigned char* u, unsigned char* v) +{ + int topCoordX = -1; + int topCoordY = -1; + int bottomCoordX = -1; + int bottomCoordY = -1; + + for (int j = 0; j < 4; j++) + { + for (int i = 0; i < 4; i++) + { + //Skip same coordinate + if (i == j) + { + continue; + } + + //This is a left coord + if (u[j] < u[i]) + { + topCoordX = u[j]; + } + + //This is a top coord + if (v[i] < v[j]) + { + topCoordY = v[i]; + } + } + } + + for (int j = 0; j < 4; j++) + { + for (int i = 0; i < 4; i++) + { + //Skip same coordinate + if (i == j) + { + continue; + } + + //This is a right coord + if (u[j] > u[i]) + { + bottomCoordX = u[j]; + } + + //This is a bottom coord + if (v[i] > v[j]) + { + bottomCoordY = v[i]; + } + } + } + + *x = topCoordX; + *y = topCoordY; + *w = (bottomCoordX - topCoordX) + 1; + *h = (bottomCoordY - topCoordY) + 1; + + //Round up next multiple of 2 + //*w = (*w + 1) & ~0x1; + //*h = (*h + 1) & ~0x1; + + //Round down next multiple of 2 + //*w -= (*w % 2); + //*h -= (*h % 2); +} + +#define EXTERNAL_LOGO + +void Emulator_HintTextureAtlas(unsigned short texTpage, unsigned short texClut, unsigned char u0, unsigned char v0, unsigned char u1, unsigned char v1, unsigned char u2, unsigned char v2, unsigned char u3, unsigned char v3, unsigned short bIsQuad) +{ + //Locate the 4-bit texture in vram, convert it and glTexSubImage to the atlas + unsigned int tpageX = GET_TPAGE_X(texTpage); + unsigned int tpageY = GET_TPAGE_Y(texTpage); + unsigned int clutX = GET_CLUT_X(texClut); + unsigned int clutY = GET_CLUT_Y(texClut); + + //Set this to true so the emulator uses atlas textures + g_hasHintedTextureAtlas = 1; + + int x = 0, y = 0, w = 0, h = 0; + unsigned char textureCoordsU[] = { u0, u1, u2, u3 }; + unsigned char textureCoordsV[] = { v0, v1, v2, v3 }; + + /* Get the top left and bottom left coordinate for TOMB5, return them plus width height */ + Emulator_GetTopLeftAndBottomLeftTextureCoordinate(&x, &y, &w, &h, &textureCoordsU[0], &textureCoordsV[0]); + + //Check if this tpage is already in our cache! + struct CachedTexture* tpageTexture = Emulator_FindTextureInCache(texTpage, texClut); + int bMustAddTexture = (tpageTexture == NULL) ? 1 : 0; + + //If not in cache, generate new texture for this tpage! + if (bMustAddTexture) + { + tpageTexture = Emulator_GetFreeCachedTexture(); + tpageTexture->tpage = texTpage; + tpageTexture->clut = texClut; +#if defined(OGL) || defined(OGLES) + glGenTextures(1, &tpageTexture->textureID); + Emulator_BindTexture(tpageTexture->textureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TPAGE_WIDTH, TPAGE_HEIGHT, 0, GL_RGBA, TEXTURE_FORMAT, NULL); +#endif + } + else + { +#if defined(OGL) || defined(OGLES) + Emulator_BindTexture(tpageTexture->textureID); +#endif + } + +#if defined(OGL) || defined(OGLES) + glBindFramebuffer(GL_FRAMEBUFFER, vramFrameBuffer); +#endif + + unsigned short* texturePage = (unsigned short*)SDL_malloc(sizeof(unsigned short) * w * h * 1024); + unsigned short* clut = (unsigned short*)SDL_malloc(sizeof(unsigned short) * 16); + unsigned short* convertedTpage = (unsigned short*)SDL_malloc(sizeof(unsigned short) * w * h * 1024); + +#if defined(OGL) || defined(OGLES) + //Read CLUT + glReadPixels(clutX, clutY, CLUT_WIDTH, CLUT_HEIGHT, GL_RGBA, TEXTURE_FORMAT, &clut[0]); + + //Read texture data + glReadPixels(tpageX + (x / 4), tpageY + y, w / 4, h, GL_RGBA, TEXTURE_FORMAT, &texturePage[0]); +#endif + + unsigned short* convertPixel = &convertedTpage[0]; + + for (int xy = 0; xy < (w / 4) * h; xy++) + { + *convertPixel++ = clut[(texturePage[xy] & (0xF << 0 * 4)) >> (0 * 4)]; + *convertPixel++ = clut[(texturePage[xy] & (0xF << 1 * 4)) >> (1 * 4)]; + *convertPixel++ = clut[(texturePage[xy] & (0xF << 2 * 4)) >> (2 * 4)]; + *convertPixel++ = clut[(texturePage[xy] & (0xF << 3 * 4)) >> (3 * 4)]; + } + +#if defined(OGLES) +#define ARGB1555toRGBA1555(x) ((x & 0x8000) >> 15) | ((x & 0x7FFF) << 1) +#pragma pack(push,1) + struct rgba5551 + { + unsigned short r : 5; + unsigned short g : 5; + unsigned short b : 5; + unsigned short a : 1; + }; + + struct abgr1555 + { + unsigned short a : 1; + unsigned short b : 5; + unsigned short g : 5; + unsigned short r : 5; + }; +#pragma pack(pop) + + for (int xy = 0; xy < w * h; xy++) + { + struct rgba5551* pixel = (struct rgba5551*) & convertedTpage[xy]; + struct abgr1555* pixel2 = (struct abgr1555*) & convertedTpage[xy]; + + unsigned short r = pixel->r; + unsigned short g = pixel->g; + unsigned short b = pixel->b; + unsigned short a = pixel->a; + pixel2->a = a; + pixel2->r = r; + pixel2->g = g; + pixel2->b = b; + } + +#endif + +#if defined(OGL) || defined(OGLES) + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, TEXTURE_FORMAT, &convertedTpage[0]); +#endif + +#if defined(_DEBUG) && 0 + char buf[32]; + sprintf(&buf[0], "TEX_%d.TGA", texTpage); + Emulator_SaveVRAM(buf, 0, 0, TPAGE_WIDTH, TPAGE_HEIGHT, FALSE); +#endif + + SDL_free(clut); + SDL_free(texturePage); + SDL_free(convertedTpage); + + //Set this to false so the emulator can search up and add textures + //That are not atlas hinted + //g_hasHintedTextureAtlas = 0; +} + + +void Emulator_InjectTIM(char* fileName, unsigned short texTpage, unsigned short texClut, unsigned char u0, unsigned char v0, unsigned char u1, unsigned char v1, unsigned char u2, unsigned char v2, unsigned char u3, unsigned char v3) +{ + /* Take from atlas */ + g_hasHintedTextureAtlas = 1; + + int x = 0, y = 0, w = 0, h = 0; + unsigned char textureCoordsU[] = { u0, u1, u2, u3 }; + unsigned char textureCoordsV[] = { v0, v1, v2, v3 }; + + /* Get the top left and bottom left coordinate for TOMB5, return them plus width height */ + Emulator_GetTopLeftAndBottomLeftTextureCoordinate(&x, &y, &w, &h, &textureCoordsU[0], &textureCoordsV[0]); + + //Check if this tpage is already in our cache! + struct CachedTexture* tpageTexture = Emulator_FindTextureInCache(texTpage, texClut); + + //Not in cache, why are we injecting? ; - ) + if (tpageTexture == NULL) + { + return; + } + +#if defined(OGL) || defined(OGLES) + Emulator_BindTexture(tpageTexture->textureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +#endif + unsigned short* texturePage = (unsigned short*)SDL_malloc(sizeof(unsigned short) * ((w * h) / 2)); + unsigned short* clut = (unsigned short*)SDL_malloc(sizeof(unsigned short) * 16); + unsigned short* convertedTpage = (unsigned short*)SDL_malloc(sizeof(unsigned short) * (w * h)); + + FILE* f = fopen("LOGO.TIM", "rb"); + fseek(f, 20, SEEK_SET); + fread(&clut[0], 16 * sizeof(short), 1, f); + fseek(f, 64, SEEK_SET); + fread(&texturePage[0], (w * h) / 2, 1, f); + fclose(f); + + //For LOGO only, temporarily set injection x y position on 256x256 tpage + x = 0; + y = 68; + + unsigned short* convertPixel = &convertedTpage[0]; + + for (int xy = 0; xy < (w / 4) * h; xy++) + { + *convertPixel++ = clut[(texturePage[xy] & (0xF << 0 * 4)) >> (0 * 4)]; + *convertPixel++ = clut[(texturePage[xy] & (0xF << 1 * 4)) >> (1 * 4)]; + *convertPixel++ = clut[(texturePage[xy] & (0xF << 2 * 4)) >> (2 * 4)]; + *convertPixel++ = clut[(texturePage[xy] & (0xF << 3 * 4)) >> (3 * 4)]; + } + +#if defined(OGLES) +#define ARGB1555toRGBA1555(x) ((x & 0x8000) >> 15) | ((x & 0x7FFF) << 1) +#pragma pack(push,1) + struct rgba5551 + { + unsigned short r : 5; + unsigned short g : 5; + unsigned short b : 5; + unsigned short a : 1; + }; + + struct abgr1555 + { + unsigned short a : 1; + unsigned short b : 5; + unsigned short g : 5; + unsigned short r : 5; + }; +#pragma pack(pop) + + for (int xy = 0; xy < w * h; xy++) + { + struct rgba5551* pixel = (struct rgba5551*) & convertedTpage[xy]; + struct abgr1555* pixel2 = (struct abgr1555*) & convertedTpage[xy]; + + unsigned short r = pixel->r; + unsigned short g = pixel->g; + unsigned short b = pixel->b; + unsigned short a = pixel->a; + pixel2->a = a; + pixel2->r = r; + pixel2->g = g; + pixel2->b = b; + } + +#endif + +#if defined(OGL) || defined(OGLES) + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, TEXTURE_FORMAT, &convertedTpage[0]); +#endif + +#if defined(_DEBUG) && 0 + char buf[32]; + sprintf(&buf[0], "TEX_%d.TGA", texTpage); + Emulator_SaveVRAM(buf, 0, 0, TPAGE_WIDTH, TPAGE_HEIGHT, FALSE); +#endif + + SDL_free(clut); + SDL_free(texturePage); + SDL_free(convertedTpage); + + //Set this to false so the emulator can search up and add textures + //That are not atlas hinted + g_hasHintedTextureAtlas = 1; +} + +void Emulator_DestroyAllTextures() +{ + //Initial texture id is -1 + for (int i = 0; i < MAX_NUM_CACHED_TEXTURES; i++) + { +#if defined(OGL) || defined(OGLES) + if (cachedTextures[i].textureID != 0xFFFFFFFF) + { + Emulator_DestroyTextures(1, &cachedTextures[i].textureID); + } +#elif defined(D3D9) + if (cachedTextures[i].texture != NULL) + { + Emulator_DestroyTextures(cachedTextures[i].texture); + } +#endif + } + +#if defined(OGL) || defined(OGLES) + //Initialise texture cache + SDL_memset(&cachedTextures[0], -1, MAX_NUM_CACHED_TEXTURES * sizeof(struct CachedTexture)); +#elif defined(D3D9) + SDL_memset(&cachedTextures[0], 0, MAX_NUM_CACHED_TEXTURES * sizeof(struct CachedTexture)); +#endif + return; +} + +void Emulator_SetPGXPVertexCount(int vertexCount) +{ +#if defined(PGXP) + pgxp_vertex_count = vertexCount; +#endif +} + +void Emulator_SetViewPort(int x, int y, int width, int height) +{ +#if defined(OGL) || defined(OGLES) + glViewport(x, y, width, height); +#elif defined(D3D9) + D3DVIEWPORT9 viewPort; + viewPort.X = x; + viewPort.Y = y; + viewPort.Width = width; + viewPort.Height = height; + viewPort.MinZ = 0.0f; + viewPort.MaxZ = 1.0f; + d3ddev->SetViewport(&viewPort); +#elif defined(VK) + VkViewport viewPort; + viewPort.x = x; + viewPort.y = y; + viewPort.width = width; + viewPort.height = height; + viewPort.minDepth = 0.0f; + viewPort.maxDepth = 1.0f; + //assert(FALSE);//Unfinished see below. + //vkCmdSetViewport(draw_cmd, 0, 1, &viewport); +#endif +} + +void Emulator_SetScissorBox(int x, int y, int width, int height) +{ +#if defined(OGL) || defined(OGLES) + glScissor(x, y, width, height); +#elif defined(D3D9) + RECT scissorBox; + scissorBox.top = y; + scissorBox.bottom = y + height; + scissorBox.left = x; + scissorBox.right = x + width; + d3ddev->SetScissorRect(&scissorBox); +#elif defined(VK) + VkRect2D scissorBox; + scissorBox.offset.x = x; + scissorBox.offset.y = y; + scissorBox.extent.width = width; + scissorBox.extent.height = height; + //assert(FALSE);//Unfinished see below. + //vkCmdSetScissor(draw_cmd, 0, 1, &scissor); +#endif +} + +#if defined(OGL) || defined(OGLES) +void Emulator_BindFrameBuffer(GLuint frameBufferObject) +#elif defined(D3D9) +void Emulator_BindFrameBuffer(IDirect3DSurface9* frameBufferObject) +#elif defined(VK) +void Emulator_BindFrameBuffer(struct FrameBuffer frameBufferObject) +#endif +{ +#if defined(OGL) || defined(OGLES) + glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject); +#elif defined(D3D9) + d3ddev->SetRenderTarget(0, frameBufferObject); +#elif defined(VK) + //assert(FALSE);//unimplemented +#endif +} + +void Emulator_CreateVertexBuffer(int numVertices, int vertexStride, void* pVertices) +{ +#if defined(OGL) || defined(OGLES) + glBufferData(GL_ARRAY_BUFFER, vertexStride * numVertices, pVertices, GL_STATIC_DRAW); +#elif defined(D3D9) + d3ddev->CreateVertexBuffer(vertexStride * numVertices, 0, (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX0), D3DPOOL_MANAGED, &g_vertexBufferObject, NULL); + VOID* pVertexData; + g_vertexBufferObject->Lock(0, 0, (void**)&pVertexData, 0); + memcpy(pVertexData, pVertices, vertexStride * numVertices); + g_vertexBufferObject->Unlock(); + d3ddev->SetStreamSource(0, g_vertexBufferObject, 0, vertexStride); +#elif defined(VK) + +#endif +} \ No newline at end of file diff --git a/src_rebuild/EMULATOR/EMULATOR.H b/src_rebuild/EMULATOR/EMULATOR.H new file mode 100644 index 00000000..8c159b9b --- /dev/null +++ b/src_rebuild/EMULATOR/EMULATOR.H @@ -0,0 +1,179 @@ +#ifndef EMULATOR_H +#define EMULATOR_H + +#include "EMULATOR_PLATFORM_SETUP.H" +#include "LIBGPU.H" + +#include +#include + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef NULL +#define NULL 0 +#endif + +#ifdef _MSC_VER +#define FUNCNAME __FUNCTION__ +#else +#define FUNCNAME __func__ +#endif + +#if defined(__ANDROID__) +#include +#define LOG_TAG_EMU "[EMU] " +#define eprintf(fmt, ...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG_EMU, fmt, ##__VA_ARGS__) +#define eprinterr(fmt, ...) eprintf("[%s] - " fmt, FUNCNAME, ##__VA_ARGS__); +#else +#define eprintf(fmt, ...) printf("[EMU] " fmt, ##__VA_ARGS__) +#define eprinterr(fmt, ...) eprintf("[%s] - " fmt, FUNCNAME, ##__VA_ARGS__); +#endif + +#if defined(__EMSCRIPTEN__) +#define UNIMPLEMENTED() 0; +#else +#define UNIMPLEMENTED() eprinterr("Unimplemented!\n"); +#endif + +#define RESOLUTION_SCALE (1) + +#define VRAM_WIDTH (1024 * RESOLUTION_SCALE) +#define VRAM_HEIGHT (512 * RESOLUTION_SCALE) + +#define TPAGE_WIDTH (256) +#define TPAGE_HEIGHT (256) + +#define CLUT_WIDTH (16) +#define CLUT_HEIGHT (1) + +#define CTR_RUNNING (0) +#define CTR_STOPPED (1) + +#define CTR_MODE_TO_FFFF (0) +#define CTR_MODE_TO_TARG (1) + +#define CTR_CLOCK_SYS (0) +#define CTR_CLOCK_PIXEL (1) +#define CTR_HORIZ_RETRACE (1) + +#define CTR_CLOCK_SYS_ONE (0) +#define CTR_CLOCK_SYS_ONE_EIGHTH (1) + +#define GET_TPAGE_X(tpage) ((tpage << 6) & 0x7C0) % (VRAM_WIDTH / RESOLUTION_SCALE); +#define GET_TPAGE_Y(tpage) ((((tpage << 4) & 0x100) + ((tpage >> 2) & 0x200))) % (VRAM_HEIGHT / RESOLUTION_SCALE); +#define GET_TPAGE_TYPE(tpage) (tpage >> 7) & 0x3; +#define GET_CLUT_X(clut) ((clut & 0x3F) << 4); +#define GET_CLUT_Y(clut) (clut >> 6); + +typedef struct +{ + unsigned int i_cycle; + + union + { + unsigned short cycle; + unsigned short unk00; + }; + + unsigned int i_value; + + union + { + unsigned short value; + unsigned short unk01; + }; + + unsigned int i_target; + + union + { + unsigned short target; + unsigned short unk02; + }; + + + unsigned int padding00; + unsigned int padding01; +} SysCounter; + +extern SysCounter counters[3]; + +#pragma pack(push,1) +struct Vertex +{ + float x, y, z; + float u0, v0; +#if defined(OGL) || defined(OGLES) || defined(VK) + float col[4]; +#elif defined(D3D9) + D3DCOLOR col; +#endif +}; +#pragma pack(pop) + + +enum BlendMode +{ + BM_AVERAGE, + BM_ADD, + BM_SUBTRACT, + BM_ADD_QUATER_SOURCE, + BM_DEFAULT +}; + +extern unsigned int g_lastBoundTexture; +#if defined(OGL) || defined(OGLES) +extern int Emulator_InitialiseGL(); +#elif defined(D3D9) +extern int Emulator_InitialiseD3D(); +#endif +extern void Emulator_SaveVRAM(const char* outputFileName, int x, int y, int width, int height, int bReadFromFrameBuffer); +extern void Emulator_ShutDown(); +extern void Emulator_SwapWindow(); +#if defined(OGL) || defined(OGLES) || defined(VK) +extern unsigned int Emulator_GenerateTpage(unsigned short tpage, unsigned short clut); +#elif defined(D3D9) +IDirect3DTexture9* Emulator_GenerateTpage(unsigned short tpage, unsigned short clut); +#endif +extern void Emulator_DestroyFrameBuffer(unsigned int* fbo); +extern void Emulator_GenerateFrameBuffer(unsigned int* fbo); +extern void Emulator_GenerateAndBindNullWhite(); +extern void Emulator_CheckTextureIntersection(RECT16* rect); +extern void Emulator_SetBlendMode(int mode, int semiTransparent); +extern void Emulator_CounterLoop(); +extern void Emulator_GenerateLineArray(struct Vertex* vertex, short* p0, short* p1, short* p2, short* p3); +extern void Emulator_GenerateVertexArrayQuad(struct Vertex* vertex, short* p0, short* p1, short* p2, short* p3, short w, short h); +extern void Emulator_GenerateTexcoordArrayQuad(struct Vertex* vertex, unsigned char* uv0, unsigned char* uv1, unsigned char* uv2, unsigned char* uv3, short w, short h); +extern void Emulator_GenerateColourArrayQuad(struct Vertex* vertex, unsigned char* col0, unsigned char* col1, unsigned char* col2, unsigned char* col3, int bMultiplyColour); +#if defined(OGL) || defined(OGLES) || defined(D3D9) || defined(VK) +extern void Emulator_Ortho2D(float left, float right, float bottom, float top, float znear, float zfar); +extern void Emulator_Scalef(float sx, float sy, float sz); +#endif +#if defined(OGL) || defined(OGLES) || defined(VK) +extern void Emulator_BindTexture(unsigned int textureId); +#elif defined(D3D9) +extern void Emulator_BindTexture(IDirect3DTexture9* texture); +#endif +extern void Emulator_DestroyTextures(int numTextures, unsigned int* textures); +extern void Emulator_SetViewPort(int x, int y, int width, int height); +extern void Emulator_SetScissorBox(int x, int y, int width, int height); +#if defined(OGL) || defined(OGLES) +extern void Emulator_BindFrameBuffer(GLuint frameBufferObject); +#elif defined(D3D9) +extern void Emulator_BindFrameBuffer(IDirect3DSurface9* frameBufferObject); +#elif defined(VK) +extern void Emulator_BindFrameBuffer(struct FrameBuffer frameBufferObject); +#else +extern void Emulator_BindFrameBuffer(int frameBufferObject); +#endif +extern void Emulator_CreateVertexBuffer(int numVertices, int vertexStride, void* pVertices); +#if defined(D3D9) +extern IDirect3DDevice9* d3ddev; +extern IDirect3DVertexDeclaration9* g_vertexDecl; +#endif + +#endif \ No newline at end of file diff --git a/src_rebuild/EMULATOR/EMULATOR_GLOBALS.H b/src_rebuild/EMULATOR/EMULATOR_GLOBALS.H new file mode 100644 index 00000000..c8dfd07b --- /dev/null +++ b/src_rebuild/EMULATOR/EMULATOR_GLOBALS.H @@ -0,0 +1,78 @@ +#ifndef EMULATOR_GLOBALS_H +#define EMULATOR_GLOBALS_H + + +#include + + +#if defined(D3D9) +extern IDirect3DTexture9* nullWhiteTexture; +extern IDirect3DTexture9* vramTexture; +extern IDirect3DSurface9* vramFrameBuffer; +extern LPDIRECT3DVERTEXBUFFER9 g_vertexBufferObject; +#elif defined(VK) + +struct FrameBufferAttachment +{ + VkImage image; + VkDeviceMemory mem; + VkImageView view; +}; + +struct FrameBuffer +{ + int32_t width, height; + VkFramebuffer frameBuffer; + FrameBufferAttachment color, depth; + VkRenderPass renderPass; + VkSampler sampler; + VkDescriptorImageInfo descriptor; +}; + +extern struct FrameBuffer vramFrameBuffer; +extern unsigned int nullWhiteTexture; +#else +extern unsigned int nullWhiteTexture; +extern unsigned int vramFrameBuffer; +extern unsigned int vramTexture; +#endif +extern int screenWidth; +extern int screenHeight; +extern int windowWidth; +extern int windowHeight; +extern uint32_t DMAControlRegister; +extern int assetsLoaded; +extern unsigned int g_defaultShaderProgram; + +#if defined(OGL) || defined(OGLES) || defined(VK) +extern int g_defaultFBO; +#elif defined(D3D9) +extern IDirect3DSurface9* g_defaultFBO; +#else +extern int g_defaultFBO; +#endif + +struct CachedTexture +{ +#if defined(OGL) || defined(OGLES) + unsigned int textureID; +#elif defined(D3D9) + IDirect3DTexture9* texture; +#endif + unsigned short tpage; + unsigned short clut; + unsigned int lastAccess; +}; + +#define MAX_NUM_CACHED_TEXTURES (512) + +extern struct CachedTexture cachedTextures[MAX_NUM_CACHED_TEXTURES]; + +extern unsigned short UpdateGameControllerInput(SDL_GameController* pad); +extern unsigned short UpdateKeyboardInput(); + +extern SDL_GameController* padHandle[]; +extern unsigned char* padData[]; +extern const unsigned char* keyboardState; + +#endif \ No newline at end of file diff --git a/src_rebuild/EMULATOR/EMULATOR_PLATFORM_SETUP.H b/src_rebuild/EMULATOR/EMULATOR_PLATFORM_SETUP.H new file mode 100644 index 00000000..f55df0c8 --- /dev/null +++ b/src_rebuild/EMULATOR/EMULATOR_PLATFORM_SETUP.H @@ -0,0 +1,98 @@ +#ifndef EMULATOR_PLATFORM_SETUP_H +#define EMULATOR_PLATFORM_SETUP_H + +/* + * Platform specific emulator setup + */ +#if (defined(_WINDOWS) || defined(__APPLE__) || defined(__linux__) || defined(__MINGW32__)) && !defined(__ANDROID__) +//Open Graphics Library (Embedded Systems) +//#define OGLES +//#define OGLES_VERSION 2 + +//Open Graphics Library +#define OGL + +//Direct3D9 +//#define D3D9 + +//Vulkan +//#define VK + +#if defined(OGL) +#define SDL2 +#define GLEW +#endif + +#elif defined(__EMSCRIPTEN__) || defined(__ANDROID__) +#define OGLES +#define OGLES_VERSION (2) +#if OGLES_VERSION == 2 +#define ES2_SHADERS +#elif OGLES_VERSION == 3 +#define ES3_SHADERS +#endif +#define SDL2 +#endif + +#if defined(GLEW) +#define GL_GLEXT_PROTOTYPES 1 +#include +#endif + +/* + * Emulator render options. + */ +#define RO_DOUBLE_BUFFERED + +#if defined(__APPLE__) || defined(__EMSCRIPTEN__) +//#include +#endif + +/* + * SDL.H inclusion. + */ + +#if defined(__APPLE__) +#include +#include +#elif defined(__EMSCRIPTEN__) +#include +#elif (defined(_WINDOWS) || defined(__MINGW32__) || defined(__linux__)) && !defined(__ANDROID__) +#include +#elif defined (__ANDROID__) +#include +#endif + +#if defined (OGL) +#include ///@FIXME see mac! +#elif defined (OGLES) +#include +#if OGLES_VERSION == 2 +#define GL_GLEXT_PROTOTYPES +#include +#include +#elif OGLES_VERSION == 3 +#include +#endif +#include +#elif defined(VK) +#include +#define VK_USE_PLATFORM_WIN32_KHR +#include +#elif defined(D3D9) +#include +#include +#include +#endif + +#if !defined (__EMSCRIPTEN__) +//#include +#endif + +#if defined(OGL) +#define TEXTURE_FORMAT GL_UNSIGNED_SHORT_1_5_5_5_REV +#elif defined(OGLES) +#define TEXTURE_FORMAT GL_UNSIGNED_SHORT_5_5_5_1 +#endif + +#endif \ No newline at end of file diff --git a/src_rebuild/EMULATOR/EMULATOR_PRIVATE.H b/src_rebuild/EMULATOR/EMULATOR_PRIVATE.H new file mode 100644 index 00000000..877217cb --- /dev/null +++ b/src_rebuild/EMULATOR/EMULATOR_PRIVATE.H @@ -0,0 +1,31 @@ +#ifndef EMULATOR_PRIVATE_H +#define EMULATOR_PRIVATE_H + +/* Usually called when loading game textures to tell the emulator how to form an atlas for faster drawing */ +extern void Emulator_HintTextureAtlas(unsigned short tpage, unsigned short clut, unsigned char u0, unsigned char v0, unsigned char u1, unsigned char v1, unsigned char u2, unsigned char v2, unsigned char u3, unsigned char v3, unsigned short bIsQuad); + +/* Usually called at the beginning of main function */ +extern void Emulator_Initialise(char* windowName, int screenWidth, int screenHeight); + +/* Usually called after ClearOTag/ClearOTagR */ +extern void Emulator_BeginScene(); + +/* Usually called after DrawOTag/DrawOTagEnv */ +extern void Emulator_EndScene(); + +/* Explicitly updates emulator input loop */ +extern void Emulator_UpdateInput(); + +/* Usually called at the end if main function */ +extern void Emulator_ShutDown(); + +/* Placeholder, can inject a TIM file into vram */ +extern void Emulator_InjectTIM(char* fileName, unsigned short texTpage, unsigned short texClut, unsigned char u0, unsigned char v0, unsigned char u1, unsigned char v1, unsigned char u2, unsigned char v2, unsigned char u3, unsigned char v3); + +/* Usually called when loading a game level to specifically delete all emulator textures for optimisation purposes */ +extern void Emulator_DestroyAllTextures(); + +/* Sets the maximum vertex count value for PGXP vertex caching */ +extern void Emulator_SetPGXPVertexCount(int vertexCount); + +#endif \ No newline at end of file diff --git a/src_rebuild/EMULATOR/EMULATOR_SETUP.H b/src_rebuild/EMULATOR/EMULATOR_SETUP.H new file mode 100644 index 00000000..e78deac8 --- /dev/null +++ b/src_rebuild/EMULATOR/EMULATOR_SETUP.H @@ -0,0 +1,7 @@ +#ifndef EMULATOR_SETUP_H +#define EMULATOR_SETUP_H + +//Disc image filename to load for disc image builds +#define DISC_IMAGE_FILENAME "TOMB5.BIN" + +#endif \ No newline at end of file diff --git a/src_rebuild/EMULATOR/EMULATOR_VERSION.H b/src_rebuild/EMULATOR/EMULATOR_VERSION.H new file mode 100644 index 00000000..973e37cb --- /dev/null +++ b/src_rebuild/EMULATOR/EMULATOR_VERSION.H @@ -0,0 +1,19 @@ +#ifndef EMULATOR_VERSION_H +#define EMULATOR_VERSION_H + +/* Name of the Emulator */ +#define EMULATOR_NAME "LIBPSX" + +/* Emulator version */ +#define EMULATOR_MAJOR_VERSION (1) +#define EMULATOR_MINOR_VERSION (93) + +/* Compile date and time */ +#define EMULATOR_COMPILE_DATE (__DATE__) +#define EMULATOR_COMPILE_TIME (__TIME__) + +/* Psy-Q version */ +#define PSYQ_MAJOR_VERSION (4) +#define PSYQ_MINOR_VERSION (7) + +#endif \ No newline at end of file diff --git a/src_rebuild/EMULATOR/GPU_D3D9.C b/src_rebuild/EMULATOR/GPU_D3D9.C new file mode 100644 index 00000000..e69de29b diff --git a/src_rebuild/EMULATOR/GPU_D3D9.H b/src_rebuild/EMULATOR/GPU_D3D9.H new file mode 100644 index 00000000..e69de29b diff --git a/src_rebuild/EMULATOR/GTEREG.H b/src_rebuild/EMULATOR/GTEREG.H new file mode 100644 index 00000000..878ad3cf --- /dev/null +++ b/src_rebuild/EMULATOR/GTEREG.H @@ -0,0 +1,118 @@ +#ifndef GTEREG_H +#define GTEREG_H + +//Externals +extern int LIM(int value, int max, int min, unsigned int flag); + +extern GTERegisters gteRegs; + +extern int docop2(int op); + +/* Data Registers mtc2 mfc2 */ +#define VX0 (gteRegs.CP2D.p[ 0 ].sw.l) +#define VY0 (gteRegs.CP2D.p[ 0 ].sw.h) +#define VZ0 (gteRegs.CP2D.p[ 1 ].sw.l) +#define VX1 (gteRegs.CP2D.p[ 2 ].w.l) +#define VY1 (gteRegs.CP2D.p[ 2 ].w.h) +#define VZ1 (gteRegs.CP2D.p[ 3 ].w.l) +#define VX2 (gteRegs.CP2D.p[ 4 ].w.l) +#define VY2 (gteRegs.CP2D.p[ 4 ].w.h) +#define VZ2 (gteRegs.CP2D.p[ 5 ].w.l) +#define R (gteRegs.CP2D.p[ 6 ].b.l) +#define G (gteRegs.CP2D.p[ 6 ].b.h) +#define B (gteRegs.CP2D.p[ 6 ].b.h2) +#define CODE (gteRegs.CP2D.p[ 6 ].b.h3) +#define OTZ (gteRegs.CP2D.p[ 7 ].w.l) +#define IR0 (gteRegs.CP2D.p[ 8 ].sw.l) +#define IR1 (gteRegs.CP2D.p[ 9 ].sw.l) +#define IR2 (gteRegs.CP2D.p[ 10 ].sw.l) +#define IR3 (gteRegs.CP2D.p[ 11 ].sw.l) +#define SXY0 (gteRegs.CP2D.p[ 12 ].d) +#define SX0 (gteRegs.CP2D.p[ 12 ].sw.l) +#define SY0 (gteRegs.CP2D.p[ 12 ].sw.h) +#define SXY1 (gteRegs.CP2D.p[ 13 ].d) +#define SX1 (gteRegs.CP2D.p[ 13 ].sw.l) +#define SY1 (gteRegs.CP2D.p[ 13 ].sw.h) +#define SXY2 (gteRegs.CP2D.p[ 14 ].d) +#define SX2 (gteRegs.CP2D.p[ 14 ].sw.l) +#define SY2 (gteRegs.CP2D.p[ 14 ].sw.h) +#define SXYP (gteRegs.CP2D.p[ 15 ].d) +#define SXP (gteRegs.CP2D.p[ 15 ].sw.l) +#define SYP (gteRegs.CP2D.p[ 15 ].sw.h) +#define SZ0 (gteRegs.CP2D.p[ 16 ].w.l) +#define SZ1 (gteRegs.CP2D.p[ 17 ].w.l) +#define SZ2 (gteRegs.CP2D.p[ 18 ].w.l) +#define SZ3 (gteRegs.CP2D.p[ 19 ].w.l) +#define RGB0 (gteRegs.CP2D.p[ 20 ].d) +#define R0 (gteRegs.CP2D.p[ 20 ].b.l) +#define G0 (gteRegs.CP2D.p[ 20 ].b.h) +#define B0 (gteRegs.CP2D.p[ 20 ].b.h2) +#define CD0 (gteRegs.CP2D.p[ 20 ].b.h3) +#define RGB1 (gteRegs.CP2D.p[ 21 ].d) +#define R1 (gteRegs.CP2D.p[ 21 ].b.l) +#define G1 (gteRegs.CP2D.p[ 21 ].b.h) +#define B1 (gteRegs.CP2D.p[ 21 ].b.h2) +#define CD1 (gteRegs.CP2D.p[ 21 ].b.h3) +#define RGB2 (gteRegs.CP2D.p[ 22 ].d) +#define R2 (gteRegs.CP2D.p[ 22 ].b.l) +#define G2 (gteRegs.CP2D.p[ 22 ].b.h) +#define B2 (gteRegs.CP2D.p[ 22 ].b.h2) +#define CD2 (gteRegs.CP2D.p[ 22 ].b.h3) +#define RES1 (gteRegs.CP2D.p[ 23 ].d) +#define MAC0 (gteRegs.CP2D.p[ 24 ].sd) +#define MAC1 (gteRegs.CP2D.p[ 25 ].sd) +#define MAC2 (gteRegs.CP2D.p[ 26 ].sd) +#define MAC3 (gteRegs.CP2D.p[ 27 ].sd) +#define IRGB (gteRegs.CP2D.p[ 28 ].d) +#define ORGB (gteRegs.CP2D.p[ 29 ].d) +#define LZCS (gteRegs.CP2D.p[ 30 ].d) +#define LZCR (gteRegs.CP2D.p[ 31 ].d) + +/* Control Registers ctc2 cfc2*/ + +#define R11 (gteRegs.CP2C.p[ 0 ].sw.l) +#define R12 (gteRegs.CP2C.p[ 0 ].sw.h) +#define R13 (gteRegs.CP2C.p[ 1 ].sw.l) +#define R21 (gteRegs.CP2C.p[ 1 ].sw.h) +#define R22 (gteRegs.CP2C.p[ 2 ].sw.l) +#define R23 (gteRegs.CP2C.p[ 2 ].sw.h) +#define R31 (gteRegs.CP2C.p[ 3 ].sw.l) +#define R32 (gteRegs.CP2C.p[ 3 ].sw.h) +#define R33 (gteRegs.CP2C.p[ 4 ].sw.l) +#define TRX (gteRegs.CP2C.p[ 5 ].sd) +#define TRY (gteRegs.CP2C.p[ 6 ].sd) +#define TRZ (gteRegs.CP2C.p[ 7 ].sd) +#define L11 (gteRegs.CP2C.p[ 8 ].sw.l) +#define L12 (gteRegs.CP2C.p[ 8 ].sw.h) +#define L13 (gteRegs.CP2C.p[ 9 ].sw.l) +#define L21 (gteRegs.CP2C.p[ 9 ].sw.h) +#define L22 (gteRegs.CP2C.p[ 10 ].sw.l) +#define L23 (gteRegs.CP2C.p[ 10 ].sw.h) +#define L31 (gteRegs.CP2C.p[ 11 ].sw.l) +#define L32 (gteRegs.CP2C.p[ 11 ].sw.h) +#define L33 (gteRegs.CP2C.p[ 12 ].sw.l) +#define RBK (gteRegs.CP2C.p[ 13 ].sd) +#define GBK (gteRegs.CP2C.p[ 14 ].sd) +#define BBK (gteRegs.CP2C.p[ 15 ].sd) +#define LR1 (gteRegs.CP2C.p[ 16 ].sw.l) +#define LR2 (gteRegs.CP2C.p[ 16 ].sw.h) +#define LR3 (gteRegs.CP2C.p[ 17 ].sw.l) +#define LG1 (gteRegs.CP2C.p[ 17 ].sw.h) +#define LG2 (gteRegs.CP2C.p[ 18 ].sw.l) +#define LG3 (gteRegs.CP2C.p[ 18 ].sw.h) +#define LB1 (gteRegs.CP2C.p[ 19 ].sw.l) +#define LB2 (gteRegs.CP2C.p[ 19 ].sw.h) +#define LB3 (gteRegs.CP2C.p[ 20 ].sw.l) +#define RFC (gteRegs.CP2C.p[ 21 ].sd) +#define GFC (gteRegs.CP2C.p[ 22 ].sd) +#define BFC (gteRegs.CP2C.p[ 23 ].sd) +#define OFX (gteRegs.CP2C.p[ 24 ].sd) +#define OFY (gteRegs.CP2C.p[ 25 ].sd) +#define H (gteRegs.CP2C.p[ 26 ].sw.l) +#define DQA (gteRegs.CP2C.p[ 27 ].sw.l) +#define DQB (gteRegs.CP2C.p[ 28 ].sd) +#define ZSF3 (gteRegs.CP2C.p[ 29 ].sw.l) +#define ZSF4 (gteRegs.CP2C.p[ 30 ].sw.l) +#define FLAG (gteRegs.CP2C.p[ 31 ].d) + +#endif \ No newline at end of file diff --git a/src_rebuild/EMULATOR/INLINE_C.C b/src_rebuild/EMULATOR/INLINE_C.C new file mode 100644 index 00000000..28c0e7b6 --- /dev/null +++ b/src_rebuild/EMULATOR/INLINE_C.C @@ -0,0 +1,29 @@ +#include "INLINE_C.H" + +#include "LIBGTE.H" +#include "GTEREG.H" + +void gte_SetGeomScreen(int h) +{ + H = h; +} + +int gte_ldlzc(int input) +{ + int leadingZeroCount = 0; + + if (input > 0) + { + for (int i = (sizeof(int) * 8)-1; i >= 0 ; i--) + { + if (input & (1 << i)) + { + break; + } + + leadingZeroCount++; + } + } + + return leadingZeroCount; +} \ No newline at end of file diff --git a/src_rebuild/EMULATOR/INLINE_C.H b/src_rebuild/EMULATOR/INLINE_C.H new file mode 100644 index 00000000..8defb4b8 --- /dev/null +++ b/src_rebuild/EMULATOR/INLINE_C.H @@ -0,0 +1,7 @@ +#ifndef INLINE_C_H +#define INLINE_C_H + +extern void gte_SetGeomScreen(int h); +extern int gte_ldlzc(int input); + +#endif \ No newline at end of file diff --git a/src_rebuild/EMULATOR/KERNEL.H b/src_rebuild/EMULATOR/KERNEL.H new file mode 100644 index 00000000..eca2eaf4 --- /dev/null +++ b/src_rebuild/EMULATOR/KERNEL.H @@ -0,0 +1,157 @@ +#ifndef KERNEL_H +#define KERNEL_H + +#ifndef R3000_H +#include "R3000.H" +#endif + +#ifndef ASM_H +#include "ASM.H" +#endif + +#define DescMask 0xff000000 +#define DescTH DescMask +#define DescHW 0xf0000000 +#define DescEV 0xf1000000 +#define DescRC 0xf2000000 +#define DescUEV 0xf3000000 +#define DescSW 0xf4000000 + +#define HwVBLANK (DescHW|0x01) +#define HwGPU (DescHW|0x02) +#define HwCdRom (DescHW|0x03) +#define HwDMAC (DescHW|0x04) +#define HwRTC0 (DescHW|0x05) +#define HwRTC1 (DescHW|0x06) +#define HwRTC2 (DescHW|0x07) +#define HwCNTL (DescHW|0x08) +#define HwSPU (DescHW|0x09) +#define HwPIO (DescHW|0x0a) +#define HwSIO (DescHW|0x0b) + +#define HwCPU (DescHW|0x10) +#define HwCARD (DescHW|0x11) +#define HwCARD_0 (DescHW|0x12) +#define HwCARD_1 (DescHW|0x13) +#define SwCARD (DescSW|0x01) +#define SwMATH (DescSW|0x02) + +#define RCntCNT0 (DescRC|0x00) +#define RCntCNT1 (DescRC|0x01) +#define RCntCNT2 (DescRC|0x02) +#define RCntCNT3 (DescRC|0x03) + +#define RCntMdINTR 0x1000 +#define RCntMdNOINTR 0x2000 +#define RCntMdSC 0x0001 +#define RCntMdSP 0x0000 +#define RCntMdFR 0x0000 +#define RCntMdGATE 0x0010 + +#define EvSpCZ 0x0001 /* counter becomes zero */ +#define EvSpINT 0x0002 /* interrupted */ +#define EvSpIOE 0x0004 /* end of i/o */ +#define EvSpCLOSE 0x0008 /* file was closed */ +#define EvSpACK 0x0010 /* command acknowledged */ +#define EvSpCOMP 0x0020 /* command completed */ +#define EvSpDR 0x0040 /* data ready */ +#define EvSpDE 0x0080 /* data end */ +#define EvSpTIMOUT 0x0100 /* time out */ +#define EvSpUNKNOWN 0x0200 /* unknown command */ +#define EvSpIOER 0x0400 /* end of read buffer */ +#define EvSpIOEW 0x0800 /* end of write buffer */ +#define EvSpTRAP 0x1000 /* general interrupt */ +#define EvSpNEW 0x2000 /* new device */ +#define EvSpSYSCALL 0x4000 /* system call instruction */ +#define EvSpERROR 0x8000 /* error happned */ +#define EvSpPERROR 0x8001 /* previous write error happned */ +#define EvSpEDOM 0x0301 /* domain error in libmath */ +#define EvSpERANGE 0x0302 /* range error in libmath */ + +#define EvMdINTR 0x1000 +#define EvMdNOINTR 0x2000 + +#define EvStUNUSED 0x0000 +#define EvStWAIT 0x1000 +#define EvStACTIVE 0x2000 +#define EvStALREADY 0x4000 + +#define TcbMdRT 0x1000 /* reserved by system */ +#define TcbMdPRI 0x2000 /* reserved by system */ + +#define TcbStUNUSED 0x1000 +#define TcbStACTIVE 0x4000 + +struct ToT { + unsigned long *head; + long size; +}; + +struct TCBH { + struct TCB *entry; /* NULL */ + long flag; +}; + +struct TCB { + long status; + long mode; + unsigned long reg[NREGS]; /* never change the offset of this */ + long system[6]; /* reserved by system */ +}; + +struct EvCB { + unsigned long desc; + long status; + long spec; + long mode; + long (*FHandler)(); + long system[2]; /* reserved by system */ +}; + +//#if !defined(D3D9) +#if 0///@FIXME Really not defined D3D9 :/ +struct EXEC { + unsigned long pc0; + unsigned long gp0; + unsigned long t_addr; + unsigned long t_size; + unsigned long d_addr; + unsigned long d_size; + unsigned long b_addr; + unsigned long b_size; + unsigned long s_addr; + unsigned long s_size; + unsigned long sp,fp,gp,ret,base; +}; + + +struct XF_HDR { + char key[8]; + unsigned long text; + unsigned long data; + struct EXEC exec; + char title[60]; /* "PlayStation(tm) Executable A1" */ +}; +#endif + +struct DIRENTRY { + char name[20]; + long attr; + long size; + struct DIRENTRY *next; + long head; + char system[4]; +}; + + +extern struct ToT SysToT[32]; + +extern long SysClearRCnt[]; + +#ifndef NULL +#define NULL (0) +#endif + +#endif /* _KERNEL_H */ + + diff --git a/src_rebuild/EMULATOR/LIBAPI.C b/src_rebuild/EMULATOR/LIBAPI.C new file mode 100644 index 00000000..553bc0e2 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBAPI.C @@ -0,0 +1,506 @@ +#include "LIBAPI.H" + +#include +#include "EMULATOR.H" + +int sp = 0; + +int dword_300[] = { 0x20, 0xD, 0x0, 0x0 }; +int dword_308[] = { 0x10, 0x20, 0x40, 0x1 }; + +long SetRCnt(long spec, unsigned short target, long mode)//(F) +{ + int value = 0x48; + + spec &= 0xFFFF; + if (spec > 2) + { + return 0; + } + + counters[spec].value = 0; + counters[spec].target = target; + + if (spec < 2) + { + if ((mode & 0x10)) + { + value = 0x49; + } + else if ((mode & 0x1))//loc_148 + { + value |= 0x100; + } + } + else + { + //loc_158 + if (spec == 2 && !(mode & 1)) + { + value = 0x248; + }//loc_174 + } + //loc_174 + if ((mode & 0x1000)) + { + value |= 0x10; + }//loc_180 + + counters[spec].value = value; + + return 1; +} + +long GetRCnt(long spec)//(F) +{ + spec &= 0xFFFF; + + if (spec > 2) + { + return 0; + } + + return counters[spec].cycle; +} + +long ResetRCnt(long spec)//(F) +{ + spec &= 0xFFFF; + + if (spec > 2) + { + return 0; + } + + counters[spec].cycle = 0; + + return 1; +} + +long StartRCnt(long spec)//(F) +{ + spec &= 0xFFFF; + dword_300[1] |= dword_308[spec]; + return spec < 3 ? 1 : 0; +} + +long StopRCnt(long spec)//TODO +{ + return 0; +} +#undef OpenEvent +long OpenEvent(unsigned long unk00, long unk01, long unk02, long(*func)()) +{ + UNIMPLEMENTED(); + return 0; +} + +long CloseEvent(long unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +long WaitEvent(long unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +long TestEvent(long unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +long EnableEvent(long unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +long DisableEvent(long unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +void DeliverEvent(unsigned long unk00, unsigned long unk01) +{ + UNIMPLEMENTED(); +} + +void UnDeliverEvent(unsigned long unk00, unsigned long unk01) +{ + UNIMPLEMENTED(); +} + +long OpenTh(long(*func)(), unsigned long unk01, unsigned long unk02) +{ + UNIMPLEMENTED(); + return 0; +} + +int CloseTh(long unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +int ChangeTh(long unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +long open(char* unk00, unsigned long unk01) +{ + UNIMPLEMENTED(); + return 0; +} + +long close(long unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +long lseek(long unk00, long unk01, long unk02) +{ + UNIMPLEMENTED(); + return 0; +} + +long read(long unk00, void* unk01, long unk02) +{ + UNIMPLEMENTED(); + return 0; +} + +long write(long unk00, void* unk01, long unk02) +{ + UNIMPLEMENTED(); + return 0; +} + +long ioctl(long unk00, long unk01, long unk02) +{ + UNIMPLEMENTED(); + return 0; +} + +struct DIRENTRY* firstfile(char* unk00, struct DIRENTRY* unk01) +{ + UNIMPLEMENTED(); + return 0; +} + +struct DIRENTRY* nextfile(struct DIRENTRY* unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +long erase(char* unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +long undelete(char* unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +long format(char* unk00) +{ + UNIMPLEMENTED(); + return 0; +} +long rename(char* unk00, char* unk01) +{ + UNIMPLEMENTED(); + return 0; +} + +long cd(char* unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +long LoadTest(char* unk00, struct EXEC* unk01) +{ + UNIMPLEMENTED(); + return 0; +} + +long Load(char * unk00, struct EXEC* unk01) +{ + UNIMPLEMENTED(); + return 0; +} + +long Exec(struct EXEC * unk00, long unk01, char** unk02) +{ + UNIMPLEMENTED(); + return 0; +} + +long LoadExec(char * unk00, unsigned long unk01, unsigned long unk02) +{ + UNIMPLEMENTED(); + return 0; +} + +long InitPAD(char * unk00, long unk01, char* unk02, long unk03) +{ + UNIMPLEMENTED(); + return 0; +} + +long StartPAD() +{ + UNIMPLEMENTED(); + return 0; +} + +void StopPAD() +{ + UNIMPLEMENTED(); +} + +void EnablePAD() +{ + UNIMPLEMENTED(); +} + +void DisablePAD() +{ + UNIMPLEMENTED(); +} + +void FlushCache() +{ + UNIMPLEMENTED(); +} + +void ReturnFromException() +{ + UNIMPLEMENTED(); +} + +int EnterCriticalSection() +{ + UNIMPLEMENTED(); + return 0; +} + +void ExitCriticalSection() +{ + UNIMPLEMENTED(); +} + +void Exception() +{ + UNIMPLEMENTED(); +} + +void SwEnterCriticalSection() +{ + UNIMPLEMENTED(); +} +void SwExitCriticalSection() +{ + UNIMPLEMENTED(); +} + +unsigned long SetSp(unsigned long newsp)//(F) +{ + unsigned long old_sp = sp; + sp = newsp; + return old_sp; +} + +unsigned long GetSp() +{ + UNIMPLEMENTED(); + return 0; +} + +unsigned long GetGp() +{ + UNIMPLEMENTED(); + return 0; +} + +unsigned long GetCr() +{ + UNIMPLEMENTED(); + return 0; +} + +unsigned long GetSr() +{ + UNIMPLEMENTED(); + return 0; +} + +unsigned long GetSysSp() +{ + UNIMPLEMENTED(); + return 0; +} + +long SetConf(unsigned long unk00, unsigned long unk01, unsigned long unk02) +{ + UNIMPLEMENTED(); + return 0; +} + +void GetConf(unsigned long* unk00, unsigned long* unk01, unsigned long* unk02) +{ + UNIMPLEMENTED(); +} + +long _get_errno(void) +{ + UNIMPLEMENTED(); + return 0; +} + +long _get_error(long unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +void SystemError(char unk00, long unk01) +{ + UNIMPLEMENTED(); +} + +void SetMem(long unk00) +{ + UNIMPLEMENTED(); +} + +long Krom2RawAdd(unsigned long unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +long Krom2RawAdd2(unsigned short unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +void _96_init(void) +{ + UNIMPLEMENTED(); +} + +void _96_remove(void) +{ + UNIMPLEMENTED(); +} + +void _boot(void) +{ + UNIMPLEMENTED(); +} + +void ChangeClearPAD(long unk00) +{ + UNIMPLEMENTED(); +} + +void InitCARD(long val) +{ + UNIMPLEMENTED(); +} + +long StartCARD() +{ + UNIMPLEMENTED(); + return 0; +} + +long StopCARD() +{ + UNIMPLEMENTED(); + return 0; +} + +void _bu_init() +{ + UNIMPLEMENTED(); +} + +long _card_info(long chan) +{ + UNIMPLEMENTED(); + return 0; +} + +long _card_clear(long chan) +{ + UNIMPLEMENTED(); + return 0; +} + +long _card_load(long chan) +{ + UNIMPLEMENTED(); + return 0; +} + +long _card_auto(long val) +{ + UNIMPLEMENTED(); + return 0; +} + +void _new_card() +{ + UNIMPLEMENTED(); +} + +long _card_status(long drv) +{ + UNIMPLEMENTED(); + return 0; +} + +long _card_wait(long drv) +{ + UNIMPLEMENTED(); + return 0; +} + +unsigned long _card_chan(void) +{ + UNIMPLEMENTED(); + return 0; +} + +long _card_write(long chan, long block, unsigned char *buf) +{ + UNIMPLEMENTED(); + return 0; +} + +long _card_read(long chan, long block, unsigned char *buf) +{ + UNIMPLEMENTED(); + return 0; +} + +long _card_format(long chan) +{ + UNIMPLEMENTED(); + return 0; +} diff --git a/src_rebuild/EMULATOR/LIBAPI.H b/src_rebuild/EMULATOR/LIBAPI.H new file mode 100644 index 00000000..f4684b63 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBAPI.H @@ -0,0 +1,104 @@ +#ifndef LIBAPI_H +#define LIBAPI_H + +#ifndef EMU_KERNEL_H +#include "KERNEL.H" +#endif + +extern long SetRCnt(long spec, unsigned short target, long mode); +extern long GetRCnt(long spec); +extern long ResetRCnt(long spec); +extern long StartRCnt(long spec); +extern long StopRCnt(long spec); + +extern long OpenEvent(unsigned long unk00,long,long,long (*func)()); +extern long CloseEvent(long unk00); +extern long WaitEvent(long unk00); +extern long TestEvent(long unk00); +extern long EnableEvent(long unk00); +extern long DisableEvent(long unk00); +extern void DeliverEvent(unsigned long unk00, unsigned long); +extern void UnDeliverEvent(unsigned long unk00, unsigned long); + +extern long OpenTh(long (*func)(), unsigned long , unsigned long); +extern int CloseTh(long unk00); +extern int ChangeTh(long unk00); + +extern long open(char* unk00, unsigned long); +extern long close(long unk00); +extern long lseek(long unk00, long, long); +extern long read(long unk00, void *, long); +extern long write(long unk00, void *, long); +extern long ioctl(long unk00, long, long); +extern struct DIRENTRY* firstfile(char* unk00, struct DIRENTRY *); +extern struct DIRENTRY* nextfile(struct DIRENTRY* unk00); +extern long erase(char* unk00); + + +extern long undelete(char* unk00); +extern long format(char* unk00); +extern long rename(char* unk00, char *); +extern long cd(char* unk00); + +extern long LoadTest(char* unk00, struct EXEC *); +extern long Load(char * unk00, struct EXEC *); +extern long Exec(struct EXEC * unk00, long, char **); +extern long LoadExec(char * unk00, unsigned long, unsigned long); + +extern long InitPAD(char * unk00,long ,char *,long); +extern long StartPAD(); +extern void StopPAD(); +extern void EnablePAD(); +extern void DisablePAD(); + +extern void FlushCache(); +extern void ReturnFromException(); +extern int EnterCriticalSection(); +extern void ExitCriticalSection(); +extern void Exception(); +extern void SwEnterCriticalSection(); +extern void SwExitCriticalSection(); + +extern unsigned long SetSp(unsigned long newsp); +extern unsigned long GetSp(); +extern unsigned long GetGp(); +extern unsigned long GetCr(); +extern unsigned long GetSr(); +extern unsigned long GetSysSp(); + +extern long SetConf(unsigned long,unsigned long,unsigned long); +extern void GetConf(unsigned long *,unsigned long *,unsigned long *); + +extern long _get_errno(void); +extern long _get_error(long); + +extern void SystemError( char, long); +extern void SetMem(long); + +extern long Krom2RawAdd( unsigned long ); +extern long Krom2RawAdd2(unsigned short); + +extern void _96_init(void); +extern void _96_remove(void); +extern void _boot(void); + +extern void ChangeClearPAD( long ); + +/* prototypes added by shino 96/05/22 */ +extern void InitCARD(long val); +extern long StartCARD(); +extern long StopCARD(); +extern void _bu_init(); +extern long _card_info(long chan); +extern long _card_clear(long chan); +extern long _card_load(long chan); +extern long _card_auto(long val); +extern void _new_card(); +extern long _card_status(long drv); +extern long _card_wait(long drv); +extern unsigned long _card_chan(void); +extern long _card_write(long chan, long block, unsigned char *buf); +extern long _card_read(long chan, long block, unsigned char *buf); +extern long _card_format(long chan); + +#endif diff --git a/src_rebuild/EMULATOR/LIBCD.C b/src_rebuild/EMULATOR/LIBCD.C new file mode 100644 index 00000000..05e239a8 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBCD.C @@ -0,0 +1,251 @@ +#include "LIBCD.H" + +#include "EMULATOR_SETUP.H" +#include "EMULATOR.H" + +#include +#include + +int CD_Debug = 0; + +FILE* openFile = NULL; + +typedef struct commandQueue +{ + unsigned int mode; + unsigned char* p; + unsigned int processed; + unsigned int count; +}commandQueue_s, *commandQueue_p; + +#define COMMAND_QUEUE_SIZE 128 + +struct commandQueue comQueue[COMMAND_QUEUE_SIZE]; +int comQueueIndex = 0; +int comQueueCount = 0; +int currentSector = 0; +int sectorSize = 2352;//TODO obtain properly from cue sheet +int CD_com = 0; + +#pragma pack(push, 1) +struct TOC +{ + unsigned char tocEntryLength; + unsigned char extEntryLength; + unsigned int sectorPosition[2]; + unsigned int fileSize[2]; + unsigned char date[7]; + unsigned char flags; + unsigned char fileUnitSize; + unsigned char interleaveGapSize; + unsigned short volSeqNum[2]; + unsigned char nameLength; +}; + +struct Sector +{ + unsigned char sync[12]; /// Sync pattern (usually 00 FF FF FF FF FF FF FF FF FF FF 00) + unsigned char addr[3]; /// Sector address (see below for encoding details) + unsigned char mode; /// Mode (usually 2 for Mode 2 Form 1/2 sectors) + unsigned char subHead[8]; /// Sub-header (00 00 08 00 00 00 08 00 for Form 1 data sectors) + unsigned char data[2048]; /// Data (form 1) + unsigned char edc[4]; /// Error-detection code (CRC32 of data area) + unsigned char ecc[276]; /// Error-correction code (uses Reed-Solomon ECC algorithm) +}; +#pragma pack(pop) + +CdlFILE* CdSearchFile(CdlFILE* fp, char* name) +{ + SDL_memset(fp, 0, sizeof(CdlFILE)); + + if (name[0] == '\\') + { + name++; + } + + if (openFile != NULL) + { + fseek(openFile, 22 * sectorSize, SEEK_SET); + + int tocLocalOffset = 0; + struct Sector sector; + fread(§or, sizeof(struct Sector), 1, openFile); + struct TOC* toc = (struct TOC*)§or.data[0]; + while (toc->tocEntryLength != 0) + { + if (strcmp((char*)§or.data[tocLocalOffset + sizeof(struct TOC)], name) == 0) + { + memcpy(&fp->name[0], (char*)§or.data[tocLocalOffset + sizeof(struct TOC)], strlen(name)); + fp->size = toc->fileSize[0]; + fseek(openFile, toc->sectorPosition[0] * sectorSize, SEEK_SET); + fread(§or, sizeof(struct Sector), 1, openFile); + fp->pos.minute = sector.addr[0]; + fp->pos.second = sector.addr[1]; + fp->pos.sector = sector.addr[2]; + + +#if _DEBUG + eprintf("Found %s\n", name); +#endif + return fp; + } + tocLocalOffset += toc->tocEntryLength; + toc = (struct TOC*)§or.data[tocLocalOffset]; + } + } + + return NULL; +} + +CdlLOC* CdIntToPos(int i, CdlLOC* p) +{ + i += 150; + p->sector = ENCODE_BCD(i % 75); + int rem = i / 75; + p->second = ENCODE_BCD(rem % 60); + p->minute = ENCODE_BCD(rem / 60); + return p; +} + +int CdControl(u_char com, u_char * param, u_char * result) +{ + CdlFILE* cd = (CdlFILE*)param; + + CD_com = com; + + switch (com) + { + case CdlSetloc: + fseek(openFile, CdPosToInt(&cd->pos)*sectorSize, SEEK_SET); + break; + default: + eprinterr("Unhandled command 0x%02X!\n", com); + break; + } + + return 0; +} + +int CdControlB(u_char com, u_char* param, u_char* result) +{ + CdlFILE* cd = (CdlFILE*)param; + + CD_com = com; + + switch (com) + { + case CdlSetloc: + fseek(openFile, CdPosToInt(&cd->pos)*sectorSize, SEEK_SET); + break; + default: + eprinterr("Unhandled command 0x%02X!\n", com); + break; + } + + return 0; +} + +int CdControlF(u_char com, u_char * param) +{ + CdlFILE* cd = (CdlFILE*)param; + + CD_com = com; + + switch (com) + { + case CdlSetloc: + fseek(openFile, CdPosToInt(&cd->pos)*sectorSize, SEEK_SET); + break; + case CdlSetfilter: + //fseek(openFile, CdPosToInt(&cd->pos) * sectorSize, SEEK_SET); + break; + default: + eprinterr("Unhandled command 0x%02X!\n", com); + break; + } + + return 0; +} + +int CdPosToInt(CdlLOC* p) +{ + return (75 * (60 * DECODE_BCD(p->minute) + DECODE_BCD(p->second))) + DECODE_BCD(p->sector) - 150; +} + +int CdRead(int sectors, u_long* buf, int mode) +{ + for (int i = 0; i < COMMAND_QUEUE_SIZE; i++) + { + if (comQueue[i].processed == 1) + { + comQueue[i].mode = CdlReadS; + comQueue[i].p = (unsigned char*)buf; + comQueue[i].processed = 0; + comQueue[i].count = sectors; + break; + } + } + return 0; +} + +int CdReadSync(int mode, u_char* result) +{ + for (int i = 0; i < COMMAND_QUEUE_SIZE; i++) + { + if (comQueue[i].processed == 0) + { + struct Sector sector; + fread(§or, sizeof(struct Sector), 1, openFile); + + memcpy(comQueue[i].p, §or.data[0], 2048); + comQueue[i].p += 2048; + + if (--comQueue[i].count == 0) + { + comQueue[i].processed = 1; + break; + } + + return 1; + } + } + return 0; +} + +int CdSetDebug(int level) +{ + int lastLevel = CD_Debug; + CD_Debug = level; + return lastLevel; +} + +int CdSync(int mode, u_char * result) +{ + UNIMPLEMENTED(); + return 0; +} + +int CdInit(void) +{ + SDL_memset(&comQueue, 0, sizeof(comQueue)); + currentSector = 0; + openFile = fopen(DISC_IMAGE_FILENAME, "rb"); + + if (openFile == NULL) + { + eprinterr("Failed to open disc image file! %s\n", DISC_IMAGE_FILENAME); + return 0; + } + + for (int i = 0; i < COMMAND_QUEUE_SIZE; i++) + { + comQueue[i].processed = 1; + } + + return 1; +} + +int CdLastCom(void) +{ + return CD_com; +} diff --git a/src_rebuild/EMULATOR/LIBCD.H b/src_rebuild/EMULATOR/LIBCD.H new file mode 100644 index 00000000..73bc1cf6 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBCD.H @@ -0,0 +1,248 @@ +#ifndef LIBCD_H +#define LIBCD_H + +#include "TYPES.H" + + +#define DECODE_BCD(x) (((x) >> 4) * 10 + ((x) & 0xF)) +#define ENCODE_BCD(x) ((((x) / 10) << 4) | ((x) % 10)) + +#define CdlModeStream 0x100 /* Normal Streaming */ +#define CdlModeStream2 0x120 /* SUB HEADER information includes */ +#define CdlModeSpeed 0x80 /* 0: normal speed 1: double speed */ +#define CdlModeRT 0x40 /* 0: ADPCM off 1: ADPCM on */ +#define CdlModeSize1 0x20 /* 0: 2048 byte 1: 2340byte */ +#define CdlModeSize0 0x10 /* 0: - 1: 2328byte */ +#define CdlModeSF 0x08 /* 0: Channel off 1: Channel on */ +#define CdlModeRept 0x04 /* 0: Report off 1: Report on */ +#define CdlModeAP 0x02 /* 0: AutoPause off 1: AutoPause on */ +#define CdlModeDA 0x01 /* 0: CD-DA off 1: CD-DA on */ + +/* + * Status Contents + */ +#define CdlStatPlay 0x80 /* playing CD-DA */ +#define CdlStatSeek 0x40 /* seeking */ +#define CdlStatRead 0x20 /* reading data sectors */ +#define CdlStatShellOpen 0x10 /* once shell open */ +#define CdlStatSeekError 0x04 /* seek error detected */ +#define CdlStatStandby 0x02 /* spindle motor rotating */ +#define CdlStatError 0x01 /* command error detected */ + +/* + * Macros for CdGetDiskType() + */ +#define CdlStatNoDisk 0 +#define CdlOtherFormat 1 +#define CdlCdromFormat 2 + +/* + * CD-ROM Primitive Commands + */ +#define CdlNop 0x01 +#define CdlSetloc 0x02 +#define CdlPlay 0x03 +#define CdlForward 0x04 +#define CdlBackward 0x05 +#define CdlReadN 0x06 +#define CdlStandby 0x07 +#define CdlStop 0x08 +#define CdlPause 0x09 +#define CdlMute 0x0b +#define CdlDemute 0x0c +#define CdlSetfilter 0x0d +#define CdlSetmode 0x0e +#define CdlGetparam 0x0f +#define CdlGetlocL 0x10 +#define CdlGetlocP 0x11 +#define CdlGetTN 0x13 +#define CdlGetTD 0x14 +#define CdlSeekL 0x15 +#define CdlSeekP 0x16 +#define CdlReadS 0x1B + +/* + * Interrupts + */ +#define CdlNoIntr 0x00 /* No interrupt */ +#define CdlDataReady 0x01 /* Data Ready */ +#define CdlComplete 0x02 /* Command Complete */ +#define CdlAcknowledge 0x03 /* Acknowledge (reserved) */ +#define CdlDataEnd 0x04 /* End of Data Detected */ +#define CdlDiskError 0x05 /* Error Detected */ + +/* + * Library Macros + */ +#ifndef btoi +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ +#endif +#ifndef itob +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ +#endif + +#define CdSeekL(p) CdControl(CdlSeekL, (u_char *)p, 0) +#define CdSeekP(p) CdControl(CdlSeekP, (u_char *)p, 0) +#define CdStandby() CdControl(CdlStandby, 0, 0) +#define CdPause() CdControl(CdlPause, 0, 0) +#define CdStop() CdControl(CdlStop, 0, 0) +#define CdMute() CdControl(CdlMute, 0, 0) +#define CdDeMute() CdControl(CdlDemute, 0, 0) +#define CdForward() CdControl(CdlForward, 0, 0) +#define CdBackward() CdControl(CdlBackward, 0, 0) + +/* + * Position + */ +#define CdlMAXTOC 100 + +/* + * Callback + */ + +typedef void (*CdlCB)(u_char,u_char *); + +/* + * Location + */ +typedef struct { + u_char minute; /* minute (BCD) */ + u_char second; /* second (BCD) */ + u_char sector; /* sector (BCD) */ + u_char track; /* track (void) */ +} CdlLOC; + +/* + * ADPCM Filter + */ +typedef struct { + u_char file; /* file ID (always 1) */ + u_char chan; /* channel ID */ + u_short pad; +} CdlFILTER; + +/* + * Attenuator + */ +typedef struct { + u_char val0; /* volume for CD(L) -> SPU (L) */ + u_char val1; /* volume for CD(L) -> SPU (R) */ + u_char val2; /* volume for CD(R) -> SPU (L) */ + u_char val3; /* volume for CD(R) -> SPU (R) */ +} CdlATV; + +/* + * Low Level File System for CdSearchFile() + */ +#define CdlMAXFILE 64 /* max number of files in a diRECT16ory */ +#define CdlMAXDIR 128 /* max number of total diRECT16ories */ +#define CdlMAXLEVEL 8 /* max levels of diRECT16ories */ + +typedef struct { + CdlLOC pos; /* file location */ + u_long size; /* file size */ + char name[16]; /* file name (body) */ +} CdlFILE; + + +/*#define MULTI_INTERRUPT */ +#ifndef MULTI_INTERRUPT +#define pauseMULI() +#define restartMULI() +#endif + +/* + * Streaming Structures + */ +typedef struct { + u_short id; + u_short type; + u_short secCount; + u_short nSectors; + u_long frameCount; + u_long frameSize; + + u_short width; + u_short height; + u_long dummy1; + u_long dummy2; + CdlLOC loc; +} StHEADER; /* CD-ROM STR structure */ + +#define StFREE 0x0000 +#define StREWIND 0x0001 +#define StCOMPLETE 0x0002 +#define StBUSY 0x0003 +#define StLOCK 0x0004 + +#define EDC 0 +#define SECTOR_SIZE (512) /* Sector Size (word) */ +#define HEADER_SIZE (8) /* Header Size (word) */ + +#define StSTATUS 0x00 +#define StVER 0x00 +#define StTYPE 0x01 +#define StSECTOR_OFFSET 0x02 +#define StSECTOR_SIZE 0x03 +#define StFRAME_NO 0x04 +#define StFRAME_SIZE 0x06 + +#define StMOVIE_WIDTH 0x08 +#define StMOVIE_HEIGHT 0x09 + + +void StSetRing(u_long *ring_addr,u_long ring_size); +void StClearRing(void); +void StUnSetRing(void); +void StSetStream(u_long mode,u_long start_frame,u_long end_frame, + void (*func1)(),void (*func2)()); +void StSetEmulate(u_long *addr,u_long mode,u_long start_frame, + u_long end_frame,void (*func1)(),void (*func2)()); +u_long StFreeRing(u_long *base); +u_long StGetNext(u_long **addr,u_long **header); +u_long StGetNextS(u_long **addr,u_long **header); +u_short StNextStatus(u_long **addr,u_long **header); +void StRingStatus(short *free_sectors,short *over_sectors); +void StSetMask(u_long mask,u_long start,u_long end); +void StCdInterrupt(void); +int StGetBackloc(CdlLOC *loc); +int StSetChannel(u_long channel); + +void CdFlush(void); +CdlFILE *CdSearchFile(CdlFILE *fp, char *name); +CdlLOC *CdIntToPos(int i, CdlLOC *p) ; +char *CdComstr(u_char com); +char *CdIntstr(u_char intr); +int CdControl(u_char com, u_char *param, u_char *result); +int CdControlB(u_char com, u_char *param, u_char *result); +int CdControlF(u_char com, u_char *param); +int CdGetSector(void *madr, int size); +int CdGetSector2( void* madr, int size ); +int CdDataSync(int mode); +int CdGetToc(CdlLOC *loc) ; +int CdPlay(int mode, int *track, int offset); +int CdMix(CdlATV *vol); +int CdPosToInt(CdlLOC *p); +int CdRead(int sectors, u_long *buf, int mode); +int CdRead2(long mode); +int CdReadFile(char *file, u_long *addr, int nbyte); +int CdReadSync(int mode, u_char *result); +int CdReady(int mode, u_char *result) ; +int CdSetDebug(int level); +int CdSync(int mode, u_char *result) ; +void (*CdDataCallback(void (*func)())); +CdlCB CdReadCallback(CdlCB func); +CdlCB CdReadyCallback(CdlCB func); +CdlCB CdSyncCallback(CdlCB func); +int CdInit(void); +int CdReset(int mode); +int CdStatus(void); +int CdLastCom(void); +CdlLOC *CdLastPos(void); +int CdMode(void); +int CdDiskReady( int mode ); +int CdGetDiskType( void ); +struct EXEC *CdReadExec(char *file); +void CdReadBreak( void ); + +#endif diff --git a/src_rebuild/EMULATOR/LIBETC.C b/src_rebuild/EMULATOR/LIBETC.C new file mode 100644 index 00000000..25c51453 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBETC.C @@ -0,0 +1,58 @@ +#include "LIBETC.H" + +#include "EMULATOR_PRIVATE.H" +#include "EMULATOR.H" + +#if defined(_WINDOWS) +#include +#endif + +void(*vsync_callback)(void) = NULL; + +int ResetCallback(void) +{ + vsync_callback = NULL; + return 0; +} + +int VSync(int mode) +{ + ///static int startTime = SDL_GetTicks(); + + if (mode == 0) + { + if (vsync_callback != NULL) + { + vsync_callback(); + } + + Emulator_EndScene(); + ///return (SDL_GetTicks() - startTime / 1000); + } + else if (mode > 0) + { + while (mode--) + { + //vblank + } + Emulator_EndScene(); + } + else if (mode < 0) + { + //Unimplemented + ///return (SDL_GetTicks() / 1000); + } + + return 0;//Assert? +} + +int VSyncCallback(void(*f)(void)) +{ + vsync_callback = f; + return 0; +} + +long GetVideoMode(void) +{ + return MODE_NTSC; +} diff --git a/src_rebuild/EMULATOR/LIBETC.H b/src_rebuild/EMULATOR/LIBETC.H new file mode 100644 index 00000000..be26a217 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBETC.H @@ -0,0 +1,56 @@ +#ifndef LIBETC_H +#define LIBETC_H + +#include "TYPES.H" + +extern int PadIdentifier; + +#define PADLup (1<<12) +#define PADLdown (1<<14) +#define PADLleft (1<<15) +#define PADLright (1<<13) +#define PADRup (1<< 4) +#define PADRdown (1<< 6) +#define PADRleft (1<< 7) +#define PADRright (1<< 5) +#define PADi (1<< 9) +#define PADj (1<<10) +#define PADk (1<< 8) +#define PADl (1<< 3) +#define PADm (1<< 1) +#define PADn (1<< 2) +#define PADo (1<< 0) +#define PADh (1<<11) +#define PADL1 PADn +#define PADL2 PADo +#define PADR1 PADl +#define PADR2 PADm +#define PADstart PADh +#define PADselect PADk + +#define MOUSEleft (1<<3) +#define MOUSEright (1<<2) + +#define _PAD(x,y) ((y)<<((x)<<4)) + +#define getScratchAddr(offset) ((u_long *)(0x1f800000+(offset)*4)) + +#define MODE_NTSC 0 +#define MODE_PAL 1 + +extern int CheckCallback(void); +extern void PadInit(int mode); +extern int ResetCallback(void); +extern int RestartCallback(void); +extern int StopCallback(void); +extern int VSync(int mode); +extern int VSyncCallback(void (*f)(void)) ; +extern long GetVideoMode (void); +extern long SetVideoMode (long mode); +extern u_long PadRead(int id); +extern void PadStop(void); +extern void(*vsync_callback)(void); + +#endif + + diff --git a/src_rebuild/EMULATOR/LIBGPU.C b/src_rebuild/EMULATOR/LIBGPU.C new file mode 100644 index 00000000..d694cc90 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBGPU.C @@ -0,0 +1,2886 @@ +#include "LIBGPU.H" + +#include "EMULATOR.H" +#include "EMULATOR_GLOBALS.H" +#include "EMULATOR_PRIVATE.H" + +#include + +#include + +#include +#include +#include +#include + +DISPENV word_33BC; +DRAWENV activeDrawEnv; +DRAWENV byte_9CCA4; +int dword_3410 = 0; +char byte_3352 = 0; + +#if defined(OGL) || defined(OGLES) +#define POLY_TYPE_TRIANGLES GL_TRIANGLES +#define POLY_TYPE_LINES GL_LINES +#elif defined(D3D9) +#define POLY_TYPE_TRIANGLES D3DPT_TRIANGLELIST +#define POLY_TYPE_LINES D3DPT_LINELIST +#else +#define POLY_TYPE_TRIANGLES 0 +#define POLY_TYPE_LINES 1 +#endif + +#if 0 +char fontDebugTexture[] = +{ +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x00,0x00, +0x00,0x10,0x11,0x00,0x00,0x11,0x11,0x01,0x00,0x10,0x00,0x00,0x00,0x10,0x01,0x00, +0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x10,0x00, +0x00,0x01,0x01,0x01,0x00,0x11,0x00,0x01,0x00,0x01,0x01,0x00,0x00,0x11,0x00,0x00, +0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x01,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x11,0x01, +0x00,0x01,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x11,0x00,0x00,0x00,0x01,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00, +0x00,0x10,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x11,0x11,0x01, +0x00,0x00,0x00,0x00,0x00,0x11,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00, +0x00,0x00,0x01,0x01,0x00,0x10,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x00, +0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x11,0x00,0x00,0x00,0x01,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x11,0x01, +0x00,0x01,0x01,0x01,0x00,0x01,0x10,0x01,0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x01,0x00, +0x00,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x01,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00, +0x00,0x10,0x11,0x00,0x00,0x01,0x10,0x01,0x00,0x10,0x01,0x01,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00, +0x00,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x10,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x00, +0x00,0x00,0x10,0x00,0x00,0x11,0x11,0x01,0x00,0x00,0x11,0x00,0x00,0x11,0x11,0x01, +0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x11,0x00, +0x00,0x01,0x00,0x01,0x00,0x10,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, +0x00,0x00,0x11,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x01, +0x00,0x01,0x10,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01, +0x00,0x10,0x10,0x00,0x00,0x11,0x11,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x10,0x00, +0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00, +0x00,0x00,0x01,0x00,0x00,0x11,0x11,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00, +0x00,0x01,0x01,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x11,0x00, +0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x11,0x11,0x00,0x00,0x00,0x10,0x00, +0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x01,0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00, +0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00, +0x00,0x11,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01, +0x00,0x11,0x11,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00, +0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x01,0x00,0x00,0x11,0x11,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00, +0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x01, +0x00,0x00,0x10,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00, +0x00,0x01,0x00,0x01,0x00,0x00,0x10,0x00,0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00, +0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x00,0x00,0x11,0x11,0x01,0x00,0x10,0x11,0x00, +0x00,0x00,0x10,0x00,0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x00,0x00,0x00,0x01,0x00, +0x00,0x10,0x11,0x00,0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x00,0x00,0x11,0x11,0x00,0x00,0x10,0x11,0x00, +0x00,0x11,0x11,0x00,0x00,0x11,0x11,0x01,0x00,0x11,0x11,0x01,0x00,0x10,0x11,0x00, +0x00,0x01,0x00,0x01,0x00,0x10,0x11,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01, +0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x10,0x11,0x00, +0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, +0x00,0x10,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01, +0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x10,0x00, +0x00,0x01,0x00,0x00,0x00,0x11,0x10,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, +0x00,0x01,0x11,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00, +0x00,0x10,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00, +0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x01,0x00, +0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x11,0x00,0x01,0x00,0x01,0x00,0x01, +0x00,0x01,0x01,0x01,0x00,0x11,0x11,0x01,0x00,0x11,0x11,0x00,0x00,0x01,0x00,0x00, +0x00,0x10,0x00,0x01,0x00,0x11,0x11,0x00,0x00,0x11,0x11,0x00,0x00,0x01,0x00,0x00, +0x00,0x11,0x11,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x11,0x00,0x00, +0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x01,0x01,0x00,0x01,0x00,0x01, +0x00,0x01,0x11,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00, +0x00,0x10,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x01, +0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x01,0x00, +0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x10,0x01,0x00,0x01,0x00,0x01, +0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, +0x00,0x10,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01, +0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x10,0x00, +0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, +0x00,0x10,0x11,0x00,0x00,0x01,0x00,0x01,0x00,0x11,0x11,0x00,0x00,0x10,0x11,0x00, +0x00,0x11,0x11,0x00,0x00,0x11,0x11,0x01,0x00,0x01,0x00,0x00,0x00,0x10,0x11,0x00, +0x00,0x01,0x00,0x01,0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x00,0x00,0x01,0x00,0x01, +0x00,0x11,0x11,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x10,0x11,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x11,0x11,0x00,0x00,0x10,0x11,0x00,0x00,0x11,0x11,0x00,0x00,0x10,0x11,0x00, +0x00,0x11,0x11,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, +0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x11,0x11,0x01,0x00,0x00,0x01,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x00,0x00, +0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, +0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, +0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x00, +0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00, +0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00, +0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, +0x00,0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00, +0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x11,0x11,0x00,0x00,0x01,0x00,0x01,0x00,0x11,0x11,0x00,0x00,0x10,0x11,0x00, +0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, +0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x11,0x11,0x01,0x00,0x00,0x01,0x00, +0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x10,0x10,0x00,0x00,0x01,0x01,0x01, +0x00,0x10,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00, +0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x01,0x10,0x00,0x00,0x01,0x00,0x01, +0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x10,0x10,0x00,0x00,0x11,0x10,0x01, +0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00, +0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x01,0x00,0x00,0x00,0x10,0x01,0x01,0x00,0x01,0x00,0x01,0x00,0x10,0x11,0x00, +0x00,0x00,0x01,0x00,0x00,0x10,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01, +0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x11,0x11,0x01,0x00,0x00,0x01,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x01, +0x00,0x00,0x00,0x00,0x00,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; +#endif +//unk_E88 +unsigned char fontDebugClut[] = { 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +int g_swapInterval = 0; +int g_wireframeMode = 0; +int g_texturelessMode = 0; + +struct VertexBufferSplitIndex +{ + unsigned short splitIndex; + unsigned short numVertices; +#if defined(OGL) || defined(OGLES) || defined(VK) + unsigned int textureId; +#elif defined(D3D9) + IDirect3DTexture9* textureId; +#endif + unsigned char semiTrans; + unsigned char abr; + unsigned char primitiveType; +}; + +//#define DEBUG_POLY_COUNT + +#if defined(DEBUG_POLY_COUNT) +static int polygon_count = 0; +#endif + +#define MAX_NUM_POLY_BUFFER_VERTICES (12040)//?FIXME +#define MAX_NUM_INDEX_BUFFERS (4096) +struct Vertex g_vertexBuffer[MAX_NUM_POLY_BUFFER_VERTICES]; +unsigned char* g_IndexBuffer[MAX_NUM_INDEX_BUFFERS]; +struct VertexBufferSplitIndex g_splitIndices[MAX_NUM_INDEX_BUFFERS]; +int g_vertexIndex = 0; +int currentIndexBuffer = 0; +int g_numSplitIndices = 0; + +//#define WIREFRAME_MODE + +#if defined(USE_32_BIT_ADDR) +unsigned long terminator[2] = { -1, 0 }; +#else +unsigned long terminator = -1; +#endif + +void(*drawsync_callback)(void) = NULL; + +void* off_3348[]= +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +int ClearImage(RECT16* rect, u_char r, u_char g, u_char b) +{ + Emulator_CheckTextureIntersection(rect); + Emulator_BindFrameBuffer(vramFrameBuffer); + Emulator_SetScissorBox(rect->x * RESOLUTION_SCALE, rect->y * RESOLUTION_SCALE, rect->w * RESOLUTION_SCALE, rect->h * RESOLUTION_SCALE); + +#if defined(OGL) || defined(OGLES) + glClearColor(r/255.0f, g/255.0f, b/255.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +#elif defined(D3D9) + D3DRECT convertedRect; + convertedRect.x1 = rect->x * RESOLUTION_SCALE; + convertedRect.x2 = (rect->x * RESOLUTION_SCALE) + (rect->w * RESOLUTION_SCALE); + convertedRect.y1 = rect->y * RESOLUTION_SCALE; + convertedRect.y2 = (rect->y * RESOLUTION_SCALE) + (rect->h * RESOLUTION_SCALE); + if FAILED(d3ddev->Clear(1, &convertedRect, D3DCLEAR_TARGET, D3DXCOLOR(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f), 1.0f, 0)) + { + eprinterr("Failed to clear Render Target"); + } +#endif + return 0; +} + +int DrawSync(int mode) +{ + if (drawsync_callback != NULL) + { + drawsync_callback(); + } + + return 0; +} + +int LoadImagePSX(RECT16* rect, u_long* p) +{ + Emulator_CheckTextureIntersection(rect); + Emulator_SetScissorBox(rect->x * RESOLUTION_SCALE, rect->y * RESOLUTION_SCALE, rect->w * RESOLUTION_SCALE, rect->h * RESOLUTION_SCALE); + +#if defined(OGL) || defined(OGLES) + Emulator_BindTexture(vramTexture); + glTexSubImage2D(GL_TEXTURE_2D, 0, rect->x * RESOLUTION_SCALE, rect->y * RESOLUTION_SCALE, rect->w, rect->h, GL_RGBA, TEXTURE_FORMAT, &p[0]); +#elif defined(D3D9) + D3DLOCKED_RECT lockedRect; + RECT convertedRect; + convertedRect.top = rect->y * RESOLUTION_SCALE; + convertedRect.bottom = (rect->y * RESOLUTION_SCALE) + (rect->h * RESOLUTION_SCALE); + convertedRect.left = rect->x * RESOLUTION_SCALE; + convertedRect.right = (rect->x * RESOLUTION_SCALE) + (rect->w * RESOLUTION_SCALE); + vramFrameBuffer->LockRect(&lockedRect, &convertedRect, 0); + + unsigned short* src = (unsigned short*)p; + unsigned short* dest = (unsigned short*)lockedRect.pBits; + + for (int y = 0; y < rect->h; y++) + { + for (int x = 0; x < rect->w; x++) + { + dest[x] = src[x]; + } + + src += rect->w; + dest += lockedRect.Pitch / 2; + } + + vramFrameBuffer->UnlockRect(); +#endif + +#if _DEBUG && 0 + Emulator_SaveVRAM("VRAM3.TGA", 0, 0, rect->w, rect->h, TRUE); +#endif + + return 0; +} + +int MargePrim(void* p0, void* p1) +{ + int v0 = ((unsigned char*)p0)[3]; + int v1 = ((unsigned char*)p1)[3]; + + v0 += v1; + v1 = v0 + 1; + + if (v1 < 0x11) + { + ((char*)p0)[3] = v1; + ((int*)p1)[0] = 0; + return 0; + } + + return -1; +} + +int MoveImage(RECT16* rect, int x, int y) +{ + /* + RECT drawRect; + drawRect.x = x; + drawRect.y = y; + drawRect.w = rect->w; + drawRect.h = rect->h; + Emulator_CheckTextureIntersection(drawRect); + */ + + Emulator_SetScissorBox(x * RESOLUTION_SCALE, y * RESOLUTION_SCALE, x + rect->w * RESOLUTION_SCALE, y + rect->h * RESOLUTION_SCALE); + +#if defined(OGL) || defined(OGLES) + Emulator_BindTexture(vramTexture); +#endif + + unsigned short* pixels = (unsigned short*)SDL_malloc(rect->w * RESOLUTION_SCALE * rect->h * RESOLUTION_SCALE * sizeof(unsigned short)); +#if defined(OGL) || defined(OGLES) + glReadPixels(rect->x * RESOLUTION_SCALE, rect->y * RESOLUTION_SCALE, rect->w * RESOLUTION_SCALE, rect->h * RESOLUTION_SCALE, GL_RGBA, TEXTURE_FORMAT, &pixels[0]); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rect->w, rect->h, GL_RGBA, TEXTURE_FORMAT, &pixels[0]); +#elif defined(D3D9) + D3DLOCKED_RECT lockedRect; + RECT convertedRect; + convertedRect.top = rect->y * RESOLUTION_SCALE; + convertedRect.bottom = (rect->y * RESOLUTION_SCALE) + (rect->h * RESOLUTION_SCALE); + convertedRect.left = rect->x * RESOLUTION_SCALE; + convertedRect.right = (rect->x * RESOLUTION_SCALE) + (rect->w * RESOLUTION_SCALE); + vramFrameBuffer->LockRect(&lockedRect, &convertedRect, 0); + + unsigned short* src = (unsigned short*)lockedRect.pBits; + unsigned short* dest = pixels; + + for (int y = 0; y < rect->h; y++) + { + for (int x = 0; x < rect->w; x++) + { + dest[x] = src[x]; + } + + src += lockedRect.Pitch / 2; + dest += rect->w; + } + vramFrameBuffer->UnlockRect(); + + convertedRect.top = y * RESOLUTION_SCALE; + convertedRect.bottom = (y * RESOLUTION_SCALE) + (rect->h * RESOLUTION_SCALE); + convertedRect.left = x * RESOLUTION_SCALE; + convertedRect.right = (x * RESOLUTION_SCALE) + (rect->w * RESOLUTION_SCALE); + vramFrameBuffer->LockRect(&lockedRect, &convertedRect, 0); + + src = pixels; + dest = (unsigned short*)lockedRect.pBits; + + for (int y = 0; y < rect->h; y++) + { + for (int x = 0; x < rect->w; x++) + { + dest[x] = src[x]; + } + + src += rect->w; + dest += lockedRect.Pitch / 2; + } + vramFrameBuffer->UnlockRect(); +#endif + return 0; +} + +int ResetGraph(int mode) +{ + UNIMPLEMENTED(); + return 0; +} + +int SetGraphDebug(int level) +{ + UNIMPLEMENTED(); + return 0; +} + +int StoreImage(RECT16* rect, u_long * p) +{ + Emulator_BindFrameBuffer(vramFrameBuffer); +#if defined(OGL) + glReadPixels(rect->x, rect->y, rect->w, rect->h, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, &p[0]); +#elif defined(OGLES) + glReadPixels(rect->x, rect->y, rect->w, rect->h, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short*)&p[0]); +#elif defined(D3D9) + assert(FALSE);//Unimplemented +#elif defined(VK) + assert(FALSE);//Unimplemented +#endif + return 0; +} + +u_long* ClearOTag(u_long* ot, int n) +{ + //Nothing to do here. + if (n == 0) + return NULL; + + //last is special terminator + ot[n - 1] = (unsigned long)&terminator; + + for (int i = n - 2; i > -1; i--) + { + ot[i] = (unsigned long)&ot[i + 1]; + } + + return NULL; +} + +u_long* ClearOTagR(u_long* ot, int n) +{ + //Nothing to do here. + if (n == 0) + return NULL; + + //First is special terminator + setaddr(ot, &terminator); + setlen(ot, 0); + +#if defined(USE_32_BIT_ADDR) + for (int i = 2; i < n * 2; i+=2) +#else + for (int i = 1; i < n ; i++) +#endif + { +#if defined(USE_32_BIT_ADDR) + setaddr(&ot[i], (unsigned long)&ot[i - 2]); +#else + setaddr(&ot[i], (unsigned long)&ot[i - 1]); +#endif + setlen(&ot[i], 0); + } + + return NULL; +} + +void SetDispMask(int mask) +{ + UNIMPLEMENTED(); +} + +int FntPrint(char* text, ...) +{ + UNIMPLEMENTED(); + return 0; +} + +DISPENV* GetDispEnv(DISPENV* env)//(F) +{ + memcpy(env, &word_33BC, sizeof(DISPENV)); + return env; +} + +DISPENV* PutDispEnv(DISPENV* env)//To Finish +{ + memcpy((char*)&word_33BC, env, sizeof(DISPENV)); + return 0; +} + +DISPENV* SetDefDispEnv(DISPENV* env, int x, int y, int w, int h)//(F) +{ + env->disp.x = x; + env->disp.y = y; + env->disp.w = w; + env->screen.x = 0; + env->screen.y = 0; + env->screen.w = 0; + env->screen.h = 0; + env->isrgb24 = 0; + env->isinter = 0; + env->pad1 = 0; + env->pad0 = 0; + env->disp.h = h; + return 0; +} + +DRAWENV* GetDrawEnv(DRAWENV* env) +{ + UNIMPLEMENTED(); + return NULL; +} + +DRAWENV* PutDrawEnv(DRAWENV* env)//Guessed +{ + memcpy((char*)&activeDrawEnv, env, sizeof(DRAWENV)); + return 0; +} + +DRAWENV* SetDefDrawEnv(DRAWENV* env, int x, int y, int w, int h)//(F) +{ + env->clip.x = x; + env->clip.y = y; + env->clip.w = w; + env->tw.x = 0; + env->tw.y = 0; + env->tw.w = 0; + env->tw.h = 0; + env->r0 = 0; + env->g0 = 0; + env->b0 = 0; + env->dtd = 1; + env->clip.h = h; + + if (GetVideoMode() == 0) + { + env->dfe = h < 0x121 ? 1 : 0; + } + else + { + env->dfe = h < 0x101 ? 1 : 0; + } + + env->ofs[0] = x; + env->ofs[1] = y; + + env->tpage = 10; + env->isbg = 0; + + return env; +} + +void SetDrawEnv(DR_ENV* dr_env, DRAWENV* env) +{ + +} + +void SetDrawMode(DR_MODE* p, int dfe, int dtd, int tpage, RECT16* tw) +{ + setDrawMode(p, dfe, dtd, tpage, tw); +} + +u_long DrawSyncCallback(void(*func)(void)) +{ + drawsync_callback = func; + return 0; +} + +u_short GetClut(int x, int y) +{ + return getClut(x, y); +} + +#if defined(OGLES) || defined(OGL) +GLuint vbo; +GLuint vao; +#elif defined(D3D9) +LPDIRECT3DVERTEXBUFFER9 g_vertexBufferObject = NULL; +#endif + +static unsigned short lastTpage = 0xFFFF; +static unsigned short lastClut = 0xFFFF; +static unsigned short lastSemiTrans = 0xFFFF; +static unsigned short lastPolyType = 0xFFFF; +static unsigned short numVertices = 0; + +void DrawOTagEnv(u_long* p, DRAWENV* env)// +{ +#if defined(DEBUG_POLY_COUNT) + polygon_count = 0; +#endif + +#if defined(OGL) || defined(OGLES) + /* Tell the shader to discard black */ + glUniform1i(glGetUniformLocation(g_defaultShaderProgram, "bDiscardBlack"), TRUE); +#endif + + PutDrawEnv(env); + + if (env->dtd) + { + //glEnable(GL_DITHER); + } + else + { + //glDisable(GL_DITHER); + } + + if (activeDrawEnv.isbg) + { + ClearImage(&activeDrawEnv.clip, activeDrawEnv.r0, activeDrawEnv.g0, activeDrawEnv.b0); + } + + if (p != NULL) + { + lastClut = 0xFFFF; + lastTpage = 0xFFFF; + lastSemiTrans = 0xFFFF; + lastPolyType = 0xFFFF; + numVertices = 0; + g_vertexIndex = 0; + g_numSplitIndices = 0; + SDL_memset(&g_vertexBuffer[0], 0, MAX_NUM_POLY_BUFFER_VERTICES * sizeof(struct Vertex)); + SDL_memset(&g_splitIndices[0], 0, MAX_NUM_INDEX_BUFFERS * sizeof(struct VertexBufferSplitIndex)); + + Emulator_Ortho2D(0.0f, VRAM_WIDTH, 0.0f, VRAM_HEIGHT, 0.0f, 1.0f); + Emulator_Scalef(RESOLUTION_SCALE, RESOLUTION_SCALE, RESOLUTION_SCALE); + Emulator_BindFrameBuffer(vramFrameBuffer); + Emulator_SetScissorBox(activeDrawEnv.clip.x * RESOLUTION_SCALE, activeDrawEnv.clip.y * RESOLUTION_SCALE, activeDrawEnv.clip.w * RESOLUTION_SCALE, activeDrawEnv.clip.h * RESOLUTION_SCALE); + Emulator_SetViewPort(activeDrawEnv.clip.x * RESOLUTION_SCALE, activeDrawEnv.clip.y * RESOLUTION_SCALE, VRAM_WIDTH, VRAM_HEIGHT); + + P_TAG* pTag = (P_TAG*)p; + +#if defined(OGL) || defined(OGLES) + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); +#endif +#if (defined OGL) || (defined(OGLES) && OGLES_VERSION == 3) + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); +#elif (defined OGL) || (defined(OGLES) && OGLES_VERSION == 2) + glGenVertexArraysOES(1, &vao); + glBindVertexArrayOES(vao); +#endif +#if defined(OGL) || defined(OGLES) + GLint posAttrib = glGetAttribLocation(g_defaultShaderProgram, "a_position"); + GLint colAttrib = glGetAttribLocation(g_defaultShaderProgram, "a_colour"); + GLint texAttrib = glGetAttribLocation(g_defaultShaderProgram, "a_texcoord"); + glEnableVertexAttribArray(posAttrib); + glEnableVertexAttribArray(colAttrib); + glEnableVertexAttribArray(texAttrib); + glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), 0); + glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), (GLvoid*)12); + glVertexAttribPointer(colAttrib, 4, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), (GLvoid*)20); +#endif + + do + { + if (pTag->len > 0) + { + ParseLinkedPrimitiveList((uintptr_t)pTag, (uintptr_t)pTag + (uintptr_t)(pTag->len * 4) + 4 + LEN_OFFSET); + } + pTag = (P_TAG*)pTag->addr; + }while ((uintptr_t)pTag != (uintptr_t)&terminator); + + Emulator_CreateVertexBuffer(MAX_NUM_POLY_BUFFER_VERTICES, sizeof(Vertex), (void*)&g_vertexBuffer[0]); + + for (int i = 0; i < g_numSplitIndices; i++) + { + if (g_texturelessMode) + { +#if defined(VK) + //Unimplemented + assert(FALSE); +#else + Emulator_BindTexture(nullWhiteTexture); +#endif + } + else + { +#if !defined(__EMSCRIPTEN__) + //assert(g_splitIndices[i].textureId < 1000); +#endif + Emulator_BindTexture(g_splitIndices[i].textureId); + } + + Emulator_SetBlendMode(g_splitIndices[i].abr, g_splitIndices[i].semiTrans); + + if (g_wireframeMode) + { +#if defined(OGL) + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#elif defined(D3D9) + d3ddev->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); +#endif + } + + +#if defined(OGL) || defined(OGLES) + glDrawArrays(g_splitIndices[i].primitiveType, g_splitIndices[i].splitIndex, g_splitIndices[i].numVertices); +#elif defined(D3D9) + d3ddev->DrawPrimitive((D3DPRIMITIVETYPE)g_splitIndices[i].primitiveType, g_splitIndices[i].splitIndex, g_splitIndices[i].numVertices/3); +#endif + + + if (g_wireframeMode) + { +#if defined(OGL) + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#elif defined(D3D9) + d3ddev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); +#endif + } + + } + +#if defined(OGL) || defined(OGLES) + glDeleteBuffers(1, &vbo); + glDisableVertexAttribArray(posAttrib); + glDisableVertexAttribArray(colAttrib); + glDisableVertexAttribArray(texAttrib); +#elif defined(D3D9) + g_vertexBufferObject->Release(); +#endif + +#if (defined OGL) || (defined(OGLES) && OGLES_VERSION == 3) + glDeleteVertexArrays(1, &vao); +#elif (defined OGL) || (defined(OGLES) && OGLES_VERSION == 2) + glDeleteVertexArraysOES(1, &vao); +#endif + Emulator_SetViewPort(0, 0, windowWidth, windowHeight); + } + + Emulator_CheckTextureIntersection(&env->clip); + +#if defined(PGXP) + /* Reset the ztable */ + memset(&pgxp_vertex_buffer[0], 0, pgxp_vertex_index * sizeof(PGXPVertex)); + + /* Reset the ztable index of */ + pgxp_vertex_index = 0; +#endif +} + +void ParseLinkedPrimitiveList(unsigned int packetStart, unsigned int packetEnd)//@TODO sync with ParsePrimitive +{ + unsigned int currentAddress = packetStart; + + while (currentAddress != packetEnd) + { + P_TAG* pTag = (P_TAG*)currentAddress; + + int textured = (pTag->code & 0x4) != 0; + + int blend_mode = 0; + + if (textured) + { + if ((pTag->code & 0x1) != 0) + { + blend_mode = 2; + } + else + { + blend_mode = 1; + } + } + else + { + blend_mode = 0; + } + + int semi_transparent = (pTag->code & 2) != 0; + + switch (pTag->code & ~3) + { + case 0x0: + { + currentAddress += 4; + break; + } + case 0x20: + { + POLY_F3* poly = (POLY_F3*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x2, NULL, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + + g_vertexIndex += 3; + numVertices += 3; + + currentAddress += sizeof(POLY_F3); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0x24: + { + POLY_FT3* poly = (POLY_FT3*)pTag; + + if (lastTpage == 0xFFFF || lastClut == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = poly->tpage; + lastClut = poly->clut; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (poly->tpage != lastTpage || poly->clut != lastClut || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = poly->tpage; + lastClut = poly->clut; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x2, NULL, -1, -1); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, &poly->u1, &poly->u2, NULL, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + + g_vertexIndex += 3; + numVertices += 3; + currentAddress += sizeof(POLY_FT3); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0x28: + { + POLY_F4* poly = (POLY_F4*)pTag; + + if (lastTpage == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (activeDrawEnv.tpage != lastTpage || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x3, &poly->x2, -1, -1); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], NULL, NULL, NULL, NULL, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + currentAddress += sizeof(POLY_F4); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0x2C: + { + POLY_FT4* poly = (POLY_FT4*)pTag; + + if (lastTpage == 0xFFFF || lastClut == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = poly->tpage; + lastClut = poly->clut; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (poly->tpage != lastTpage || poly->clut != lastClut || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = poly->tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x3, &poly->x2, -1, -1); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, &poly->u1, &poly->u3, &poly->u2, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + + currentAddress += sizeof(POLY_FT4); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0x30: + { + POLY_G3* poly = (POLY_G3*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastSemiTrans = semi_transparent; + lastTpage = activeDrawEnv.tpage; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastSemiTrans = semi_transparent; + lastTpage = activeDrawEnv.tpage; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x2, NULL, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r1, &poly->r2, NULL, TRUE); + + g_vertexIndex += 3; + numVertices += 3; + + currentAddress += sizeof(POLY_G3); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0x34: + { + POLY_GT3* poly = (POLY_GT3*)pTag; + + if (lastTpage == 0xFFFF || lastClut == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = poly->tpage; + lastClut = poly->clut; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (poly->tpage != lastTpage || poly->clut != lastClut || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = poly->tpage; + lastClut = poly->clut; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x2, NULL, -1, -1); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, &poly->u1, &poly->u2, NULL, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r1, &poly->r2, NULL, TRUE); + + g_vertexIndex += 3; + numVertices += 3; + + currentAddress += sizeof(POLY_GT3); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0x38: + { + POLY_G4* poly = (POLY_G4*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x3, &poly->x2, -1, -1); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], NULL, NULL, NULL, NULL, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r1, &poly->r3, &poly->r2, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + + currentAddress += sizeof(POLY_G4); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0x3C: + { + POLY_GT4* poly = (POLY_GT4*)pTag; + + if (lastTpage == 0xFFFF || lastClut == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = poly->tpage; + lastClut = poly->clut; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (poly->tpage != lastTpage || poly->clut != lastClut || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = poly->tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x3, &poly->x2, -1, -1); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, &poly->u1, &poly->u3, &poly->u2, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r1, &poly->r3, &poly->r2, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + + currentAddress += sizeof(POLY_GT4); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0x40: + { + LINE_F2* poly = (LINE_F2*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_LINES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_LINES) + { + lastPolyType = POLY_TYPE_LINES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateLineArray(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, NULL, NULL); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + + g_vertexIndex += 2; + numVertices += 2; + + currentAddress += sizeof(LINE_F2); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0x48: + { + LINE_F3* poly = (LINE_F3*)pTag; + int forceNewLine = FALSE; + + for (int i = 0; i < 2; i++) + { + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_LINES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_LINES || forceNewLine == TRUE) + { + lastPolyType = POLY_TYPE_LINES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + if (i == 0) + { + //First line + Emulator_GenerateLineArray(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, NULL, NULL); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + g_vertexIndex += 2; + numVertices += 2; + forceNewLine = TRUE; + } + else + { + //Second line + Emulator_GenerateLineArray(&g_vertexBuffer[g_vertexIndex], &poly->x1, &poly->x2, NULL, NULL); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + g_vertexIndex += 2; + numVertices += 2; + } +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + } + + currentAddress += sizeof(LINE_F3); + break; + } + case 0x50: + { + LINE_G2* poly = (LINE_G2*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_LINES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_LINES) + { + lastPolyType = POLY_TYPE_LINES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateLineArray(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, NULL, NULL); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r1, NULL, NULL, TRUE); + + g_vertexIndex += 2; + numVertices += 2; + + currentAddress += sizeof(LINE_G2); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0x60: + { + TILE* poly = (TILE*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, NULL, NULL, NULL, poly->w, poly->h); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + + currentAddress += sizeof(TILE); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + + break; + } + case 0x64: + { + SPRT* poly = (SPRT*)pTag; + + if (lastTpage == 0xFFFF || lastClut == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (activeDrawEnv.tpage != lastTpage || poly->clut != lastClut || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, NULL, NULL, NULL, poly->w, poly->h); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, NULL, NULL, NULL, poly->w, poly->h); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + + currentAddress += sizeof(SPRT); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0x68: + { + TILE_1* poly = (TILE_1*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, NULL, NULL, NULL, 1, 1); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], NULL, NULL, NULL, NULL, 1, 1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + + currentAddress += sizeof(TILE_1); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0x70: + { + TILE_8* poly = (TILE_8*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, NULL, NULL, NULL, 8, 8); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], NULL, NULL, NULL, NULL, 8, 8); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + + currentAddress += sizeof(TILE_8); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0x74: + { + SPRT_8* poly = (SPRT_8*)pTag; + + if (lastTpage == 0xFFFF || lastClut == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (activeDrawEnv.tpage != lastTpage || poly->clut != lastClut || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, NULL, NULL, NULL, 8, 8); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, NULL, NULL, NULL, 8, 8); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + + currentAddress += sizeof(SPRT_8); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0x78: + { + TILE_16* poly = (TILE_16*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = nullWhiteTexture; + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, NULL, NULL, NULL, 16, 16); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], NULL, NULL, NULL, NULL, 16, 16); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + + currentAddress += sizeof(TILE_16); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0x7C: + { + SPRT_16* poly = (SPRT_16*)pTag; + + if (lastTpage == 0xFFFF || lastClut == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (activeDrawEnv.tpage != lastTpage || poly->clut != lastClut || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, NULL, NULL, NULL, 16, 16); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, NULL, NULL, NULL, 16, 16); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + + currentAddress += sizeof(SPRT_16); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + break; + } + case 0xE0: + { + switch (pTag->code) + { + case 0xE1: + { +#if defined(USE_32_BIT_ADDR) + unsigned short tpage = ((unsigned short*)pTag)[4]; +#else + unsigned short tpage = ((unsigned short*)pTag)[2]; +#endif + //if (tpage != 0) + { + activeDrawEnv.tpage = tpage; + } + + currentAddress += sizeof(DR_TPAGE); +#if defined(DEBUG_POLY_COUNT) + polygon_count++; +#endif + + break; + } + default: + { + eprinterr("Primitive type error"); + assert(FALSE); + break; + } + } + break; + } + default: + //Unhandled poly type + eprinterr("Unhandled primitive type: %02X type2:%02X\n", pTag->code, pTag->code & ~3); + break; + } + } + + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; +} + +void ParsePrimitive(P_TAG* pTag) +{ + int textured = (pTag->code & 0x4) != 0; + + int blend_mode = 0; + + if (textured) + { + if ((pTag->code & 0x1) != 0) + { + blend_mode = 2; + } + else + { + blend_mode = 1; + } + } + else + { + blend_mode = 0; + } + + int semi_transparent = (pTag->code & 2) != 0; + + switch (pTag->code & ~3) + { + case 0x0: + { + break; + } + case 0x20: + { + POLY_F3* poly = (POLY_F3*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x2, NULL, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + + g_vertexIndex += 3; + numVertices += 3; + break; + } + case 0x24: + { + POLY_FT3* poly = (POLY_FT3*)pTag; + + if (lastTpage == 0xFFFF || lastClut == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = poly->tpage; + lastClut = poly->clut; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (poly->tpage != lastTpage || poly->clut != lastClut || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = poly->tpage; + lastClut = poly->clut; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x2, NULL, -1, -1); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, &poly->u1, &poly->u2, NULL, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + + g_vertexIndex += 3; + numVertices += 3; + break; + } + case 0x28: + { + POLY_F4* poly = (POLY_F4*)pTag; + + if (lastTpage == 0xFFFF || lastPolyType == 0xFFFF || lastSemiTrans == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastSemiTrans = semi_transparent; + lastTpage = activeDrawEnv.tpage; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (activeDrawEnv.tpage != lastTpage || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastSemiTrans = semi_transparent; + lastTpage = activeDrawEnv.tpage; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x3, &poly->x2, -1, -1); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], NULL, NULL, NULL, NULL, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + break; + } + case 0x2C: + { + POLY_FT4* poly = (POLY_FT4*)pTag; + + if (lastTpage == 0xFFFF || lastClut == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = poly->tpage; + lastClut = poly->clut; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (poly->tpage != lastTpage || poly->clut != lastClut || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = poly->tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x3, &poly->x2, -1, -1); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, &poly->u1, &poly->u3, &poly->u2, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + break; + } + case 0x30: + { + POLY_G3* poly = (POLY_G3*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x2, NULL, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r1, &poly->r2, NULL, TRUE); + + g_vertexIndex += 3; + numVertices += 3; + break; + } + case 0x34: + { + POLY_GT3* poly = (POLY_GT3*)pTag; + + if (lastTpage == 0xFFFF || lastClut == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = poly->tpage; + lastClut = poly->clut; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (poly->tpage != lastTpage || poly->clut != lastClut || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = poly->tpage; + lastClut = poly->clut; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x2, NULL, -1, -1); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, &poly->u1, &poly->u2, NULL, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r1, &poly->r2, NULL, TRUE); + + g_vertexIndex += 3; + numVertices += 3; + break; + } + case 0x38: + { + POLY_G4* poly = (POLY_G4*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x3, &poly->x2, -1, -1); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], NULL, NULL, NULL, NULL, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r1, &poly->r3, &poly->r2, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + break; + } + case 0x3C: + { + POLY_GT4* poly = (POLY_GT4*)pTag; + + if (lastTpage == 0xFFFF || lastClut == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = poly->tpage; + lastClut = poly->clut; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (poly->tpage != lastTpage || poly->clut != lastClut || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = poly->tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x3, &poly->x2, -1, -1); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, &poly->u1, &poly->u3, &poly->u2, -1, -1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r1, &poly->r3, &poly->r2, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + break; + } + case 0x40: + { + LINE_F2* poly = (LINE_F2*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_LINES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_LINES) + { + lastPolyType = POLY_TYPE_LINES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateLineArray(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, NULL, NULL); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + + g_vertexIndex += 2; + numVertices += 2; + break; + } + case 0x48: + { + LINE_F3* poly = (LINE_F3*)pTag; + int forceNewLine = FALSE; + + for (int i = 0; i < 2; i++) + { + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_LINES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_LINES || forceNewLine == TRUE) + { + lastPolyType = POLY_TYPE_LINES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + if (i == 0) + { + //First line + Emulator_GenerateLineArray(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, NULL, NULL); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + g_vertexIndex += 2; + numVertices += 2; + forceNewLine = TRUE; + } + else + { + //Second line + Emulator_GenerateLineArray(&g_vertexBuffer[g_vertexIndex], &poly->x1, &poly->x2, NULL, NULL); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + g_vertexIndex += 2; + numVertices += 2; + } + } + break; + } + case 0x50: + { + LINE_G2* poly = (LINE_G2*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_LINES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_LINES) + { + lastPolyType = POLY_TYPE_LINES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (lastTpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateLineArray(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, NULL, NULL); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r1, NULL, NULL, TRUE); + + g_vertexIndex += 2; + numVertices += 2; + break; + } + case 0x60: + { + TILE* poly = (TILE*)pTag; + + if (lastClut == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (activeDrawEnv.tpage != lastTpage || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, NULL, NULL, NULL, poly->w, poly->h); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + + break; + } + case 0x64: + { + SPRT* poly = (SPRT*)pTag; + + if (lastClut == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (activeDrawEnv.tpage != lastTpage || poly->clut != lastClut || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, NULL, NULL, NULL, poly->w, poly->h); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, NULL, NULL, NULL, poly->w, poly->h); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + break; + } + case 0x68: + { + TILE_1* poly = (TILE_1*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (activeDrawEnv.tpage != lastTpage || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, NULL, NULL, NULL, 1, 1); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], NULL, NULL, NULL, NULL, 1, 1); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + break; + } + case 0x70: + { + TILE_8* poly = (TILE_8*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (activeDrawEnv.tpage != lastTpage || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, NULL, NULL, NULL, 8, 8); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], NULL, NULL, NULL, NULL, 8, 8); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + break; + } + case 0x74: + { + SPRT_8* poly = (SPRT_8*)pTag; + + if (lastClut == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (activeDrawEnv.tpage != lastTpage || poly->clut != lastClut || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, NULL, NULL, NULL, 8, 8); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, NULL, NULL, NULL, 8, 8); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + break; + } + case 0x78: + { + TILE_16* poly = (TILE_16*)pTag; + + if (lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (activeDrawEnv.tpage != lastTpage || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, NULL, NULL, NULL, 16, 16); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], NULL, NULL, NULL, NULL, 16, 16); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + break; + } + case 0x7C: + { + SPRT_16* poly = (SPRT_16*)pTag; + + if (lastClut == 0xFFFF || lastSemiTrans == 0xFFFF || lastPolyType == 0xFFFF) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + } + else if (activeDrawEnv.tpage != lastTpage || poly->clut != lastClut || semi_transparent != lastSemiTrans || lastPolyType != POLY_TYPE_TRIANGLES) + { + lastPolyType = POLY_TYPE_TRIANGLES; + lastClut = poly->clut; + lastTpage = activeDrawEnv.tpage; + lastSemiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].primitiveType = lastPolyType; + g_splitIndices[g_numSplitIndices].textureId = Emulator_GenerateTpage(lastTpage, lastClut); + g_splitIndices[g_numSplitIndices].semiTrans = semi_transparent; + g_splitIndices[g_numSplitIndices].abr = (activeDrawEnv.tpage >> 5) & 3; + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; + g_splitIndices[g_numSplitIndices++].splitIndex = g_vertexIndex; + numVertices = 0; + } + + Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, NULL, NULL, NULL, 16, 16); + Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, NULL, NULL, NULL, 16, 16); + Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, NULL, NULL, NULL, TRUE); + + //Make tri + g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 3]; + g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex]; + g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 2]; + + g_vertexIndex += 6; + numVertices += 6; + break; + } + case 0xE0: + { + switch (pTag->code) + { + case 0xE1: + { + unsigned short tpage = ((unsigned short*)pTag)[2]; + if (tpage != 0) + { + activeDrawEnv.tpage = tpage; + } + break; + } + default: + { + assert(FALSE); + break; + } + } + break; + } + default: + //Unhandled poly type + eprinterr("Unhandled primitive type: %02X type2:%02X\n", pTag->code, pTag->code & ~3); + break; + } + + g_splitIndices[g_numSplitIndices - 1].numVertices = numVertices; +} + +void SetSprt16(SPRT_16* p) +{ + setSprt16(p); +} + +void SetSprt8(SPRT_8* p) +{ + setSprt8(p); +} + +void SetTile(TILE* p) +{ + setTile(p); +} + +void SetPolyGT4(POLY_GT4* p) +{ + setPolyGT4(p); +} + +void SetSemiTrans(void* p, int abe) +{ + setSemiTrans(p, abe); +} + +void SetShadeTex(void* p, int tge) +{ + setShadeTex(p, tge); +} + +void SetSprt(SPRT* p) +{ + UNIMPLEMENTED(); +} + +void SetDumpFnt(int id) +{ + UNIMPLEMENTED(); +} + +void SetLineF3(LINE_F3* p) +{ + setLineF3(p); +} + +void FntLoad(int tx, int ty) +{ + UNIMPLEMENTED(); +} + +void AddPrim(void* ot, void* p) +{ + addPrim(ot, p); +} + +void AddPrims(void* ot, void* p0, void* p1) +{ + addPrims(ot, p0, p1); +} + +void CatPrim(void* p0, void* p1) +{ + catPrim(p0, p1); +} + +void DrawOTag(u_long* p) +{ +#if defined(OGL) || defined(OGLES) + /* Tell the shader to discard black */ + glUniform1i(glGetUniformLocation(g_defaultShaderProgram, "bDiscardBlack"), TRUE); +#endif + + if (activeDrawEnv.dtd) + { + //glEnable(GL_DITHER); + } + else + { + //glDisable(GL_DITHER); + } + + if (activeDrawEnv.isbg) + { + ClearImage(&activeDrawEnv.clip, activeDrawEnv.r0, activeDrawEnv.g0, activeDrawEnv.b0); + } + + if (p != NULL) + { + lastClut = 0xFFFF; + lastTpage = 0xFFFF; + lastSemiTrans = 0xFFFF; + lastPolyType = 0xFFFF; + numVertices = 0; + g_vertexIndex = 0; + g_numSplitIndices = 0; + + SDL_memset(&g_vertexBuffer[0], 0, MAX_NUM_POLY_BUFFER_VERTICES * sizeof(struct Vertex)); + SDL_memset(&g_splitIndices[0], 0, MAX_NUM_INDEX_BUFFERS * sizeof(struct VertexBufferSplitIndex)); + + Emulator_Ortho2D(0.0f, VRAM_WIDTH, 0.0f, VRAM_HEIGHT, 0.0f, 1.0f); + Emulator_Scalef(RESOLUTION_SCALE, RESOLUTION_SCALE, RESOLUTION_SCALE); + Emulator_BindFrameBuffer(vramFrameBuffer); + Emulator_SetScissorBox(activeDrawEnv.clip.x * RESOLUTION_SCALE, activeDrawEnv.clip.y * RESOLUTION_SCALE, activeDrawEnv.clip.w * RESOLUTION_SCALE, activeDrawEnv.clip.h * RESOLUTION_SCALE); + Emulator_SetViewPort(activeDrawEnv.clip.x * RESOLUTION_SCALE, activeDrawEnv.clip.y * RESOLUTION_SCALE, VRAM_WIDTH, VRAM_HEIGHT); + + P_TAG* pTag = (P_TAG*)p; + +#if defined(OGL) || defined(OGLES) + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); +#endif + +#if (defined OGL) || (defined(OGLES) && OGLES_VERSION == 3) + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); +#elif (defined OGL) || (defined(OGLES) && OGLES_VERSION == 2) + glGenVertexArraysOES(1, &vao); + glBindVertexArrayOES(vao); +#endif + +#if defined(OGL) || defined(OGLES) + GLint posAttrib = glGetAttribLocation(g_defaultShaderProgram, "a_position"); + GLint colAttrib = glGetAttribLocation(g_defaultShaderProgram, "a_colour"); + GLint texAttrib = glGetAttribLocation(g_defaultShaderProgram, "a_texcoord"); + glEnableVertexAttribArray(posAttrib); + glEnableVertexAttribArray(colAttrib); + glEnableVertexAttribArray(texAttrib); + glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), 0); + glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), (GLvoid*)12); + glVertexAttribPointer(colAttrib, 4, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), (GLvoid*)20); +#endif + + do + { + if (pTag->len > 0) + { + ParseLinkedPrimitiveList((uintptr_t)pTag, (uintptr_t)pTag + (uintptr_t)(pTag->len * 4) + 4); + } + pTag = (P_TAG*)pTag->addr; + } while ((unsigned long)pTag != (unsigned long)& terminator); + +#if defined(OGL) || defined(OGLES) + glBufferData(GL_ARRAY_BUFFER, sizeof(struct Vertex) * MAX_NUM_POLY_BUFFER_VERTICES, &g_vertexBuffer[0], GL_STATIC_DRAW); +#endif + + for (int i = 0; i < g_numSplitIndices; i++) + { + if (g_texturelessMode) + { +#if defined(OGL) || defined(OGLES) + Emulator_BindTexture(nullWhiteTexture); +#else + ///@TODO D3D9 +#endif + } + else + { + Emulator_BindTexture(g_splitIndices[i].textureId); + } + + Emulator_SetBlendMode(g_splitIndices[i].abr, g_splitIndices[i].semiTrans); + +#if defined(OGL) + if (g_wireframeMode) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } +#endif + +#if defined(OGL) || defined(OGLES) + glDrawArrays(g_splitIndices[i].primitiveType, g_splitIndices[i].splitIndex, g_splitIndices[i].numVertices); +#endif + +#if defined(OGL) || defined(OGLES) + if (g_wireframeMode) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } +#endif + } + +#if defined(OGL) || defined(OGLES) + glDeleteBuffers(1, &vbo); + glDisableVertexAttribArray(posAttrib); + glDisableVertexAttribArray(colAttrib); + glDisableVertexAttribArray(texAttrib); +#endif +#if (defined OGL) || (defined(OGLES) && OGLES_VERSION == 3) + glDeleteVertexArrays(1, &vao); +#elif (defined OGL) || (defined(OGLES) && OGLES_VERSION == 2) + glDeleteVertexArraysOES(1, &vao); +#endif + Emulator_SetViewPort(0, 0, windowWidth, windowHeight); + } + + Emulator_CheckTextureIntersection(&activeDrawEnv.clip); + +#if defined(PGXP) + /* Reset the ztable */ + memset(&pgxp_vertex_buffer[0], 0, pgxp_vertex_index * sizeof(PGXPVertex)); + + /* Reset the ztable index used */ + pgxp_vertex_index = 0; +#endif +} + +u_short LoadTPage(u_long* pix, int tp, int abr, int x, int y, int w, int h) +{ + RECT16 imageArea; + imageArea.x = x; + imageArea.y = y; + imageArea.h = h; + + enum + { + TP_4BIT, + TP_8BIT, + TP_16BIT + }; + + switch (tp) + { + case TP_4BIT: + { + //loc_278 + if (w >= 0) + { + imageArea.w = w >> 2; + } + else + { + imageArea.w = (w + 3) >> 2; + } + break; + } + case TP_8BIT: + { + //loc_290 + imageArea.w = (w + (w >> 31)) >> 1; + break; + } + case TP_16BIT: + { + //loc_2A4 + imageArea.w = w; + break; + } + } + + //loc_2AC + LoadImagePSX(&imageArea, pix); + return GetTPage(tp, abr, x, y) & 0xFFFF; +} + +u_short GetTPage(int tp, int abr, int x, int y) +{ + return getTPage(tp, abr, x, y); +} + +u_short LoadClut(u_long* clut, int x, int y) +{ + RECT16 rect;//&var_18 + setRECT16(&rect, x, y, 256, 1); + LoadImagePSX(&rect, clut); + return GetClut(x, y) & 0xFFFF; +} + +u_short LoadClut2(u_long* clut, int x, int y) +{ + RECT16 drawArea; + drawArea.x = x; + drawArea.y = y; + drawArea.w = 16; + drawArea.h = 1; + LoadImagePSX(&drawArea, clut); + return getClut(x, y); +} + +u_long* KanjiFntFlush(int id) +{ + UNIMPLEMENTED(); + return 0; +} + +u_long* FntFlush(int id) +{ + UNIMPLEMENTED(); + return 0; +} + +int KanjiFntOpen(int x, int y, int w, int h, int dx, int dy, int cx, int cy, int isbg, int n) +{ + UNIMPLEMENTED(); + return 0; +} + +int FntOpen(int x, int y, int w, int h, int isbg, int n) +{ + UNIMPLEMENTED(); + return 0; +} + +void SetPolyF4(POLY_F4* p) +{ + setPolyF4(p); +} + +void SetPolyFT4(POLY_FT4* p) +{ + setPolyFT4(p); +} + +void SetPolyG4(POLY_G4* p) +{ + setPolyG4(p); +} + +void DrawPrim(void* p) +{ +#if defined(OGL) || defined(OGLES) + /* Tell the shader to discard black */ + glUniform1i(glGetUniformLocation(g_defaultShaderProgram, "bDiscardBlack"), TRUE); +#endif + + if (activeDrawEnv.dtd) + { + //glEnable(GL_DITHER); + } + else + { + //glDisable(GL_DITHER); + } + + if (p != NULL) + { + lastClut = 0xFFFF; + lastTpage = 0xFFFF; + numVertices = 0; + g_vertexIndex = 0; + g_numSplitIndices = 0; + SDL_memset(&g_vertexBuffer[0], 0, MAX_NUM_POLY_BUFFER_VERTICES * sizeof(struct Vertex)); + SDL_memset(&g_splitIndices[0], 0, MAX_NUM_INDEX_BUFFERS * sizeof(struct VertexBufferSplitIndex)); + + Emulator_Ortho2D(0.0f, VRAM_WIDTH, 0.0f, VRAM_HEIGHT, 0.0f, 1.0f); + Emulator_Scalef(RESOLUTION_SCALE, RESOLUTION_SCALE, RESOLUTION_SCALE); + Emulator_BindFrameBuffer(vramFrameBuffer); + Emulator_SetScissorBox(activeDrawEnv.clip.x * RESOLUTION_SCALE, activeDrawEnv.clip.y * RESOLUTION_SCALE, activeDrawEnv.clip.w * RESOLUTION_SCALE, activeDrawEnv.clip.h * RESOLUTION_SCALE); + Emulator_SetViewPort(activeDrawEnv.clip.x * RESOLUTION_SCALE, activeDrawEnv.clip.y * RESOLUTION_SCALE, VRAM_WIDTH, VRAM_HEIGHT); + + P_TAG* pTag = (P_TAG*)p; + +#if defined(OGL) || defined(OGLES) + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); +#endif + +#if (defined OGL) || (defined(OGLES) && OGLES_VERSION == 3) + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); +#elif (defined OGL) || (defined(OGLES) && OGLES_VERSION == 2) + glGenVertexArraysOES(1, &vao); + glBindVertexArrayOES(vao); +#endif +#if defined(OGL) || defined(OGLES) + GLint posAttrib = glGetAttribLocation(g_defaultShaderProgram, "a_position"); + GLint colAttrib = glGetAttribLocation(g_defaultShaderProgram, "a_colour"); + GLint texAttrib = glGetAttribLocation(g_defaultShaderProgram, "a_texcoord"); + glEnableVertexAttribArray(posAttrib); + glEnableVertexAttribArray(colAttrib); + glEnableVertexAttribArray(texAttrib); + glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), 0); + glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), (GLvoid*)12); + glVertexAttribPointer(colAttrib, 4, GL_FLOAT, GL_FALSE, sizeof(struct Vertex), (GLvoid*)20); +#endif + ParsePrimitive(pTag); + +#if defined(OGL) || defined(OGLES) + glBufferData(GL_ARRAY_BUFFER, sizeof(struct Vertex) * MAX_NUM_POLY_BUFFER_VERTICES, &g_vertexBuffer[0], GL_STATIC_DRAW); +#endif + for (int i = 0; i < g_numSplitIndices; i++) + { + if (g_texturelessMode) + { + Emulator_BindTexture(nullWhiteTexture); + } + else + { + Emulator_BindTexture(g_splitIndices[i].textureId); + } + + Emulator_SetBlendMode(g_splitIndices[i].abr, g_splitIndices[i].semiTrans); + +#if defined(OGL) + if (g_wireframeMode) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } +#endif +#if defined(OGL) || defined(OGLES) + glDrawArrays(g_splitIndices[i].primitiveType, g_splitIndices[i].splitIndex, g_splitIndices[i].numVertices); +#endif +#if defined(OGL) + if (g_wireframeMode) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } +#endif + } + +#if defined(OGL) || defined(OGLES) + glDeleteBuffers(1, &vbo); + glDisableVertexAttribArray(posAttrib); + glDisableVertexAttribArray(colAttrib); + glDisableVertexAttribArray(texAttrib); +#endif +#if (defined OGL) || (defined(OGLES) && OGLES_VERSION == 3) + glDeleteVertexArrays(1, &vao); +#elif (defined OGL) || (defined(OGLES) && OGLES_VERSION == 2) + glDeleteVertexArraysOES(1, &vao); +#endif + + Emulator_SetViewPort(0, 0, windowWidth, windowHeight); + } + + Emulator_CheckTextureIntersection(&activeDrawEnv.clip); + +#if defined(PGXP) + /* Reset the ztable */ + memset(&pgxp_vertex_buffer[0], 0, pgxp_vertex_index * sizeof(PGXPVertex)); + + /* Reset the ztable index used */ + pgxp_vertex_index = 0; +#endif +} + +void TermPrim(void* p) +{ + termPrim(p); +} \ No newline at end of file diff --git a/src_rebuild/EMULATOR/LIBGPU.H b/src_rebuild/EMULATOR/LIBGPU.H new file mode 100644 index 00000000..e3ee69e2 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBGPU.H @@ -0,0 +1,1081 @@ +#ifndef LIBGPU_H +#define LIBGPU_H + +#include "LIBGTE.H" + +extern int (*GPU_printf)(const char *fmt, ...); + +#define WAIT_TIME 0x800000 + +#define limitRange(x, l, h) ((x)=((x)<(l)?(l):(x)>(h)?(h):(x))) + +#define setVector(v, _x, _y, _z) \ + (v)->vx = _x, (v)->vy = _y, (v)->vz = _z + +#define applyVector(v, _x, _y, _z, op) \ + (v)->vx op _x, (v)->vy op _y, (v)->vz op _z + +#define copyVector(v0, v1) \ + (v0)->vx = (v1)->vx, (v0)->vy = (v1)->vy, (v0)->vz = (v1)->vz + +#define addVector(v0, v1) \ + (v0)->vx += (v1)->vx, \ + (v0)->vy += (v1)->vy, \ + (v0)->vz += (v1)->vz + +#define dumpVector(str, v) \ + GPU_printf("%s=(%d,%d,%d)\n", str, (v)->vx, (v)->vy, (v)->vz) + +#define dumpMatrix(x) \ + GPU_printf("\t%5d,%5d,%5d\n",(x)->m[0][0],(x)->m[0][1],(x)->m[0][2]),\ + GPU_printf("\t%5d,%5d,%5d\n",(x)->m[1][0],(x)->m[1][1],(x)->m[1][2]),\ + GPU_printf("\t%5d,%5d,%5d\n",(x)->m[2][0],(x)->m[2][1],(x)->m[2][2]) + +#define setRECT16(r, _x, _y, _w, _h) \ + (r)->x = (_x),(r)->y = (_y),(r)->w = (_w),(r)->h = (_h) + +/* + * Set Primitive Attributes + */ +#define setTPage(p,tp,abr,x,y) \ + ((p)->tpage = getTPage(tp,abr,x,y)) + +#define setClut(p,x,y) \ + ((p)->clut = getClut(x,y)) + +/* + * Set Primitive Colors + */ +#define setRGB0(p,_r0,_g0,_b0) \ + (p)->r0 = _r0,(p)->g0 = _g0,(p)->b0 = _b0 + +#define setRGB1(p,_r1,_g1,_b1) \ + (p)->r1 = _r1,(p)->g1 = _g1,(p)->b1 = _b1 + +#define setRGB2(p,_r2,_g2,_b2) \ + (p)->r2 = _r2,(p)->g2 = _g2,(p)->b2 = _b2 + +#define setRGB3(p,_r3,_g3,_b3) \ + (p)->r3 = _r3,(p)->g3 = _g3,(p)->b3 = _b3 + + + + +#define setRGBP0(p,_r0,_g0,_b0,_p0) \ + (p)->r0 = _r0,(p)->g0 = _g0,(p)->b0 = _b0,(p)->p0 = _p0 + +#define setRGBP1(p,_r1,_g1,_b1,_p1) \ + (p)->r1 = _r1,(p)->g1 = _g1,(p)->b1 = _b1,(p)->p1 = _p1 + +#define setRGBP2(p,_r2,_g2,_b2,_p2) \ + (p)->r2 = _r2,(p)->g2 = _g2,(p)->b2 = _b2,(p)->p2 = _p2 + +#define setRGBP3(p,_r3,_g3,_b3,_p3) \ + (p)->r3 = _r3,(p)->g3 = _g3,(p)->b3 = _b3,(p)->p3 = _p3 + +/* + * Set Primitive Screen Points + */ +#define setXY0(p,_x0,_y0) \ + (p)->x0 = (_x0), (p)->y0 = (_y0) \ + +#define setXY2(p,_x0,_y0,_x1,_y1) \ + (p)->x0 = (_x0), (p)->y0 = (_y0), \ + (p)->x1 = (_x1), (p)->y1 = (_y1) + +#define setXY3(p,_x0,_y0,_x1,_y1,_x2,_y2) \ + (p)->x0 = (_x0), (p)->y0 = (_y0), \ + (p)->x1 = (_x1), (p)->y1 = (_y1), \ + (p)->x2 = (_x2), (p)->y2 = (_y2) + +#define setXY4(p,_x0,_y0,_x1,_y1,_x2,_y2,_x3,_y3) \ + (p)->x0 = (_x0), (p)->y0 = (_y0), \ + (p)->x1 = (_x1), (p)->y1 = (_y1), \ + (p)->x2 = (_x2), (p)->y2 = (_y2), \ + (p)->x3 = (_x3), (p)->y3 = (_y3) + +#define setXYWH(p,_x0,_y0,_w,_h) \ + (p)->x0 = (_x0), (p)->y0 = (_y0), \ + (p)->x1 = (_x0)+(_w), (p)->y1 = (_y0), \ + (p)->x2 = (_x0), (p)->y2 = (_y0)+(_h), \ + (p)->x3 = (_x0)+(_w), (p)->y3 = (_y0)+(_h) + +/* + * Set Primitive Width/Height + */ +#define setWH(p,_w,_h) (p)->w = _w, (p)->h = _h + +/* + * Set Primitive Texture Points + */ +#define setUV0(p,_u0,_v0) \ + (p)->u0 = (_u0), (p)->v0 = (_v0) \ + +#define setUV3(p,_u0,_v0,_u1,_v1,_u2,_v2) \ + (p)->u0 = (_u0), (p)->v0 = (_v0), \ + (p)->u1 = (_u1), (p)->v1 = (_v1), \ + (p)->u2 = (_u2), (p)->v2 = (_v2) + +#define setUV4(p,_u0,_v0,_u1,_v1,_u2,_v2,_u3,_v3) \ + (p)->u0 = (_u0), (p)->v0 = (_v0), \ + (p)->u1 = (_u1), (p)->v1 = (_v1), \ + (p)->u2 = (_u2), (p)->v2 = (_v2), \ + (p)->u3 = (_u3), (p)->v3 = (_v3) + +#define setUVWH(p,_u0,_v0,_w,_h) \ + (p)->u0 = (_u0), (p)->v0 = (_v0), \ + (p)->u1 = (_u0)+(_w), (p)->v1 = (_v0), \ + (p)->u2 = (_u0), (p)->v2 = (_v0)+(_h), \ + (p)->u3 = (_u0)+(_w), (p)->v3 = (_v0)+(_h) + + +/* + * Dump Primivie Parameters + */ +#define dumpRECT16(r) \ + GPU_printf("(%d,%d)-(%d,%d)\n", (r)->x,(r)->y,(r)->w,(r)->h) + +#define dumpWH(p) GPU_printf("(%d,%d)\n", (p)->w, (p)->h ) +#define dumpXY0(p) GPU_printf("(%d,%d)\n", (p)->x0, (p)->y0) +#define dumpUV0(p) GPU_printf("(%d,%d)\n", (p)->u0, (p)->v0) + +#define dumpXY2(p) \ + GPU_printf("(%d,%d)-(%d,%d)\n", \ + (p)->x0, (p)->y0, (p)->x1, (p)->y1) + +#define dumpXY3(p) \ + GPU_printf("(%d,%d)-(%d,%d)-(%d,%d)\n", \ + (p)->x0, (p)->y0, (p)->x1, (p)->y1, \ + (p)->x2, (p)->y2) + +#define dumpUV3(p) \ + GPU_printf("(%d,%d)-(%d,%d)-(%d,%d)\n", \ + (p)->u0, (p)->v0, (p)->u1, (p)->v1, \ + (p)->u2, (p)->v2) + +#define dumpXY4(p) \ + GPU_printf("(%d,%d)-(%d,%d)-(%d,%d)-(%d,%d)\n", \ + (p)->x0, (p)->y0, (p)->x1, (p)->y1, \ + (p)->x2, (p)->y2, (p)->x3, (p)->y3) + +#define dumpUV4(p) \ + GPU_printf("(%d,%d)-(%d,%d)-(%d,%d)-(%d,%d)\n", \ + (p)->u0, (p)->v0, (p)->u1, (p)->v1, \ + (p)->u2, (p)->v2, (p)->u3, (p)->v3) + +#define dumpRGB0(p) \ + GPU_printf("(%3d,%3d,%3d)\n", (p)->r0, (p)->g0, (p)->b0) + +#define dumpRGB1(p) \ + GPU_printf("(%3d,%3d,%3d)\n", (p)->r1, (p)->g1, (p)->b1) + +#define dumpRGB2(p) \ + GPU_printf("(%3d,%3d,%3d)\n", (p)->r2, (p)->g2, (p)->b2) + +#define dumpRGB3(p) \ + GPU_printf("(%3d,%3d,%3d)\n", (p)->r3, (p)->g3, (p)->b3) + + /* + * Primitive Handling Macros + */ + +#define LEN_OFFSET (4) + +#if defined(PGXP) +#define setpgxpindex(p, _pgxp_index) (((P_TAG *)(p))->pgxp_index = (u_short)(_pgxp_index)) +#endif +#define setlen( p, _len) (((P_TAG *)(p))->len = (u_char)(_len)) +#define setaddr(p, _addr) (((P_TAG *)(p))->addr = (u_long)(_addr)) +#define setcode(p, _code) (((P_TAG *)(p))->code = (u_char)(_code)) +#define getlen(p) (u_char)(((P_TAG *)(p))->len) +#define getcode(p) (u_char)(((P_TAG *)(p))->code) +#define getaddr(p) (u_long)(((P_TAG *)(p))->addr) + +#define nextPrim(p) (void *)((((P_TAG *)(p))->addr)|0x80000000) +#define isendprim(p) ((((P_TAG *)(p))->addr)==0xffffff) + +#if defined(PGXP) +#define addPrim(ot, p) setaddr(p, getaddr(ot)), setaddr(ot, p), setpgxpindex(p, pgxp_vertex_index) +#else +#define addPrim(ot, p) setaddr(p, getaddr(ot)), setaddr(ot, p) +#endif +#define addPrims(ot, p0, p1) setaddr(p1, getaddr(ot)),setaddr(ot, p0) + +#define catPrim(p0, p1) setaddr(p0, p1) +#define termPrim(p) setaddr(p, 0xffffffff) + +#define setSemiTrans(p, abe) \ + ((abe)?setcode(p, getcode(p)|0x02):setcode(p, getcode(p)&~0x02)) + +#define setShadeTex(p, tge) \ + ((tge)?setcode(p, getcode(p)|0x01):setcode(p, getcode(p)&~0x01)) + +#define getTPage(tp, abr, x, y) \ + ((((tp)&0x3)<<7)|(((abr)&0x3)<<5)|(((y)&0x100)>>4)|(((x)&0x3ff)>>6)| \ + (((y)&0x200)<<2)) + +#define getClut(x, y) \ + (((y)<<6)|(((x)>>4)&0x3f)) + +#define dumpTPage(tpage) \ + GPU_printf("tpage: (%d,%d,%d,%d)\n", \ + ((tpage)>>7)&0x003,((tpage)>>5)&0x003, \ + ((tpage)<<6)&0x7c0, \ + (((tpage)<<4)&0x100)+(((tpage)>>2)&0x200)) + +#define dumpClut(clut) \ + GPU_printf("clut: (%d,%d)\n", (clut&0x3f)<<4, (clut>>6)) + +#define _get_mode(dfe, dtd, tpage) \ + ((0xe1000000)|((dtd)?0x0200:0)| \ + ((dfe)?0x0400:0)|((tpage)&0x9ff)) + +#if defined(USE_32_BIT_ADDR) +#define setDrawTPage(p, dfe, dtd, tpage) \ + setlen(p, 1), \ + ((u_long *)(p))[2] = _get_mode(dfe, dtd, tpage) +#else +#define setDrawTPage(p, dfe, dtd, tpage) \ + setlen(p, 1), \ + ((u_long *)(p))[1] = _get_mode(dfe, dtd, tpage) +#endif + +#define _get_tw(tw) \ + (tw ? ((0xe2000000)|((((tw)->y&0xff)>>3)<<15)| \ + ((((tw)->x&0xff)>>3)<<10)|(((~((tw)->h-1)&0xff)>>3)<<5)| \ + (((~((tw)->w-1)&0xff)>>3))) : 0) + +#define setTexWindow(p, tw) \ + setlen(p, 2), \ + ((u_long *)(p))[1] = _get_tw(tw), \ + ((u_long *)(p))[2] = 0 + +#define _get_len(RECT16) \ + (((RECT16)->w*(RECT16)->h+1)/2+4) + +#define setDrawLoad(pt, RECT16) \ + (_get_len(RECT16) <= 16) ? ( \ + (setlen(pt, _get_len(RECT16))), \ + ((pt)->code[0] = 0xa0000000), \ + ((pt)->code[1] = *((u_long *)&(RECT16)->x)), \ + ((pt)->code[2] = *((u_long *)&(RECT16)->w)), \ + ((pt)->p[_get_len(RECT16)-4] = 0x01000000) \ + ) : ( \ + (setlen(pt,0)) \ + ) + +#define setDrawStp(p, pbw) \ + setlen(p, 2), \ + ((u_long *)p)[1] = 0xe6000000|(pbw?0x01:0), \ + ((u_long *)p)[2] = 0 + +#define setDrawMode(p, dfe, dtd, tpage, tw) \ + setlen(p, 2), \ + ((u_long *)p)[1] = _get_mode(dfe, dtd, tpage), \ + ((u_long *)p)[2] = _get_tw((RECT16 *)tw) + + +/* Primitive Lentgh Code */ +/*-------------------------------------------------------------------- */ +/* */ +#define setPolyF3(p) setlen(p, 4), setcode(p, 0x20) +#define setPolyFT3(p) setlen(p, 7), setcode(p, 0x24) +#define setPolyG3(p) setlen(p, 6), setcode(p, 0x30) +#define setPolyGT3(p) setlen(p, 9), setcode(p, 0x34) +#define setPolyF4(p) setlen(p, 5), setcode(p, 0x28) +#define setPolyFT4(p) setlen(p, 9), setcode(p, 0x2c) +#define setPolyG4(p) setlen(p, 8), setcode(p, 0x38) +#define setPolyGT4(p) setlen(p, 12), setcode(p, 0x3c) + +#define setSprt8(p) setlen(p, 3), setcode(p, 0x74) +#define setSprt16(p) setlen(p, 3), setcode(p, 0x7c) +#define setSprt(p) setlen(p, 4), setcode(p, 0x64) + +#define setTile1(p) setlen(p, 2), setcode(p, 0x68) +#define setTile8(p) setlen(p, 2), setcode(p, 0x70) +#define setTile16(p) setlen(p, 2), setcode(p, 0x78) +#define setTile(p) setlen(p, 3), setcode(p, 0x60) +#define setLineF2(p) setlen(p, 3), setcode(p, 0x40) +#define setLineG2(p) setlen(p, 4), setcode(p, 0x50) +#define setLineF3(p) setlen(p, 5), setcode(p, 0x48),(p)->pad = 0x55555555 +#define setLineG3(p) setlen(p, 7), setcode(p, 0x58),(p)->pad = 0x55555555, \ + (p)->p2 = 0 +#define setLineF4(p) setlen(p, 6), setcode(p, 0x4c),(p)->pad = 0x55555555 +#define setLineG4(p) setlen(p, 9), setcode(p, 0x5c),(p)->pad = 0x55555555, \ + (p)->p2 = 0, (p)->p3 = 0 + +/* + * RECT16angle: + */ +#pragma pack(push,1) + +typedef struct { + short x, y; /* offset point on VRAM */ + short w, h; /* width and height */ +} RECT16; + +typedef struct { + int x, y; /* offset point on VRAM */ + int w, h; /* width and height */ +} RECT32; + +/* + * Environment + */ +typedef struct { + u_long tag; + u_long code[15]; +} DR_ENV; /* Packed Drawing Environment */ + +typedef struct { + RECT16 clip; /* clip area */ + short ofs[2]; /* drawing offset */ + RECT16 tw; /* texture window */ + u_short tpage; /* texture page */ + u_char dtd; /* dither flag (0:off, 1:on) */ + u_char dfe; /* flag to draw on display area (0:off 1:on) */ + u_char isbg; /* enable to auto-clear */ + u_char r0, g0, b0; /* initital background color */ + DR_ENV dr_env; /* reserved */ +} DRAWENV; + +typedef struct { + RECT16 disp; /* display area */ + RECT16 screen; /* display start point */ + u_char isinter; /* interlace 0: off 1: on */ + u_char isrgb24; /* RGB24 bit mode */ + u_char pad0, pad1; /* reserved */ +} DISPENV; + +/* + * Polygon Primitive Definitions + */ +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long addr; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + unsigned addr: 24; + unsigned len: 8; +#endif + u_char r0, g0, b0, code; +} P_TAG; + +typedef struct { + u_char r0, g0, b0, code; +} P_CODE; + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + short x1, y1; + short x2, y2; +} POLY_F3; /* Flat Triangle */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + short x1, y1; + short x2, y2; + short x3, y3; +} POLY_F4; /* Flat Quadrangle */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + u_char u0, v0; u_short clut; + short x1, y1; + u_char u1, v1; u_short tpage; + short x2, y2; + u_char u2, v2; u_short pad1; +} POLY_FT3; /* Flat Textured Triangle */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + u_char u0, v0; u_short clut; + short x1, y1; + u_char u1, v1; u_short tpage; + short x2, y2; + u_char u2, v2; u_short pad1; + short x3, y3; + u_char u3, v3; u_short pad2; +} POLY_FT4; /* Flat Textured Quadrangle */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + u_char r1, g1, b1, pad1; + short x1, y1; + u_char r2, g2, b2, pad2; + short x2, y2; +} POLY_G3; /* Gouraud Triangle */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + u_char r1, g1, b1, pad1; + short x1, y1; + u_char r2, g2, b2, pad2; + short x2, y2; + u_char r3, g3, b3, pad3; + short x3, y3; +} POLY_G4; /* Gouraud Quadrangle */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + u_char u0, v0; u_short clut; + u_char r1, g1, b1, p1; + short x1, y1; + u_char u1, v1; u_short tpage; + u_char r2, g2, b2, p2; + short x2, y2; + u_char u2, v2; u_short pad2; +} POLY_GT3; /* Gouraud Textured Triangle */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + u_char u0, v0; u_short clut; + u_char r1, g1, b1, p1; + short x1, y1; + u_char u1, v1; u_short tpage; + u_char r2, g2, b2, p2; + short x2, y2; + u_char u2, v2; u_short pad2; + u_char r3, g3, b3, p3;//10 + short x3, y3;//11 + u_char u3, v3; u_short pad3; +} POLY_GT4; /* Gouraud Textured Quadrangle */ + +/* + * Line Primitive Definitions + */ +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + short x1, y1; +} LINE_F2; /* Unconnected Flat Line */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + u_char r1, g1, b1, p1; + short x1, y1; +} LINE_G2; /* Unconnected Gouraud Line */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + short x1, y1; + short x2, y2; + u_long pad; +} LINE_F3; /* 2 connected Flat Line */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + u_char r1, g1, b1, p1; + short x1, y1; + u_char r2, g2, b2, p2; + short x2, y2; + u_long pad; +} LINE_G3; /* 2 connected Gouraud Line */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + short x1, y1; + short x2, y2; + short x3, y3; + u_long pad; +} LINE_F4; /* 3 connected Flat Line Quadrangle */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + u_char r1, g1, b1, p1; + short x1, y1; + u_char r2, g2, b2, p2; + short x2, y2; + u_char r3, g3, b3, p3; + short x3, y3; + u_long pad; +} LINE_G4; /* 3 connected Gouraud Line */ + +/* + * Sprite Primitive Definitions + */ +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + u_char u0, v0; u_short clut; + short w, h; +} SPRT; /* free size Sprite */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + u_char u0, v0; u_short clut; +} SPRT_16; /* 16x16 Sprite */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + u_char u0, v0; u_short clut; +} SPRT_8; /* 8x8 Sprite */ + +/* + * Tile Primitive Definitions + */ +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; + short w, h; +} TILE; /* free size Tile */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; +} TILE_16; /* 16x16 Tile */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; +} TILE_8; /* 8x8 Tile */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_char r0, g0, b0, code; + short x0, y0; +} TILE_1; /* 1x1 Tile */ + +/* + * Special Primitive Definitions + */ +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_long code[2]; +} DR_MODE; /* Drawing Mode */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_long code[2]; +} DR_TWIN; /* Texture Window */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_long code[2]; +} DR_AREA; /* Drawing Area */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_long code[2]; +} DR_OFFSET; /* Drawing Offset */ + +typedef struct { /* MoveImage */ +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_long code[5]; +} DR_MOVE; + +typedef struct { /* LoadImage */ +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_long code[3]; + u_long p[13]; +} DR_LOAD; + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_long code[1]; +} DR_TPAGE; /* Drawing TPage */ + +typedef struct { +#if defined(USE_32_BIT_ADDR) + unsigned long tag; +#if defined(PGXP) + unsigned short len; + unsigned short pgxp_index; +#else + unsigned long len; +#endif +#else + u_long tag; +#endif + u_long code[2]; +} DR_STP; /* Drawing STP */ + +/* + * Font Stream Parameters + */ +#define FNT_MAX_ID 8 /* max number of stream ID */ +#define FNT_MAX_SPRT 1024 /* max number of sprites in all streams */ + +/* + * Multi-purpose Sony-TMD primitive + */ +typedef struct { + u_long id; + u_char r0, g0, b0, p0; /* Color of vertex 0 */ + u_char r1, g1, b1, p1; /* Color of vertex 1 */ + u_char r2, g2, b2, p2; /* Color of vertex 2 */ + u_char r3, g3, b3, p3; /* Color of vertex 3 */ + u_short tpage, clut; /* texture page ID, clut ID */ + u_char u0, v0, u1, v1; /* texture corner point */ + u_char u2, v2, u3, v3; + + /* independent vertex model */ + SVECTOR x0, x1, x2, x3; /* 3D corner point */ + SVECTOR n0, n1, n2, n3; /* 3D corner normal vector */ + + /* Common vertex model */ + SVECTOR *v_ofs; /* offset to vertex database */ + SVECTOR *n_ofs; /* offset to normal database */ + + u_short vert0, vert1; /* index of vertex */ + u_short vert2, vert3; + u_short norm0, norm1; /* index of normal */ + u_short norm2, norm3; + + +} TMD_PRIM; + +/* + * Multi-purpose TIM image + */ +typedef struct { + u_long mode; /* pixel mode */ + RECT16 *cRECT16; /* CLUT RECT16angle on frame buffer */ + u_long *caddr; /* CLUT address on main memory */ + RECT16 *pRECT16; /* texture image RECT16angle on frame buffer */ + u_long *paddr; /* texture image address on main memory */ +} TIM_IMAGE; + +#pragma pack(pop) + +/* + * Prototypes + */ +#ifndef _FNTPRINT_ +#define _FNTPRINT_ +extern int FntPrint(char* text, ...); +#endif /* _FNTPRINT_ */ +#ifndef _KANJIFNTPRINT_ +#define _KANJIFNTPRINT_ +extern int KanjiFntPrint(char* text, ...); +#endif /* _KANJIFNTPRINT_ */ + +extern DISPENV *GetDispEnv(DISPENV *env); +extern DISPENV *PutDispEnv(DISPENV *env); +extern DISPENV *SetDefDispEnv(DISPENV *env, int x, int y, int w, int h); +extern DRAWENV *GetDrawEnv(DRAWENV *env); +extern DRAWENV *PutDrawEnv(DRAWENV *env); +extern DRAWENV *SetDefDrawEnv(DRAWENV *env, int x, int y, int w, int h); +extern TIM_IMAGE *ReadTIM(TIM_IMAGE *timimg); +extern TMD_PRIM *ReadTMD(TMD_PRIM *tmdprim); +extern int CheckPrim(char *s, u_long *p); +extern int ClearImage(RECT16 *RECT16, u_char r, u_char g, u_char b); +extern int ClearImage2(RECT16 *RECT16, u_char r, u_char g, u_char b); +extern int DrawSync(int mode); +extern int FntOpen(int x, int y, int w, int h, int isbg, int n); +extern int GetGraphDebug(void); +extern int GetTimSize(u_char *sjis); +extern int IsEndPrim(void *p); +extern int KanjiFntOpen(int x, int y, int w, int h, int dx, int dy, int cx, int cy, int isbg, int n); +extern void KanjiFntClose(void); +extern int Krom2Tim(u_char *sjis, u_long *taddr, int dx, int dy, int cdx, int cdy, u_int fg, u_int bg); +extern int LoadImagePSX(RECT16 *rect, u_long *p); +extern int MargePrim(void *p0, void *p1); +extern int MoveImage(RECT16* rect, int x, int y); +extern int OpenTIM(u_long *addr); +extern int OpenTMD(u_long *tmd, int obj_no); +extern int ResetGraph(int mode); +extern int SetGraphDebug(int level); +extern int StoreImage(RECT16 *rect, u_long *p); +extern u_long *ClearOTag(u_long *ot, int n); +extern u_long *ClearOTagR(u_long *ot, int n); +extern u_long *FntFlush(int id); +extern u_long *KanjiFntFlush(int id); +extern u_long DrawSyncCallback(void (*func)(void)); +extern u_short GetClut(int x, int y); +extern u_short GetTPage(int tp, int abr, int x, int y); +extern u_short LoadClut(u_long *clut, int x, int y); +extern u_short LoadClut2(u_long *clut, int x, int y); +extern u_short LoadTPage(u_long *pix, int tp, int abr, int x, int y, int w, int h); +extern void *NextPrim(void *p); +extern void AddPrim(void *ot, void *p); +extern void AddPrims(void *ot, void *p0, void *p1); +extern void CatPrim(void *p0, void *p1); +extern void DrawOTag(u_long *p); +extern void DrawOTagIO(u_long *p); +extern void DrawOTagEnv(u_long *p, DRAWENV *env); +extern void DrawPrim(void *p); +extern void DumpClut(u_short clut); +extern void DumpDispEnv(DISPENV *env); +extern void DumpDrawEnv(DRAWENV *env); +extern void DumpOTag(u_long *p); +extern void DumpTPage(u_short tpage); +extern void FntLoad(int tx, int ty); +extern void SetDispMask(int mask); +extern void SetDrawArea(DR_AREA *p, RECT16 *r); +extern void SetDrawEnv(DR_ENV *dr_env, DRAWENV *env); +extern void SetDrawLoad(DR_LOAD *p, RECT16 *RECT16); +extern void SetDrawMode(DR_MODE *p, int dfe, int dtd, int tpage, RECT16 *tw); +extern void SetDrawTPage(DR_TPAGE *p, int dfe, int dtd, int tpage); +extern void SetDrawMove(DR_MOVE *p, RECT16 *RECT16, int x, int y); +extern void SetDrawOffset(DR_OFFSET *p, u_short *ofs); +extern void SetDrawStp(DR_STP *p, int pbw); +extern void SetDumpFnt(int id); +extern void SetLineF2(LINE_F2 *p); +extern void SetLineF3(LINE_F3 *p); +extern void SetLineF4(LINE_F4 *p); +extern void SetLineG2(LINE_G2 *p); +extern void SetLineG3(LINE_G3 *p); +extern void SetLineG4(LINE_G4 *p); +extern void SetPolyF3(POLY_F3 *p); +extern void SetPolyF4(POLY_F4 *p); +extern void SetPolyFT3(POLY_FT3 *p); +extern void SetPolyFT4(POLY_FT4 *p); +extern void SetPolyG3(POLY_G3 *p); +extern void SetPolyG4(POLY_G4 *p); +extern void SetPolyGT3(POLY_GT3 *p); +extern void SetPolyGT4(POLY_GT4 *p); +extern void SetSemiTrans(void *p, int abe); +extern void SetShadeTex(void *p, int tge); +extern void SetSprt(SPRT *p); +extern void SetSprt16(SPRT_16 *p); +extern void SetSprt8(SPRT_8 *p); +extern void SetTexWindow(DR_TWIN *p, RECT16 *tw); +extern void SetTile(TILE *p); +extern void SetTile1(TILE_1 *p); +extern void SetTile16(TILE_16 *p); +extern void SetTile8(TILE_8 *p); +extern void TermPrim(void *p); +extern u_long *BreakDraw(void); +extern void ContinueDraw(u_long *insaddr, u_long *contaddr); +extern int IsIdleGPU(int max_count); +extern int GetODE(void); +extern int LoadImage2(RECT16 *RECT16, u_long *p); +extern int StoreImage2(RECT16 *RECT16, u_long *p); +extern int MoveImage2(RECT16 *RECT16, int x, int y); +extern int DrawOTag2(u_long *p); +extern void GetDrawMode(DR_MODE *p); +extern void GetTexWindow(DR_TWIN *p); +extern void GetDrawArea(DR_AREA *p); +extern void GetDrawOffset(DR_OFFSET *p); +extern void GetDrawEnv2(DR_ENV *p); + +extern DISPENV word_33BC; +extern DRAWENV activeDrawEnv; +extern void ParseLinkedPrimitiveList(unsigned int packetStart, unsigned int packetEnd); +extern void ParsePrimitive(P_TAG* pTag); +extern int g_swapInterval; +extern int g_wireframeMode; +extern int g_texturelessMode; + +#endif diff --git a/src_rebuild/EMULATOR/LIBGTE.C b/src_rebuild/EMULATOR/LIBGTE.C new file mode 100644 index 00000000..195e9485 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBGTE.C @@ -0,0 +1,3016 @@ +#include "LIBGTE.H" +#include +#include "EMULATOR.H" +#include "EMULATOR_PRIVATE.H" +#include + + +#define WIDE_SCREEN (0) + +#if defined(PGXP) +#define MAX_NUM_VERTICES 32768 +//Index of last vertex added to vertex buffer +int pgxp_vertex_index = 0; + +int pgxp_vertex_count = 0; + +struct PGXPVertex pgxp_vertex_buffer[MAX_NUM_VERTICES]; +#endif + +GTERegisters gteRegs; + + +#define GTE_SF(op) ((op >> 19) & 1) +#define GTE_MX(op) ((op >> 17) & 3) +#define GTE_V(op) ((op >> 15) & 3) +#define GTE_CV(op) ((op >> 13) & 3) +#define GTE_LM(op) ((op >> 10) & 1) +#define GTE_FUNCT(op) (op & 63) + +#define gteop(code) (code & 0x1ffffff) + +/* Data Registers mtc2 mfc2 */ +#define VX0 (gteRegs.CP2D.p[ 0 ].sw.l) +#define VY0 (gteRegs.CP2D.p[ 0 ].sw.h) +#define VZ0 (gteRegs.CP2D.p[ 1 ].sw.l) +#define VX1 (gteRegs.CP2D.p[ 2 ].w.l) +#define VY1 (gteRegs.CP2D.p[ 2 ].w.h) +#define VZ1 (gteRegs.CP2D.p[ 3 ].w.l) +#define VX2 (gteRegs.CP2D.p[ 4 ].w.l) +#define VY2 (gteRegs.CP2D.p[ 4 ].w.h) +#define VZ2 (gteRegs.CP2D.p[ 5 ].w.l) +#define R (gteRegs.CP2D.p[ 6 ].b.l) +#define G (gteRegs.CP2D.p[ 6 ].b.h) +#define B (gteRegs.CP2D.p[ 6 ].b.h2) +#define CODE (gteRegs.CP2D.p[ 6 ].b.h3) +#define OTZ (gteRegs.CP2D.p[ 7 ].w.l) +#define IR0 (gteRegs.CP2D.p[ 8 ].sw.l) +#define IR1 (gteRegs.CP2D.p[ 9 ].sw.l) +#define IR2 (gteRegs.CP2D.p[ 10 ].sw.l) +#define IR3 (gteRegs.CP2D.p[ 11 ].sw.l) +#define SXY0 (gteRegs.CP2D.p[ 12 ].d) +#define SX0 (gteRegs.CP2D.p[ 12 ].sw.l) +#define SY0 (gteRegs.CP2D.p[ 12 ].sw.h) +#define SXY1 (gteRegs.CP2D.p[ 13 ].d) +#define SX1 (gteRegs.CP2D.p[ 13 ].sw.l) +#define SY1 (gteRegs.CP2D.p[ 13 ].sw.h) +#define SXY2 (gteRegs.CP2D.p[ 14 ].d) +#define SX2 (gteRegs.CP2D.p[ 14 ].sw.l) +#define SY2 (gteRegs.CP2D.p[ 14 ].sw.h) +#define SXYP (gteRegs.CP2D.p[ 15 ].d) +#define SXP (gteRegs.CP2D.p[ 15 ].sw.l) +#define SYP (gteRegs.CP2D.p[ 15 ].sw.h) +#define SZ0 (gteRegs.CP2D.p[ 16 ].w.l) +#define SZ1 (gteRegs.CP2D.p[ 17 ].w.l) +#define SZ2 (gteRegs.CP2D.p[ 18 ].w.l) +#define SZ3 (gteRegs.CP2D.p[ 19 ].w.l) +#define RGB0 (gteRegs.CP2D.p[ 20 ].d) +#define R0 (gteRegs.CP2D.p[ 20 ].b.l) +#define G0 (gteRegs.CP2D.p[ 20 ].b.h) +#define B0 (gteRegs.CP2D.p[ 20 ].b.h2) +#define CD0 (gteRegs.CP2D.p[ 20 ].b.h3) +#define RGB1 (gteRegs.CP2D.p[ 21 ].d) +#define R1 (gteRegs.CP2D.p[ 21 ].b.l) +#define G1 (gteRegs.CP2D.p[ 21 ].b.h) +#define B1 (gteRegs.CP2D.p[ 21 ].b.h2) +#define CD1 (gteRegs.CP2D.p[ 21 ].b.h3) +#define RGB2 (gteRegs.CP2D.p[ 22 ].d) +#define R2 (gteRegs.CP2D.p[ 22 ].b.l) +#define G2 (gteRegs.CP2D.p[ 22 ].b.h) +#define B2 (gteRegs.CP2D.p[ 22 ].b.h2) +#define CD2 (gteRegs.CP2D.p[ 22 ].b.h3) +#define RES1 (gteRegs.CP2D.p[ 23 ].d) +#define MAC0 (gteRegs.CP2D.p[ 24 ].sd) +#define MAC1 (gteRegs.CP2D.p[ 25 ].sd) +#define MAC2 (gteRegs.CP2D.p[ 26 ].sd) +#define MAC3 (gteRegs.CP2D.p[ 27 ].sd) +#define IRGB (gteRegs.CP2D.p[ 28 ].d) +#define ORGB (gteRegs.CP2D.p[ 29 ].d) +#define LZCS (gteRegs.CP2D.p[ 30 ].d) +#define LZCR (gteRegs.CP2D.p[ 31 ].d) + +/* Control Registers ctc2 cfc2*/ +#define R11 (gteRegs.CP2C.p[ 0 ].sw.l) +#define R12 (gteRegs.CP2C.p[ 0 ].sw.h) +#define R13 (gteRegs.CP2C.p[ 1 ].sw.l) +#define R21 (gteRegs.CP2C.p[ 1 ].sw.h) +#define R22 (gteRegs.CP2C.p[ 2 ].sw.l) +#define R23 (gteRegs.CP2C.p[ 2 ].sw.h) +#define R31 (gteRegs.CP2C.p[ 3 ].sw.l) +#define R32 (gteRegs.CP2C.p[ 3 ].sw.h) +#define R33 (gteRegs.CP2C.p[ 4 ].sw.l) +#define TRX (gteRegs.CP2C.p[ 5 ].sd) +#define TRY (gteRegs.CP2C.p[ 6 ].sd) +#define TRZ (gteRegs.CP2C.p[ 7 ].sd) +#define L11 (gteRegs.CP2C.p[ 8 ].sw.l) +#define L12 (gteRegs.CP2C.p[ 8 ].sw.h) +#define L13 (gteRegs.CP2C.p[ 9 ].sw.l) +#define L21 (gteRegs.CP2C.p[ 9 ].sw.h) +#define L22 (gteRegs.CP2C.p[ 10 ].sw.l) +#define L23 (gteRegs.CP2C.p[ 10 ].sw.h) +#define L31 (gteRegs.CP2C.p[ 11 ].sw.l) +#define L32 (gteRegs.CP2C.p[ 11 ].sw.h) +#define L33 (gteRegs.CP2C.p[ 12 ].sw.l) +#define RBK (gteRegs.CP2C.p[ 13 ].sd) +#define GBK (gteRegs.CP2C.p[ 14 ].sd) +#define BBK (gteRegs.CP2C.p[ 15 ].sd) +#define LR1 (gteRegs.CP2C.p[ 16 ].sw.l) +#define LR2 (gteRegs.CP2C.p[ 16 ].sw.h) +#define LR3 (gteRegs.CP2C.p[ 17 ].sw.l) +#define LG1 (gteRegs.CP2C.p[ 17 ].sw.h) +#define LG2 (gteRegs.CP2C.p[ 18 ].sw.l) +#define LG3 (gteRegs.CP2C.p[ 18 ].sw.h) +#define LB1 (gteRegs.CP2C.p[ 19 ].sw.l) +#define LB2 (gteRegs.CP2C.p[ 19 ].sw.h) +#define LB3 (gteRegs.CP2C.p[ 20 ].sw.l) +#define RFC (gteRegs.CP2C.p[ 21 ].sd) +#define GFC (gteRegs.CP2C.p[ 22 ].sd) +#define BFC (gteRegs.CP2C.p[ 23 ].sd) +#define OFX (gteRegs.CP2C.p[ 24 ].sd) +#define OFY (gteRegs.CP2C.p[ 25 ].sd) +#define H (gteRegs.CP2C.p[ 26 ].sw.l) +#define DQA (gteRegs.CP2C.p[ 27 ].sw.l) +#define DQB (gteRegs.CP2C.p[ 28 ].sd) +#define ZSF3 (gteRegs.CP2C.p[ 29 ].sw.l) +#define ZSF4 (gteRegs.CP2C.p[ 30 ].sw.l) +#define FLAG (gteRegs.CP2C.p[ 31 ].d) + +#define VX(n) (n < 3 ? gteRegs.CP2D.p[ n << 1 ].sw.l : IR1) +#define VY(n) (n < 3 ? gteRegs.CP2D.p[ n << 1 ].sw.h : IR2) +#define VZ(n) (n < 3 ? gteRegs.CP2D.p[ (n << 1) + 1 ].sw.l : IR3) +#define MX11(n) (n < 3 ? gteRegs.CP2C.p[ (n << 3) ].sw.l : -R << 4) +#define MX12(n) (n < 3 ? gteRegs.CP2C.p[ (n << 3) ].sw.h : R << 4) +#define MX13(n) (n < 3 ? gteRegs.CP2C.p[ (n << 3) + 1 ].sw.l : IR0) +#define MX21(n) (n < 3 ? gteRegs.CP2C.p[ (n << 3) + 1 ].sw.h : R13) +#define MX22(n) (n < 3 ? gteRegs.CP2C.p[ (n << 3) + 2 ].sw.l : R13) +#define MX23(n) (n < 3 ? gteRegs.CP2C.p[ (n << 3) + 2 ].sw.h : R13) +#define MX31(n) (n < 3 ? gteRegs.CP2C.p[ (n << 3) + 3 ].sw.l : R22) +#define MX32(n) (n < 3 ? gteRegs.CP2C.p[ (n << 3) + 3 ].sw.h : R22) +#define MX33(n) (n < 3 ? gteRegs.CP2C.p[ (n << 3) + 4 ].sw.l : R22) +#define CV1(n) (n < 3 ? gteRegs.CP2C.p[ (n << 3) + 5 ].sd : 0) +#define CV2(n) (n < 3 ? gteRegs.CP2C.p[ (n << 3) + 6 ].sd : 0) +#define CV3(n) (n < 3 ? gteRegs.CP2C.p[ (n << 3) + 7 ].sd : 0) + +unsigned char ida_chars[] = +{ + 0x00, 0x00, 0x00, 0x10, 0x06, 0x00, 0x00, 0x10, 0x0D, 0x00, + 0x00, 0x10, 0x13, 0x00, 0x00, 0x10, 0x19, 0x00, 0x00, 0x10, + 0x1F, 0x00, 0x00, 0x10, 0x26, 0x00, 0x00, 0x10, 0x2C, 0x00, + 0x00, 0x10, 0x32, 0x00, 0x00, 0x10, 0x39, 0x00, 0x00, 0x10, + 0x3F, 0x00, 0x00, 0x10, 0x45, 0x00, 0xFF, 0x0F, 0x4B, 0x00, + 0xFF, 0x0F, 0x52, 0x00, 0xFF, 0x0F, 0x58, 0x00, 0xFF, 0x0F, + 0x5E, 0x00, 0xFF, 0x0F, 0x65, 0x00, 0xFF, 0x0F, 0x6B, 0x00, + 0xFF, 0x0F, 0x71, 0x00, 0xFE, 0x0F, 0x77, 0x00, 0xFE, 0x0F, + 0x7E, 0x00, 0xFE, 0x0F, 0x84, 0x00, 0xFE, 0x0F, 0x8A, 0x00, + 0xFE, 0x0F, 0x90, 0x00, 0xFD, 0x0F, 0x97, 0x00, 0xFD, 0x0F, + 0x9D, 0x00, 0xFD, 0x0F, 0xA3, 0x00, 0xFD, 0x0F, 0xAA, 0x00, + 0xFC, 0x0F, 0xB0, 0x00, 0xFC, 0x0F, 0xB6, 0x00, 0xFC, 0x0F, + 0xBC, 0x00, 0xFC, 0x0F, 0xC3, 0x00, 0xFB, 0x0F, 0xC9, 0x00, + 0xFB, 0x0F, 0xCF, 0x00, 0xFB, 0x0F, 0xD6, 0x00, 0xFA, 0x0F, + 0xDC, 0x00, 0xFA, 0x0F, 0xE2, 0x00, 0xFA, 0x0F, 0xE8, 0x00, + 0xF9, 0x0F, 0xEF, 0x00, 0xF9, 0x0F, 0xF5, 0x00, 0xF9, 0x0F, + 0xFB, 0x00, 0xF8, 0x0F, 0x01, 0x01, 0xF8, 0x0F, 0x08, 0x01, + 0xF8, 0x0F, 0x0E, 0x01, 0xF7, 0x0F, 0x14, 0x01, 0xF7, 0x0F, + 0x1B, 0x01, 0xF6, 0x0F, 0x21, 0x01, 0xF6, 0x0F, 0x27, 0x01, + 0xF5, 0x0F, 0x2D, 0x01, 0xF5, 0x0F, 0x34, 0x01, 0xF4, 0x0F, + 0x3A, 0x01, 0xF4, 0x0F, 0x40, 0x01, 0xF3, 0x0F, 0x46, 0x01, + 0xF3, 0x0F, 0x4D, 0x01, 0xF2, 0x0F, 0x53, 0x01, 0xF2, 0x0F, + 0x59, 0x01, 0xF1, 0x0F, 0x5F, 0x01, 0xF1, 0x0F, 0x66, 0x01, + 0xF0, 0x0F, 0x6C, 0x01, 0xF0, 0x0F, 0x72, 0x01, 0xEF, 0x0F, + 0x78, 0x01, 0xEF, 0x0F, 0x7F, 0x01, 0xEE, 0x0F, 0x85, 0x01, + 0xED, 0x0F, 0x8B, 0x01, 0xED, 0x0F, 0x91, 0x01, 0xEC, 0x0F, + 0x98, 0x01, 0xEC, 0x0F, 0x9E, 0x01, 0xEB, 0x0F, 0xA4, 0x01, + 0xEA, 0x0F, 0xAA, 0x01, 0xEA, 0x0F, 0xB1, 0x01, 0xE9, 0x0F, + 0xB7, 0x01, 0xE8, 0x0F, 0xBD, 0x01, 0xE8, 0x0F, 0xC3, 0x01, + 0xE7, 0x0F, 0xCA, 0x01, 0xE6, 0x0F, 0xD0, 0x01, 0xE6, 0x0F, + 0xD6, 0x01, 0xE5, 0x0F, 0xDC, 0x01, 0xE4, 0x0F, 0xE3, 0x01, + 0xE3, 0x0F, 0xE9, 0x01, 0xE3, 0x0F, 0xEF, 0x01, 0xE2, 0x0F, + 0xF5, 0x01, 0xE1, 0x0F, 0xFC, 0x01, 0xE0, 0x0F, 0x02, 0x02, + 0xE0, 0x0F, 0x08, 0x02, 0xDF, 0x0F, 0x0E, 0x02, 0xDE, 0x0F, + 0x15, 0x02, 0xDD, 0x0F, 0x1B, 0x02, 0xDC, 0x0F, 0x21, 0x02, + 0xDC, 0x0F, 0x27, 0x02, 0xDB, 0x0F, 0x2D, 0x02, 0xDA, 0x0F, + 0x34, 0x02, 0xD9, 0x0F, 0x3A, 0x02, 0xD8, 0x0F, 0x40, 0x02, + 0xD7, 0x0F, 0x46, 0x02, 0xD6, 0x0F, 0x4D, 0x02, 0xD5, 0x0F, + 0x53, 0x02, 0xD5, 0x0F, 0x59, 0x02, 0xD4, 0x0F, 0x5F, 0x02, + 0xD3, 0x0F, 0x65, 0x02, 0xD2, 0x0F, 0x6C, 0x02, 0xD1, 0x0F, + 0x72, 0x02, 0xD0, 0x0F, 0x78, 0x02, 0xCF, 0x0F, 0x7E, 0x02, + 0xCE, 0x0F, 0x84, 0x02, 0xCD, 0x0F, 0x8B, 0x02, 0xCC, 0x0F, + 0x91, 0x02, 0xCB, 0x0F, 0x97, 0x02, 0xCA, 0x0F, 0x9D, 0x02, + 0xC9, 0x0F, 0xA3, 0x02, 0xC8, 0x0F, 0xAA, 0x02, 0xC7, 0x0F, + 0xB0, 0x02, 0xC6, 0x0F, 0xB6, 0x02, 0xC5, 0x0F, 0xBC, 0x02, + 0xC4, 0x0F, 0xC2, 0x02, 0xC3, 0x0F, 0xC9, 0x02, 0xC2, 0x0F, + 0xCF, 0x02, 0xC0, 0x0F, 0xD5, 0x02, 0xBF, 0x0F, 0xDB, 0x02, + 0xBE, 0x0F, 0xE1, 0x02, 0xBD, 0x0F, 0xE8, 0x02, 0xBC, 0x0F, + 0xEE, 0x02, 0xBB, 0x0F, 0xF4, 0x02, 0xBA, 0x0F, 0xFA, 0x02, + 0xB8, 0x0F, 0x00, 0x03, 0xB7, 0x0F, 0x06, 0x03, 0xB6, 0x0F, + 0x0D, 0x03, 0xB5, 0x0F, 0x13, 0x03, 0xB4, 0x0F, 0x19, 0x03, + 0xB3, 0x0F, 0x1F, 0x03, 0xB1, 0x0F, 0x25, 0x03, 0xB0, 0x0F, + 0x2B, 0x03, 0xAF, 0x0F, 0x32, 0x03, 0xAE, 0x0F, 0x38, 0x03, + 0xAC, 0x0F, 0x3E, 0x03, 0xAB, 0x0F, 0x44, 0x03, 0xAA, 0x0F, + 0x4A, 0x03, 0xA8, 0x0F, 0x50, 0x03, 0xA7, 0x0F, 0x56, 0x03, + 0xA6, 0x0F, 0x5D, 0x03, 0xA5, 0x0F, 0x63, 0x03, 0xA3, 0x0F, + 0x69, 0x03, 0xA2, 0x0F, 0x6F, 0x03, 0xA1, 0x0F, 0x75, 0x03, + 0x9F, 0x0F, 0x7B, 0x03, 0x9E, 0x0F, 0x81, 0x03, 0x9C, 0x0F, + 0x88, 0x03, 0x9B, 0x0F, 0x8E, 0x03, 0x9A, 0x0F, 0x94, 0x03, + 0x98, 0x0F, 0x9A, 0x03, 0x97, 0x0F, 0xA0, 0x03, 0x95, 0x0F, + 0xA6, 0x03, 0x94, 0x0F, 0xAC, 0x03, 0x93, 0x0F, 0xB2, 0x03, + 0x91, 0x0F, 0xB9, 0x03, 0x90, 0x0F, 0xBF, 0x03, 0x8E, 0x0F, + 0xC5, 0x03, 0x8D, 0x0F, 0xCB, 0x03, 0x8B, 0x0F, 0xD1, 0x03, + 0x8A, 0x0F, 0xD7, 0x03, 0x88, 0x0F, 0xDD, 0x03, 0x87, 0x0F, + 0xE3, 0x03, 0x85, 0x0F, 0xE9, 0x03, 0x84, 0x0F, 0xEF, 0x03, + 0x82, 0x0F, 0xF6, 0x03, 0x81, 0x0F, 0xFC, 0x03, 0x7F, 0x0F, + 0x02, 0x04, 0x7D, 0x0F, 0x08, 0x04, 0x7C, 0x0F, 0x0E, 0x04, + 0x7A, 0x0F, 0x14, 0x04, 0x79, 0x0F, 0x1A, 0x04, 0x77, 0x0F, + 0x20, 0x04, 0x76, 0x0F, 0x26, 0x04, 0x74, 0x0F, 0x2C, 0x04, + 0x72, 0x0F, 0x32, 0x04, 0x71, 0x0F, 0x38, 0x04, 0x6F, 0x0F, + 0x3E, 0x04, 0x6D, 0x0F, 0x44, 0x04, 0x6C, 0x0F, 0x4B, 0x04, + 0x6A, 0x0F, 0x51, 0x04, 0x68, 0x0F, 0x57, 0x04, 0x67, 0x0F, + 0x5D, 0x04, 0x65, 0x0F, 0x63, 0x04, 0x63, 0x0F, 0x69, 0x04, + 0x61, 0x0F, 0x6F, 0x04, 0x60, 0x0F, 0x75, 0x04, 0x5E, 0x0F, + 0x7B, 0x04, 0x5C, 0x0F, 0x81, 0x04, 0x5A, 0x0F, 0x87, 0x04, + 0x59, 0x0F, 0x8D, 0x04, 0x57, 0x0F, 0x93, 0x04, 0x55, 0x0F, + 0x99, 0x04, 0x53, 0x0F, 0x9F, 0x04, 0x51, 0x0F, 0xA5, 0x04, + 0x50, 0x0F, 0xAB, 0x04, 0x4E, 0x0F, 0xB1, 0x04, 0x4C, 0x0F, + 0xB7, 0x04, 0x4A, 0x0F, 0xBD, 0x04, 0x48, 0x0F, 0xC3, 0x04, + 0x46, 0x0F, 0xC9, 0x04, 0x45, 0x0F, 0xCF, 0x04, 0x43, 0x0F, + 0xD5, 0x04, 0x41, 0x0F, 0xDB, 0x04, 0x3F, 0x0F, 0xE1, 0x04, + 0x3D, 0x0F, 0xE7, 0x04, 0x3B, 0x0F, 0xED, 0x04, 0x39, 0x0F, + 0xF3, 0x04, 0x37, 0x0F, 0xF9, 0x04, 0x35, 0x0F, 0xFF, 0x04, + 0x33, 0x0F, 0x05, 0x05, 0x31, 0x0F, 0x0B, 0x05, 0x2F, 0x0F, + 0x11, 0x05, 0x2D, 0x0F, 0x17, 0x05, 0x2B, 0x0F, 0x1D, 0x05, + 0x29, 0x0F, 0x23, 0x05, 0x27, 0x0F, 0x29, 0x05, 0x25, 0x0F, + 0x2F, 0x05, 0x23, 0x0F, 0x34, 0x05, 0x21, 0x0F, 0x3A, 0x05, + 0x1F, 0x0F, 0x40, 0x05, 0x1D, 0x0F, 0x46, 0x05, 0x1B, 0x0F, + 0x4C, 0x05, 0x19, 0x0F, 0x52, 0x05, 0x17, 0x0F, 0x58, 0x05, + 0x15, 0x0F, 0x5E, 0x05, 0x13, 0x0F, 0x64, 0x05, 0x11, 0x0F, + 0x6A, 0x05, 0x0E, 0x0F, 0x70, 0x05, 0x0C, 0x0F, 0x76, 0x05, + 0x0A, 0x0F, 0x7C, 0x05, 0x08, 0x0F, 0x81, 0x05, 0x06, 0x0F, + 0x87, 0x05, 0x04, 0x0F, 0x8D, 0x05, 0x02, 0x0F, 0x93, 0x05, + 0xFF, 0x0E, 0x99, 0x05, 0xFD, 0x0E, 0x9F, 0x05, 0xFB, 0x0E, + 0xA5, 0x05, 0xF9, 0x0E, 0xAB, 0x05, 0xF7, 0x0E, 0xB1, 0x05, + 0xF4, 0x0E, 0xB6, 0x05, 0xF2, 0x0E, 0xBC, 0x05, 0xF0, 0x0E, + 0xC2, 0x05, 0xEE, 0x0E, 0xC8, 0x05, 0xEB, 0x0E, 0xCE, 0x05, + 0xE9, 0x0E, 0xD4, 0x05, 0xE7, 0x0E, 0xDA, 0x05, 0xE4, 0x0E, + 0xDF, 0x05, 0xE2, 0x0E, 0xE5, 0x05, 0xE0, 0x0E, 0xEB, 0x05, + 0xDD, 0x0E, 0xF1, 0x05, 0xDB, 0x0E, 0xF7, 0x05, 0xD9, 0x0E, + 0xFD, 0x05, 0xD6, 0x0E, 0x02, 0x06, 0xD4, 0x0E, 0x08, 0x06, + 0xD2, 0x0E, 0x0E, 0x06, 0xCF, 0x0E, 0x14, 0x06, 0xCD, 0x0E, + 0x1A, 0x06, 0xCB, 0x0E, 0x1F, 0x06, 0xC8, 0x0E, 0x25, 0x06, + 0xC6, 0x0E, 0x2B, 0x06, 0xC3, 0x0E, 0x31, 0x06, 0xC1, 0x0E, + 0x37, 0x06, 0xBF, 0x0E, 0x3C, 0x06, 0xBC, 0x0E, 0x42, 0x06, + 0xBA, 0x0E, 0x48, 0x06, 0xB7, 0x0E, 0x4E, 0x06, 0xB5, 0x0E, + 0x54, 0x06, 0xB2, 0x0E, 0x59, 0x06, 0xB0, 0x0E, 0x5F, 0x06, + 0xAD, 0x0E, 0x65, 0x06, 0xAB, 0x0E, 0x6B, 0x06, 0xA8, 0x0E, + 0x70, 0x06, 0xA6, 0x0E, 0x76, 0x06, 0xA3, 0x0E, 0x7C, 0x06, + 0xA1, 0x0E, 0x82, 0x06, 0x9E, 0x0E, 0x87, 0x06, 0x9B, 0x0E, + 0x8D, 0x06, 0x99, 0x0E, 0x93, 0x06, 0x96, 0x0E, 0x99, 0x06, + 0x94, 0x0E, 0x9E, 0x06, 0x91, 0x0E, 0xA4, 0x06, 0x8F, 0x0E, + 0xAA, 0x06, 0x8C, 0x0E, 0xAF, 0x06, 0x89, 0x0E, 0xB5, 0x06, + 0x87, 0x0E, 0xBB, 0x06, 0x84, 0x0E, 0xC1, 0x06, 0x81, 0x0E, + 0xC6, 0x06, 0x7F, 0x0E, 0xCC, 0x06, 0x7C, 0x0E, 0xD2, 0x06, + 0x79, 0x0E, 0xD7, 0x06, 0x77, 0x0E, 0xDD, 0x06, 0x74, 0x0E, + 0xE3, 0x06, 0x71, 0x0E, 0xE8, 0x06, 0x6F, 0x0E, 0xEE, 0x06, + 0x6C, 0x0E, 0xF4, 0x06, 0x69, 0x0E, 0xF9, 0x06, 0x66, 0x0E, + 0xFF, 0x06, 0x64, 0x0E, 0x05, 0x07, 0x61, 0x0E, 0x0A, 0x07, + 0x5E, 0x0E, 0x10, 0x07, 0x5B, 0x0E, 0x15, 0x07, 0x59, 0x0E, + 0x1B, 0x07, 0x56, 0x0E, 0x21, 0x07, 0x53, 0x0E, 0x26, 0x07, + 0x50, 0x0E, 0x2C, 0x07, 0x4D, 0x0E, 0x32, 0x07, 0x4B, 0x0E, + 0x37, 0x07, 0x48, 0x0E, 0x3D, 0x07, 0x45, 0x0E, 0x42, 0x07, + 0x42, 0x0E, 0x48, 0x07, 0x3F, 0x0E, 0x4E, 0x07, 0x3C, 0x0E, + 0x53, 0x07, 0x3A, 0x0E, 0x59, 0x07, 0x37, 0x0E, 0x5E, 0x07, + 0x34, 0x0E, 0x64, 0x07, 0x31, 0x0E, 0x6A, 0x07, 0x2E, 0x0E, + 0x6F, 0x07, 0x2B, 0x0E, 0x75, 0x07, 0x28, 0x0E, 0x7A, 0x07, + 0x25, 0x0E, 0x80, 0x07, 0x22, 0x0E, 0x85, 0x07, 0x1F, 0x0E, + 0x8B, 0x07, 0x1C, 0x0E, 0x90, 0x07, 0x19, 0x0E, 0x96, 0x07, + 0x16, 0x0E, 0x9B, 0x07, 0x13, 0x0E, 0xA1, 0x07, 0x10, 0x0E, + 0xA6, 0x07, 0x0D, 0x0E, 0xAC, 0x07, 0x0A, 0x0E, 0xB2, 0x07, + 0x07, 0x0E, 0xB7, 0x07, 0x04, 0x0E, 0xBD, 0x07, 0x01, 0x0E, + 0xC2, 0x07, 0xFE, 0x0D, 0xC8, 0x07, 0xFB, 0x0D, 0xCD, 0x07, + 0xF8, 0x0D, 0xD2, 0x07, 0xF5, 0x0D, 0xD8, 0x07, 0xF2, 0x0D, + 0xDD, 0x07, 0xEF, 0x0D, 0xE3, 0x07, 0xEC, 0x0D, 0xE8, 0x07, + 0xE9, 0x0D, 0xEE, 0x07, 0xE6, 0x0D, 0xF3, 0x07, 0xE3, 0x0D, + 0xF9, 0x07, 0xDF, 0x0D, 0xFE, 0x07, 0xDC, 0x0D, 0x04, 0x08, + 0xD9, 0x0D, 0x09, 0x08, 0xD6, 0x0D, 0x0E, 0x08, 0xD3, 0x0D, + 0x14, 0x08, 0xD0, 0x0D, 0x19, 0x08, 0xCC, 0x0D, 0x1F, 0x08, + 0xC9, 0x0D, 0x24, 0x08, 0xC6, 0x0D, 0x2A, 0x08, 0xC3, 0x0D, + 0x2F, 0x08, 0xC0, 0x0D, 0x34, 0x08, 0xBC, 0x0D, 0x3A, 0x08, + 0xB9, 0x0D, 0x3F, 0x08, 0xB6, 0x0D, 0x45, 0x08, 0xB3, 0x0D, + 0x4A, 0x08, 0xB0, 0x0D, 0x4F, 0x08, 0xAC, 0x0D, 0x55, 0x08, + 0xA9, 0x0D, 0x5A, 0x08, 0xA6, 0x0D, 0x5F, 0x08, 0xA2, 0x0D, + 0x65, 0x08, 0x9F, 0x0D, 0x6A, 0x08, 0x9C, 0x0D, 0x6F, 0x08, + 0x99, 0x0D, 0x75, 0x08, 0x95, 0x0D, 0x7A, 0x08, 0x92, 0x0D, + 0x7F, 0x08, 0x8F, 0x0D, 0x85, 0x08, 0x8B, 0x0D, 0x8A, 0x08, + 0x88, 0x0D, 0x8F, 0x08, 0x85, 0x0D, 0x95, 0x08, 0x81, 0x0D, + 0x9A, 0x08, 0x7E, 0x0D, 0x9F, 0x08, 0x7A, 0x0D, 0xA5, 0x08, + 0x77, 0x0D, 0xAA, 0x08, 0x74, 0x0D, 0xAF, 0x08, 0x70, 0x0D, + 0xB4, 0x08, 0x6D, 0x0D, 0xBA, 0x08, 0x69, 0x0D, 0xBF, 0x08, + 0x66, 0x0D, 0xC4, 0x08, 0x62, 0x0D, 0xC9, 0x08, 0x5F, 0x0D, + 0xCF, 0x08, 0x5C, 0x0D, 0xD4, 0x08, 0x58, 0x0D, 0xD9, 0x08, + 0x55, 0x0D, 0xDE, 0x08, 0x51, 0x0D, 0xE4, 0x08, 0x4E, 0x0D, + 0xE9, 0x08, 0x4A, 0x0D, 0xEE, 0x08, 0x47, 0x0D, 0xF3, 0x08, + 0x43, 0x0D, 0xF8, 0x08, 0x40, 0x0D, 0xFE, 0x08, 0x3C, 0x0D, + 0x03, 0x09, 0x39, 0x0D, 0x08, 0x09, 0x35, 0x0D, 0x0D, 0x09, + 0x32, 0x0D, 0x12, 0x09, 0x2E, 0x0D, 0x18, 0x09, 0x2A, 0x0D, + 0x1D, 0x09, 0x27, 0x0D, 0x22, 0x09, 0x23, 0x0D, 0x27, 0x09, + 0x20, 0x0D, 0x2C, 0x09, 0x1C, 0x0D, 0x31, 0x09, 0x18, 0x0D, + 0x37, 0x09, 0x15, 0x0D, 0x3C, 0x09, 0x11, 0x0D, 0x41, 0x09, + 0x0E, 0x0D, 0x46, 0x09, 0x0A, 0x0D, 0x4B, 0x09, 0x06, 0x0D, + 0x50, 0x09, 0x03, 0x0D, 0x55, 0x09, 0xFF, 0x0C, 0x5A, 0x09, + 0xFB, 0x0C, 0x5F, 0x09, 0xF8, 0x0C, 0x65, 0x09, 0xF4, 0x0C, + 0x6A, 0x09, 0xF0, 0x0C, 0x6F, 0x09, 0xED, 0x0C, 0x74, 0x09, + 0xE9, 0x0C, 0x79, 0x09, 0xE5, 0x0C, 0x7E, 0x09, 0xE1, 0x0C, + 0x83, 0x09, 0xDE, 0x0C, 0x88, 0x09, 0xDA, 0x0C, 0x8D, 0x09, + 0xD6, 0x0C, 0x92, 0x09, 0xD2, 0x0C, 0x97, 0x09, 0xCF, 0x0C, + 0x9C, 0x09, 0xCB, 0x0C, 0xA1, 0x09, 0xC7, 0x0C, 0xA6, 0x09, + 0xC3, 0x0C, 0xAB, 0x09, 0xC0, 0x0C, 0xB0, 0x09, 0xBC, 0x0C, + 0xB5, 0x09, 0xB8, 0x0C, 0xBA, 0x09, 0xB4, 0x0C, 0xBF, 0x09, + 0xB0, 0x0C, 0xC4, 0x09, 0xAC, 0x0C, 0xC9, 0x09, 0xA9, 0x0C, + 0xCE, 0x09, 0xA5, 0x0C, 0xD3, 0x09, 0xA1, 0x0C, 0xD8, 0x09, + 0x9D, 0x0C, 0xDD, 0x09, 0x99, 0x0C, 0xE2, 0x09, 0x95, 0x0C, + 0xE7, 0x09, 0x91, 0x0C, 0xEC, 0x09, 0x8E, 0x0C, 0xF1, 0x09, + 0x8A, 0x0C, 0xF6, 0x09, 0x86, 0x0C, 0xFB, 0x09, 0x82, 0x0C, + 0xFF, 0x09, 0x7E, 0x0C, 0x04, 0x0A, 0x7A, 0x0C, 0x09, 0x0A, + 0x76, 0x0C, 0x0E, 0x0A, 0x72, 0x0C, 0x13, 0x0A, 0x6E, 0x0C, + 0x18, 0x0A, 0x6A, 0x0C, 0x1D, 0x0A, 0x66, 0x0C, 0x22, 0x0A, + 0x62, 0x0C, 0x26, 0x0A, 0x5E, 0x0C, 0x2B, 0x0A, 0x5A, 0x0C, + 0x30, 0x0A, 0x56, 0x0C, 0x35, 0x0A, 0x52, 0x0C, 0x3A, 0x0A, + 0x4E, 0x0C, 0x3F, 0x0A, 0x4A, 0x0C, 0x44, 0x0A, 0x46, 0x0C, + 0x48, 0x0A, 0x42, 0x0C, 0x4D, 0x0A, 0x3E, 0x0C, 0x52, 0x0A, + 0x3A, 0x0C, 0x57, 0x0A, 0x36, 0x0C, 0x5C, 0x0A, 0x32, 0x0C, + 0x60, 0x0A, 0x2E, 0x0C, 0x65, 0x0A, 0x2A, 0x0C, 0x6A, 0x0A, + 0x26, 0x0C, 0x6F, 0x0A, 0x22, 0x0C, 0x73, 0x0A, 0x1E, 0x0C, + 0x78, 0x0A, 0x19, 0x0C, 0x7D, 0x0A, 0x15, 0x0C, 0x82, 0x0A, + 0x11, 0x0C, 0x86, 0x0A, 0x0D, 0x0C, 0x8B, 0x0A, 0x09, 0x0C, + 0x90, 0x0A, 0x05, 0x0C, 0x95, 0x0A, 0x01, 0x0C, 0x99, 0x0A, + 0xFC, 0x0B, 0x9E, 0x0A, 0xF8, 0x0B, 0xA3, 0x0A, 0xF4, 0x0B, + 0xA7, 0x0A, 0xF0, 0x0B, 0xAC, 0x0A, 0xEC, 0x0B, 0xB1, 0x0A, + 0xE8, 0x0B, 0xB5, 0x0A, 0xE3, 0x0B, 0xBA, 0x0A, 0xDF, 0x0B, + 0xBF, 0x0A, 0xDB, 0x0B, 0xC3, 0x0A, 0xD7, 0x0B, 0xC8, 0x0A, + 0xD2, 0x0B, 0xCD, 0x0A, 0xCE, 0x0B, 0xD1, 0x0A, 0xCA, 0x0B, + 0xD6, 0x0A, 0xC6, 0x0B, 0xDB, 0x0A, 0xC1, 0x0B, 0xDF, 0x0A, + 0xBD, 0x0B, 0xE4, 0x0A, 0xB9, 0x0B, 0xE8, 0x0A, 0xB5, 0x0B, + 0xED, 0x0A, 0xB0, 0x0B, 0xF2, 0x0A, 0xAC, 0x0B, 0xF6, 0x0A, + 0xA8, 0x0B, 0xFB, 0x0A, 0xA3, 0x0B, 0xFF, 0x0A, 0x9F, 0x0B, + 0x04, 0x0B, 0x9B, 0x0B, 0x08, 0x0B, 0x97, 0x0B, 0x0D, 0x0B, + 0x92, 0x0B, 0x11, 0x0B, 0x8E, 0x0B, 0x16, 0x0B, 0x89, 0x0B, + 0x1B, 0x0B, 0x85, 0x0B, 0x1F, 0x0B, 0x81, 0x0B, 0x24, 0x0B, + 0x7C, 0x0B, 0x28, 0x0B, 0x78, 0x0B, 0x2D, 0x0B, 0x74, 0x0B, + 0x31, 0x0B, 0x6F, 0x0B, 0x36, 0x0B, 0x6B, 0x0B, 0x3A, 0x0B, + 0x66, 0x0B, 0x3E, 0x0B, 0x62, 0x0B, 0x43, 0x0B, 0x5E, 0x0B, + 0x47, 0x0B, 0x59, 0x0B, 0x4C, 0x0B, 0x55, 0x0B, 0x50, 0x0B, + 0x50, 0x0B, 0x55, 0x0B, 0x4C, 0x0B, 0x59, 0x0B, 0x47, 0x0B, + 0x5E, 0x0B, 0x43, 0x0B, 0x62, 0x0B, 0x3E, 0x0B, 0x66, 0x0B, + 0x3A, 0x0B, 0x6B, 0x0B, 0x36, 0x0B, 0x6F, 0x0B, 0x31, 0x0B, + 0x74, 0x0B, 0x2D, 0x0B, 0x78, 0x0B, 0x28, 0x0B, 0x7C, 0x0B, + 0x24, 0x0B, 0x81, 0x0B, 0x1F, 0x0B, 0x85, 0x0B, 0x1B, 0x0B, + 0x89, 0x0B, 0x16, 0x0B, 0x8E, 0x0B, 0x11, 0x0B, 0x92, 0x0B, + 0x0D, 0x0B, 0x97, 0x0B, 0x08, 0x0B, 0x9B, 0x0B, 0x04, 0x0B, + 0x9F, 0x0B, 0xFF, 0x0A, 0xA3, 0x0B, 0xFB, 0x0A, 0xA8, 0x0B, + 0xF6, 0x0A, 0xAC, 0x0B, 0xF2, 0x0A, 0xB0, 0x0B, 0xED, 0x0A, + 0xB5, 0x0B, 0xE8, 0x0A, 0xB9, 0x0B, 0xE4, 0x0A, 0xBD, 0x0B, + 0xDF, 0x0A, 0xC1, 0x0B, 0xDB, 0x0A, 0xC6, 0x0B, 0xD6, 0x0A, + 0xCA, 0x0B, 0xD1, 0x0A, 0xCE, 0x0B, 0xCD, 0x0A, 0xD2, 0x0B, + 0xC8, 0x0A, 0xD7, 0x0B, 0xC3, 0x0A, 0xDB, 0x0B, 0xBF, 0x0A, + 0xDF, 0x0B, 0xBA, 0x0A, 0xE3, 0x0B, 0xB5, 0x0A, 0xE8, 0x0B, + 0xB1, 0x0A, 0xEC, 0x0B, 0xAC, 0x0A, 0xF0, 0x0B, 0xA7, 0x0A, + 0xF4, 0x0B, 0xA3, 0x0A, 0xF8, 0x0B, 0x9E, 0x0A, 0xFC, 0x0B, + 0x99, 0x0A, 0x01, 0x0C, 0x95, 0x0A, 0x05, 0x0C, 0x90, 0x0A, + 0x09, 0x0C, 0x8B, 0x0A, 0x0D, 0x0C, 0x86, 0x0A, 0x11, 0x0C, + 0x82, 0x0A, 0x15, 0x0C, 0x7D, 0x0A, 0x19, 0x0C, 0x78, 0x0A, + 0x1E, 0x0C, 0x73, 0x0A, 0x22, 0x0C, 0x6F, 0x0A, 0x26, 0x0C, + 0x6A, 0x0A, 0x2A, 0x0C, 0x65, 0x0A, 0x2E, 0x0C, 0x60, 0x0A, + 0x32, 0x0C, 0x5C, 0x0A, 0x36, 0x0C, 0x57, 0x0A, 0x3A, 0x0C, + 0x52, 0x0A, 0x3E, 0x0C, 0x4D, 0x0A, 0x42, 0x0C, 0x48, 0x0A, + 0x46, 0x0C, 0x44, 0x0A, 0x4A, 0x0C, 0x3F, 0x0A, 0x4E, 0x0C, + 0x3A, 0x0A, 0x52, 0x0C, 0x35, 0x0A, 0x56, 0x0C, 0x30, 0x0A, + 0x5A, 0x0C, 0x2B, 0x0A, 0x5E, 0x0C, 0x26, 0x0A, 0x62, 0x0C, + 0x22, 0x0A, 0x66, 0x0C, 0x1D, 0x0A, 0x6A, 0x0C, 0x18, 0x0A, + 0x6E, 0x0C, 0x13, 0x0A, 0x72, 0x0C, 0x0E, 0x0A, 0x76, 0x0C, + 0x09, 0x0A, 0x7A, 0x0C, 0x04, 0x0A, 0x7E, 0x0C, 0xFF, 0x09, + 0x82, 0x0C, 0xFB, 0x09, 0x86, 0x0C, 0xF6, 0x09, 0x8A, 0x0C, + 0xF1, 0x09, 0x8E, 0x0C, 0xEC, 0x09, 0x91, 0x0C, 0xE7, 0x09, + 0x95, 0x0C, 0xE2, 0x09, 0x99, 0x0C, 0xDD, 0x09, 0x9D, 0x0C, + 0xD8, 0x09, 0xA1, 0x0C, 0xD3, 0x09, 0xA5, 0x0C, 0xCE, 0x09, + 0xA9, 0x0C, 0xC9, 0x09, 0xAC, 0x0C, 0xC4, 0x09, 0xB0, 0x0C, + 0xBF, 0x09, 0xB4, 0x0C, 0xBA, 0x09, 0xB8, 0x0C, 0xB5, 0x09, + 0xBC, 0x0C, 0xB0, 0x09, 0xC0, 0x0C, 0xAB, 0x09, 0xC3, 0x0C, + 0xA6, 0x09, 0xC7, 0x0C, 0xA1, 0x09, 0xCB, 0x0C, 0x9C, 0x09, + 0xCF, 0x0C, 0x97, 0x09, 0xD2, 0x0C, 0x92, 0x09, 0xD6, 0x0C, + 0x8D, 0x09, 0xDA, 0x0C, 0x88, 0x09, 0xDE, 0x0C, 0x83, 0x09, + 0xE1, 0x0C, 0x7E, 0x09, 0xE5, 0x0C, 0x79, 0x09, 0xE9, 0x0C, + 0x74, 0x09, 0xED, 0x0C, 0x6F, 0x09, 0xF0, 0x0C, 0x6A, 0x09, + 0xF4, 0x0C, 0x65, 0x09, 0xF8, 0x0C, 0x5F, 0x09, 0xFB, 0x0C, + 0x5A, 0x09, 0xFF, 0x0C, 0x55, 0x09, 0x03, 0x0D, 0x50, 0x09, + 0x06, 0x0D, 0x4B, 0x09, 0x0A, 0x0D, 0x46, 0x09, 0x0E, 0x0D, + 0x41, 0x09, 0x11, 0x0D, 0x3C, 0x09, 0x15, 0x0D, 0x37, 0x09, + 0x18, 0x0D, 0x31, 0x09, 0x1C, 0x0D, 0x2C, 0x09, 0x20, 0x0D, + 0x27, 0x09, 0x23, 0x0D, 0x22, 0x09, 0x27, 0x0D, 0x1D, 0x09, + 0x2A, 0x0D, 0x18, 0x09, 0x2E, 0x0D, 0x12, 0x09, 0x32, 0x0D, + 0x0D, 0x09, 0x35, 0x0D, 0x08, 0x09, 0x39, 0x0D, 0x03, 0x09, + 0x3C, 0x0D, 0xFE, 0x08, 0x40, 0x0D, 0xF8, 0x08, 0x43, 0x0D, + 0xF3, 0x08, 0x47, 0x0D, 0xEE, 0x08, 0x4A, 0x0D, 0xE9, 0x08, + 0x4E, 0x0D, 0xE4, 0x08, 0x51, 0x0D, 0xDE, 0x08, 0x55, 0x0D, + 0xD9, 0x08, 0x58, 0x0D, 0xD4, 0x08, 0x5C, 0x0D, 0xCF, 0x08, + 0x5F, 0x0D, 0xC9, 0x08, 0x62, 0x0D, 0xC4, 0x08, 0x66, 0x0D, + 0xBF, 0x08, 0x69, 0x0D, 0xBA, 0x08, 0x6D, 0x0D, 0xB4, 0x08, + 0x70, 0x0D, 0xAF, 0x08, 0x74, 0x0D, 0xAA, 0x08, 0x77, 0x0D, + 0xA5, 0x08, 0x7A, 0x0D, 0x9F, 0x08, 0x7E, 0x0D, 0x9A, 0x08, + 0x81, 0x0D, 0x95, 0x08, 0x85, 0x0D, 0x8F, 0x08, 0x88, 0x0D, + 0x8A, 0x08, 0x8B, 0x0D, 0x85, 0x08, 0x8F, 0x0D, 0x7F, 0x08, + 0x92, 0x0D, 0x7A, 0x08, 0x95, 0x0D, 0x75, 0x08, 0x99, 0x0D, + 0x6F, 0x08, 0x9C, 0x0D, 0x6A, 0x08, 0x9F, 0x0D, 0x65, 0x08, + 0xA2, 0x0D, 0x5F, 0x08, 0xA6, 0x0D, 0x5A, 0x08, 0xA9, 0x0D, + 0x55, 0x08, 0xAC, 0x0D, 0x4F, 0x08, 0xB0, 0x0D, 0x4A, 0x08, + 0xB3, 0x0D, 0x45, 0x08, 0xB6, 0x0D, 0x3F, 0x08, 0xB9, 0x0D, + 0x3A, 0x08, 0xBC, 0x0D, 0x34, 0x08, 0xC0, 0x0D, 0x2F, 0x08, + 0xC3, 0x0D, 0x2A, 0x08, 0xC6, 0x0D, 0x24, 0x08, 0xC9, 0x0D, + 0x1F, 0x08, 0xCC, 0x0D, 0x19, 0x08, 0xD0, 0x0D, 0x14, 0x08, + 0xD3, 0x0D, 0x0E, 0x08, 0xD6, 0x0D, 0x09, 0x08, 0xD9, 0x0D, + 0x04, 0x08, 0xDC, 0x0D, 0xFE, 0x07, 0xDF, 0x0D, 0xF9, 0x07, + 0xE3, 0x0D, 0xF3, 0x07, 0xE6, 0x0D, 0xEE, 0x07, 0xE9, 0x0D, + 0xE8, 0x07, 0xEC, 0x0D, 0xE3, 0x07, 0xEF, 0x0D, 0xDD, 0x07, + 0xF2, 0x0D, 0xD8, 0x07, 0xF5, 0x0D, 0xD2, 0x07, 0xF8, 0x0D, + 0xCD, 0x07, 0xFB, 0x0D, 0xC8, 0x07, 0xFE, 0x0D, 0xC2, 0x07, + 0x01, 0x0E, 0xBD, 0x07, 0x04, 0x0E, 0xB7, 0x07, 0x07, 0x0E, + 0xB2, 0x07, 0x0A, 0x0E, 0xAC, 0x07, 0x0D, 0x0E, 0xA6, 0x07, + 0x10, 0x0E, 0xA1, 0x07, 0x13, 0x0E, 0x9B, 0x07, 0x16, 0x0E, + 0x96, 0x07, 0x19, 0x0E, 0x90, 0x07, 0x1C, 0x0E, 0x8B, 0x07, + 0x1F, 0x0E, 0x85, 0x07, 0x22, 0x0E, 0x80, 0x07, 0x25, 0x0E, + 0x7A, 0x07, 0x28, 0x0E, 0x75, 0x07, 0x2B, 0x0E, 0x6F, 0x07, + 0x2E, 0x0E, 0x6A, 0x07, 0x31, 0x0E, 0x64, 0x07, 0x34, 0x0E, + 0x5E, 0x07, 0x37, 0x0E, 0x59, 0x07, 0x3A, 0x0E, 0x53, 0x07, + 0x3C, 0x0E, 0x4E, 0x07, 0x3F, 0x0E, 0x48, 0x07, 0x42, 0x0E, + 0x42, 0x07, 0x45, 0x0E, 0x3D, 0x07, 0x48, 0x0E, 0x37, 0x07, + 0x4B, 0x0E, 0x32, 0x07, 0x4D, 0x0E, 0x2C, 0x07, 0x50, 0x0E, + 0x26, 0x07, 0x53, 0x0E, 0x21, 0x07, 0x56, 0x0E, 0x1B, 0x07, + 0x59, 0x0E, 0x15, 0x07, 0x5B, 0x0E, 0x10, 0x07, 0x5E, 0x0E, + 0x0A, 0x07, 0x61, 0x0E, 0x05, 0x07, 0x64, 0x0E, 0xFF, 0x06, + 0x66, 0x0E, 0xF9, 0x06, 0x69, 0x0E, 0xF4, 0x06, 0x6C, 0x0E, + 0xEE, 0x06, 0x6F, 0x0E, 0xE8, 0x06, 0x71, 0x0E, 0xE3, 0x06, + 0x74, 0x0E, 0xDD, 0x06, 0x77, 0x0E, 0xD7, 0x06, 0x79, 0x0E, + 0xD2, 0x06, 0x7C, 0x0E, 0xCC, 0x06, 0x7F, 0x0E, 0xC6, 0x06, + 0x81, 0x0E, 0xC1, 0x06, 0x84, 0x0E, 0xBB, 0x06, 0x87, 0x0E, + 0xB5, 0x06, 0x89, 0x0E, 0xAF, 0x06, 0x8C, 0x0E, 0xAA, 0x06, + 0x8F, 0x0E, 0xA4, 0x06, 0x91, 0x0E, 0x9E, 0x06, 0x94, 0x0E, + 0x99, 0x06, 0x96, 0x0E, 0x93, 0x06, 0x99, 0x0E, 0x8D, 0x06, + 0x9B, 0x0E, 0x87, 0x06, 0x9E, 0x0E, 0x82, 0x06, 0xA1, 0x0E, + 0x7C, 0x06, 0xA3, 0x0E, 0x76, 0x06, 0xA6, 0x0E, 0x70, 0x06, + 0xA8, 0x0E, 0x6B, 0x06, 0xAB, 0x0E, 0x65, 0x06, 0xAD, 0x0E, + 0x5F, 0x06, 0xB0, 0x0E, 0x59, 0x06, 0xB2, 0x0E, 0x54, 0x06, + 0xB5, 0x0E, 0x4E, 0x06, 0xB7, 0x0E, 0x48, 0x06, 0xBA, 0x0E, + 0x42, 0x06, 0xBC, 0x0E, 0x3C, 0x06, 0xBF, 0x0E, 0x37, 0x06, + 0xC1, 0x0E, 0x31, 0x06, 0xC3, 0x0E, 0x2B, 0x06, 0xC6, 0x0E, + 0x25, 0x06, 0xC8, 0x0E, 0x1F, 0x06, 0xCB, 0x0E, 0x1A, 0x06, + 0xCD, 0x0E, 0x14, 0x06, 0xCF, 0x0E, 0x0E, 0x06, 0xD2, 0x0E, + 0x08, 0x06, 0xD4, 0x0E, 0x02, 0x06, 0xD6, 0x0E, 0xFD, 0x05, + 0xD9, 0x0E, 0xF7, 0x05, 0xDB, 0x0E, 0xF1, 0x05, 0xDD, 0x0E, + 0xEB, 0x05, 0xE0, 0x0E, 0xE5, 0x05, 0xE2, 0x0E, 0xDF, 0x05, + 0xE4, 0x0E, 0xDA, 0x05, 0xE7, 0x0E, 0xD4, 0x05, 0xE9, 0x0E, + 0xCE, 0x05, 0xEB, 0x0E, 0xC8, 0x05, 0xEE, 0x0E, 0xC2, 0x05, + 0xF0, 0x0E, 0xBC, 0x05, 0xF2, 0x0E, 0xB6, 0x05, 0xF4, 0x0E, + 0xB1, 0x05, 0xF7, 0x0E, 0xAB, 0x05, 0xF9, 0x0E, 0xA5, 0x05, + 0xFB, 0x0E, 0x9F, 0x05, 0xFD, 0x0E, 0x99, 0x05, 0xFF, 0x0E, + 0x93, 0x05, 0x02, 0x0F, 0x8D, 0x05, 0x04, 0x0F, 0x87, 0x05, + 0x06, 0x0F, 0x81, 0x05, 0x08, 0x0F, 0x7C, 0x05, 0x0A, 0x0F, + 0x76, 0x05, 0x0C, 0x0F, 0x70, 0x05, 0x0E, 0x0F, 0x6A, 0x05, + 0x11, 0x0F, 0x64, 0x05, 0x13, 0x0F, 0x5E, 0x05, 0x15, 0x0F, + 0x58, 0x05, 0x17, 0x0F, 0x52, 0x05, 0x19, 0x0F, 0x4C, 0x05, + 0x1B, 0x0F, 0x46, 0x05, 0x1D, 0x0F, 0x40, 0x05, 0x1F, 0x0F, + 0x3A, 0x05, 0x21, 0x0F, 0x34, 0x05, 0x23, 0x0F, 0x2F, 0x05, + 0x25, 0x0F, 0x29, 0x05, 0x27, 0x0F, 0x23, 0x05, 0x29, 0x0F, + 0x1D, 0x05, 0x2B, 0x0F, 0x17, 0x05, 0x2D, 0x0F, 0x11, 0x05, + 0x2F, 0x0F, 0x0B, 0x05, 0x31, 0x0F, 0x05, 0x05, 0x33, 0x0F, + 0xFF, 0x04, 0x35, 0x0F, 0xF9, 0x04, 0x37, 0x0F, 0xF3, 0x04, + 0x39, 0x0F, 0xED, 0x04, 0x3B, 0x0F, 0xE7, 0x04, 0x3D, 0x0F, + 0xE1, 0x04, 0x3F, 0x0F, 0xDB, 0x04, 0x41, 0x0F, 0xD5, 0x04, + 0x43, 0x0F, 0xCF, 0x04, 0x45, 0x0F, 0xC9, 0x04, 0x46, 0x0F, + 0xC3, 0x04, 0x48, 0x0F, 0xBD, 0x04, 0x4A, 0x0F, 0xB7, 0x04, + 0x4C, 0x0F, 0xB1, 0x04, 0x4E, 0x0F, 0xAB, 0x04, 0x50, 0x0F, + 0xA5, 0x04, 0x51, 0x0F, 0x9F, 0x04, 0x53, 0x0F, 0x99, 0x04, + 0x55, 0x0F, 0x93, 0x04, 0x57, 0x0F, 0x8D, 0x04, 0x59, 0x0F, + 0x87, 0x04, 0x5A, 0x0F, 0x81, 0x04, 0x5C, 0x0F, 0x7B, 0x04, + 0x5E, 0x0F, 0x75, 0x04, 0x60, 0x0F, 0x6F, 0x04, 0x61, 0x0F, + 0x69, 0x04, 0x63, 0x0F, 0x63, 0x04, 0x65, 0x0F, 0x5D, 0x04, + 0x67, 0x0F, 0x57, 0x04, 0x68, 0x0F, 0x51, 0x04, 0x6A, 0x0F, + 0x4B, 0x04, 0x6C, 0x0F, 0x44, 0x04, 0x6D, 0x0F, 0x3E, 0x04, + 0x6F, 0x0F, 0x38, 0x04, 0x71, 0x0F, 0x32, 0x04, 0x72, 0x0F, + 0x2C, 0x04, 0x74, 0x0F, 0x26, 0x04, 0x76, 0x0F, 0x20, 0x04, + 0x77, 0x0F, 0x1A, 0x04, 0x79, 0x0F, 0x14, 0x04, 0x7A, 0x0F, + 0x0E, 0x04, 0x7C, 0x0F, 0x08, 0x04, 0x7D, 0x0F, 0x02, 0x04, + 0x7F, 0x0F, 0xFC, 0x03, 0x81, 0x0F, 0xF6, 0x03, 0x82, 0x0F, + 0xEF, 0x03, 0x84, 0x0F, 0xE9, 0x03, 0x85, 0x0F, 0xE3, 0x03, + 0x87, 0x0F, 0xDD, 0x03, 0x88, 0x0F, 0xD7, 0x03, 0x8A, 0x0F, + 0xD1, 0x03, 0x8B, 0x0F, 0xCB, 0x03, 0x8D, 0x0F, 0xC5, 0x03, + 0x8E, 0x0F, 0xBF, 0x03, 0x90, 0x0F, 0xB9, 0x03, 0x91, 0x0F, + 0xB2, 0x03, 0x93, 0x0F, 0xAC, 0x03, 0x94, 0x0F, 0xA6, 0x03, + 0x95, 0x0F, 0xA0, 0x03, 0x97, 0x0F, 0x9A, 0x03, 0x98, 0x0F, + 0x94, 0x03, 0x9A, 0x0F, 0x8E, 0x03, 0x9B, 0x0F, 0x88, 0x03, + 0x9C, 0x0F, 0x81, 0x03, 0x9E, 0x0F, 0x7B, 0x03, 0x9F, 0x0F, + 0x75, 0x03, 0xA1, 0x0F, 0x6F, 0x03, 0xA2, 0x0F, 0x69, 0x03, + 0xA3, 0x0F, 0x63, 0x03, 0xA5, 0x0F, 0x5D, 0x03, 0xA6, 0x0F, + 0x56, 0x03, 0xA7, 0x0F, 0x50, 0x03, 0xA8, 0x0F, 0x4A, 0x03, + 0xAA, 0x0F, 0x44, 0x03, 0xAB, 0x0F, 0x3E, 0x03, 0xAC, 0x0F, + 0x38, 0x03, 0xAE, 0x0F, 0x32, 0x03, 0xAF, 0x0F, 0x2B, 0x03, + 0xB0, 0x0F, 0x25, 0x03, 0xB1, 0x0F, 0x1F, 0x03, 0xB3, 0x0F, + 0x19, 0x03, 0xB4, 0x0F, 0x13, 0x03, 0xB5, 0x0F, 0x0D, 0x03, + 0xB6, 0x0F, 0x06, 0x03, 0xB7, 0x0F, 0x00, 0x03, 0xB8, 0x0F, + 0xFA, 0x02, 0xBA, 0x0F, 0xF4, 0x02, 0xBB, 0x0F, 0xEE, 0x02, + 0xBC, 0x0F, 0xE8, 0x02, 0xBD, 0x0F, 0xE1, 0x02, 0xBE, 0x0F, + 0xDB, 0x02, 0xBF, 0x0F, 0xD5, 0x02, 0xC0, 0x0F, 0xCF, 0x02, + 0xC2, 0x0F, 0xC9, 0x02, 0xC3, 0x0F, 0xC2, 0x02, 0xC4, 0x0F, + 0xBC, 0x02, 0xC5, 0x0F, 0xB6, 0x02, 0xC6, 0x0F, 0xB0, 0x02, + 0xC7, 0x0F, 0xAA, 0x02, 0xC8, 0x0F, 0xA3, 0x02, 0xC9, 0x0F, + 0x9D, 0x02, 0xCA, 0x0F, 0x97, 0x02, 0xCB, 0x0F, 0x91, 0x02, + 0xCC, 0x0F, 0x8B, 0x02, 0xCD, 0x0F, 0x84, 0x02, 0xCE, 0x0F, + 0x7E, 0x02, 0xCF, 0x0F, 0x78, 0x02, 0xD0, 0x0F, 0x72, 0x02, + 0xD1, 0x0F, 0x6C, 0x02, 0xD2, 0x0F, 0x65, 0x02, 0xD3, 0x0F, + 0x5F, 0x02, 0xD4, 0x0F, 0x59, 0x02, 0xD5, 0x0F, 0x53, 0x02, + 0xD5, 0x0F, 0x4D, 0x02, 0xD6, 0x0F, 0x46, 0x02, 0xD7, 0x0F, + 0x40, 0x02, 0xD8, 0x0F, 0x3A, 0x02, 0xD9, 0x0F, 0x34, 0x02, + 0xDA, 0x0F, 0x2D, 0x02, 0xDB, 0x0F, 0x27, 0x02, 0xDC, 0x0F, + 0x21, 0x02, 0xDC, 0x0F, 0x1B, 0x02, 0xDD, 0x0F, 0x15, 0x02, + 0xDE, 0x0F, 0x0E, 0x02, 0xDF, 0x0F, 0x08, 0x02, 0xE0, 0x0F, + 0x02, 0x02, 0xE0, 0x0F, 0xFC, 0x01, 0xE1, 0x0F, 0xF5, 0x01, + 0xE2, 0x0F, 0xEF, 0x01, 0xE3, 0x0F, 0xE9, 0x01, 0xE3, 0x0F, + 0xE3, 0x01, 0xE4, 0x0F, 0xDC, 0x01, 0xE5, 0x0F, 0xD6, 0x01, + 0xE6, 0x0F, 0xD0, 0x01, 0xE6, 0x0F, 0xCA, 0x01, 0xE7, 0x0F, + 0xC3, 0x01, 0xE8, 0x0F, 0xBD, 0x01, 0xE8, 0x0F, 0xB7, 0x01, + 0xE9, 0x0F, 0xB1, 0x01, 0xEA, 0x0F, 0xAA, 0x01, 0xEA, 0x0F, + 0xA4, 0x01, 0xEB, 0x0F, 0x9E, 0x01, 0xEC, 0x0F, 0x98, 0x01, + 0xEC, 0x0F, 0x91, 0x01, 0xED, 0x0F, 0x8B, 0x01, 0xED, 0x0F, + 0x85, 0x01, 0xEE, 0x0F, 0x7F, 0x01, 0xEF, 0x0F, 0x78, 0x01, + 0xEF, 0x0F, 0x72, 0x01, 0xF0, 0x0F, 0x6C, 0x01, 0xF0, 0x0F, + 0x66, 0x01, 0xF1, 0x0F, 0x5F, 0x01, 0xF1, 0x0F, 0x59, 0x01, + 0xF2, 0x0F, 0x53, 0x01, 0xF2, 0x0F, 0x4D, 0x01, 0xF3, 0x0F, + 0x46, 0x01, 0xF3, 0x0F, 0x40, 0x01, 0xF4, 0x0F, 0x3A, 0x01, + 0xF4, 0x0F, 0x34, 0x01, 0xF5, 0x0F, 0x2D, 0x01, 0xF5, 0x0F, + 0x27, 0x01, 0xF6, 0x0F, 0x21, 0x01, 0xF6, 0x0F, 0x1B, 0x01, + 0xF7, 0x0F, 0x14, 0x01, 0xF7, 0x0F, 0x0E, 0x01, 0xF8, 0x0F, + 0x08, 0x01, 0xF8, 0x0F, 0x01, 0x01, 0xF8, 0x0F, 0xFB, 0x00, + 0xF9, 0x0F, 0xF5, 0x00, 0xF9, 0x0F, 0xEF, 0x00, 0xF9, 0x0F, + 0xE8, 0x00, 0xFA, 0x0F, 0xE2, 0x00, 0xFA, 0x0F, 0xDC, 0x00, + 0xFA, 0x0F, 0xD6, 0x00, 0xFB, 0x0F, 0xCF, 0x00, 0xFB, 0x0F, + 0xC9, 0x00, 0xFB, 0x0F, 0xC3, 0x00, 0xFC, 0x0F, 0xBC, 0x00, + 0xFC, 0x0F, 0xB6, 0x00, 0xFC, 0x0F, 0xB0, 0x00, 0xFC, 0x0F, + 0xAA, 0x00, 0xFD, 0x0F, 0xA3, 0x00, 0xFD, 0x0F, 0x9D, 0x00, + 0xFD, 0x0F, 0x97, 0x00, 0xFD, 0x0F, 0x90, 0x00, 0xFE, 0x0F, + 0x8A, 0x00, 0xFE, 0x0F, 0x84, 0x00, 0xFE, 0x0F, 0x7E, 0x00, + 0xFE, 0x0F, 0x77, 0x00, 0xFE, 0x0F, 0x71, 0x00, 0xFF, 0x0F, + 0x6B, 0x00, 0xFF, 0x0F, 0x65, 0x00, 0xFF, 0x0F, 0x5E, 0x00, + 0xFF, 0x0F, 0x58, 0x00, 0xFF, 0x0F, 0x52, 0x00, 0xFF, 0x0F, + 0x4B, 0x00, 0xFF, 0x0F, 0x45, 0x00, 0x00, 0x10, 0x3F, 0x00, + 0x00, 0x10, 0x39, 0x00, 0x00, 0x10, 0x32, 0x00, 0x00, 0x10, + 0x2C, 0x00, 0x00, 0x10, 0x26, 0x00, 0x00, 0x10, 0x1F, 0x00, + 0x00, 0x10, 0x19, 0x00, 0x00, 0x10, 0x13, 0x00, 0x00, 0x10, + 0x0D, 0x00, 0x00, 0x10, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x10, 0xFA, 0xFF, 0x00, 0x10, 0xF3, 0xFF, 0x00, 0x10, + 0xED, 0xFF, 0x00, 0x10, 0xE7, 0xFF, 0x00, 0x10, 0xE1, 0xFF, + 0x00, 0x10, 0xDA, 0xFF, 0x00, 0x10, 0xD4, 0xFF, 0x00, 0x10, + 0xCE, 0xFF, 0x00, 0x10, 0xC7, 0xFF, 0x00, 0x10, 0xC1, 0xFF, + 0xFF, 0x0F, 0xBB, 0xFF, 0xFF, 0x0F, 0xB5, 0xFF, 0xFF, 0x0F, + 0xAE, 0xFF, 0xFF, 0x0F, 0xA8, 0xFF, 0xFF, 0x0F, 0xA2, 0xFF, + 0xFF, 0x0F, 0x9B, 0xFF, 0xFF, 0x0F, 0x95, 0xFF, 0xFE, 0x0F, + 0x8F, 0xFF, 0xFE, 0x0F, 0x89, 0xFF, 0xFE, 0x0F, 0x82, 0xFF, + 0xFE, 0x0F, 0x7C, 0xFF, 0xFE, 0x0F, 0x76, 0xFF, 0xFD, 0x0F, + 0x70, 0xFF, 0xFD, 0x0F, 0x69, 0xFF, 0xFD, 0x0F, 0x63, 0xFF, + 0xFD, 0x0F, 0x5D, 0xFF, 0xFC, 0x0F, 0x56, 0xFF, 0xFC, 0x0F, + 0x50, 0xFF, 0xFC, 0x0F, 0x4A, 0xFF, 0xFC, 0x0F, 0x44, 0xFF, + 0xFB, 0x0F, 0x3D, 0xFF, 0xFB, 0x0F, 0x37, 0xFF, 0xFB, 0x0F, + 0x31, 0xFF, 0xFA, 0x0F, 0x2A, 0xFF, 0xFA, 0x0F, 0x24, 0xFF, + 0xFA, 0x0F, 0x1E, 0xFF, 0xF9, 0x0F, 0x18, 0xFF, 0xF9, 0x0F, + 0x11, 0xFF, 0xF9, 0x0F, 0x0B, 0xFF, 0xF8, 0x0F, 0x05, 0xFF, + 0xF8, 0x0F, 0xFF, 0xFE, 0xF8, 0x0F, 0xF8, 0xFE, 0xF7, 0x0F, + 0xF2, 0xFE, 0xF7, 0x0F, 0xEC, 0xFE, 0xF6, 0x0F, 0xE5, 0xFE, + 0xF6, 0x0F, 0xDF, 0xFE, 0xF5, 0x0F, 0xD9, 0xFE, 0xF5, 0x0F, + 0xD3, 0xFE, 0xF4, 0x0F, 0xCC, 0xFE, 0xF4, 0x0F, 0xC6, 0xFE, + 0xF3, 0x0F, 0xC0, 0xFE, 0xF3, 0x0F, 0xBA, 0xFE, 0xF2, 0x0F, + 0xB3, 0xFE, 0xF2, 0x0F, 0xAD, 0xFE, 0xF1, 0x0F, 0xA7, 0xFE, + 0xF1, 0x0F, 0xA1, 0xFE, 0xF0, 0x0F, 0x9A, 0xFE, 0xF0, 0x0F, + 0x94, 0xFE, 0xEF, 0x0F, 0x8E, 0xFE, 0xEF, 0x0F, 0x88, 0xFE, + 0xEE, 0x0F, 0x81, 0xFE, 0xED, 0x0F, 0x7B, 0xFE, 0xED, 0x0F, + 0x75, 0xFE, 0xEC, 0x0F, 0x6F, 0xFE, 0xEC, 0x0F, 0x68, 0xFE, + 0xEB, 0x0F, 0x62, 0xFE, 0xEA, 0x0F, 0x5C, 0xFE, 0xEA, 0x0F, + 0x56, 0xFE, 0xE9, 0x0F, 0x4F, 0xFE, 0xE8, 0x0F, 0x49, 0xFE, + 0xE8, 0x0F, 0x43, 0xFE, 0xE7, 0x0F, 0x3D, 0xFE, 0xE6, 0x0F, + 0x36, 0xFE, 0xE6, 0x0F, 0x30, 0xFE, 0xE5, 0x0F, 0x2A, 0xFE, + 0xE4, 0x0F, 0x24, 0xFE, 0xE3, 0x0F, 0x1D, 0xFE, 0xE3, 0x0F, + 0x17, 0xFE, 0xE2, 0x0F, 0x11, 0xFE, 0xE1, 0x0F, 0x0B, 0xFE, + 0xE0, 0x0F, 0x04, 0xFE, 0xE0, 0x0F, 0xFE, 0xFD, 0xDF, 0x0F, + 0xF8, 0xFD, 0xDE, 0x0F, 0xF2, 0xFD, 0xDD, 0x0F, 0xEB, 0xFD, + 0xDC, 0x0F, 0xE5, 0xFD, 0xDC, 0x0F, 0xDF, 0xFD, 0xDB, 0x0F, + 0xD9, 0xFD, 0xDA, 0x0F, 0xD3, 0xFD, 0xD9, 0x0F, 0xCC, 0xFD, + 0xD8, 0x0F, 0xC6, 0xFD, 0xD7, 0x0F, 0xC0, 0xFD, 0xD6, 0x0F, + 0xBA, 0xFD, 0xD5, 0x0F, 0xB3, 0xFD, 0xD5, 0x0F, 0xAD, 0xFD, + 0xD4, 0x0F, 0xA7, 0xFD, 0xD3, 0x0F, 0xA1, 0xFD, 0xD2, 0x0F, + 0x9B, 0xFD, 0xD1, 0x0F, 0x94, 0xFD, 0xD0, 0x0F, 0x8E, 0xFD, + 0xCF, 0x0F, 0x88, 0xFD, 0xCE, 0x0F, 0x82, 0xFD, 0xCD, 0x0F, + 0x7C, 0xFD, 0xCC, 0x0F, 0x75, 0xFD, 0xCB, 0x0F, 0x6F, 0xFD, + 0xCA, 0x0F, 0x69, 0xFD, 0xC9, 0x0F, 0x63, 0xFD, 0xC8, 0x0F, + 0x5D, 0xFD, 0xC7, 0x0F, 0x56, 0xFD, 0xC6, 0x0F, 0x50, 0xFD, + 0xC5, 0x0F, 0x4A, 0xFD, 0xC4, 0x0F, 0x44, 0xFD, 0xC3, 0x0F, + 0x3E, 0xFD, 0xC2, 0x0F, 0x37, 0xFD, 0xC0, 0x0F, 0x31, 0xFD, + 0xBF, 0x0F, 0x2B, 0xFD, 0xBE, 0x0F, 0x25, 0xFD, 0xBD, 0x0F, + 0x1F, 0xFD, 0xBC, 0x0F, 0x18, 0xFD, 0xBB, 0x0F, 0x12, 0xFD, + 0xBA, 0x0F, 0x0C, 0xFD, 0xB8, 0x0F, 0x06, 0xFD, 0xB7, 0x0F, + 0x00, 0xFD, 0xB6, 0x0F, 0xFA, 0xFC, 0xB5, 0x0F, 0xF3, 0xFC, + 0xB4, 0x0F, 0xED, 0xFC, 0xB3, 0x0F, 0xE7, 0xFC, 0xB1, 0x0F, + 0xE1, 0xFC, 0xB0, 0x0F, 0xDB, 0xFC, 0xAF, 0x0F, 0xD5, 0xFC, + 0xAE, 0x0F, 0xCE, 0xFC, 0xAC, 0x0F, 0xC8, 0xFC, 0xAB, 0x0F, + 0xC2, 0xFC, 0xAA, 0x0F, 0xBC, 0xFC, 0xA8, 0x0F, 0xB6, 0xFC, + 0xA7, 0x0F, 0xB0, 0xFC, 0xA6, 0x0F, 0xAA, 0xFC, 0xA5, 0x0F, + 0xA3, 0xFC, 0xA3, 0x0F, 0x9D, 0xFC, 0xA2, 0x0F, 0x97, 0xFC, + 0xA1, 0x0F, 0x91, 0xFC, 0x9F, 0x0F, 0x8B, 0xFC, 0x9E, 0x0F, + 0x85, 0xFC, 0x9C, 0x0F, 0x7F, 0xFC, 0x9B, 0x0F, 0x78, 0xFC, + 0x9A, 0x0F, 0x72, 0xFC, 0x98, 0x0F, 0x6C, 0xFC, 0x97, 0x0F, + 0x66, 0xFC, 0x95, 0x0F, 0x60, 0xFC, 0x94, 0x0F, 0x5A, 0xFC, + 0x93, 0x0F, 0x54, 0xFC, 0x91, 0x0F, 0x4E, 0xFC, 0x90, 0x0F, + 0x47, 0xFC, 0x8E, 0x0F, 0x41, 0xFC, 0x8D, 0x0F, 0x3B, 0xFC, + 0x8B, 0x0F, 0x35, 0xFC, 0x8A, 0x0F, 0x2F, 0xFC, 0x88, 0x0F, + 0x29, 0xFC, 0x87, 0x0F, 0x23, 0xFC, 0x85, 0x0F, 0x1D, 0xFC, + 0x84, 0x0F, 0x17, 0xFC, 0x82, 0x0F, 0x11, 0xFC, 0x81, 0x0F, + 0x0A, 0xFC, 0x7F, 0x0F, 0x04, 0xFC, 0x7D, 0x0F, 0xFE, 0xFB, + 0x7C, 0x0F, 0xF8, 0xFB, 0x7A, 0x0F, 0xF2, 0xFB, 0x79, 0x0F, + 0xEC, 0xFB, 0x77, 0x0F, 0xE6, 0xFB, 0x76, 0x0F, 0xE0, 0xFB, + 0x74, 0x0F, 0xDA, 0xFB, 0x72, 0x0F, 0xD4, 0xFB, 0x71, 0x0F, + 0xCE, 0xFB, 0x6F, 0x0F, 0xC8, 0xFB, 0x6D, 0x0F, 0xC2, 0xFB, + 0x6C, 0x0F, 0xBC, 0xFB, 0x6A, 0x0F, 0xB5, 0xFB, 0x68, 0x0F, + 0xAF, 0xFB, 0x67, 0x0F, 0xA9, 0xFB, 0x65, 0x0F, 0xA3, 0xFB, + 0x63, 0x0F, 0x9D, 0xFB, 0x61, 0x0F, 0x97, 0xFB, 0x60, 0x0F, + 0x91, 0xFB, 0x5E, 0x0F, 0x8B, 0xFB, 0x5C, 0x0F, 0x85, 0xFB, + 0x5A, 0x0F, 0x7F, 0xFB, 0x59, 0x0F, 0x79, 0xFB, 0x57, 0x0F, + 0x73, 0xFB, 0x55, 0x0F, 0x6D, 0xFB, 0x53, 0x0F, 0x67, 0xFB, + 0x51, 0x0F, 0x61, 0xFB, 0x50, 0x0F, 0x5B, 0xFB, 0x4E, 0x0F, + 0x55, 0xFB, 0x4C, 0x0F, 0x4F, 0xFB, 0x4A, 0x0F, 0x49, 0xFB, + 0x48, 0x0F, 0x43, 0xFB, 0x46, 0x0F, 0x3D, 0xFB, 0x45, 0x0F, + 0x37, 0xFB, 0x43, 0x0F, 0x31, 0xFB, 0x41, 0x0F, 0x2B, 0xFB, + 0x3F, 0x0F, 0x25, 0xFB, 0x3D, 0x0F, 0x1F, 0xFB, 0x3B, 0x0F, + 0x19, 0xFB, 0x39, 0x0F, 0x13, 0xFB, 0x37, 0x0F, 0x0D, 0xFB, + 0x35, 0x0F, 0x07, 0xFB, 0x33, 0x0F, 0x01, 0xFB, 0x31, 0x0F, + 0xFB, 0xFA, 0x2F, 0x0F, 0xF5, 0xFA, 0x2D, 0x0F, 0xEF, 0xFA, + 0x2B, 0x0F, 0xE9, 0xFA, 0x29, 0x0F, 0xE3, 0xFA, 0x27, 0x0F, + 0xDD, 0xFA, 0x25, 0x0F, 0xD7, 0xFA, 0x23, 0x0F, 0xD1, 0xFA, + 0x21, 0x0F, 0xCC, 0xFA, 0x1F, 0x0F, 0xC6, 0xFA, 0x1D, 0x0F, + 0xC0, 0xFA, 0x1B, 0x0F, 0xBA, 0xFA, 0x19, 0x0F, 0xB4, 0xFA, + 0x17, 0x0F, 0xAE, 0xFA, 0x15, 0x0F, 0xA8, 0xFA, 0x13, 0x0F, + 0xA2, 0xFA, 0x11, 0x0F, 0x9C, 0xFA, 0x0E, 0x0F, 0x96, 0xFA, + 0x0C, 0x0F, 0x90, 0xFA, 0x0A, 0x0F, 0x8A, 0xFA, 0x08, 0x0F, + 0x84, 0xFA, 0x06, 0x0F, 0x7F, 0xFA, 0x04, 0x0F, 0x79, 0xFA, + 0x02, 0x0F, 0x73, 0xFA, 0xFF, 0x0E, 0x6D, 0xFA, 0xFD, 0x0E, + 0x67, 0xFA, 0xFB, 0x0E, 0x61, 0xFA, 0xF9, 0x0E, 0x5B, 0xFA, + 0xF7, 0x0E, 0x55, 0xFA, 0xF4, 0x0E, 0x4F, 0xFA, 0xF2, 0x0E, + 0x4A, 0xFA, 0xF0, 0x0E, 0x44, 0xFA, 0xEE, 0x0E, 0x3E, 0xFA, + 0xEB, 0x0E, 0x38, 0xFA, 0xE9, 0x0E, 0x32, 0xFA, 0xE7, 0x0E, + 0x2C, 0xFA, 0xE4, 0x0E, 0x26, 0xFA, 0xE2, 0x0E, 0x21, 0xFA, + 0xE0, 0x0E, 0x1B, 0xFA, 0xDD, 0x0E, 0x15, 0xFA, 0xDB, 0x0E, + 0x0F, 0xFA, 0xD9, 0x0E, 0x09, 0xFA, 0xD6, 0x0E, 0x03, 0xFA, + 0xD4, 0x0E, 0xFE, 0xF9, 0xD2, 0x0E, 0xF8, 0xF9, 0xCF, 0x0E, + 0xF2, 0xF9, 0xCD, 0x0E, 0xEC, 0xF9, 0xCB, 0x0E, 0xE6, 0xF9, + 0xC8, 0x0E, 0xE1, 0xF9, 0xC6, 0x0E, 0xDB, 0xF9, 0xC3, 0x0E, + 0xD5, 0xF9, 0xC1, 0x0E, 0xCF, 0xF9, 0xBF, 0x0E, 0xC9, 0xF9, + 0xBC, 0x0E, 0xC4, 0xF9, 0xBA, 0x0E, 0xBE, 0xF9, 0xB7, 0x0E, + 0xB8, 0xF9, 0xB5, 0x0E, 0xB2, 0xF9, 0xB2, 0x0E, 0xAC, 0xF9, + 0xB0, 0x0E, 0xA7, 0xF9, 0xAD, 0x0E, 0xA1, 0xF9, 0xAB, 0x0E, + 0x9B, 0xF9, 0xA8, 0x0E, 0x95, 0xF9, 0xA6, 0x0E, 0x90, 0xF9, + 0xA3, 0x0E, 0x8A, 0xF9, 0xA1, 0x0E, 0x84, 0xF9, 0x9E, 0x0E, + 0x7E, 0xF9, 0x9B, 0x0E, 0x79, 0xF9, 0x99, 0x0E, 0x73, 0xF9, + 0x96, 0x0E, 0x6D, 0xF9, 0x94, 0x0E, 0x67, 0xF9, 0x91, 0x0E, + 0x62, 0xF9, 0x8F, 0x0E, 0x5C, 0xF9, 0x8C, 0x0E, 0x56, 0xF9, + 0x89, 0x0E, 0x51, 0xF9, 0x87, 0x0E, 0x4B, 0xF9, 0x84, 0x0E, + 0x45, 0xF9, 0x81, 0x0E, 0x3F, 0xF9, 0x7F, 0x0E, 0x3A, 0xF9, + 0x7C, 0x0E, 0x34, 0xF9, 0x79, 0x0E, 0x2E, 0xF9, 0x77, 0x0E, + 0x29, 0xF9, 0x74, 0x0E, 0x23, 0xF9, 0x71, 0x0E, 0x1D, 0xF9, + 0x6F, 0x0E, 0x18, 0xF9, 0x6C, 0x0E, 0x12, 0xF9, 0x69, 0x0E, + 0x0C, 0xF9, 0x66, 0x0E, 0x07, 0xF9, 0x64, 0x0E, 0x01, 0xF9, + 0x61, 0x0E, 0xFB, 0xF8, 0x5E, 0x0E, 0xF6, 0xF8, 0x5B, 0x0E, + 0xF0, 0xF8, 0x59, 0x0E, 0xEB, 0xF8, 0x56, 0x0E, 0xE5, 0xF8, + 0x53, 0x0E, 0xDF, 0xF8, 0x50, 0x0E, 0xDA, 0xF8, 0x4D, 0x0E, + 0xD4, 0xF8, 0x4B, 0x0E, 0xCE, 0xF8, 0x48, 0x0E, 0xC9, 0xF8, + 0x45, 0x0E, 0xC3, 0xF8, 0x42, 0x0E, 0xBE, 0xF8, 0x3F, 0x0E, + 0xB8, 0xF8, 0x3C, 0x0E, 0xB2, 0xF8, 0x3A, 0x0E, 0xAD, 0xF8, + 0x37, 0x0E, 0xA7, 0xF8, 0x34, 0x0E, 0xA2, 0xF8, 0x31, 0x0E, + 0x9C, 0xF8, 0x2E, 0x0E, 0x96, 0xF8, 0x2B, 0x0E, 0x91, 0xF8, + 0x28, 0x0E, 0x8B, 0xF8, 0x25, 0x0E, 0x86, 0xF8, 0x22, 0x0E, + 0x80, 0xF8, 0x1F, 0x0E, 0x7B, 0xF8, 0x1C, 0x0E, 0x75, 0xF8, + 0x19, 0x0E, 0x70, 0xF8, 0x16, 0x0E, 0x6A, 0xF8, 0x13, 0x0E, + 0x65, 0xF8, 0x10, 0x0E, 0x5F, 0xF8, 0x0D, 0x0E, 0x5A, 0xF8, + 0x0A, 0x0E, 0x54, 0xF8, 0x07, 0x0E, 0x4E, 0xF8, 0x04, 0x0E, + 0x49, 0xF8, 0x01, 0x0E, 0x43, 0xF8, 0xFE, 0x0D, 0x3E, 0xF8, + 0xFB, 0x0D, 0x38, 0xF8, 0xF8, 0x0D, 0x33, 0xF8, 0xF5, 0x0D, + 0x2E, 0xF8, 0xF2, 0x0D, 0x28, 0xF8, 0xEF, 0x0D, 0x23, 0xF8, + 0xEC, 0x0D, 0x1D, 0xF8, 0xE9, 0x0D, 0x18, 0xF8, 0xE6, 0x0D, + 0x12, 0xF8, 0xE3, 0x0D, 0x0D, 0xF8, 0xDF, 0x0D, 0x07, 0xF8, + 0xDC, 0x0D, 0x02, 0xF8, 0xD9, 0x0D, 0xFC, 0xF7, 0xD6, 0x0D, + 0xF7, 0xF7, 0xD3, 0x0D, 0xF2, 0xF7, 0xD0, 0x0D, 0xEC, 0xF7, + 0xCC, 0x0D, 0xE7, 0xF7, 0xC9, 0x0D, 0xE1, 0xF7, 0xC6, 0x0D, + 0xDC, 0xF7, 0xC3, 0x0D, 0xD6, 0xF7, 0xC0, 0x0D, 0xD1, 0xF7, + 0xBC, 0x0D, 0xCC, 0xF7, 0xB9, 0x0D, 0xC6, 0xF7, 0xB6, 0x0D, + 0xC1, 0xF7, 0xB3, 0x0D, 0xBB, 0xF7, 0xB0, 0x0D, 0xB6, 0xF7, + 0xAC, 0x0D, 0xB1, 0xF7, 0xA9, 0x0D, 0xAB, 0xF7, 0xA6, 0x0D, + 0xA6, 0xF7, 0xA2, 0x0D, 0xA1, 0xF7, 0x9F, 0x0D, 0x9B, 0xF7, + 0x9C, 0x0D, 0x96, 0xF7, 0x99, 0x0D, 0x91, 0xF7, 0x95, 0x0D, + 0x8B, 0xF7, 0x92, 0x0D, 0x86, 0xF7, 0x8F, 0x0D, 0x81, 0xF7, + 0x8B, 0x0D, 0x7B, 0xF7, 0x88, 0x0D, 0x76, 0xF7, 0x85, 0x0D, + 0x71, 0xF7, 0x81, 0x0D, 0x6B, 0xF7, 0x7E, 0x0D, 0x66, 0xF7, + 0x7A, 0x0D, 0x61, 0xF7, 0x77, 0x0D, 0x5B, 0xF7, 0x74, 0x0D, + 0x56, 0xF7, 0x70, 0x0D, 0x51, 0xF7, 0x6D, 0x0D, 0x4C, 0xF7, + 0x69, 0x0D, 0x46, 0xF7, 0x66, 0x0D, 0x41, 0xF7, 0x62, 0x0D, + 0x3C, 0xF7, 0x5F, 0x0D, 0x37, 0xF7, 0x5C, 0x0D, 0x31, 0xF7, + 0x58, 0x0D, 0x2C, 0xF7, 0x55, 0x0D, 0x27, 0xF7, 0x51, 0x0D, + 0x22, 0xF7, 0x4E, 0x0D, 0x1C, 0xF7, 0x4A, 0x0D, 0x17, 0xF7, + 0x47, 0x0D, 0x12, 0xF7, 0x43, 0x0D, 0x0D, 0xF7, 0x40, 0x0D, + 0x08, 0xF7, 0x3C, 0x0D, 0x02, 0xF7, 0x39, 0x0D, 0xFD, 0xF6, + 0x35, 0x0D, 0xF8, 0xF6, 0x32, 0x0D, 0xF3, 0xF6, 0x2E, 0x0D, + 0xEE, 0xF6, 0x2A, 0x0D, 0xE8, 0xF6, 0x27, 0x0D, 0xE3, 0xF6, + 0x23, 0x0D, 0xDE, 0xF6, 0x20, 0x0D, 0xD9, 0xF6, 0x1C, 0x0D, + 0xD4, 0xF6, 0x18, 0x0D, 0xCF, 0xF6, 0x15, 0x0D, 0xC9, 0xF6, + 0x11, 0x0D, 0xC4, 0xF6, 0x0E, 0x0D, 0xBF, 0xF6, 0x0A, 0x0D, + 0xBA, 0xF6, 0x06, 0x0D, 0xB5, 0xF6, 0x03, 0x0D, 0xB0, 0xF6, + 0xFF, 0x0C, 0xAB, 0xF6, 0xFB, 0x0C, 0xA6, 0xF6, 0xF8, 0x0C, + 0xA1, 0xF6, 0xF4, 0x0C, 0x9B, 0xF6, 0xF0, 0x0C, 0x96, 0xF6, + 0xED, 0x0C, 0x91, 0xF6, 0xE9, 0x0C, 0x8C, 0xF6, 0xE5, 0x0C, + 0x87, 0xF6, 0xE1, 0x0C, 0x82, 0xF6, 0xDE, 0x0C, 0x7D, 0xF6, + 0xDA, 0x0C, 0x78, 0xF6, 0xD6, 0x0C, 0x73, 0xF6, 0xD2, 0x0C, + 0x6E, 0xF6, 0xCF, 0x0C, 0x69, 0xF6, 0xCB, 0x0C, 0x64, 0xF6, + 0xC7, 0x0C, 0x5F, 0xF6, 0xC3, 0x0C, 0x5A, 0xF6, 0xC0, 0x0C, + 0x55, 0xF6, 0xBC, 0x0C, 0x50, 0xF6, 0xB8, 0x0C, 0x4B, 0xF6, + 0xB4, 0x0C, 0x46, 0xF6, 0xB0, 0x0C, 0x41, 0xF6, 0xAC, 0x0C, + 0x3C, 0xF6, 0xA9, 0x0C, 0x37, 0xF6, 0xA5, 0x0C, 0x32, 0xF6, + 0xA1, 0x0C, 0x2D, 0xF6, 0x9D, 0x0C, 0x28, 0xF6, 0x99, 0x0C, + 0x23, 0xF6, 0x95, 0x0C, 0x1E, 0xF6, 0x91, 0x0C, 0x19, 0xF6, + 0x8E, 0x0C, 0x14, 0xF6, 0x8A, 0x0C, 0x0F, 0xF6, 0x86, 0x0C, + 0x0A, 0xF6, 0x82, 0x0C, 0x05, 0xF6, 0x7E, 0x0C, 0x01, 0xF6, + 0x7A, 0x0C, 0xFC, 0xF5, 0x76, 0x0C, 0xF7, 0xF5, 0x72, 0x0C, + 0xF2, 0xF5, 0x6E, 0x0C, 0xED, 0xF5, 0x6A, 0x0C, 0xE8, 0xF5, + 0x66, 0x0C, 0xE3, 0xF5, 0x62, 0x0C, 0xDE, 0xF5, 0x5E, 0x0C, + 0xDA, 0xF5, 0x5A, 0x0C, 0xD5, 0xF5, 0x56, 0x0C, 0xD0, 0xF5, + 0x52, 0x0C, 0xCB, 0xF5, 0x4E, 0x0C, 0xC6, 0xF5, 0x4A, 0x0C, + 0xC1, 0xF5, 0x46, 0x0C, 0xBC, 0xF5, 0x42, 0x0C, 0xB8, 0xF5, + 0x3E, 0x0C, 0xB3, 0xF5, 0x3A, 0x0C, 0xAE, 0xF5, 0x36, 0x0C, + 0xA9, 0xF5, 0x32, 0x0C, 0xA4, 0xF5, 0x2E, 0x0C, 0xA0, 0xF5, + 0x2A, 0x0C, 0x9B, 0xF5, 0x26, 0x0C, 0x96, 0xF5, 0x22, 0x0C, + 0x91, 0xF5, 0x1E, 0x0C, 0x8D, 0xF5, 0x19, 0x0C, 0x88, 0xF5, + 0x15, 0x0C, 0x83, 0xF5, 0x11, 0x0C, 0x7E, 0xF5, 0x0D, 0x0C, + 0x7A, 0xF5, 0x09, 0x0C, 0x75, 0xF5, 0x05, 0x0C, 0x70, 0xF5, + 0x01, 0x0C, 0x6B, 0xF5, 0xFC, 0x0B, 0x67, 0xF5, 0xF8, 0x0B, + 0x62, 0xF5, 0xF4, 0x0B, 0x5D, 0xF5, 0xF0, 0x0B, 0x59, 0xF5, + 0xEC, 0x0B, 0x54, 0xF5, 0xE8, 0x0B, 0x4F, 0xF5, 0xE3, 0x0B, + 0x4B, 0xF5, 0xDF, 0x0B, 0x46, 0xF5, 0xDB, 0x0B, 0x41, 0xF5, + 0xD7, 0x0B, 0x3D, 0xF5, 0xD2, 0x0B, 0x38, 0xF5, 0xCE, 0x0B, + 0x33, 0xF5, 0xCA, 0x0B, 0x2F, 0xF5, 0xC6, 0x0B, 0x2A, 0xF5, + 0xC1, 0x0B, 0x25, 0xF5, 0xBD, 0x0B, 0x21, 0xF5, 0xB9, 0x0B, + 0x1C, 0xF5, 0xB5, 0x0B, 0x18, 0xF5, 0xB0, 0x0B, 0x13, 0xF5, + 0xAC, 0x0B, 0x0E, 0xF5, 0xA8, 0x0B, 0x0A, 0xF5, 0xA3, 0x0B, + 0x05, 0xF5, 0x9F, 0x0B, 0x01, 0xF5, 0x9B, 0x0B, 0xFC, 0xF4, + 0x97, 0x0B, 0xF8, 0xF4, 0x92, 0x0B, 0xF3, 0xF4, 0x8E, 0x0B, + 0xEF, 0xF4, 0x89, 0x0B, 0xEA, 0xF4, 0x85, 0x0B, 0xE5, 0xF4, + 0x81, 0x0B, 0xE1, 0xF4, 0x7C, 0x0B, 0xDC, 0xF4, 0x78, 0x0B, + 0xD8, 0xF4, 0x74, 0x0B, 0xD3, 0xF4, 0x6F, 0x0B, 0xCF, 0xF4, + 0x6B, 0x0B, 0xCA, 0xF4, 0x66, 0x0B, 0xC6, 0xF4, 0x62, 0x0B, + 0xC2, 0xF4, 0x5E, 0x0B, 0xBD, 0xF4, 0x59, 0x0B, 0xB9, 0xF4, + 0x55, 0x0B, 0xB4, 0xF4, 0x50, 0x0B, 0xB0, 0xF4, 0x4C, 0x0B, + 0xAB, 0xF4, 0x47, 0x0B, 0xA7, 0xF4, 0x43, 0x0B, 0xA2, 0xF4, + 0x3E, 0x0B, 0x9E, 0xF4, 0x3A, 0x0B, 0x9A, 0xF4, 0x36, 0x0B, + 0x95, 0xF4, 0x31, 0x0B, 0x91, 0xF4, 0x2D, 0x0B, 0x8C, 0xF4, + 0x28, 0x0B, 0x88, 0xF4, 0x24, 0x0B, 0x84, 0xF4, 0x1F, 0x0B, + 0x7F, 0xF4, 0x1B, 0x0B, 0x7B, 0xF4, 0x16, 0x0B, 0x77, 0xF4, + 0x11, 0x0B, 0x72, 0xF4, 0x0D, 0x0B, 0x6E, 0xF4, 0x08, 0x0B, + 0x69, 0xF4, 0x04, 0x0B, 0x65, 0xF4, 0xFF, 0x0A, 0x61, 0xF4, + 0xFB, 0x0A, 0x5D, 0xF4, 0xF6, 0x0A, 0x58, 0xF4, 0xF2, 0x0A, + 0x54, 0xF4, 0xED, 0x0A, 0x50, 0xF4, 0xE8, 0x0A, 0x4B, 0xF4, + 0xE4, 0x0A, 0x47, 0xF4, 0xDF, 0x0A, 0x43, 0xF4, 0xDB, 0x0A, + 0x3F, 0xF4, 0xD6, 0x0A, 0x3A, 0xF4, 0xD1, 0x0A, 0x36, 0xF4, + 0xCD, 0x0A, 0x32, 0xF4, 0xC8, 0x0A, 0x2E, 0xF4, 0xC3, 0x0A, + 0x29, 0xF4, 0xBF, 0x0A, 0x25, 0xF4, 0xBA, 0x0A, 0x21, 0xF4, + 0xB5, 0x0A, 0x1D, 0xF4, 0xB1, 0x0A, 0x18, 0xF4, 0xAC, 0x0A, + 0x14, 0xF4, 0xA7, 0x0A, 0x10, 0xF4, 0xA3, 0x0A, 0x0C, 0xF4, + 0x9E, 0x0A, 0x08, 0xF4, 0x99, 0x0A, 0x04, 0xF4, 0x95, 0x0A, + 0xFF, 0xF3, 0x90, 0x0A, 0xFB, 0xF3, 0x8B, 0x0A, 0xF7, 0xF3, + 0x86, 0x0A, 0xF3, 0xF3, 0x82, 0x0A, 0xEF, 0xF3, 0x7D, 0x0A, + 0xEB, 0xF3, 0x78, 0x0A, 0xE7, 0xF3, 0x73, 0x0A, 0xE2, 0xF3, + 0x6F, 0x0A, 0xDE, 0xF3, 0x6A, 0x0A, 0xDA, 0xF3, 0x65, 0x0A, + 0xD6, 0xF3, 0x60, 0x0A, 0xD2, 0xF3, 0x5C, 0x0A, 0xCE, 0xF3, + 0x57, 0x0A, 0xCA, 0xF3, 0x52, 0x0A, 0xC6, 0xF3, 0x4D, 0x0A, + 0xC2, 0xF3, 0x48, 0x0A, 0xBE, 0xF3, 0x44, 0x0A, 0xBA, 0xF3, + 0x3F, 0x0A, 0xB6, 0xF3, 0x3A, 0x0A, 0xB2, 0xF3, 0x35, 0x0A, + 0xAE, 0xF3, 0x30, 0x0A, 0xAA, 0xF3, 0x2B, 0x0A, 0xA6, 0xF3, + 0x26, 0x0A, 0xA2, 0xF3, 0x22, 0x0A, 0x9E, 0xF3, 0x1D, 0x0A, + 0x9A, 0xF3, 0x18, 0x0A, 0x96, 0xF3, 0x13, 0x0A, 0x92, 0xF3, + 0x0E, 0x0A, 0x8E, 0xF3, 0x09, 0x0A, 0x8A, 0xF3, 0x04, 0x0A, + 0x86, 0xF3, 0xFF, 0x09, 0x82, 0xF3, 0xFB, 0x09, 0x7E, 0xF3, + 0xF6, 0x09, 0x7A, 0xF3, 0xF1, 0x09, 0x76, 0xF3, 0xEC, 0x09, + 0x72, 0xF3, 0xE7, 0x09, 0x6F, 0xF3, 0xE2, 0x09, 0x6B, 0xF3, + 0xDD, 0x09, 0x67, 0xF3, 0xD8, 0x09, 0x63, 0xF3, 0xD3, 0x09, + 0x5F, 0xF3, 0xCE, 0x09, 0x5B, 0xF3, 0xC9, 0x09, 0x57, 0xF3, + 0xC4, 0x09, 0x54, 0xF3, 0xBF, 0x09, 0x50, 0xF3, 0xBA, 0x09, + 0x4C, 0xF3, 0xB5, 0x09, 0x48, 0xF3, 0xB0, 0x09, 0x44, 0xF3, + 0xAB, 0x09, 0x40, 0xF3, 0xA6, 0x09, 0x3D, 0xF3, 0xA1, 0x09, + 0x39, 0xF3, 0x9C, 0x09, 0x35, 0xF3, 0x97, 0x09, 0x31, 0xF3, + 0x92, 0x09, 0x2E, 0xF3, 0x8D, 0x09, 0x2A, 0xF3, 0x88, 0x09, + 0x26, 0xF3, 0x83, 0x09, 0x22, 0xF3, 0x7E, 0x09, 0x1F, 0xF3, + 0x79, 0x09, 0x1B, 0xF3, 0x74, 0x09, 0x17, 0xF3, 0x6F, 0x09, + 0x13, 0xF3, 0x6A, 0x09, 0x10, 0xF3, 0x65, 0x09, 0x0C, 0xF3, + 0x5F, 0x09, 0x08, 0xF3, 0x5A, 0x09, 0x05, 0xF3, 0x55, 0x09, + 0x01, 0xF3, 0x50, 0x09, 0xFD, 0xF2, 0x4B, 0x09, 0xFA, 0xF2, + 0x46, 0x09, 0xF6, 0xF2, 0x41, 0x09, 0xF2, 0xF2, 0x3C, 0x09, + 0xEF, 0xF2, 0x37, 0x09, 0xEB, 0xF2, 0x31, 0x09, 0xE8, 0xF2, + 0x2C, 0x09, 0xE4, 0xF2, 0x27, 0x09, 0xE0, 0xF2, 0x22, 0x09, + 0xDD, 0xF2, 0x1D, 0x09, 0xD9, 0xF2, 0x18, 0x09, 0xD6, 0xF2, + 0x12, 0x09, 0xD2, 0xF2, 0x0D, 0x09, 0xCE, 0xF2, 0x08, 0x09, + 0xCB, 0xF2, 0x03, 0x09, 0xC7, 0xF2, 0xFE, 0x08, 0xC4, 0xF2, + 0xF8, 0x08, 0xC0, 0xF2, 0xF3, 0x08, 0xBD, 0xF2, 0xEE, 0x08, + 0xB9, 0xF2, 0xE9, 0x08, 0xB6, 0xF2, 0xE4, 0x08, 0xB2, 0xF2, + 0xDE, 0x08, 0xAF, 0xF2, 0xD9, 0x08, 0xAB, 0xF2, 0xD4, 0x08, + 0xA8, 0xF2, 0xCF, 0x08, 0xA4, 0xF2, 0xC9, 0x08, 0xA1, 0xF2, + 0xC4, 0x08, 0x9E, 0xF2, 0xBF, 0x08, 0x9A, 0xF2, 0xBA, 0x08, + 0x97, 0xF2, 0xB4, 0x08, 0x93, 0xF2, 0xAF, 0x08, 0x90, 0xF2, + 0xAA, 0x08, 0x8C, 0xF2, 0xA5, 0x08, 0x89, 0xF2, 0x9F, 0x08, + 0x86, 0xF2, 0x9A, 0x08, 0x82, 0xF2, 0x95, 0x08, 0x7F, 0xF2, + 0x8F, 0x08, 0x7B, 0xF2, 0x8A, 0x08, 0x78, 0xF2, 0x85, 0x08, + 0x75, 0xF2, 0x7F, 0x08, 0x71, 0xF2, 0x7A, 0x08, 0x6E, 0xF2, + 0x75, 0x08, 0x6B, 0xF2, 0x6F, 0x08, 0x67, 0xF2, 0x6A, 0x08, + 0x64, 0xF2, 0x65, 0x08, 0x61, 0xF2, 0x5F, 0x08, 0x5E, 0xF2, + 0x5A, 0x08, 0x5A, 0xF2, 0x55, 0x08, 0x57, 0xF2, 0x4F, 0x08, + 0x54, 0xF2, 0x4A, 0x08, 0x50, 0xF2, 0x45, 0x08, 0x4D, 0xF2, + 0x3F, 0x08, 0x4A, 0xF2, 0x3A, 0x08, 0x47, 0xF2, 0x34, 0x08, + 0x44, 0xF2, 0x2F, 0x08, 0x40, 0xF2, 0x2A, 0x08, 0x3D, 0xF2, + 0x24, 0x08, 0x3A, 0xF2, 0x1F, 0x08, 0x37, 0xF2, 0x19, 0x08, + 0x34, 0xF2, 0x14, 0x08, 0x30, 0xF2, 0x0E, 0x08, 0x2D, 0xF2, + 0x09, 0x08, 0x2A, 0xF2, 0x04, 0x08, 0x27, 0xF2, 0xFE, 0x07, + 0x24, 0xF2, 0xF9, 0x07, 0x21, 0xF2, 0xF3, 0x07, 0x1D, 0xF2, + 0xEE, 0x07, 0x1A, 0xF2, 0xE8, 0x07, 0x17, 0xF2, 0xE3, 0x07, + 0x14, 0xF2, 0xDD, 0x07, 0x11, 0xF2, 0xD8, 0x07, 0x0E, 0xF2, + 0xD2, 0x07, 0x0B, 0xF2, 0xCD, 0x07, 0x08, 0xF2, 0xC8, 0x07, + 0x05, 0xF2, 0xC2, 0x07, 0x02, 0xF2, 0xBD, 0x07, 0xFF, 0xF1, + 0xB7, 0x07, 0xFC, 0xF1, 0xB2, 0x07, 0xF9, 0xF1, 0xAC, 0x07, + 0xF6, 0xF1, 0xA6, 0x07, 0xF3, 0xF1, 0xA1, 0x07, 0xF0, 0xF1, + 0x9B, 0x07, 0xED, 0xF1, 0x96, 0x07, 0xEA, 0xF1, 0x90, 0x07, + 0xE7, 0xF1, 0x8B, 0x07, 0xE4, 0xF1, 0x85, 0x07, 0xE1, 0xF1, + 0x80, 0x07, 0xDE, 0xF1, 0x7A, 0x07, 0xDB, 0xF1, 0x75, 0x07, + 0xD8, 0xF1, 0x6F, 0x07, 0xD5, 0xF1, 0x6A, 0x07, 0xD2, 0xF1, + 0x64, 0x07, 0xCF, 0xF1, 0x5E, 0x07, 0xCC, 0xF1, 0x59, 0x07, + 0xC9, 0xF1, 0x53, 0x07, 0xC6, 0xF1, 0x4E, 0x07, 0xC4, 0xF1, + 0x48, 0x07, 0xC1, 0xF1, 0x42, 0x07, 0xBE, 0xF1, 0x3D, 0x07, + 0xBB, 0xF1, 0x37, 0x07, 0xB8, 0xF1, 0x32, 0x07, 0xB5, 0xF1, + 0x2C, 0x07, 0xB3, 0xF1, 0x26, 0x07, 0xB0, 0xF1, 0x21, 0x07, + 0xAD, 0xF1, 0x1B, 0x07, 0xAA, 0xF1, 0x15, 0x07, 0xA7, 0xF1, + 0x10, 0x07, 0xA5, 0xF1, 0x0A, 0x07, 0xA2, 0xF1, 0x05, 0x07, + 0x9F, 0xF1, 0xFF, 0x06, 0x9C, 0xF1, 0xF9, 0x06, 0x9A, 0xF1, + 0xF4, 0x06, 0x97, 0xF1, 0xEE, 0x06, 0x94, 0xF1, 0xE8, 0x06, + 0x91, 0xF1, 0xE3, 0x06, 0x8F, 0xF1, 0xDD, 0x06, 0x8C, 0xF1, + 0xD7, 0x06, 0x89, 0xF1, 0xD2, 0x06, 0x87, 0xF1, 0xCC, 0x06, + 0x84, 0xF1, 0xC6, 0x06, 0x81, 0xF1, 0xC1, 0x06, 0x7F, 0xF1, + 0xBB, 0x06, 0x7C, 0xF1, 0xB5, 0x06, 0x79, 0xF1, 0xAF, 0x06, + 0x77, 0xF1, 0xAA, 0x06, 0x74, 0xF1, 0xA4, 0x06, 0x71, 0xF1, + 0x9E, 0x06, 0x6F, 0xF1, 0x99, 0x06, 0x6C, 0xF1, 0x93, 0x06, + 0x6A, 0xF1, 0x8D, 0x06, 0x67, 0xF1, 0x87, 0x06, 0x65, 0xF1, + 0x82, 0x06, 0x62, 0xF1, 0x7C, 0x06, 0x5F, 0xF1, 0x76, 0x06, + 0x5D, 0xF1, 0x70, 0x06, 0x5A, 0xF1, 0x6B, 0x06, 0x58, 0xF1, + 0x65, 0x06, 0x55, 0xF1, 0x5F, 0x06, 0x53, 0xF1, 0x59, 0x06, + 0x50, 0xF1, 0x54, 0x06, 0x4E, 0xF1, 0x4E, 0x06, 0x4B, 0xF1, + 0x48, 0x06, 0x49, 0xF1, 0x42, 0x06, 0x46, 0xF1, 0x3C, 0x06, + 0x44, 0xF1, 0x37, 0x06, 0x41, 0xF1, 0x31, 0x06, 0x3F, 0xF1, + 0x2B, 0x06, 0x3D, 0xF1, 0x25, 0x06, 0x3A, 0xF1, 0x1F, 0x06, + 0x38, 0xF1, 0x1A, 0x06, 0x35, 0xF1, 0x14, 0x06, 0x33, 0xF1, + 0x0E, 0x06, 0x31, 0xF1, 0x08, 0x06, 0x2E, 0xF1, 0x02, 0x06, + 0x2C, 0xF1, 0xFD, 0x05, 0x2A, 0xF1, 0xF7, 0x05, 0x27, 0xF1, + 0xF1, 0x05, 0x25, 0xF1, 0xEB, 0x05, 0x23, 0xF1, 0xE5, 0x05, + 0x20, 0xF1, 0xDF, 0x05, 0x1E, 0xF1, 0xDA, 0x05, 0x1C, 0xF1, + 0xD4, 0x05, 0x19, 0xF1, 0xCE, 0x05, 0x17, 0xF1, 0xC8, 0x05, + 0x15, 0xF1, 0xC2, 0x05, 0x12, 0xF1, 0xBC, 0x05, 0x10, 0xF1, + 0xB6, 0x05, 0x0E, 0xF1, 0xB1, 0x05, 0x0C, 0xF1, 0xAB, 0x05, + 0x09, 0xF1, 0xA5, 0x05, 0x07, 0xF1, 0x9F, 0x05, 0x05, 0xF1, + 0x99, 0x05, 0x03, 0xF1, 0x93, 0x05, 0x01, 0xF1, 0x8D, 0x05, + 0xFE, 0xF0, 0x87, 0x05, 0xFC, 0xF0, 0x81, 0x05, 0xFA, 0xF0, + 0x7C, 0x05, 0xF8, 0xF0, 0x76, 0x05, 0xF6, 0xF0, 0x70, 0x05, + 0xF4, 0xF0, 0x6A, 0x05, 0xF2, 0xF0, 0x64, 0x05, 0xEF, 0xF0, + 0x5E, 0x05, 0xED, 0xF0, 0x58, 0x05, 0xEB, 0xF0, 0x52, 0x05, + 0xE9, 0xF0, 0x4C, 0x05, 0xE7, 0xF0, 0x46, 0x05, 0xE5, 0xF0, + 0x40, 0x05, 0xE3, 0xF0, 0x3A, 0x05, 0xE1, 0xF0, 0x34, 0x05, + 0xDF, 0xF0, 0x2F, 0x05, 0xDD, 0xF0, 0x29, 0x05, 0xDB, 0xF0, + 0x23, 0x05, 0xD9, 0xF0, 0x1D, 0x05, 0xD7, 0xF0, 0x17, 0x05, + 0xD5, 0xF0, 0x11, 0x05, 0xD3, 0xF0, 0x0B, 0x05, 0xD1, 0xF0, + 0x05, 0x05, 0xCF, 0xF0, 0xFF, 0x04, 0xCD, 0xF0, 0xF9, 0x04, + 0xCB, 0xF0, 0xF3, 0x04, 0xC9, 0xF0, 0xED, 0x04, 0xC7, 0xF0, + 0xE7, 0x04, 0xC5, 0xF0, 0xE1, 0x04, 0xC3, 0xF0, 0xDB, 0x04, + 0xC1, 0xF0, 0xD5, 0x04, 0xBF, 0xF0, 0xCF, 0x04, 0xBD, 0xF0, + 0xC9, 0x04, 0xBB, 0xF0, 0xC3, 0x04, 0xBA, 0xF0, 0xBD, 0x04, + 0xB8, 0xF0, 0xB7, 0x04, 0xB6, 0xF0, 0xB1, 0x04, 0xB4, 0xF0, + 0xAB, 0x04, 0xB2, 0xF0, 0xA5, 0x04, 0xB0, 0xF0, 0x9F, 0x04, + 0xAF, 0xF0, 0x99, 0x04, 0xAD, 0xF0, 0x93, 0x04, 0xAB, 0xF0, + 0x8D, 0x04, 0xA9, 0xF0, 0x87, 0x04, 0xA7, 0xF0, 0x81, 0x04, + 0xA6, 0xF0, 0x7B, 0x04, 0xA4, 0xF0, 0x75, 0x04, 0xA2, 0xF0, + 0x6F, 0x04, 0xA0, 0xF0, 0x69, 0x04, 0x9F, 0xF0, 0x63, 0x04, + 0x9D, 0xF0, 0x5D, 0x04, 0x9B, 0xF0, 0x57, 0x04, 0x99, 0xF0, + 0x51, 0x04, 0x98, 0xF0, 0x4B, 0x04, 0x96, 0xF0, 0x44, 0x04, + 0x94, 0xF0, 0x3E, 0x04, 0x93, 0xF0, 0x38, 0x04, 0x91, 0xF0, + 0x32, 0x04, 0x8F, 0xF0, 0x2C, 0x04, 0x8E, 0xF0, 0x26, 0x04, + 0x8C, 0xF0, 0x20, 0x04, 0x8A, 0xF0, 0x1A, 0x04, 0x89, 0xF0, + 0x14, 0x04, 0x87, 0xF0, 0x0E, 0x04, 0x86, 0xF0, 0x08, 0x04, + 0x84, 0xF0, 0x02, 0x04, 0x83, 0xF0, 0xFC, 0x03, 0x81, 0xF0, + 0xF6, 0x03, 0x7F, 0xF0, 0xEF, 0x03, 0x7E, 0xF0, 0xE9, 0x03, + 0x7C, 0xF0, 0xE3, 0x03, 0x7B, 0xF0, 0xDD, 0x03, 0x79, 0xF0, + 0xD7, 0x03, 0x78, 0xF0, 0xD1, 0x03, 0x76, 0xF0, 0xCB, 0x03, + 0x75, 0xF0, 0xC5, 0x03, 0x73, 0xF0, 0xBF, 0x03, 0x72, 0xF0, + 0xB9, 0x03, 0x70, 0xF0, 0xB2, 0x03, 0x6F, 0xF0, 0xAC, 0x03, + 0x6D, 0xF0, 0xA6, 0x03, 0x6C, 0xF0, 0xA0, 0x03, 0x6B, 0xF0, + 0x9A, 0x03, 0x69, 0xF0, 0x94, 0x03, 0x68, 0xF0, 0x8E, 0x03, + 0x66, 0xF0, 0x88, 0x03, 0x65, 0xF0, 0x81, 0x03, 0x64, 0xF0, + 0x7B, 0x03, 0x62, 0xF0, 0x75, 0x03, 0x61, 0xF0, 0x6F, 0x03, + 0x5F, 0xF0, 0x69, 0x03, 0x5E, 0xF0, 0x63, 0x03, 0x5D, 0xF0, + 0x5D, 0x03, 0x5B, 0xF0, 0x56, 0x03, 0x5A, 0xF0, 0x50, 0x03, + 0x59, 0xF0, 0x4A, 0x03, 0x58, 0xF0, 0x44, 0x03, 0x56, 0xF0, + 0x3E, 0x03, 0x55, 0xF0, 0x38, 0x03, 0x54, 0xF0, 0x32, 0x03, + 0x52, 0xF0, 0x2B, 0x03, 0x51, 0xF0, 0x25, 0x03, 0x50, 0xF0, + 0x1F, 0x03, 0x4F, 0xF0, 0x19, 0x03, 0x4D, 0xF0, 0x13, 0x03, + 0x4C, 0xF0, 0x0D, 0x03, 0x4B, 0xF0, 0x06, 0x03, 0x4A, 0xF0, + 0x00, 0x03, 0x49, 0xF0, 0xFA, 0x02, 0x48, 0xF0, 0xF4, 0x02, + 0x46, 0xF0, 0xEE, 0x02, 0x45, 0xF0, 0xE8, 0x02, 0x44, 0xF0, + 0xE1, 0x02, 0x43, 0xF0, 0xDB, 0x02, 0x42, 0xF0, 0xD5, 0x02, + 0x41, 0xF0, 0xCF, 0x02, 0x40, 0xF0, 0xC9, 0x02, 0x3E, 0xF0, + 0xC2, 0x02, 0x3D, 0xF0, 0xBC, 0x02, 0x3C, 0xF0, 0xB6, 0x02, + 0x3B, 0xF0, 0xB0, 0x02, 0x3A, 0xF0, 0xAA, 0x02, 0x39, 0xF0, + 0xA3, 0x02, 0x38, 0xF0, 0x9D, 0x02, 0x37, 0xF0, 0x97, 0x02, + 0x36, 0xF0, 0x91, 0x02, 0x35, 0xF0, 0x8B, 0x02, 0x34, 0xF0, + 0x84, 0x02, 0x33, 0xF0, 0x7E, 0x02, 0x32, 0xF0, 0x78, 0x02, + 0x31, 0xF0, 0x72, 0x02, 0x30, 0xF0, 0x6C, 0x02, 0x2F, 0xF0, + 0x65, 0x02, 0x2E, 0xF0, 0x5F, 0x02, 0x2D, 0xF0, 0x59, 0x02, + 0x2C, 0xF0, 0x53, 0x02, 0x2B, 0xF0, 0x4D, 0x02, 0x2B, 0xF0, + 0x46, 0x02, 0x2A, 0xF0, 0x40, 0x02, 0x29, 0xF0, 0x3A, 0x02, + 0x28, 0xF0, 0x34, 0x02, 0x27, 0xF0, 0x2D, 0x02, 0x26, 0xF0, + 0x27, 0x02, 0x25, 0xF0, 0x21, 0x02, 0x24, 0xF0, 0x1B, 0x02, + 0x24, 0xF0, 0x15, 0x02, 0x23, 0xF0, 0x0E, 0x02, 0x22, 0xF0, + 0x08, 0x02, 0x21, 0xF0, 0x02, 0x02, 0x20, 0xF0, 0xFC, 0x01, + 0x20, 0xF0, 0xF5, 0x01, 0x1F, 0xF0, 0xEF, 0x01, 0x1E, 0xF0, + 0xE9, 0x01, 0x1D, 0xF0, 0xE3, 0x01, 0x1D, 0xF0, 0xDC, 0x01, + 0x1C, 0xF0, 0xD6, 0x01, 0x1B, 0xF0, 0xD0, 0x01, 0x1A, 0xF0, + 0xCA, 0x01, 0x1A, 0xF0, 0xC3, 0x01, 0x19, 0xF0, 0xBD, 0x01, + 0x18, 0xF0, 0xB7, 0x01, 0x18, 0xF0, 0xB1, 0x01, 0x17, 0xF0, + 0xAA, 0x01, 0x16, 0xF0, 0xA4, 0x01, 0x16, 0xF0, 0x9E, 0x01, + 0x15, 0xF0, 0x98, 0x01, 0x14, 0xF0, 0x91, 0x01, 0x14, 0xF0, + 0x8B, 0x01, 0x13, 0xF0, 0x85, 0x01, 0x13, 0xF0, 0x7F, 0x01, + 0x12, 0xF0, 0x78, 0x01, 0x11, 0xF0, 0x72, 0x01, 0x11, 0xF0, + 0x6C, 0x01, 0x10, 0xF0, 0x66, 0x01, 0x10, 0xF0, 0x5F, 0x01, + 0x0F, 0xF0, 0x59, 0x01, 0x0F, 0xF0, 0x53, 0x01, 0x0E, 0xF0, + 0x4D, 0x01, 0x0E, 0xF0, 0x46, 0x01, 0x0D, 0xF0, 0x40, 0x01, + 0x0D, 0xF0, 0x3A, 0x01, 0x0C, 0xF0, 0x34, 0x01, 0x0C, 0xF0, + 0x2D, 0x01, 0x0B, 0xF0, 0x27, 0x01, 0x0B, 0xF0, 0x21, 0x01, + 0x0A, 0xF0, 0x1B, 0x01, 0x0A, 0xF0, 0x14, 0x01, 0x09, 0xF0, + 0x0E, 0x01, 0x09, 0xF0, 0x08, 0x01, 0x08, 0xF0, 0x01, 0x01, + 0x08, 0xF0, 0xFB, 0x00, 0x08, 0xF0, 0xF5, 0x00, 0x07, 0xF0, + 0xEF, 0x00, 0x07, 0xF0, 0xE8, 0x00, 0x07, 0xF0, 0xE2, 0x00, + 0x06, 0xF0, 0xDC, 0x00, 0x06, 0xF0, 0xD6, 0x00, 0x06, 0xF0, + 0xCF, 0x00, 0x05, 0xF0, 0xC9, 0x00, 0x05, 0xF0, 0xC3, 0x00, + 0x05, 0xF0, 0xBC, 0x00, 0x04, 0xF0, 0xB6, 0x00, 0x04, 0xF0, + 0xB0, 0x00, 0x04, 0xF0, 0xAA, 0x00, 0x04, 0xF0, 0xA3, 0x00, + 0x03, 0xF0, 0x9D, 0x00, 0x03, 0xF0, 0x97, 0x00, 0x03, 0xF0, + 0x90, 0x00, 0x03, 0xF0, 0x8A, 0x00, 0x02, 0xF0, 0x84, 0x00, + 0x02, 0xF0, 0x7E, 0x00, 0x02, 0xF0, 0x77, 0x00, 0x02, 0xF0, + 0x71, 0x00, 0x02, 0xF0, 0x6B, 0x00, 0x01, 0xF0, 0x65, 0x00, + 0x01, 0xF0, 0x5E, 0x00, 0x01, 0xF0, 0x58, 0x00, 0x01, 0xF0, + 0x52, 0x00, 0x01, 0xF0, 0x4B, 0x00, 0x01, 0xF0, 0x45, 0x00, + 0x01, 0xF0, 0x3F, 0x00, 0x00, 0xF0, 0x39, 0x00, 0x00, 0xF0, + 0x32, 0x00, 0x00, 0xF0, 0x2C, 0x00, 0x00, 0xF0, 0x26, 0x00, + 0x00, 0xF0, 0x1F, 0x00, 0x00, 0xF0, 0x19, 0x00, 0x00, 0xF0, + 0x13, 0x00, 0x00, 0xF0, 0x0D, 0x00, 0x00, 0xF0, 0x06, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xFA, 0xFF, 0x00, 0xF0, + 0xF3, 0xFF, 0x00, 0xF0, 0xED, 0xFF, 0x00, 0xF0, 0xE7, 0xFF, + 0x00, 0xF0, 0xE1, 0xFF, 0x00, 0xF0, 0xDA, 0xFF, 0x00, 0xF0, + 0xD4, 0xFF, 0x00, 0xF0, 0xCE, 0xFF, 0x00, 0xF0, 0xC7, 0xFF, + 0x00, 0xF0, 0xC1, 0xFF, 0x00, 0xF0, 0xBB, 0xFF, 0x01, 0xF0, + 0xB5, 0xFF, 0x01, 0xF0, 0xAE, 0xFF, 0x01, 0xF0, 0xA8, 0xFF, + 0x01, 0xF0, 0xA2, 0xFF, 0x01, 0xF0, 0x9B, 0xFF, 0x01, 0xF0, + 0x95, 0xFF, 0x01, 0xF0, 0x8F, 0xFF, 0x02, 0xF0, 0x89, 0xFF, + 0x02, 0xF0, 0x82, 0xFF, 0x02, 0xF0, 0x7C, 0xFF, 0x02, 0xF0, + 0x76, 0xFF, 0x02, 0xF0, 0x70, 0xFF, 0x03, 0xF0, 0x69, 0xFF, + 0x03, 0xF0, 0x63, 0xFF, 0x03, 0xF0, 0x5D, 0xFF, 0x03, 0xF0, + 0x56, 0xFF, 0x04, 0xF0, 0x50, 0xFF, 0x04, 0xF0, 0x4A, 0xFF, + 0x04, 0xF0, 0x44, 0xFF, 0x04, 0xF0, 0x3D, 0xFF, 0x05, 0xF0, + 0x37, 0xFF, 0x05, 0xF0, 0x31, 0xFF, 0x05, 0xF0, 0x2A, 0xFF, + 0x06, 0xF0, 0x24, 0xFF, 0x06, 0xF0, 0x1E, 0xFF, 0x06, 0xF0, + 0x18, 0xFF, 0x07, 0xF0, 0x11, 0xFF, 0x07, 0xF0, 0x0B, 0xFF, + 0x07, 0xF0, 0x05, 0xFF, 0x08, 0xF0, 0xFF, 0xFE, 0x08, 0xF0, + 0xF8, 0xFE, 0x08, 0xF0, 0xF2, 0xFE, 0x09, 0xF0, 0xEC, 0xFE, + 0x09, 0xF0, 0xE5, 0xFE, 0x0A, 0xF0, 0xDF, 0xFE, 0x0A, 0xF0, + 0xD9, 0xFE, 0x0B, 0xF0, 0xD3, 0xFE, 0x0B, 0xF0, 0xCC, 0xFE, + 0x0C, 0xF0, 0xC6, 0xFE, 0x0C, 0xF0, 0xC0, 0xFE, 0x0D, 0xF0, + 0xBA, 0xFE, 0x0D, 0xF0, 0xB3, 0xFE, 0x0E, 0xF0, 0xAD, 0xFE, + 0x0E, 0xF0, 0xA7, 0xFE, 0x0F, 0xF0, 0xA1, 0xFE, 0x0F, 0xF0, + 0x9A, 0xFE, 0x10, 0xF0, 0x94, 0xFE, 0x10, 0xF0, 0x8E, 0xFE, + 0x11, 0xF0, 0x88, 0xFE, 0x11, 0xF0, 0x81, 0xFE, 0x12, 0xF0, + 0x7B, 0xFE, 0x13, 0xF0, 0x75, 0xFE, 0x13, 0xF0, 0x6F, 0xFE, + 0x14, 0xF0, 0x68, 0xFE, 0x14, 0xF0, 0x62, 0xFE, 0x15, 0xF0, + 0x5C, 0xFE, 0x16, 0xF0, 0x56, 0xFE, 0x16, 0xF0, 0x4F, 0xFE, + 0x17, 0xF0, 0x49, 0xFE, 0x18, 0xF0, 0x43, 0xFE, 0x18, 0xF0, + 0x3D, 0xFE, 0x19, 0xF0, 0x36, 0xFE, 0x1A, 0xF0, 0x30, 0xFE, + 0x1A, 0xF0, 0x2A, 0xFE, 0x1B, 0xF0, 0x24, 0xFE, 0x1C, 0xF0, + 0x1D, 0xFE, 0x1D, 0xF0, 0x17, 0xFE, 0x1D, 0xF0, 0x11, 0xFE, + 0x1E, 0xF0, 0x0B, 0xFE, 0x1F, 0xF0, 0x04, 0xFE, 0x20, 0xF0, + 0xFE, 0xFD, 0x20, 0xF0, 0xF8, 0xFD, 0x21, 0xF0, 0xF2, 0xFD, + 0x22, 0xF0, 0xEB, 0xFD, 0x23, 0xF0, 0xE5, 0xFD, 0x24, 0xF0, + 0xDF, 0xFD, 0x24, 0xF0, 0xD9, 0xFD, 0x25, 0xF0, 0xD3, 0xFD, + 0x26, 0xF0, 0xCC, 0xFD, 0x27, 0xF0, 0xC6, 0xFD, 0x28, 0xF0, + 0xC0, 0xFD, 0x29, 0xF0, 0xBA, 0xFD, 0x2A, 0xF0, 0xB3, 0xFD, + 0x2B, 0xF0, 0xAD, 0xFD, 0x2B, 0xF0, 0xA7, 0xFD, 0x2C, 0xF0, + 0xA1, 0xFD, 0x2D, 0xF0, 0x9B, 0xFD, 0x2E, 0xF0, 0x94, 0xFD, + 0x2F, 0xF0, 0x8E, 0xFD, 0x30, 0xF0, 0x88, 0xFD, 0x31, 0xF0, + 0x82, 0xFD, 0x32, 0xF0, 0x7C, 0xFD, 0x33, 0xF0, 0x75, 0xFD, + 0x34, 0xF0, 0x6F, 0xFD, 0x35, 0xF0, 0x69, 0xFD, 0x36, 0xF0, + 0x63, 0xFD, 0x37, 0xF0, 0x5D, 0xFD, 0x38, 0xF0, 0x56, 0xFD, + 0x39, 0xF0, 0x50, 0xFD, 0x3A, 0xF0, 0x4A, 0xFD, 0x3B, 0xF0, + 0x44, 0xFD, 0x3C, 0xF0, 0x3E, 0xFD, 0x3D, 0xF0, 0x37, 0xFD, + 0x3E, 0xF0, 0x31, 0xFD, 0x40, 0xF0, 0x2B, 0xFD, 0x41, 0xF0, + 0x25, 0xFD, 0x42, 0xF0, 0x1F, 0xFD, 0x43, 0xF0, 0x18, 0xFD, + 0x44, 0xF0, 0x12, 0xFD, 0x45, 0xF0, 0x0C, 0xFD, 0x46, 0xF0, + 0x06, 0xFD, 0x48, 0xF0, 0x00, 0xFD, 0x49, 0xF0, 0xFA, 0xFC, + 0x4A, 0xF0, 0xF3, 0xFC, 0x4B, 0xF0, 0xED, 0xFC, 0x4C, 0xF0, + 0xE7, 0xFC, 0x4D, 0xF0, 0xE1, 0xFC, 0x4F, 0xF0, 0xDB, 0xFC, + 0x50, 0xF0, 0xD5, 0xFC, 0x51, 0xF0, 0xCE, 0xFC, 0x52, 0xF0, + 0xC8, 0xFC, 0x54, 0xF0, 0xC2, 0xFC, 0x55, 0xF0, 0xBC, 0xFC, + 0x56, 0xF0, 0xB6, 0xFC, 0x58, 0xF0, 0xB0, 0xFC, 0x59, 0xF0, + 0xAA, 0xFC, 0x5A, 0xF0, 0xA3, 0xFC, 0x5B, 0xF0, 0x9D, 0xFC, + 0x5D, 0xF0, 0x97, 0xFC, 0x5E, 0xF0, 0x91, 0xFC, 0x5F, 0xF0, + 0x8B, 0xFC, 0x61, 0xF0, 0x85, 0xFC, 0x62, 0xF0, 0x7F, 0xFC, + 0x64, 0xF0, 0x78, 0xFC, 0x65, 0xF0, 0x72, 0xFC, 0x66, 0xF0, + 0x6C, 0xFC, 0x68, 0xF0, 0x66, 0xFC, 0x69, 0xF0, 0x60, 0xFC, + 0x6B, 0xF0, 0x5A, 0xFC, 0x6C, 0xF0, 0x54, 0xFC, 0x6D, 0xF0, + 0x4E, 0xFC, 0x6F, 0xF0, 0x47, 0xFC, 0x70, 0xF0, 0x41, 0xFC, + 0x72, 0xF0, 0x3B, 0xFC, 0x73, 0xF0, 0x35, 0xFC, 0x75, 0xF0, + 0x2F, 0xFC, 0x76, 0xF0, 0x29, 0xFC, 0x78, 0xF0, 0x23, 0xFC, + 0x79, 0xF0, 0x1D, 0xFC, 0x7B, 0xF0, 0x17, 0xFC, 0x7C, 0xF0, + 0x11, 0xFC, 0x7E, 0xF0, 0x0A, 0xFC, 0x7F, 0xF0, 0x04, 0xFC, + 0x81, 0xF0, 0xFE, 0xFB, 0x83, 0xF0, 0xF8, 0xFB, 0x84, 0xF0, + 0xF2, 0xFB, 0x86, 0xF0, 0xEC, 0xFB, 0x87, 0xF0, 0xE6, 0xFB, + 0x89, 0xF0, 0xE0, 0xFB, 0x8A, 0xF0, 0xDA, 0xFB, 0x8C, 0xF0, + 0xD4, 0xFB, 0x8E, 0xF0, 0xCE, 0xFB, 0x8F, 0xF0, 0xC8, 0xFB, + 0x91, 0xF0, 0xC2, 0xFB, 0x93, 0xF0, 0xBC, 0xFB, 0x94, 0xF0, + 0xB5, 0xFB, 0x96, 0xF0, 0xAF, 0xFB, 0x98, 0xF0, 0xA9, 0xFB, + 0x99, 0xF0, 0xA3, 0xFB, 0x9B, 0xF0, 0x9D, 0xFB, 0x9D, 0xF0, + 0x97, 0xFB, 0x9F, 0xF0, 0x91, 0xFB, 0xA0, 0xF0, 0x8B, 0xFB, + 0xA2, 0xF0, 0x85, 0xFB, 0xA4, 0xF0, 0x7F, 0xFB, 0xA6, 0xF0, + 0x79, 0xFB, 0xA7, 0xF0, 0x73, 0xFB, 0xA9, 0xF0, 0x6D, 0xFB, + 0xAB, 0xF0, 0x67, 0xFB, 0xAD, 0xF0, 0x61, 0xFB, 0xAF, 0xF0, + 0x5B, 0xFB, 0xB0, 0xF0, 0x55, 0xFB, 0xB2, 0xF0, 0x4F, 0xFB, + 0xB4, 0xF0, 0x49, 0xFB, 0xB6, 0xF0, 0x43, 0xFB, 0xB8, 0xF0, + 0x3D, 0xFB, 0xBA, 0xF0, 0x37, 0xFB, 0xBB, 0xF0, 0x31, 0xFB, + 0xBD, 0xF0, 0x2B, 0xFB, 0xBF, 0xF0, 0x25, 0xFB, 0xC1, 0xF0, + 0x1F, 0xFB, 0xC3, 0xF0, 0x19, 0xFB, 0xC5, 0xF0, 0x13, 0xFB, + 0xC7, 0xF0, 0x0D, 0xFB, 0xC9, 0xF0, 0x07, 0xFB, 0xCB, 0xF0, + 0x01, 0xFB, 0xCD, 0xF0, 0xFB, 0xFA, 0xCF, 0xF0, 0xF5, 0xFA, + 0xD1, 0xF0, 0xEF, 0xFA, 0xD3, 0xF0, 0xE9, 0xFA, 0xD5, 0xF0, + 0xE3, 0xFA, 0xD7, 0xF0, 0xDD, 0xFA, 0xD9, 0xF0, 0xD7, 0xFA, + 0xDB, 0xF0, 0xD1, 0xFA, 0xDD, 0xF0, 0xCC, 0xFA, 0xDF, 0xF0, + 0xC6, 0xFA, 0xE1, 0xF0, 0xC0, 0xFA, 0xE3, 0xF0, 0xBA, 0xFA, + 0xE5, 0xF0, 0xB4, 0xFA, 0xE7, 0xF0, 0xAE, 0xFA, 0xE9, 0xF0, + 0xA8, 0xFA, 0xEB, 0xF0, 0xA2, 0xFA, 0xED, 0xF0, 0x9C, 0xFA, + 0xEF, 0xF0, 0x96, 0xFA, 0xF2, 0xF0, 0x90, 0xFA, 0xF4, 0xF0, + 0x8A, 0xFA, 0xF6, 0xF0, 0x84, 0xFA, 0xF8, 0xF0, 0x7F, 0xFA, + 0xFA, 0xF0, 0x79, 0xFA, 0xFC, 0xF0, 0x73, 0xFA, 0xFE, 0xF0, + 0x6D, 0xFA, 0x01, 0xF1, 0x67, 0xFA, 0x03, 0xF1, 0x61, 0xFA, + 0x05, 0xF1, 0x5B, 0xFA, 0x07, 0xF1, 0x55, 0xFA, 0x09, 0xF1, + 0x4F, 0xFA, 0x0C, 0xF1, 0x4A, 0xFA, 0x0E, 0xF1, 0x44, 0xFA, + 0x10, 0xF1, 0x3E, 0xFA, 0x12, 0xF1, 0x38, 0xFA, 0x15, 0xF1, + 0x32, 0xFA, 0x17, 0xF1, 0x2C, 0xFA, 0x19, 0xF1, 0x26, 0xFA, + 0x1C, 0xF1, 0x21, 0xFA, 0x1E, 0xF1, 0x1B, 0xFA, 0x20, 0xF1, + 0x15, 0xFA, 0x23, 0xF1, 0x0F, 0xFA, 0x25, 0xF1, 0x09, 0xFA, + 0x27, 0xF1, 0x03, 0xFA, 0x2A, 0xF1, 0xFE, 0xF9, 0x2C, 0xF1, + 0xF8, 0xF9, 0x2E, 0xF1, 0xF2, 0xF9, 0x31, 0xF1, 0xEC, 0xF9, + 0x33, 0xF1, 0xE6, 0xF9, 0x35, 0xF1, 0xE1, 0xF9, 0x38, 0xF1, + 0xDB, 0xF9, 0x3A, 0xF1, 0xD5, 0xF9, 0x3D, 0xF1, 0xCF, 0xF9, + 0x3F, 0xF1, 0xC9, 0xF9, 0x41, 0xF1, 0xC4, 0xF9, 0x44, 0xF1, + 0xBE, 0xF9, 0x46, 0xF1, 0xB8, 0xF9, 0x49, 0xF1, 0xB2, 0xF9, + 0x4B, 0xF1, 0xAC, 0xF9, 0x4E, 0xF1, 0xA7, 0xF9, 0x50, 0xF1, + 0xA1, 0xF9, 0x53, 0xF1, 0x9B, 0xF9, 0x55, 0xF1, 0x95, 0xF9, + 0x58, 0xF1, 0x90, 0xF9, 0x5A, 0xF1, 0x8A, 0xF9, 0x5D, 0xF1, + 0x84, 0xF9, 0x5F, 0xF1, 0x7E, 0xF9, 0x62, 0xF1, 0x79, 0xF9, + 0x65, 0xF1, 0x73, 0xF9, 0x67, 0xF1, 0x6D, 0xF9, 0x6A, 0xF1, + 0x67, 0xF9, 0x6C, 0xF1, 0x62, 0xF9, 0x6F, 0xF1, 0x5C, 0xF9, + 0x71, 0xF1, 0x56, 0xF9, 0x74, 0xF1, 0x51, 0xF9, 0x77, 0xF1, + 0x4B, 0xF9, 0x79, 0xF1, 0x45, 0xF9, 0x7C, 0xF1, 0x3F, 0xF9, + 0x7F, 0xF1, 0x3A, 0xF9, 0x81, 0xF1, 0x34, 0xF9, 0x84, 0xF1, + 0x2E, 0xF9, 0x87, 0xF1, 0x29, 0xF9, 0x89, 0xF1, 0x23, 0xF9, + 0x8C, 0xF1, 0x1D, 0xF9, 0x8F, 0xF1, 0x18, 0xF9, 0x91, 0xF1, + 0x12, 0xF9, 0x94, 0xF1, 0x0C, 0xF9, 0x97, 0xF1, 0x07, 0xF9, + 0x9A, 0xF1, 0x01, 0xF9, 0x9C, 0xF1, 0xFB, 0xF8, 0x9F, 0xF1, + 0xF6, 0xF8, 0xA2, 0xF1, 0xF0, 0xF8, 0xA5, 0xF1, 0xEB, 0xF8, + 0xA7, 0xF1, 0xE5, 0xF8, 0xAA, 0xF1, 0xDF, 0xF8, 0xAD, 0xF1, + 0xDA, 0xF8, 0xB0, 0xF1, 0xD4, 0xF8, 0xB3, 0xF1, 0xCE, 0xF8, + 0xB5, 0xF1, 0xC9, 0xF8, 0xB8, 0xF1, 0xC3, 0xF8, 0xBB, 0xF1, + 0xBE, 0xF8, 0xBE, 0xF1, 0xB8, 0xF8, 0xC1, 0xF1, 0xB2, 0xF8, + 0xC4, 0xF1, 0xAD, 0xF8, 0xC6, 0xF1, 0xA7, 0xF8, 0xC9, 0xF1, + 0xA2, 0xF8, 0xCC, 0xF1, 0x9C, 0xF8, 0xCF, 0xF1, 0x96, 0xF8, + 0xD2, 0xF1, 0x91, 0xF8, 0xD5, 0xF1, 0x8B, 0xF8, 0xD8, 0xF1, + 0x86, 0xF8, 0xDB, 0xF1, 0x80, 0xF8, 0xDE, 0xF1, 0x7B, 0xF8, + 0xE1, 0xF1, 0x75, 0xF8, 0xE4, 0xF1, 0x70, 0xF8, 0xE7, 0xF1, + 0x6A, 0xF8, 0xEA, 0xF1, 0x65, 0xF8, 0xED, 0xF1, 0x5F, 0xF8, + 0xF0, 0xF1, 0x5A, 0xF8, 0xF3, 0xF1, 0x54, 0xF8, 0xF6, 0xF1, + 0x4E, 0xF8, 0xF9, 0xF1, 0x49, 0xF8, 0xFC, 0xF1, 0x43, 0xF8, + 0xFF, 0xF1, 0x3E, 0xF8, 0x02, 0xF2, 0x38, 0xF8, 0x05, 0xF2, + 0x33, 0xF8, 0x08, 0xF2, 0x2E, 0xF8, 0x0B, 0xF2, 0x28, 0xF8, + 0x0E, 0xF2, 0x23, 0xF8, 0x11, 0xF2, 0x1D, 0xF8, 0x14, 0xF2, + 0x18, 0xF8, 0x17, 0xF2, 0x12, 0xF8, 0x1A, 0xF2, 0x0D, 0xF8, + 0x1D, 0xF2, 0x07, 0xF8, 0x21, 0xF2, 0x02, 0xF8, 0x24, 0xF2, + 0xFC, 0xF7, 0x27, 0xF2, 0xF7, 0xF7, 0x2A, 0xF2, 0xF2, 0xF7, + 0x2D, 0xF2, 0xEC, 0xF7, 0x30, 0xF2, 0xE7, 0xF7, 0x34, 0xF2, + 0xE1, 0xF7, 0x37, 0xF2, 0xDC, 0xF7, 0x3A, 0xF2, 0xD6, 0xF7, + 0x3D, 0xF2, 0xD1, 0xF7, 0x40, 0xF2, 0xCC, 0xF7, 0x44, 0xF2, + 0xC6, 0xF7, 0x47, 0xF2, 0xC1, 0xF7, 0x4A, 0xF2, 0xBB, 0xF7, + 0x4D, 0xF2, 0xB6, 0xF7, 0x50, 0xF2, 0xB1, 0xF7, 0x54, 0xF2, + 0xAB, 0xF7, 0x57, 0xF2, 0xA6, 0xF7, 0x5A, 0xF2, 0xA1, 0xF7, + 0x5E, 0xF2, 0x9B, 0xF7, 0x61, 0xF2, 0x96, 0xF7, 0x64, 0xF2, + 0x91, 0xF7, 0x67, 0xF2, 0x8B, 0xF7, 0x6B, 0xF2, 0x86, 0xF7, + 0x6E, 0xF2, 0x81, 0xF7, 0x71, 0xF2, 0x7B, 0xF7, 0x75, 0xF2, + 0x76, 0xF7, 0x78, 0xF2, 0x71, 0xF7, 0x7B, 0xF2, 0x6B, 0xF7, + 0x7F, 0xF2, 0x66, 0xF7, 0x82, 0xF2, 0x61, 0xF7, 0x86, 0xF2, + 0x5B, 0xF7, 0x89, 0xF2, 0x56, 0xF7, 0x8C, 0xF2, 0x51, 0xF7, + 0x90, 0xF2, 0x4C, 0xF7, 0x93, 0xF2, 0x46, 0xF7, 0x97, 0xF2, + 0x41, 0xF7, 0x9A, 0xF2, 0x3C, 0xF7, 0x9E, 0xF2, 0x37, 0xF7, + 0xA1, 0xF2, 0x31, 0xF7, 0xA4, 0xF2, 0x2C, 0xF7, 0xA8, 0xF2, + 0x27, 0xF7, 0xAB, 0xF2, 0x22, 0xF7, 0xAF, 0xF2, 0x1C, 0xF7, + 0xB2, 0xF2, 0x17, 0xF7, 0xB6, 0xF2, 0x12, 0xF7, 0xB9, 0xF2, + 0x0D, 0xF7, 0xBD, 0xF2, 0x08, 0xF7, 0xC0, 0xF2, 0x02, 0xF7, + 0xC4, 0xF2, 0xFD, 0xF6, 0xC7, 0xF2, 0xF8, 0xF6, 0xCB, 0xF2, + 0xF3, 0xF6, 0xCE, 0xF2, 0xEE, 0xF6, 0xD2, 0xF2, 0xE8, 0xF6, + 0xD6, 0xF2, 0xE3, 0xF6, 0xD9, 0xF2, 0xDE, 0xF6, 0xDD, 0xF2, + 0xD9, 0xF6, 0xE0, 0xF2, 0xD4, 0xF6, 0xE4, 0xF2, 0xCF, 0xF6, + 0xE8, 0xF2, 0xC9, 0xF6, 0xEB, 0xF2, 0xC4, 0xF6, 0xEF, 0xF2, + 0xBF, 0xF6, 0xF2, 0xF2, 0xBA, 0xF6, 0xF6, 0xF2, 0xB5, 0xF6, + 0xFA, 0xF2, 0xB0, 0xF6, 0xFD, 0xF2, 0xAB, 0xF6, 0x01, 0xF3, + 0xA6, 0xF6, 0x05, 0xF3, 0xA1, 0xF6, 0x08, 0xF3, 0x9B, 0xF6, + 0x0C, 0xF3, 0x96, 0xF6, 0x10, 0xF3, 0x91, 0xF6, 0x13, 0xF3, + 0x8C, 0xF6, 0x17, 0xF3, 0x87, 0xF6, 0x1B, 0xF3, 0x82, 0xF6, + 0x1F, 0xF3, 0x7D, 0xF6, 0x22, 0xF3, 0x78, 0xF6, 0x26, 0xF3, + 0x73, 0xF6, 0x2A, 0xF3, 0x6E, 0xF6, 0x2E, 0xF3, 0x69, 0xF6, + 0x31, 0xF3, 0x64, 0xF6, 0x35, 0xF3, 0x5F, 0xF6, 0x39, 0xF3, + 0x5A, 0xF6, 0x3D, 0xF3, 0x55, 0xF6, 0x40, 0xF3, 0x50, 0xF6, + 0x44, 0xF3, 0x4B, 0xF6, 0x48, 0xF3, 0x46, 0xF6, 0x4C, 0xF3, + 0x41, 0xF6, 0x50, 0xF3, 0x3C, 0xF6, 0x54, 0xF3, 0x37, 0xF6, + 0x57, 0xF3, 0x32, 0xF6, 0x5B, 0xF3, 0x2D, 0xF6, 0x5F, 0xF3, + 0x28, 0xF6, 0x63, 0xF3, 0x23, 0xF6, 0x67, 0xF3, 0x1E, 0xF6, + 0x6B, 0xF3, 0x19, 0xF6, 0x6F, 0xF3, 0x14, 0xF6, 0x72, 0xF3, + 0x0F, 0xF6, 0x76, 0xF3, 0x0A, 0xF6, 0x7A, 0xF3, 0x05, 0xF6, + 0x7E, 0xF3, 0x01, 0xF6, 0x82, 0xF3, 0xFC, 0xF5, 0x86, 0xF3, + 0xF7, 0xF5, 0x8A, 0xF3, 0xF2, 0xF5, 0x8E, 0xF3, 0xED, 0xF5, + 0x92, 0xF3, 0xE8, 0xF5, 0x96, 0xF3, 0xE3, 0xF5, 0x9A, 0xF3, + 0xDE, 0xF5, 0x9E, 0xF3, 0xDA, 0xF5, 0xA2, 0xF3, 0xD5, 0xF5, + 0xA6, 0xF3, 0xD0, 0xF5, 0xAA, 0xF3, 0xCB, 0xF5, 0xAE, 0xF3, + 0xC6, 0xF5, 0xB2, 0xF3, 0xC1, 0xF5, 0xB6, 0xF3, 0xBC, 0xF5, + 0xBA, 0xF3, 0xB8, 0xF5, 0xBE, 0xF3, 0xB3, 0xF5, 0xC2, 0xF3, + 0xAE, 0xF5, 0xC6, 0xF3, 0xA9, 0xF5, 0xCA, 0xF3, 0xA4, 0xF5, + 0xCE, 0xF3, 0xA0, 0xF5, 0xD2, 0xF3, 0x9B, 0xF5, 0xD6, 0xF3, + 0x96, 0xF5, 0xDA, 0xF3, 0x91, 0xF5, 0xDE, 0xF3, 0x8D, 0xF5, + 0xE2, 0xF3, 0x88, 0xF5, 0xE7, 0xF3, 0x83, 0xF5, 0xEB, 0xF3, + 0x7E, 0xF5, 0xEF, 0xF3, 0x7A, 0xF5, 0xF3, 0xF3, 0x75, 0xF5, + 0xF7, 0xF3, 0x70, 0xF5, 0xFB, 0xF3, 0x6B, 0xF5, 0xFF, 0xF3, + 0x67, 0xF5, 0x04, 0xF4, 0x62, 0xF5, 0x08, 0xF4, 0x5D, 0xF5, + 0x0C, 0xF4, 0x59, 0xF5, 0x10, 0xF4, 0x54, 0xF5, 0x14, 0xF4, + 0x4F, 0xF5, 0x18, 0xF4, 0x4B, 0xF5, 0x1D, 0xF4, 0x46, 0xF5, + 0x21, 0xF4, 0x41, 0xF5, 0x25, 0xF4, 0x3D, 0xF5, 0x29, 0xF4, + 0x38, 0xF5, 0x2E, 0xF4, 0x33, 0xF5, 0x32, 0xF4, 0x2F, 0xF5, + 0x36, 0xF4, 0x2A, 0xF5, 0x3A, 0xF4, 0x25, 0xF5, 0x3F, 0xF4, + 0x21, 0xF5, 0x43, 0xF4, 0x1C, 0xF5, 0x47, 0xF4, 0x18, 0xF5, + 0x4B, 0xF4, 0x13, 0xF5, 0x50, 0xF4, 0x0E, 0xF5, 0x54, 0xF4, + 0x0A, 0xF5, 0x58, 0xF4, 0x05, 0xF5, 0x5D, 0xF4, 0x01, 0xF5, + 0x61, 0xF4, 0xFC, 0xF4, 0x65, 0xF4, 0xF8, 0xF4, 0x69, 0xF4, + 0xF3, 0xF4, 0x6E, 0xF4, 0xEF, 0xF4, 0x72, 0xF4, 0xEA, 0xF4, + 0x77, 0xF4, 0xE5, 0xF4, 0x7B, 0xF4, 0xE1, 0xF4, 0x7F, 0xF4, + 0xDC, 0xF4, 0x84, 0xF4, 0xD8, 0xF4, 0x88, 0xF4, 0xD3, 0xF4, + 0x8C, 0xF4, 0xCF, 0xF4, 0x91, 0xF4, 0xCA, 0xF4, 0x95, 0xF4, + 0xC6, 0xF4, 0x9A, 0xF4, 0xC2, 0xF4, 0x9E, 0xF4, 0xBD, 0xF4, + 0xA2, 0xF4, 0xB9, 0xF4, 0xA7, 0xF4, 0xB4, 0xF4, 0xAB, 0xF4, + 0xB0, 0xF4, 0xB0, 0xF4, 0xAB, 0xF4, 0xB4, 0xF4, 0xA7, 0xF4, + 0xB9, 0xF4, 0xA2, 0xF4, 0xBD, 0xF4, 0x9E, 0xF4, 0xC2, 0xF4, + 0x9A, 0xF4, 0xC6, 0xF4, 0x95, 0xF4, 0xCA, 0xF4, 0x91, 0xF4, + 0xCF, 0xF4, 0x8C, 0xF4, 0xD3, 0xF4, 0x88, 0xF4, 0xD8, 0xF4, + 0x84, 0xF4, 0xDC, 0xF4, 0x7F, 0xF4, 0xE1, 0xF4, 0x7B, 0xF4, + 0xE5, 0xF4, 0x77, 0xF4, 0xEA, 0xF4, 0x72, 0xF4, 0xEF, 0xF4, + 0x6E, 0xF4, 0xF3, 0xF4, 0x69, 0xF4, 0xF8, 0xF4, 0x65, 0xF4, + 0xFC, 0xF4, 0x61, 0xF4, 0x01, 0xF5, 0x5D, 0xF4, 0x05, 0xF5, + 0x58, 0xF4, 0x0A, 0xF5, 0x54, 0xF4, 0x0E, 0xF5, 0x50, 0xF4, + 0x13, 0xF5, 0x4B, 0xF4, 0x18, 0xF5, 0x47, 0xF4, 0x1C, 0xF5, + 0x43, 0xF4, 0x21, 0xF5, 0x3F, 0xF4, 0x25, 0xF5, 0x3A, 0xF4, + 0x2A, 0xF5, 0x36, 0xF4, 0x2F, 0xF5, 0x32, 0xF4, 0x33, 0xF5, + 0x2E, 0xF4, 0x38, 0xF5, 0x29, 0xF4, 0x3D, 0xF5, 0x25, 0xF4, + 0x41, 0xF5, 0x21, 0xF4, 0x46, 0xF5, 0x1D, 0xF4, 0x4B, 0xF5, + 0x18, 0xF4, 0x4F, 0xF5, 0x14, 0xF4, 0x54, 0xF5, 0x10, 0xF4, + 0x59, 0xF5, 0x0C, 0xF4, 0x5D, 0xF5, 0x08, 0xF4, 0x62, 0xF5, + 0x04, 0xF4, 0x67, 0xF5, 0xFF, 0xF3, 0x6B, 0xF5, 0xFB, 0xF3, + 0x70, 0xF5, 0xF7, 0xF3, 0x75, 0xF5, 0xF3, 0xF3, 0x7A, 0xF5, + 0xEF, 0xF3, 0x7E, 0xF5, 0xEB, 0xF3, 0x83, 0xF5, 0xE7, 0xF3, + 0x88, 0xF5, 0xE2, 0xF3, 0x8D, 0xF5, 0xDE, 0xF3, 0x91, 0xF5, + 0xDA, 0xF3, 0x96, 0xF5, 0xD6, 0xF3, 0x9B, 0xF5, 0xD2, 0xF3, + 0xA0, 0xF5, 0xCE, 0xF3, 0xA4, 0xF5, 0xCA, 0xF3, 0xA9, 0xF5, + 0xC6, 0xF3, 0xAE, 0xF5, 0xC2, 0xF3, 0xB3, 0xF5, 0xBE, 0xF3, + 0xB8, 0xF5, 0xBA, 0xF3, 0xBC, 0xF5, 0xB6, 0xF3, 0xC1, 0xF5, + 0xB2, 0xF3, 0xC6, 0xF5, 0xAE, 0xF3, 0xCB, 0xF5, 0xAA, 0xF3, + 0xD0, 0xF5, 0xA6, 0xF3, 0xD5, 0xF5, 0xA2, 0xF3, 0xDA, 0xF5, + 0x9E, 0xF3, 0xDE, 0xF5, 0x9A, 0xF3, 0xE3, 0xF5, 0x96, 0xF3, + 0xE8, 0xF5, 0x92, 0xF3, 0xED, 0xF5, 0x8E, 0xF3, 0xF2, 0xF5, + 0x8A, 0xF3, 0xF7, 0xF5, 0x86, 0xF3, 0xFC, 0xF5, 0x82, 0xF3, + 0x01, 0xF6, 0x7E, 0xF3, 0x05, 0xF6, 0x7A, 0xF3, 0x0A, 0xF6, + 0x76, 0xF3, 0x0F, 0xF6, 0x72, 0xF3, 0x14, 0xF6, 0x6F, 0xF3, + 0x19, 0xF6, 0x6B, 0xF3, 0x1E, 0xF6, 0x67, 0xF3, 0x23, 0xF6, + 0x63, 0xF3, 0x28, 0xF6, 0x5F, 0xF3, 0x2D, 0xF6, 0x5B, 0xF3, + 0x32, 0xF6, 0x57, 0xF3, 0x37, 0xF6, 0x54, 0xF3, 0x3C, 0xF6, + 0x50, 0xF3, 0x41, 0xF6, 0x4C, 0xF3, 0x46, 0xF6, 0x48, 0xF3, + 0x4B, 0xF6, 0x44, 0xF3, 0x50, 0xF6, 0x40, 0xF3, 0x55, 0xF6, + 0x3D, 0xF3, 0x5A, 0xF6, 0x39, 0xF3, 0x5F, 0xF6, 0x35, 0xF3, + 0x64, 0xF6, 0x31, 0xF3, 0x69, 0xF6, 0x2E, 0xF3, 0x6E, 0xF6, + 0x2A, 0xF3, 0x73, 0xF6, 0x26, 0xF3, 0x78, 0xF6, 0x22, 0xF3, + 0x7D, 0xF6, 0x1F, 0xF3, 0x82, 0xF6, 0x1B, 0xF3, 0x87, 0xF6, + 0x17, 0xF3, 0x8C, 0xF6, 0x13, 0xF3, 0x91, 0xF6, 0x10, 0xF3, + 0x96, 0xF6, 0x0C, 0xF3, 0x9B, 0xF6, 0x08, 0xF3, 0xA1, 0xF6, + 0x05, 0xF3, 0xA6, 0xF6, 0x01, 0xF3, 0xAB, 0xF6, 0xFD, 0xF2, + 0xB0, 0xF6, 0xFA, 0xF2, 0xB5, 0xF6, 0xF6, 0xF2, 0xBA, 0xF6, + 0xF2, 0xF2, 0xBF, 0xF6, 0xEF, 0xF2, 0xC4, 0xF6, 0xEB, 0xF2, + 0xC9, 0xF6, 0xE8, 0xF2, 0xCF, 0xF6, 0xE4, 0xF2, 0xD4, 0xF6, + 0xE0, 0xF2, 0xD9, 0xF6, 0xDD, 0xF2, 0xDE, 0xF6, 0xD9, 0xF2, + 0xE3, 0xF6, 0xD6, 0xF2, 0xE8, 0xF6, 0xD2, 0xF2, 0xEE, 0xF6, + 0xCE, 0xF2, 0xF3, 0xF6, 0xCB, 0xF2, 0xF8, 0xF6, 0xC7, 0xF2, + 0xFD, 0xF6, 0xC4, 0xF2, 0x02, 0xF7, 0xC0, 0xF2, 0x08, 0xF7, + 0xBD, 0xF2, 0x0D, 0xF7, 0xB9, 0xF2, 0x12, 0xF7, 0xB6, 0xF2, + 0x17, 0xF7, 0xB2, 0xF2, 0x1C, 0xF7, 0xAF, 0xF2, 0x22, 0xF7, + 0xAB, 0xF2, 0x27, 0xF7, 0xA8, 0xF2, 0x2C, 0xF7, 0xA4, 0xF2, + 0x31, 0xF7, 0xA1, 0xF2, 0x37, 0xF7, 0x9E, 0xF2, 0x3C, 0xF7, + 0x9A, 0xF2, 0x41, 0xF7, 0x97, 0xF2, 0x46, 0xF7, 0x93, 0xF2, + 0x4C, 0xF7, 0x90, 0xF2, 0x51, 0xF7, 0x8C, 0xF2, 0x56, 0xF7, + 0x89, 0xF2, 0x5B, 0xF7, 0x86, 0xF2, 0x61, 0xF7, 0x82, 0xF2, + 0x66, 0xF7, 0x7F, 0xF2, 0x6B, 0xF7, 0x7B, 0xF2, 0x71, 0xF7, + 0x78, 0xF2, 0x76, 0xF7, 0x75, 0xF2, 0x7B, 0xF7, 0x71, 0xF2, + 0x81, 0xF7, 0x6E, 0xF2, 0x86, 0xF7, 0x6B, 0xF2, 0x8B, 0xF7, + 0x67, 0xF2, 0x91, 0xF7, 0x64, 0xF2, 0x96, 0xF7, 0x61, 0xF2, + 0x9B, 0xF7, 0x5E, 0xF2, 0xA1, 0xF7, 0x5A, 0xF2, 0xA6, 0xF7, + 0x57, 0xF2, 0xAB, 0xF7, 0x54, 0xF2, 0xB1, 0xF7, 0x50, 0xF2, + 0xB6, 0xF7, 0x4D, 0xF2, 0xBB, 0xF7, 0x4A, 0xF2, 0xC1, 0xF7, + 0x47, 0xF2, 0xC6, 0xF7, 0x44, 0xF2, 0xCC, 0xF7, 0x40, 0xF2, + 0xD1, 0xF7, 0x3D, 0xF2, 0xD6, 0xF7, 0x3A, 0xF2, 0xDC, 0xF7, + 0x37, 0xF2, 0xE1, 0xF7, 0x34, 0xF2, 0xE7, 0xF7, 0x30, 0xF2, + 0xEC, 0xF7, 0x2D, 0xF2, 0xF2, 0xF7, 0x2A, 0xF2, 0xF7, 0xF7, + 0x27, 0xF2, 0xFC, 0xF7, 0x24, 0xF2, 0x02, 0xF8, 0x21, 0xF2, + 0x07, 0xF8, 0x1D, 0xF2, 0x0D, 0xF8, 0x1A, 0xF2, 0x12, 0xF8, + 0x17, 0xF2, 0x18, 0xF8, 0x14, 0xF2, 0x1D, 0xF8, 0x11, 0xF2, + 0x23, 0xF8, 0x0E, 0xF2, 0x28, 0xF8, 0x0B, 0xF2, 0x2E, 0xF8, + 0x08, 0xF2, 0x33, 0xF8, 0x05, 0xF2, 0x38, 0xF8, 0x02, 0xF2, + 0x3E, 0xF8, 0xFF, 0xF1, 0x43, 0xF8, 0xFC, 0xF1, 0x49, 0xF8, + 0xF9, 0xF1, 0x4E, 0xF8, 0xF6, 0xF1, 0x54, 0xF8, 0xF3, 0xF1, + 0x5A, 0xF8, 0xF0, 0xF1, 0x5F, 0xF8, 0xED, 0xF1, 0x65, 0xF8, + 0xEA, 0xF1, 0x6A, 0xF8, 0xE7, 0xF1, 0x70, 0xF8, 0xE4, 0xF1, + 0x75, 0xF8, 0xE1, 0xF1, 0x7B, 0xF8, 0xDE, 0xF1, 0x80, 0xF8, + 0xDB, 0xF1, 0x86, 0xF8, 0xD8, 0xF1, 0x8B, 0xF8, 0xD5, 0xF1, + 0x91, 0xF8, 0xD2, 0xF1, 0x96, 0xF8, 0xCF, 0xF1, 0x9C, 0xF8, + 0xCC, 0xF1, 0xA2, 0xF8, 0xC9, 0xF1, 0xA7, 0xF8, 0xC6, 0xF1, + 0xAD, 0xF8, 0xC4, 0xF1, 0xB2, 0xF8, 0xC1, 0xF1, 0xB8, 0xF8, + 0xBE, 0xF1, 0xBE, 0xF8, 0xBB, 0xF1, 0xC3, 0xF8, 0xB8, 0xF1, + 0xC9, 0xF8, 0xB5, 0xF1, 0xCE, 0xF8, 0xB3, 0xF1, 0xD4, 0xF8, + 0xB0, 0xF1, 0xDA, 0xF8, 0xAD, 0xF1, 0xDF, 0xF8, 0xAA, 0xF1, + 0xE5, 0xF8, 0xA7, 0xF1, 0xEB, 0xF8, 0xA5, 0xF1, 0xF0, 0xF8, + 0xA2, 0xF1, 0xF6, 0xF8, 0x9F, 0xF1, 0xFB, 0xF8, 0x9C, 0xF1, + 0x01, 0xF9, 0x9A, 0xF1, 0x07, 0xF9, 0x97, 0xF1, 0x0C, 0xF9, + 0x94, 0xF1, 0x12, 0xF9, 0x91, 0xF1, 0x18, 0xF9, 0x8F, 0xF1, + 0x1D, 0xF9, 0x8C, 0xF1, 0x23, 0xF9, 0x89, 0xF1, 0x29, 0xF9, + 0x87, 0xF1, 0x2E, 0xF9, 0x84, 0xF1, 0x34, 0xF9, 0x81, 0xF1, + 0x3A, 0xF9, 0x7F, 0xF1, 0x3F, 0xF9, 0x7C, 0xF1, 0x45, 0xF9, + 0x79, 0xF1, 0x4B, 0xF9, 0x77, 0xF1, 0x51, 0xF9, 0x74, 0xF1, + 0x56, 0xF9, 0x71, 0xF1, 0x5C, 0xF9, 0x6F, 0xF1, 0x62, 0xF9, + 0x6C, 0xF1, 0x67, 0xF9, 0x6A, 0xF1, 0x6D, 0xF9, 0x67, 0xF1, + 0x73, 0xF9, 0x65, 0xF1, 0x79, 0xF9, 0x62, 0xF1, 0x7E, 0xF9, + 0x5F, 0xF1, 0x84, 0xF9, 0x5D, 0xF1, 0x8A, 0xF9, 0x5A, 0xF1, + 0x90, 0xF9, 0x58, 0xF1, 0x95, 0xF9, 0x55, 0xF1, 0x9B, 0xF9, + 0x53, 0xF1, 0xA1, 0xF9, 0x50, 0xF1, 0xA7, 0xF9, 0x4E, 0xF1, + 0xAC, 0xF9, 0x4B, 0xF1, 0xB2, 0xF9, 0x49, 0xF1, 0xB8, 0xF9, + 0x46, 0xF1, 0xBE, 0xF9, 0x44, 0xF1, 0xC4, 0xF9, 0x41, 0xF1, + 0xC9, 0xF9, 0x3F, 0xF1, 0xCF, 0xF9, 0x3D, 0xF1, 0xD5, 0xF9, + 0x3A, 0xF1, 0xDB, 0xF9, 0x38, 0xF1, 0xE1, 0xF9, 0x35, 0xF1, + 0xE6, 0xF9, 0x33, 0xF1, 0xEC, 0xF9, 0x31, 0xF1, 0xF2, 0xF9, + 0x2E, 0xF1, 0xF8, 0xF9, 0x2C, 0xF1, 0xFE, 0xF9, 0x2A, 0xF1, + 0x03, 0xFA, 0x27, 0xF1, 0x09, 0xFA, 0x25, 0xF1, 0x0F, 0xFA, + 0x23, 0xF1, 0x15, 0xFA, 0x20, 0xF1, 0x1B, 0xFA, 0x1E, 0xF1, + 0x21, 0xFA, 0x1C, 0xF1, 0x26, 0xFA, 0x19, 0xF1, 0x2C, 0xFA, + 0x17, 0xF1, 0x32, 0xFA, 0x15, 0xF1, 0x38, 0xFA, 0x12, 0xF1, + 0x3E, 0xFA, 0x10, 0xF1, 0x44, 0xFA, 0x0E, 0xF1, 0x4A, 0xFA, + 0x0C, 0xF1, 0x4F, 0xFA, 0x09, 0xF1, 0x55, 0xFA, 0x07, 0xF1, + 0x5B, 0xFA, 0x05, 0xF1, 0x61, 0xFA, 0x03, 0xF1, 0x67, 0xFA, + 0x01, 0xF1, 0x6D, 0xFA, 0xFE, 0xF0, 0x73, 0xFA, 0xFC, 0xF0, + 0x79, 0xFA, 0xFA, 0xF0, 0x7F, 0xFA, 0xF8, 0xF0, 0x84, 0xFA, + 0xF6, 0xF0, 0x8A, 0xFA, 0xF4, 0xF0, 0x90, 0xFA, 0xF2, 0xF0, + 0x96, 0xFA, 0xEF, 0xF0, 0x9C, 0xFA, 0xED, 0xF0, 0xA2, 0xFA, + 0xEB, 0xF0, 0xA8, 0xFA, 0xE9, 0xF0, 0xAE, 0xFA, 0xE7, 0xF0, + 0xB4, 0xFA, 0xE5, 0xF0, 0xBA, 0xFA, 0xE3, 0xF0, 0xC0, 0xFA, + 0xE1, 0xF0, 0xC6, 0xFA, 0xDF, 0xF0, 0xCC, 0xFA, 0xDD, 0xF0, + 0xD1, 0xFA, 0xDB, 0xF0, 0xD7, 0xFA, 0xD9, 0xF0, 0xDD, 0xFA, + 0xD7, 0xF0, 0xE3, 0xFA, 0xD5, 0xF0, 0xE9, 0xFA, 0xD3, 0xF0, + 0xEF, 0xFA, 0xD1, 0xF0, 0xF5, 0xFA, 0xCF, 0xF0, 0xFB, 0xFA, + 0xCD, 0xF0, 0x01, 0xFB, 0xCB, 0xF0, 0x07, 0xFB, 0xC9, 0xF0, + 0x0D, 0xFB, 0xC7, 0xF0, 0x13, 0xFB, 0xC5, 0xF0, 0x19, 0xFB, + 0xC3, 0xF0, 0x1F, 0xFB, 0xC1, 0xF0, 0x25, 0xFB, 0xBF, 0xF0, + 0x2B, 0xFB, 0xBD, 0xF0, 0x31, 0xFB, 0xBB, 0xF0, 0x37, 0xFB, + 0xBA, 0xF0, 0x3D, 0xFB, 0xB8, 0xF0, 0x43, 0xFB, 0xB6, 0xF0, + 0x49, 0xFB, 0xB4, 0xF0, 0x4F, 0xFB, 0xB2, 0xF0, 0x55, 0xFB, + 0xB0, 0xF0, 0x5B, 0xFB, 0xAF, 0xF0, 0x61, 0xFB, 0xAD, 0xF0, + 0x67, 0xFB, 0xAB, 0xF0, 0x6D, 0xFB, 0xA9, 0xF0, 0x73, 0xFB, + 0xA7, 0xF0, 0x79, 0xFB, 0xA6, 0xF0, 0x7F, 0xFB, 0xA4, 0xF0, + 0x85, 0xFB, 0xA2, 0xF0, 0x8B, 0xFB, 0xA0, 0xF0, 0x91, 0xFB, + 0x9F, 0xF0, 0x97, 0xFB, 0x9D, 0xF0, 0x9D, 0xFB, 0x9B, 0xF0, + 0xA3, 0xFB, 0x99, 0xF0, 0xA9, 0xFB, 0x98, 0xF0, 0xAF, 0xFB, + 0x96, 0xF0, 0xB5, 0xFB, 0x94, 0xF0, 0xBC, 0xFB, 0x93, 0xF0, + 0xC2, 0xFB, 0x91, 0xF0, 0xC8, 0xFB, 0x8F, 0xF0, 0xCE, 0xFB, + 0x8E, 0xF0, 0xD4, 0xFB, 0x8C, 0xF0, 0xDA, 0xFB, 0x8A, 0xF0, + 0xE0, 0xFB, 0x89, 0xF0, 0xE6, 0xFB, 0x87, 0xF0, 0xEC, 0xFB, + 0x86, 0xF0, 0xF2, 0xFB, 0x84, 0xF0, 0xF8, 0xFB, 0x83, 0xF0, + 0xFE, 0xFB, 0x81, 0xF0, 0x04, 0xFC, 0x7F, 0xF0, 0x0A, 0xFC, + 0x7E, 0xF0, 0x11, 0xFC, 0x7C, 0xF0, 0x17, 0xFC, 0x7B, 0xF0, + 0x1D, 0xFC, 0x79, 0xF0, 0x23, 0xFC, 0x78, 0xF0, 0x29, 0xFC, + 0x76, 0xF0, 0x2F, 0xFC, 0x75, 0xF0, 0x35, 0xFC, 0x73, 0xF0, + 0x3B, 0xFC, 0x72, 0xF0, 0x41, 0xFC, 0x70, 0xF0, 0x47, 0xFC, + 0x6F, 0xF0, 0x4E, 0xFC, 0x6D, 0xF0, 0x54, 0xFC, 0x6C, 0xF0, + 0x5A, 0xFC, 0x6B, 0xF0, 0x60, 0xFC, 0x69, 0xF0, 0x66, 0xFC, + 0x68, 0xF0, 0x6C, 0xFC, 0x66, 0xF0, 0x72, 0xFC, 0x65, 0xF0, + 0x78, 0xFC, 0x64, 0xF0, 0x7F, 0xFC, 0x62, 0xF0, 0x85, 0xFC, + 0x61, 0xF0, 0x8B, 0xFC, 0x5F, 0xF0, 0x91, 0xFC, 0x5E, 0xF0, + 0x97, 0xFC, 0x5D, 0xF0, 0x9D, 0xFC, 0x5B, 0xF0, 0xA3, 0xFC, + 0x5A, 0xF0, 0xAA, 0xFC, 0x59, 0xF0, 0xB0, 0xFC, 0x58, 0xF0, + 0xB6, 0xFC, 0x56, 0xF0, 0xBC, 0xFC, 0x55, 0xF0, 0xC2, 0xFC, + 0x54, 0xF0, 0xC8, 0xFC, 0x52, 0xF0, 0xCE, 0xFC, 0x51, 0xF0, + 0xD5, 0xFC, 0x50, 0xF0, 0xDB, 0xFC, 0x4F, 0xF0, 0xE1, 0xFC, + 0x4D, 0xF0, 0xE7, 0xFC, 0x4C, 0xF0, 0xED, 0xFC, 0x4B, 0xF0, + 0xF3, 0xFC, 0x4A, 0xF0, 0xFA, 0xFC, 0x49, 0xF0, 0x00, 0xFD, + 0x48, 0xF0, 0x06, 0xFD, 0x46, 0xF0, 0x0C, 0xFD, 0x45, 0xF0, + 0x12, 0xFD, 0x44, 0xF0, 0x18, 0xFD, 0x43, 0xF0, 0x1F, 0xFD, + 0x42, 0xF0, 0x25, 0xFD, 0x41, 0xF0, 0x2B, 0xFD, 0x40, 0xF0, + 0x31, 0xFD, 0x3E, 0xF0, 0x37, 0xFD, 0x3D, 0xF0, 0x3E, 0xFD, + 0x3C, 0xF0, 0x44, 0xFD, 0x3B, 0xF0, 0x4A, 0xFD, 0x3A, 0xF0, + 0x50, 0xFD, 0x39, 0xF0, 0x56, 0xFD, 0x38, 0xF0, 0x5D, 0xFD, + 0x37, 0xF0, 0x63, 0xFD, 0x36, 0xF0, 0x69, 0xFD, 0x35, 0xF0, + 0x6F, 0xFD, 0x34, 0xF0, 0x75, 0xFD, 0x33, 0xF0, 0x7C, 0xFD, + 0x32, 0xF0, 0x82, 0xFD, 0x31, 0xF0, 0x88, 0xFD, 0x30, 0xF0, + 0x8E, 0xFD, 0x2F, 0xF0, 0x94, 0xFD, 0x2E, 0xF0, 0x9B, 0xFD, + 0x2D, 0xF0, 0xA1, 0xFD, 0x2C, 0xF0, 0xA7, 0xFD, 0x2B, 0xF0, + 0xAD, 0xFD, 0x2B, 0xF0, 0xB3, 0xFD, 0x2A, 0xF0, 0xBA, 0xFD, + 0x29, 0xF0, 0xC0, 0xFD, 0x28, 0xF0, 0xC6, 0xFD, 0x27, 0xF0, + 0xCC, 0xFD, 0x26, 0xF0, 0xD3, 0xFD, 0x25, 0xF0, 0xD9, 0xFD, + 0x24, 0xF0, 0xDF, 0xFD, 0x24, 0xF0, 0xE5, 0xFD, 0x23, 0xF0, + 0xEB, 0xFD, 0x22, 0xF0, 0xF2, 0xFD, 0x21, 0xF0, 0xF8, 0xFD, + 0x20, 0xF0, 0xFE, 0xFD, 0x20, 0xF0, 0x04, 0xFE, 0x1F, 0xF0, + 0x0B, 0xFE, 0x1E, 0xF0, 0x11, 0xFE, 0x1D, 0xF0, 0x17, 0xFE, + 0x1D, 0xF0, 0x1D, 0xFE, 0x1C, 0xF0, 0x24, 0xFE, 0x1B, 0xF0, + 0x2A, 0xFE, 0x1A, 0xF0, 0x30, 0xFE, 0x1A, 0xF0, 0x36, 0xFE, + 0x19, 0xF0, 0x3D, 0xFE, 0x18, 0xF0, 0x43, 0xFE, 0x18, 0xF0, + 0x49, 0xFE, 0x17, 0xF0, 0x4F, 0xFE, 0x16, 0xF0, 0x56, 0xFE, + 0x16, 0xF0, 0x5C, 0xFE, 0x15, 0xF0, 0x62, 0xFE, 0x14, 0xF0, + 0x68, 0xFE, 0x14, 0xF0, 0x6F, 0xFE, 0x13, 0xF0, 0x75, 0xFE, + 0x13, 0xF0, 0x7B, 0xFE, 0x12, 0xF0, 0x81, 0xFE, 0x11, 0xF0, + 0x88, 0xFE, 0x11, 0xF0, 0x8E, 0xFE, 0x10, 0xF0, 0x94, 0xFE, + 0x10, 0xF0, 0x9A, 0xFE, 0x0F, 0xF0, 0xA1, 0xFE, 0x0F, 0xF0, + 0xA7, 0xFE, 0x0E, 0xF0, 0xAD, 0xFE, 0x0E, 0xF0, 0xB3, 0xFE, + 0x0D, 0xF0, 0xBA, 0xFE, 0x0D, 0xF0, 0xC0, 0xFE, 0x0C, 0xF0, + 0xC6, 0xFE, 0x0C, 0xF0, 0xCC, 0xFE, 0x0B, 0xF0, 0xD3, 0xFE, + 0x0B, 0xF0, 0xD9, 0xFE, 0x0A, 0xF0, 0xDF, 0xFE, 0x0A, 0xF0, + 0xE5, 0xFE, 0x09, 0xF0, 0xEC, 0xFE, 0x09, 0xF0, 0xF2, 0xFE, + 0x08, 0xF0, 0xF8, 0xFE, 0x08, 0xF0, 0xFF, 0xFE, 0x08, 0xF0, + 0x05, 0xFF, 0x07, 0xF0, 0x0B, 0xFF, 0x07, 0xF0, 0x11, 0xFF, + 0x07, 0xF0, 0x18, 0xFF, 0x06, 0xF0, 0x1E, 0xFF, 0x06, 0xF0, + 0x24, 0xFF, 0x06, 0xF0, 0x2A, 0xFF, 0x05, 0xF0, 0x31, 0xFF, + 0x05, 0xF0, 0x37, 0xFF, 0x05, 0xF0, 0x3D, 0xFF, 0x04, 0xF0, + 0x44, 0xFF, 0x04, 0xF0, 0x4A, 0xFF, 0x04, 0xF0, 0x50, 0xFF, + 0x04, 0xF0, 0x56, 0xFF, 0x03, 0xF0, 0x5D, 0xFF, 0x03, 0xF0, + 0x63, 0xFF, 0x03, 0xF0, 0x69, 0xFF, 0x03, 0xF0, 0x70, 0xFF, + 0x02, 0xF0, 0x76, 0xFF, 0x02, 0xF0, 0x7C, 0xFF, 0x02, 0xF0, + 0x82, 0xFF, 0x02, 0xF0, 0x89, 0xFF, 0x02, 0xF0, 0x8F, 0xFF, + 0x01, 0xF0, 0x95, 0xFF, 0x01, 0xF0, 0x9B, 0xFF, 0x01, 0xF0, + 0xA2, 0xFF, 0x01, 0xF0, 0xA8, 0xFF, 0x01, 0xF0, 0xAE, 0xFF, + 0x01, 0xF0, 0xB5, 0xFF, 0x01, 0xF0, 0xBB, 0xFF, 0x00, 0xF0, + 0xC1, 0xFF, 0x00, 0xF0, 0xC7, 0xFF, 0x00, 0xF0, 0xCE, 0xFF, + 0x00, 0xF0, 0xD4, 0xFF, 0x00, 0xF0, 0xDA, 0xFF, 0x00, 0xF0, + 0xE1, 0xFF, 0x00, 0xF0, 0xE7, 0xFF, 0x00, 0xF0, 0xED, 0xFF, + 0x00, 0xF0, 0xF3, 0xFF, 0x00, 0xF0, 0xFA, 0xFF, 0x00, 0xF0, + 0x00, 0x00, 0x00, 0xF0, 0x06, 0x00, 0x00, 0xF0, 0x0D, 0x00, + 0x00, 0xF0, 0x13, 0x00, 0x00, 0xF0, 0x19, 0x00, 0x00, 0xF0, + 0x1F, 0x00, 0x00, 0xF0, 0x26, 0x00, 0x00, 0xF0, 0x2C, 0x00, + 0x00, 0xF0, 0x32, 0x00, 0x00, 0xF0, 0x39, 0x00, 0x00, 0xF0, + 0x3F, 0x00, 0x01, 0xF0, 0x45, 0x00, 0x01, 0xF0, 0x4B, 0x00, + 0x01, 0xF0, 0x52, 0x00, 0x01, 0xF0, 0x58, 0x00, 0x01, 0xF0, + 0x5E, 0x00, 0x01, 0xF0, 0x65, 0x00, 0x01, 0xF0, 0x6B, 0x00, + 0x02, 0xF0, 0x71, 0x00, 0x02, 0xF0, 0x77, 0x00, 0x02, 0xF0, + 0x7E, 0x00, 0x02, 0xF0, 0x84, 0x00, 0x02, 0xF0, 0x8A, 0x00, + 0x03, 0xF0, 0x90, 0x00, 0x03, 0xF0, 0x97, 0x00, 0x03, 0xF0, + 0x9D, 0x00, 0x03, 0xF0, 0xA3, 0x00, 0x04, 0xF0, 0xAA, 0x00, + 0x04, 0xF0, 0xB0, 0x00, 0x04, 0xF0, 0xB6, 0x00, 0x04, 0xF0, + 0xBC, 0x00, 0x05, 0xF0, 0xC3, 0x00, 0x05, 0xF0, 0xC9, 0x00, + 0x05, 0xF0, 0xCF, 0x00, 0x06, 0xF0, 0xD6, 0x00, 0x06, 0xF0, + 0xDC, 0x00, 0x06, 0xF0, 0xE2, 0x00, 0x07, 0xF0, 0xE8, 0x00, + 0x07, 0xF0, 0xEF, 0x00, 0x07, 0xF0, 0xF5, 0x00, 0x08, 0xF0, + 0xFB, 0x00, 0x08, 0xF0, 0x01, 0x01, 0x08, 0xF0, 0x08, 0x01, + 0x09, 0xF0, 0x0E, 0x01, 0x09, 0xF0, 0x14, 0x01, 0x0A, 0xF0, + 0x1B, 0x01, 0x0A, 0xF0, 0x21, 0x01, 0x0B, 0xF0, 0x27, 0x01, + 0x0B, 0xF0, 0x2D, 0x01, 0x0C, 0xF0, 0x34, 0x01, 0x0C, 0xF0, + 0x3A, 0x01, 0x0D, 0xF0, 0x40, 0x01, 0x0D, 0xF0, 0x46, 0x01, + 0x0E, 0xF0, 0x4D, 0x01, 0x0E, 0xF0, 0x53, 0x01, 0x0F, 0xF0, + 0x59, 0x01, 0x0F, 0xF0, 0x5F, 0x01, 0x10, 0xF0, 0x66, 0x01, + 0x10, 0xF0, 0x6C, 0x01, 0x11, 0xF0, 0x72, 0x01, 0x11, 0xF0, + 0x78, 0x01, 0x12, 0xF0, 0x7F, 0x01, 0x13, 0xF0, 0x85, 0x01, + 0x13, 0xF0, 0x8B, 0x01, 0x14, 0xF0, 0x91, 0x01, 0x14, 0xF0, + 0x98, 0x01, 0x15, 0xF0, 0x9E, 0x01, 0x16, 0xF0, 0xA4, 0x01, + 0x16, 0xF0, 0xAA, 0x01, 0x17, 0xF0, 0xB1, 0x01, 0x18, 0xF0, + 0xB7, 0x01, 0x18, 0xF0, 0xBD, 0x01, 0x19, 0xF0, 0xC3, 0x01, + 0x1A, 0xF0, 0xCA, 0x01, 0x1A, 0xF0, 0xD0, 0x01, 0x1B, 0xF0, + 0xD6, 0x01, 0x1C, 0xF0, 0xDC, 0x01, 0x1D, 0xF0, 0xE3, 0x01, + 0x1D, 0xF0, 0xE9, 0x01, 0x1E, 0xF0, 0xEF, 0x01, 0x1F, 0xF0, + 0xF5, 0x01, 0x20, 0xF0, 0xFC, 0x01, 0x20, 0xF0, 0x02, 0x02, + 0x21, 0xF0, 0x08, 0x02, 0x22, 0xF0, 0x0E, 0x02, 0x23, 0xF0, + 0x15, 0x02, 0x24, 0xF0, 0x1B, 0x02, 0x24, 0xF0, 0x21, 0x02, + 0x25, 0xF0, 0x27, 0x02, 0x26, 0xF0, 0x2D, 0x02, 0x27, 0xF0, + 0x34, 0x02, 0x28, 0xF0, 0x3A, 0x02, 0x29, 0xF0, 0x40, 0x02, + 0x2A, 0xF0, 0x46, 0x02, 0x2B, 0xF0, 0x4D, 0x02, 0x2B, 0xF0, + 0x53, 0x02, 0x2C, 0xF0, 0x59, 0x02, 0x2D, 0xF0, 0x5F, 0x02, + 0x2E, 0xF0, 0x65, 0x02, 0x2F, 0xF0, 0x6C, 0x02, 0x30, 0xF0, + 0x72, 0x02, 0x31, 0xF0, 0x78, 0x02, 0x32, 0xF0, 0x7E, 0x02, + 0x33, 0xF0, 0x84, 0x02, 0x34, 0xF0, 0x8B, 0x02, 0x35, 0xF0, + 0x91, 0x02, 0x36, 0xF0, 0x97, 0x02, 0x37, 0xF0, 0x9D, 0x02, + 0x38, 0xF0, 0xA3, 0x02, 0x39, 0xF0, 0xAA, 0x02, 0x3A, 0xF0, + 0xB0, 0x02, 0x3B, 0xF0, 0xB6, 0x02, 0x3C, 0xF0, 0xBC, 0x02, + 0x3D, 0xF0, 0xC2, 0x02, 0x3E, 0xF0, 0xC9, 0x02, 0x40, 0xF0, + 0xCF, 0x02, 0x41, 0xF0, 0xD5, 0x02, 0x42, 0xF0, 0xDB, 0x02, + 0x43, 0xF0, 0xE1, 0x02, 0x44, 0xF0, 0xE8, 0x02, 0x45, 0xF0, + 0xEE, 0x02, 0x46, 0xF0, 0xF4, 0x02, 0x48, 0xF0, 0xFA, 0x02, + 0x49, 0xF0, 0x00, 0x03, 0x4A, 0xF0, 0x06, 0x03, 0x4B, 0xF0, + 0x0D, 0x03, 0x4C, 0xF0, 0x13, 0x03, 0x4D, 0xF0, 0x19, 0x03, + 0x4F, 0xF0, 0x1F, 0x03, 0x50, 0xF0, 0x25, 0x03, 0x51, 0xF0, + 0x2B, 0x03, 0x52, 0xF0, 0x32, 0x03, 0x54, 0xF0, 0x38, 0x03, + 0x55, 0xF0, 0x3E, 0x03, 0x56, 0xF0, 0x44, 0x03, 0x58, 0xF0, + 0x4A, 0x03, 0x59, 0xF0, 0x50, 0x03, 0x5A, 0xF0, 0x56, 0x03, + 0x5B, 0xF0, 0x5D, 0x03, 0x5D, 0xF0, 0x63, 0x03, 0x5E, 0xF0, + 0x69, 0x03, 0x5F, 0xF0, 0x6F, 0x03, 0x61, 0xF0, 0x75, 0x03, + 0x62, 0xF0, 0x7B, 0x03, 0x64, 0xF0, 0x81, 0x03, 0x65, 0xF0, + 0x88, 0x03, 0x66, 0xF0, 0x8E, 0x03, 0x68, 0xF0, 0x94, 0x03, + 0x69, 0xF0, 0x9A, 0x03, 0x6B, 0xF0, 0xA0, 0x03, 0x6C, 0xF0, + 0xA6, 0x03, 0x6D, 0xF0, 0xAC, 0x03, 0x6F, 0xF0, 0xB2, 0x03, + 0x70, 0xF0, 0xB9, 0x03, 0x72, 0xF0, 0xBF, 0x03, 0x73, 0xF0, + 0xC5, 0x03, 0x75, 0xF0, 0xCB, 0x03, 0x76, 0xF0, 0xD1, 0x03, + 0x78, 0xF0, 0xD7, 0x03, 0x79, 0xF0, 0xDD, 0x03, 0x7B, 0xF0, + 0xE3, 0x03, 0x7C, 0xF0, 0xE9, 0x03, 0x7E, 0xF0, 0xEF, 0x03, + 0x7F, 0xF0, 0xF6, 0x03, 0x81, 0xF0, 0xFC, 0x03, 0x83, 0xF0, + 0x02, 0x04, 0x84, 0xF0, 0x08, 0x04, 0x86, 0xF0, 0x0E, 0x04, + 0x87, 0xF0, 0x14, 0x04, 0x89, 0xF0, 0x1A, 0x04, 0x8A, 0xF0, + 0x20, 0x04, 0x8C, 0xF0, 0x26, 0x04, 0x8E, 0xF0, 0x2C, 0x04, + 0x8F, 0xF0, 0x32, 0x04, 0x91, 0xF0, 0x38, 0x04, 0x93, 0xF0, + 0x3E, 0x04, 0x94, 0xF0, 0x44, 0x04, 0x96, 0xF0, 0x4B, 0x04, + 0x98, 0xF0, 0x51, 0x04, 0x99, 0xF0, 0x57, 0x04, 0x9B, 0xF0, + 0x5D, 0x04, 0x9D, 0xF0, 0x63, 0x04, 0x9F, 0xF0, 0x69, 0x04, + 0xA0, 0xF0, 0x6F, 0x04, 0xA2, 0xF0, 0x75, 0x04, 0xA4, 0xF0, + 0x7B, 0x04, 0xA6, 0xF0, 0x81, 0x04, 0xA7, 0xF0, 0x87, 0x04, + 0xA9, 0xF0, 0x8D, 0x04, 0xAB, 0xF0, 0x93, 0x04, 0xAD, 0xF0, + 0x99, 0x04, 0xAF, 0xF0, 0x9F, 0x04, 0xB0, 0xF0, 0xA5, 0x04, + 0xB2, 0xF0, 0xAB, 0x04, 0xB4, 0xF0, 0xB1, 0x04, 0xB6, 0xF0, + 0xB7, 0x04, 0xB8, 0xF0, 0xBD, 0x04, 0xBA, 0xF0, 0xC3, 0x04, + 0xBB, 0xF0, 0xC9, 0x04, 0xBD, 0xF0, 0xCF, 0x04, 0xBF, 0xF0, + 0xD5, 0x04, 0xC1, 0xF0, 0xDB, 0x04, 0xC3, 0xF0, 0xE1, 0x04, + 0xC5, 0xF0, 0xE7, 0x04, 0xC7, 0xF0, 0xED, 0x04, 0xC9, 0xF0, + 0xF3, 0x04, 0xCB, 0xF0, 0xF9, 0x04, 0xCD, 0xF0, 0xFF, 0x04, + 0xCF, 0xF0, 0x05, 0x05, 0xD1, 0xF0, 0x0B, 0x05, 0xD3, 0xF0, + 0x11, 0x05, 0xD5, 0xF0, 0x17, 0x05, 0xD7, 0xF0, 0x1D, 0x05, + 0xD9, 0xF0, 0x23, 0x05, 0xDB, 0xF0, 0x29, 0x05, 0xDD, 0xF0, + 0x2F, 0x05, 0xDF, 0xF0, 0x34, 0x05, 0xE1, 0xF0, 0x3A, 0x05, + 0xE3, 0xF0, 0x40, 0x05, 0xE5, 0xF0, 0x46, 0x05, 0xE7, 0xF0, + 0x4C, 0x05, 0xE9, 0xF0, 0x52, 0x05, 0xEB, 0xF0, 0x58, 0x05, + 0xED, 0xF0, 0x5E, 0x05, 0xEF, 0xF0, 0x64, 0x05, 0xF2, 0xF0, + 0x6A, 0x05, 0xF4, 0xF0, 0x70, 0x05, 0xF6, 0xF0, 0x76, 0x05, + 0xF8, 0xF0, 0x7C, 0x05, 0xFA, 0xF0, 0x81, 0x05, 0xFC, 0xF0, + 0x87, 0x05, 0xFE, 0xF0, 0x8D, 0x05, 0x01, 0xF1, 0x93, 0x05, + 0x03, 0xF1, 0x99, 0x05, 0x05, 0xF1, 0x9F, 0x05, 0x07, 0xF1, + 0xA5, 0x05, 0x09, 0xF1, 0xAB, 0x05, 0x0C, 0xF1, 0xB1, 0x05, + 0x0E, 0xF1, 0xB6, 0x05, 0x10, 0xF1, 0xBC, 0x05, 0x12, 0xF1, + 0xC2, 0x05, 0x15, 0xF1, 0xC8, 0x05, 0x17, 0xF1, 0xCE, 0x05, + 0x19, 0xF1, 0xD4, 0x05, 0x1C, 0xF1, 0xDA, 0x05, 0x1E, 0xF1, + 0xDF, 0x05, 0x20, 0xF1, 0xE5, 0x05, 0x23, 0xF1, 0xEB, 0x05, + 0x25, 0xF1, 0xF1, 0x05, 0x27, 0xF1, 0xF7, 0x05, 0x2A, 0xF1, + 0xFD, 0x05, 0x2C, 0xF1, 0x02, 0x06, 0x2E, 0xF1, 0x08, 0x06, + 0x31, 0xF1, 0x0E, 0x06, 0x33, 0xF1, 0x14, 0x06, 0x35, 0xF1, + 0x1A, 0x06, 0x38, 0xF1, 0x1F, 0x06, 0x3A, 0xF1, 0x25, 0x06, + 0x3D, 0xF1, 0x2B, 0x06, 0x3F, 0xF1, 0x31, 0x06, 0x41, 0xF1, + 0x37, 0x06, 0x44, 0xF1, 0x3C, 0x06, 0x46, 0xF1, 0x42, 0x06, + 0x49, 0xF1, 0x48, 0x06, 0x4B, 0xF1, 0x4E, 0x06, 0x4E, 0xF1, + 0x54, 0x06, 0x50, 0xF1, 0x59, 0x06, 0x53, 0xF1, 0x5F, 0x06, + 0x55, 0xF1, 0x65, 0x06, 0x58, 0xF1, 0x6B, 0x06, 0x5A, 0xF1, + 0x70, 0x06, 0x5D, 0xF1, 0x76, 0x06, 0x5F, 0xF1, 0x7C, 0x06, + 0x62, 0xF1, 0x82, 0x06, 0x65, 0xF1, 0x87, 0x06, 0x67, 0xF1, + 0x8D, 0x06, 0x6A, 0xF1, 0x93, 0x06, 0x6C, 0xF1, 0x99, 0x06, + 0x6F, 0xF1, 0x9E, 0x06, 0x71, 0xF1, 0xA4, 0x06, 0x74, 0xF1, + 0xAA, 0x06, 0x77, 0xF1, 0xAF, 0x06, 0x79, 0xF1, 0xB5, 0x06, + 0x7C, 0xF1, 0xBB, 0x06, 0x7F, 0xF1, 0xC1, 0x06, 0x81, 0xF1, + 0xC6, 0x06, 0x84, 0xF1, 0xCC, 0x06, 0x87, 0xF1, 0xD2, 0x06, + 0x89, 0xF1, 0xD7, 0x06, 0x8C, 0xF1, 0xDD, 0x06, 0x8F, 0xF1, + 0xE3, 0x06, 0x91, 0xF1, 0xE8, 0x06, 0x94, 0xF1, 0xEE, 0x06, + 0x97, 0xF1, 0xF4, 0x06, 0x9A, 0xF1, 0xF9, 0x06, 0x9C, 0xF1, + 0xFF, 0x06, 0x9F, 0xF1, 0x05, 0x07, 0xA2, 0xF1, 0x0A, 0x07, + 0xA5, 0xF1, 0x10, 0x07, 0xA7, 0xF1, 0x15, 0x07, 0xAA, 0xF1, + 0x1B, 0x07, 0xAD, 0xF1, 0x21, 0x07, 0xB0, 0xF1, 0x26, 0x07, + 0xB3, 0xF1, 0x2C, 0x07, 0xB5, 0xF1, 0x32, 0x07, 0xB8, 0xF1, + 0x37, 0x07, 0xBB, 0xF1, 0x3D, 0x07, 0xBE, 0xF1, 0x42, 0x07, + 0xC1, 0xF1, 0x48, 0x07, 0xC4, 0xF1, 0x4E, 0x07, 0xC6, 0xF1, + 0x53, 0x07, 0xC9, 0xF1, 0x59, 0x07, 0xCC, 0xF1, 0x5E, 0x07, + 0xCF, 0xF1, 0x64, 0x07, 0xD2, 0xF1, 0x6A, 0x07, 0xD5, 0xF1, + 0x6F, 0x07, 0xD8, 0xF1, 0x75, 0x07, 0xDB, 0xF1, 0x7A, 0x07, + 0xDE, 0xF1, 0x80, 0x07, 0xE1, 0xF1, 0x85, 0x07, 0xE4, 0xF1, + 0x8B, 0x07, 0xE7, 0xF1, 0x90, 0x07, 0xEA, 0xF1, 0x96, 0x07, + 0xED, 0xF1, 0x9B, 0x07, 0xF0, 0xF1, 0xA1, 0x07, 0xF3, 0xF1, + 0xA6, 0x07, 0xF6, 0xF1, 0xAC, 0x07, 0xF9, 0xF1, 0xB2, 0x07, + 0xFC, 0xF1, 0xB7, 0x07, 0xFF, 0xF1, 0xBD, 0x07, 0x02, 0xF2, + 0xC2, 0x07, 0x05, 0xF2, 0xC8, 0x07, 0x08, 0xF2, 0xCD, 0x07, + 0x0B, 0xF2, 0xD2, 0x07, 0x0E, 0xF2, 0xD8, 0x07, 0x11, 0xF2, + 0xDD, 0x07, 0x14, 0xF2, 0xE3, 0x07, 0x17, 0xF2, 0xE8, 0x07, + 0x1A, 0xF2, 0xEE, 0x07, 0x1D, 0xF2, 0xF3, 0x07, 0x21, 0xF2, + 0xF9, 0x07, 0x24, 0xF2, 0xFE, 0x07, 0x27, 0xF2, 0x04, 0x08, + 0x2A, 0xF2, 0x09, 0x08, 0x2D, 0xF2, 0x0E, 0x08, 0x30, 0xF2, + 0x14, 0x08, 0x34, 0xF2, 0x19, 0x08, 0x37, 0xF2, 0x1F, 0x08, + 0x3A, 0xF2, 0x24, 0x08, 0x3D, 0xF2, 0x2A, 0x08, 0x40, 0xF2, + 0x2F, 0x08, 0x44, 0xF2, 0x34, 0x08, 0x47, 0xF2, 0x3A, 0x08, + 0x4A, 0xF2, 0x3F, 0x08, 0x4D, 0xF2, 0x45, 0x08, 0x50, 0xF2, + 0x4A, 0x08, 0x54, 0xF2, 0x4F, 0x08, 0x57, 0xF2, 0x55, 0x08, + 0x5A, 0xF2, 0x5A, 0x08, 0x5E, 0xF2, 0x5F, 0x08, 0x61, 0xF2, + 0x65, 0x08, 0x64, 0xF2, 0x6A, 0x08, 0x67, 0xF2, 0x6F, 0x08, + 0x6B, 0xF2, 0x75, 0x08, 0x6E, 0xF2, 0x7A, 0x08, 0x71, 0xF2, + 0x7F, 0x08, 0x75, 0xF2, 0x85, 0x08, 0x78, 0xF2, 0x8A, 0x08, + 0x7B, 0xF2, 0x8F, 0x08, 0x7F, 0xF2, 0x95, 0x08, 0x82, 0xF2, + 0x9A, 0x08, 0x86, 0xF2, 0x9F, 0x08, 0x89, 0xF2, 0xA5, 0x08, + 0x8C, 0xF2, 0xAA, 0x08, 0x90, 0xF2, 0xAF, 0x08, 0x93, 0xF2, + 0xB4, 0x08, 0x97, 0xF2, 0xBA, 0x08, 0x9A, 0xF2, 0xBF, 0x08, + 0x9E, 0xF2, 0xC4, 0x08, 0xA1, 0xF2, 0xC9, 0x08, 0xA4, 0xF2, + 0xCF, 0x08, 0xA8, 0xF2, 0xD4, 0x08, 0xAB, 0xF2, 0xD9, 0x08, + 0xAF, 0xF2, 0xDE, 0x08, 0xB2, 0xF2, 0xE4, 0x08, 0xB6, 0xF2, + 0xE9, 0x08, 0xB9, 0xF2, 0xEE, 0x08, 0xBD, 0xF2, 0xF3, 0x08, + 0xC0, 0xF2, 0xF8, 0x08, 0xC4, 0xF2, 0xFE, 0x08, 0xC7, 0xF2, + 0x03, 0x09, 0xCB, 0xF2, 0x08, 0x09, 0xCE, 0xF2, 0x0D, 0x09, + 0xD2, 0xF2, 0x12, 0x09, 0xD6, 0xF2, 0x18, 0x09, 0xD9, 0xF2, + 0x1D, 0x09, 0xDD, 0xF2, 0x22, 0x09, 0xE0, 0xF2, 0x27, 0x09, + 0xE4, 0xF2, 0x2C, 0x09, 0xE8, 0xF2, 0x31, 0x09, 0xEB, 0xF2, + 0x37, 0x09, 0xEF, 0xF2, 0x3C, 0x09, 0xF2, 0xF2, 0x41, 0x09, + 0xF6, 0xF2, 0x46, 0x09, 0xFA, 0xF2, 0x4B, 0x09, 0xFD, 0xF2, + 0x50, 0x09, 0x01, 0xF3, 0x55, 0x09, 0x05, 0xF3, 0x5A, 0x09, + 0x08, 0xF3, 0x5F, 0x09, 0x0C, 0xF3, 0x65, 0x09, 0x10, 0xF3, + 0x6A, 0x09, 0x13, 0xF3, 0x6F, 0x09, 0x17, 0xF3, 0x74, 0x09, + 0x1B, 0xF3, 0x79, 0x09, 0x1F, 0xF3, 0x7E, 0x09, 0x22, 0xF3, + 0x83, 0x09, 0x26, 0xF3, 0x88, 0x09, 0x2A, 0xF3, 0x8D, 0x09, + 0x2E, 0xF3, 0x92, 0x09, 0x31, 0xF3, 0x97, 0x09, 0x35, 0xF3, + 0x9C, 0x09, 0x39, 0xF3, 0xA1, 0x09, 0x3D, 0xF3, 0xA6, 0x09, + 0x40, 0xF3, 0xAB, 0x09, 0x44, 0xF3, 0xB0, 0x09, 0x48, 0xF3, + 0xB5, 0x09, 0x4C, 0xF3, 0xBA, 0x09, 0x50, 0xF3, 0xBF, 0x09, + 0x54, 0xF3, 0xC4, 0x09, 0x57, 0xF3, 0xC9, 0x09, 0x5B, 0xF3, + 0xCE, 0x09, 0x5F, 0xF3, 0xD3, 0x09, 0x63, 0xF3, 0xD8, 0x09, + 0x67, 0xF3, 0xDD, 0x09, 0x6B, 0xF3, 0xE2, 0x09, 0x6F, 0xF3, + 0xE7, 0x09, 0x72, 0xF3, 0xEC, 0x09, 0x76, 0xF3, 0xF1, 0x09, + 0x7A, 0xF3, 0xF6, 0x09, 0x7E, 0xF3, 0xFB, 0x09, 0x82, 0xF3, + 0xFF, 0x09, 0x86, 0xF3, 0x04, 0x0A, 0x8A, 0xF3, 0x09, 0x0A, + 0x8E, 0xF3, 0x0E, 0x0A, 0x92, 0xF3, 0x13, 0x0A, 0x96, 0xF3, + 0x18, 0x0A, 0x9A, 0xF3, 0x1D, 0x0A, 0x9E, 0xF3, 0x22, 0x0A, + 0xA2, 0xF3, 0x26, 0x0A, 0xA6, 0xF3, 0x2B, 0x0A, 0xAA, 0xF3, + 0x30, 0x0A, 0xAE, 0xF3, 0x35, 0x0A, 0xB2, 0xF3, 0x3A, 0x0A, + 0xB6, 0xF3, 0x3F, 0x0A, 0xBA, 0xF3, 0x44, 0x0A, 0xBE, 0xF3, + 0x48, 0x0A, 0xC2, 0xF3, 0x4D, 0x0A, 0xC6, 0xF3, 0x52, 0x0A, + 0xCA, 0xF3, 0x57, 0x0A, 0xCE, 0xF3, 0x5C, 0x0A, 0xD2, 0xF3, + 0x60, 0x0A, 0xD6, 0xF3, 0x65, 0x0A, 0xDA, 0xF3, 0x6A, 0x0A, + 0xDE, 0xF3, 0x6F, 0x0A, 0xE2, 0xF3, 0x73, 0x0A, 0xE7, 0xF3, + 0x78, 0x0A, 0xEB, 0xF3, 0x7D, 0x0A, 0xEF, 0xF3, 0x82, 0x0A, + 0xF3, 0xF3, 0x86, 0x0A, 0xF7, 0xF3, 0x8B, 0x0A, 0xFB, 0xF3, + 0x90, 0x0A, 0xFF, 0xF3, 0x95, 0x0A, 0x04, 0xF4, 0x99, 0x0A, + 0x08, 0xF4, 0x9E, 0x0A, 0x0C, 0xF4, 0xA3, 0x0A, 0x10, 0xF4, + 0xA7, 0x0A, 0x14, 0xF4, 0xAC, 0x0A, 0x18, 0xF4, 0xB1, 0x0A, + 0x1D, 0xF4, 0xB5, 0x0A, 0x21, 0xF4, 0xBA, 0x0A, 0x25, 0xF4, + 0xBF, 0x0A, 0x29, 0xF4, 0xC3, 0x0A, 0x2E, 0xF4, 0xC8, 0x0A, + 0x32, 0xF4, 0xCD, 0x0A, 0x36, 0xF4, 0xD1, 0x0A, 0x3A, 0xF4, + 0xD6, 0x0A, 0x3F, 0xF4, 0xDB, 0x0A, 0x43, 0xF4, 0xDF, 0x0A, + 0x47, 0xF4, 0xE4, 0x0A, 0x4B, 0xF4, 0xE8, 0x0A, 0x50, 0xF4, + 0xED, 0x0A, 0x54, 0xF4, 0xF2, 0x0A, 0x58, 0xF4, 0xF6, 0x0A, + 0x5D, 0xF4, 0xFB, 0x0A, 0x61, 0xF4, 0xFF, 0x0A, 0x65, 0xF4, + 0x04, 0x0B, 0x69, 0xF4, 0x08, 0x0B, 0x6E, 0xF4, 0x0D, 0x0B, + 0x72, 0xF4, 0x11, 0x0B, 0x77, 0xF4, 0x16, 0x0B, 0x7B, 0xF4, + 0x1B, 0x0B, 0x7F, 0xF4, 0x1F, 0x0B, 0x84, 0xF4, 0x24, 0x0B, + 0x88, 0xF4, 0x28, 0x0B, 0x8C, 0xF4, 0x2D, 0x0B, 0x91, 0xF4, + 0x31, 0x0B, 0x95, 0xF4, 0x36, 0x0B, 0x9A, 0xF4, 0x3A, 0x0B, + 0x9E, 0xF4, 0x3E, 0x0B, 0xA2, 0xF4, 0x43, 0x0B, 0xA7, 0xF4, + 0x47, 0x0B, 0xAB, 0xF4, 0x4C, 0x0B, 0xB0, 0xF4, 0x50, 0x0B, + 0xB4, 0xF4, 0x55, 0x0B, 0xB9, 0xF4, 0x59, 0x0B, 0xBD, 0xF4, + 0x5E, 0x0B, 0xC2, 0xF4, 0x62, 0x0B, 0xC6, 0xF4, 0x66, 0x0B, + 0xCA, 0xF4, 0x6B, 0x0B, 0xCF, 0xF4, 0x6F, 0x0B, 0xD3, 0xF4, + 0x74, 0x0B, 0xD8, 0xF4, 0x78, 0x0B, 0xDC, 0xF4, 0x7C, 0x0B, + 0xE1, 0xF4, 0x81, 0x0B, 0xE5, 0xF4, 0x85, 0x0B, 0xEA, 0xF4, + 0x89, 0x0B, 0xEF, 0xF4, 0x8E, 0x0B, 0xF3, 0xF4, 0x92, 0x0B, + 0xF8, 0xF4, 0x97, 0x0B, 0xFC, 0xF4, 0x9B, 0x0B, 0x01, 0xF5, + 0x9F, 0x0B, 0x05, 0xF5, 0xA3, 0x0B, 0x0A, 0xF5, 0xA8, 0x0B, + 0x0E, 0xF5, 0xAC, 0x0B, 0x13, 0xF5, 0xB0, 0x0B, 0x18, 0xF5, + 0xB5, 0x0B, 0x1C, 0xF5, 0xB9, 0x0B, 0x21, 0xF5, 0xBD, 0x0B, + 0x25, 0xF5, 0xC1, 0x0B, 0x2A, 0xF5, 0xC6, 0x0B, 0x2F, 0xF5, + 0xCA, 0x0B, 0x33, 0xF5, 0xCE, 0x0B, 0x38, 0xF5, 0xD2, 0x0B, + 0x3D, 0xF5, 0xD7, 0x0B, 0x41, 0xF5, 0xDB, 0x0B, 0x46, 0xF5, + 0xDF, 0x0B, 0x4B, 0xF5, 0xE3, 0x0B, 0x4F, 0xF5, 0xE8, 0x0B, + 0x54, 0xF5, 0xEC, 0x0B, 0x59, 0xF5, 0xF0, 0x0B, 0x5D, 0xF5, + 0xF4, 0x0B, 0x62, 0xF5, 0xF8, 0x0B, 0x67, 0xF5, 0xFC, 0x0B, + 0x6B, 0xF5, 0x01, 0x0C, 0x70, 0xF5, 0x05, 0x0C, 0x75, 0xF5, + 0x09, 0x0C, 0x7A, 0xF5, 0x0D, 0x0C, 0x7E, 0xF5, 0x11, 0x0C, + 0x83, 0xF5, 0x15, 0x0C, 0x88, 0xF5, 0x19, 0x0C, 0x8D, 0xF5, + 0x1E, 0x0C, 0x91, 0xF5, 0x22, 0x0C, 0x96, 0xF5, 0x26, 0x0C, + 0x9B, 0xF5, 0x2A, 0x0C, 0xA0, 0xF5, 0x2E, 0x0C, 0xA4, 0xF5, + 0x32, 0x0C, 0xA9, 0xF5, 0x36, 0x0C, 0xAE, 0xF5, 0x3A, 0x0C, + 0xB3, 0xF5, 0x3E, 0x0C, 0xB8, 0xF5, 0x42, 0x0C, 0xBC, 0xF5, + 0x46, 0x0C, 0xC1, 0xF5, 0x4A, 0x0C, 0xC6, 0xF5, 0x4E, 0x0C, + 0xCB, 0xF5, 0x52, 0x0C, 0xD0, 0xF5, 0x56, 0x0C, 0xD5, 0xF5, + 0x5A, 0x0C, 0xDA, 0xF5, 0x5E, 0x0C, 0xDE, 0xF5, 0x62, 0x0C, + 0xE3, 0xF5, 0x66, 0x0C, 0xE8, 0xF5, 0x6A, 0x0C, 0xED, 0xF5, + 0x6E, 0x0C, 0xF2, 0xF5, 0x72, 0x0C, 0xF7, 0xF5, 0x76, 0x0C, + 0xFC, 0xF5, 0x7A, 0x0C, 0x01, 0xF6, 0x7E, 0x0C, 0x05, 0xF6, + 0x82, 0x0C, 0x0A, 0xF6, 0x86, 0x0C, 0x0F, 0xF6, 0x8A, 0x0C, + 0x14, 0xF6, 0x8E, 0x0C, 0x19, 0xF6, 0x91, 0x0C, 0x1E, 0xF6, + 0x95, 0x0C, 0x23, 0xF6, 0x99, 0x0C, 0x28, 0xF6, 0x9D, 0x0C, + 0x2D, 0xF6, 0xA1, 0x0C, 0x32, 0xF6, 0xA5, 0x0C, 0x37, 0xF6, + 0xA9, 0x0C, 0x3C, 0xF6, 0xAC, 0x0C, 0x41, 0xF6, 0xB0, 0x0C, + 0x46, 0xF6, 0xB4, 0x0C, 0x4B, 0xF6, 0xB8, 0x0C, 0x50, 0xF6, + 0xBC, 0x0C, 0x55, 0xF6, 0xC0, 0x0C, 0x5A, 0xF6, 0xC3, 0x0C, + 0x5F, 0xF6, 0xC7, 0x0C, 0x64, 0xF6, 0xCB, 0x0C, 0x69, 0xF6, + 0xCF, 0x0C, 0x6E, 0xF6, 0xD2, 0x0C, 0x73, 0xF6, 0xD6, 0x0C, + 0x78, 0xF6, 0xDA, 0x0C, 0x7D, 0xF6, 0xDE, 0x0C, 0x82, 0xF6, + 0xE1, 0x0C, 0x87, 0xF6, 0xE5, 0x0C, 0x8C, 0xF6, 0xE9, 0x0C, + 0x91, 0xF6, 0xED, 0x0C, 0x96, 0xF6, 0xF0, 0x0C, 0x9B, 0xF6, + 0xF4, 0x0C, 0xA1, 0xF6, 0xF8, 0x0C, 0xA6, 0xF6, 0xFB, 0x0C, + 0xAB, 0xF6, 0xFF, 0x0C, 0xB0, 0xF6, 0x03, 0x0D, 0xB5, 0xF6, + 0x06, 0x0D, 0xBA, 0xF6, 0x0A, 0x0D, 0xBF, 0xF6, 0x0E, 0x0D, + 0xC4, 0xF6, 0x11, 0x0D, 0xC9, 0xF6, 0x15, 0x0D, 0xCF, 0xF6, + 0x18, 0x0D, 0xD4, 0xF6, 0x1C, 0x0D, 0xD9, 0xF6, 0x20, 0x0D, + 0xDE, 0xF6, 0x23, 0x0D, 0xE3, 0xF6, 0x27, 0x0D, 0xE8, 0xF6, + 0x2A, 0x0D, 0xEE, 0xF6, 0x2E, 0x0D, 0xF3, 0xF6, 0x32, 0x0D, + 0xF8, 0xF6, 0x35, 0x0D, 0xFD, 0xF6, 0x39, 0x0D, 0x02, 0xF7, + 0x3C, 0x0D, 0x08, 0xF7, 0x40, 0x0D, 0x0D, 0xF7, 0x43, 0x0D, + 0x12, 0xF7, 0x47, 0x0D, 0x17, 0xF7, 0x4A, 0x0D, 0x1C, 0xF7, + 0x4E, 0x0D, 0x22, 0xF7, 0x51, 0x0D, 0x27, 0xF7, 0x55, 0x0D, + 0x2C, 0xF7, 0x58, 0x0D, 0x31, 0xF7, 0x5C, 0x0D, 0x37, 0xF7, + 0x5F, 0x0D, 0x3C, 0xF7, 0x62, 0x0D, 0x41, 0xF7, 0x66, 0x0D, + 0x46, 0xF7, 0x69, 0x0D, 0x4C, 0xF7, 0x6D, 0x0D, 0x51, 0xF7, + 0x70, 0x0D, 0x56, 0xF7, 0x74, 0x0D, 0x5B, 0xF7, 0x77, 0x0D, + 0x61, 0xF7, 0x7A, 0x0D, 0x66, 0xF7, 0x7E, 0x0D, 0x6B, 0xF7, + 0x81, 0x0D, 0x71, 0xF7, 0x85, 0x0D, 0x76, 0xF7, 0x88, 0x0D, + 0x7B, 0xF7, 0x8B, 0x0D, 0x81, 0xF7, 0x8F, 0x0D, 0x86, 0xF7, + 0x92, 0x0D, 0x8B, 0xF7, 0x95, 0x0D, 0x91, 0xF7, 0x99, 0x0D, + 0x96, 0xF7, 0x9C, 0x0D, 0x9B, 0xF7, 0x9F, 0x0D, 0xA1, 0xF7, + 0xA2, 0x0D, 0xA6, 0xF7, 0xA6, 0x0D, 0xAB, 0xF7, 0xA9, 0x0D, + 0xB1, 0xF7, 0xAC, 0x0D, 0xB6, 0xF7, 0xB0, 0x0D, 0xBB, 0xF7, + 0xB3, 0x0D, 0xC1, 0xF7, 0xB6, 0x0D, 0xC6, 0xF7, 0xB9, 0x0D, + 0xCC, 0xF7, 0xBC, 0x0D, 0xD1, 0xF7, 0xC0, 0x0D, 0xD6, 0xF7, + 0xC3, 0x0D, 0xDC, 0xF7, 0xC6, 0x0D, 0xE1, 0xF7, 0xC9, 0x0D, + 0xE7, 0xF7, 0xCC, 0x0D, 0xEC, 0xF7, 0xD0, 0x0D, 0xF2, 0xF7, + 0xD3, 0x0D, 0xF7, 0xF7, 0xD6, 0x0D, 0xFC, 0xF7, 0xD9, 0x0D, + 0x02, 0xF8, 0xDC, 0x0D, 0x07, 0xF8, 0xDF, 0x0D, 0x0D, 0xF8, + 0xE3, 0x0D, 0x12, 0xF8, 0xE6, 0x0D, 0x18, 0xF8, 0xE9, 0x0D, + 0x1D, 0xF8, 0xEC, 0x0D, 0x23, 0xF8, 0xEF, 0x0D, 0x28, 0xF8, + 0xF2, 0x0D, 0x2E, 0xF8, 0xF5, 0x0D, 0x33, 0xF8, 0xF8, 0x0D, + 0x38, 0xF8, 0xFB, 0x0D, 0x3E, 0xF8, 0xFE, 0x0D, 0x43, 0xF8, + 0x01, 0x0E, 0x49, 0xF8, 0x04, 0x0E, 0x4E, 0xF8, 0x07, 0x0E, + 0x54, 0xF8, 0x0A, 0x0E, 0x5A, 0xF8, 0x0D, 0x0E, 0x5F, 0xF8, + 0x10, 0x0E, 0x65, 0xF8, 0x13, 0x0E, 0x6A, 0xF8, 0x16, 0x0E, + 0x70, 0xF8, 0x19, 0x0E, 0x75, 0xF8, 0x1C, 0x0E, 0x7B, 0xF8, + 0x1F, 0x0E, 0x80, 0xF8, 0x22, 0x0E, 0x86, 0xF8, 0x25, 0x0E, + 0x8B, 0xF8, 0x28, 0x0E, 0x91, 0xF8, 0x2B, 0x0E, 0x96, 0xF8, + 0x2E, 0x0E, 0x9C, 0xF8, 0x31, 0x0E, 0xA2, 0xF8, 0x34, 0x0E, + 0xA7, 0xF8, 0x37, 0x0E, 0xAD, 0xF8, 0x3A, 0x0E, 0xB2, 0xF8, + 0x3C, 0x0E, 0xB8, 0xF8, 0x3F, 0x0E, 0xBE, 0xF8, 0x42, 0x0E, + 0xC3, 0xF8, 0x45, 0x0E, 0xC9, 0xF8, 0x48, 0x0E, 0xCE, 0xF8, + 0x4B, 0x0E, 0xD4, 0xF8, 0x4D, 0x0E, 0xDA, 0xF8, 0x50, 0x0E, + 0xDF, 0xF8, 0x53, 0x0E, 0xE5, 0xF8, 0x56, 0x0E, 0xEB, 0xF8, + 0x59, 0x0E, 0xF0, 0xF8, 0x5B, 0x0E, 0xF6, 0xF8, 0x5E, 0x0E, + 0xFB, 0xF8, 0x61, 0x0E, 0x01, 0xF9, 0x64, 0x0E, 0x07, 0xF9, + 0x66, 0x0E, 0x0C, 0xF9, 0x69, 0x0E, 0x12, 0xF9, 0x6C, 0x0E, + 0x18, 0xF9, 0x6F, 0x0E, 0x1D, 0xF9, 0x71, 0x0E, 0x23, 0xF9, + 0x74, 0x0E, 0x29, 0xF9, 0x77, 0x0E, 0x2E, 0xF9, 0x79, 0x0E, + 0x34, 0xF9, 0x7C, 0x0E, 0x3A, 0xF9, 0x7F, 0x0E, 0x3F, 0xF9, + 0x81, 0x0E, 0x45, 0xF9, 0x84, 0x0E, 0x4B, 0xF9, 0x87, 0x0E, + 0x51, 0xF9, 0x89, 0x0E, 0x56, 0xF9, 0x8C, 0x0E, 0x5C, 0xF9, + 0x8F, 0x0E, 0x62, 0xF9, 0x91, 0x0E, 0x67, 0xF9, 0x94, 0x0E, + 0x6D, 0xF9, 0x96, 0x0E, 0x73, 0xF9, 0x99, 0x0E, 0x79, 0xF9, + 0x9B, 0x0E, 0x7E, 0xF9, 0x9E, 0x0E, 0x84, 0xF9, 0xA1, 0x0E, + 0x8A, 0xF9, 0xA3, 0x0E, 0x90, 0xF9, 0xA6, 0x0E, 0x95, 0xF9, + 0xA8, 0x0E, 0x9B, 0xF9, 0xAB, 0x0E, 0xA1, 0xF9, 0xAD, 0x0E, + 0xA7, 0xF9, 0xB0, 0x0E, 0xAC, 0xF9, 0xB2, 0x0E, 0xB2, 0xF9, + 0xB5, 0x0E, 0xB8, 0xF9, 0xB7, 0x0E, 0xBE, 0xF9, 0xBA, 0x0E, + 0xC4, 0xF9, 0xBC, 0x0E, 0xC9, 0xF9, 0xBF, 0x0E, 0xCF, 0xF9, + 0xC1, 0x0E, 0xD5, 0xF9, 0xC3, 0x0E, 0xDB, 0xF9, 0xC6, 0x0E, + 0xE1, 0xF9, 0xC8, 0x0E, 0xE6, 0xF9, 0xCB, 0x0E, 0xEC, 0xF9, + 0xCD, 0x0E, 0xF2, 0xF9, 0xCF, 0x0E, 0xF8, 0xF9, 0xD2, 0x0E, + 0xFE, 0xF9, 0xD4, 0x0E, 0x03, 0xFA, 0xD6, 0x0E, 0x09, 0xFA, + 0xD9, 0x0E, 0x0F, 0xFA, 0xDB, 0x0E, 0x15, 0xFA, 0xDD, 0x0E, + 0x1B, 0xFA, 0xE0, 0x0E, 0x21, 0xFA, 0xE2, 0x0E, 0x26, 0xFA, + 0xE4, 0x0E, 0x2C, 0xFA, 0xE7, 0x0E, 0x32, 0xFA, 0xE9, 0x0E, + 0x38, 0xFA, 0xEB, 0x0E, 0x3E, 0xFA, 0xEE, 0x0E, 0x44, 0xFA, + 0xF0, 0x0E, 0x4A, 0xFA, 0xF2, 0x0E, 0x4F, 0xFA, 0xF4, 0x0E, + 0x55, 0xFA, 0xF7, 0x0E, 0x5B, 0xFA, 0xF9, 0x0E, 0x61, 0xFA, + 0xFB, 0x0E, 0x67, 0xFA, 0xFD, 0x0E, 0x6D, 0xFA, 0xFF, 0x0E, + 0x73, 0xFA, 0x02, 0x0F, 0x79, 0xFA, 0x04, 0x0F, 0x7F, 0xFA, + 0x06, 0x0F, 0x84, 0xFA, 0x08, 0x0F, 0x8A, 0xFA, 0x0A, 0x0F, + 0x90, 0xFA, 0x0C, 0x0F, 0x96, 0xFA, 0x0E, 0x0F, 0x9C, 0xFA, + 0x11, 0x0F, 0xA2, 0xFA, 0x13, 0x0F, 0xA8, 0xFA, 0x15, 0x0F, + 0xAE, 0xFA, 0x17, 0x0F, 0xB4, 0xFA, 0x19, 0x0F, 0xBA, 0xFA, + 0x1B, 0x0F, 0xC0, 0xFA, 0x1D, 0x0F, 0xC6, 0xFA, 0x1F, 0x0F, + 0xCC, 0xFA, 0x21, 0x0F, 0xD1, 0xFA, 0x23, 0x0F, 0xD7, 0xFA, + 0x25, 0x0F, 0xDD, 0xFA, 0x27, 0x0F, 0xE3, 0xFA, 0x29, 0x0F, + 0xE9, 0xFA, 0x2B, 0x0F, 0xEF, 0xFA, 0x2D, 0x0F, 0xF5, 0xFA, + 0x2F, 0x0F, 0xFB, 0xFA, 0x31, 0x0F, 0x01, 0xFB, 0x33, 0x0F, + 0x07, 0xFB, 0x35, 0x0F, 0x0D, 0xFB, 0x37, 0x0F, 0x13, 0xFB, + 0x39, 0x0F, 0x19, 0xFB, 0x3B, 0x0F, 0x1F, 0xFB, 0x3D, 0x0F, + 0x25, 0xFB, 0x3F, 0x0F, 0x2B, 0xFB, 0x41, 0x0F, 0x31, 0xFB, + 0x43, 0x0F, 0x37, 0xFB, 0x45, 0x0F, 0x3D, 0xFB, 0x46, 0x0F, + 0x43, 0xFB, 0x48, 0x0F, 0x49, 0xFB, 0x4A, 0x0F, 0x4F, 0xFB, + 0x4C, 0x0F, 0x55, 0xFB, 0x4E, 0x0F, 0x5B, 0xFB, 0x50, 0x0F, + 0x61, 0xFB, 0x51, 0x0F, 0x67, 0xFB, 0x53, 0x0F, 0x6D, 0xFB, + 0x55, 0x0F, 0x73, 0xFB, 0x57, 0x0F, 0x79, 0xFB, 0x59, 0x0F, + 0x7F, 0xFB, 0x5A, 0x0F, 0x85, 0xFB, 0x5C, 0x0F, 0x8B, 0xFB, + 0x5E, 0x0F, 0x91, 0xFB, 0x60, 0x0F, 0x97, 0xFB, 0x61, 0x0F, + 0x9D, 0xFB, 0x63, 0x0F, 0xA3, 0xFB, 0x65, 0x0F, 0xA9, 0xFB, + 0x67, 0x0F, 0xAF, 0xFB, 0x68, 0x0F, 0xB5, 0xFB, 0x6A, 0x0F, + 0xBC, 0xFB, 0x6C, 0x0F, 0xC2, 0xFB, 0x6D, 0x0F, 0xC8, 0xFB, + 0x6F, 0x0F, 0xCE, 0xFB, 0x71, 0x0F, 0xD4, 0xFB, 0x72, 0x0F, + 0xDA, 0xFB, 0x74, 0x0F, 0xE0, 0xFB, 0x76, 0x0F, 0xE6, 0xFB, + 0x77, 0x0F, 0xEC, 0xFB, 0x79, 0x0F, 0xF2, 0xFB, 0x7A, 0x0F, + 0xF8, 0xFB, 0x7C, 0x0F, 0xFE, 0xFB, 0x7D, 0x0F, 0x04, 0xFC, + 0x7F, 0x0F, 0x0A, 0xFC, 0x81, 0x0F, 0x11, 0xFC, 0x82, 0x0F, + 0x17, 0xFC, 0x84, 0x0F, 0x1D, 0xFC, 0x85, 0x0F, 0x23, 0xFC, + 0x87, 0x0F, 0x29, 0xFC, 0x88, 0x0F, 0x2F, 0xFC, 0x8A, 0x0F, + 0x35, 0xFC, 0x8B, 0x0F, 0x3B, 0xFC, 0x8D, 0x0F, 0x41, 0xFC, + 0x8E, 0x0F, 0x47, 0xFC, 0x90, 0x0F, 0x4E, 0xFC, 0x91, 0x0F, + 0x54, 0xFC, 0x93, 0x0F, 0x5A, 0xFC, 0x94, 0x0F, 0x60, 0xFC, + 0x95, 0x0F, 0x66, 0xFC, 0x97, 0x0F, 0x6C, 0xFC, 0x98, 0x0F, + 0x72, 0xFC, 0x9A, 0x0F, 0x78, 0xFC, 0x9B, 0x0F, 0x7F, 0xFC, + 0x9C, 0x0F, 0x85, 0xFC, 0x9E, 0x0F, 0x8B, 0xFC, 0x9F, 0x0F, + 0x91, 0xFC, 0xA1, 0x0F, 0x97, 0xFC, 0xA2, 0x0F, 0x9D, 0xFC, + 0xA3, 0x0F, 0xA3, 0xFC, 0xA5, 0x0F, 0xAA, 0xFC, 0xA6, 0x0F, + 0xB0, 0xFC, 0xA7, 0x0F, 0xB6, 0xFC, 0xA8, 0x0F, 0xBC, 0xFC, + 0xAA, 0x0F, 0xC2, 0xFC, 0xAB, 0x0F, 0xC8, 0xFC, 0xAC, 0x0F, + 0xCE, 0xFC, 0xAE, 0x0F, 0xD5, 0xFC, 0xAF, 0x0F, 0xDB, 0xFC, + 0xB0, 0x0F, 0xE1, 0xFC, 0xB1, 0x0F, 0xE7, 0xFC, 0xB3, 0x0F, + 0xED, 0xFC, 0xB4, 0x0F, 0xF3, 0xFC, 0xB5, 0x0F, 0xFA, 0xFC, + 0xB6, 0x0F, 0x00, 0xFD, 0xB7, 0x0F, 0x06, 0xFD, 0xB8, 0x0F, + 0x0C, 0xFD, 0xBA, 0x0F, 0x12, 0xFD, 0xBB, 0x0F, 0x18, 0xFD, + 0xBC, 0x0F, 0x1F, 0xFD, 0xBD, 0x0F, 0x25, 0xFD, 0xBE, 0x0F, + 0x2B, 0xFD, 0xBF, 0x0F, 0x31, 0xFD, 0xC0, 0x0F, 0x37, 0xFD, + 0xC2, 0x0F, 0x3E, 0xFD, 0xC3, 0x0F, 0x44, 0xFD, 0xC4, 0x0F, + 0x4A, 0xFD, 0xC5, 0x0F, 0x50, 0xFD, 0xC6, 0x0F, 0x56, 0xFD, + 0xC7, 0x0F, 0x5D, 0xFD, 0xC8, 0x0F, 0x63, 0xFD, 0xC9, 0x0F, + 0x69, 0xFD, 0xCA, 0x0F, 0x6F, 0xFD, 0xCB, 0x0F, 0x75, 0xFD, + 0xCC, 0x0F, 0x7C, 0xFD, 0xCD, 0x0F, 0x82, 0xFD, 0xCE, 0x0F, + 0x88, 0xFD, 0xCF, 0x0F, 0x8E, 0xFD, 0xD0, 0x0F, 0x94, 0xFD, + 0xD1, 0x0F, 0x9B, 0xFD, 0xD2, 0x0F, 0xA1, 0xFD, 0xD3, 0x0F, + 0xA7, 0xFD, 0xD4, 0x0F, 0xAD, 0xFD, 0xD5, 0x0F, 0xB3, 0xFD, + 0xD5, 0x0F, 0xBA, 0xFD, 0xD6, 0x0F, 0xC0, 0xFD, 0xD7, 0x0F, + 0xC6, 0xFD, 0xD8, 0x0F, 0xCC, 0xFD, 0xD9, 0x0F, 0xD3, 0xFD, + 0xDA, 0x0F, 0xD9, 0xFD, 0xDB, 0x0F, 0xDF, 0xFD, 0xDC, 0x0F, + 0xE5, 0xFD, 0xDC, 0x0F, 0xEB, 0xFD, 0xDD, 0x0F, 0xF2, 0xFD, + 0xDE, 0x0F, 0xF8, 0xFD, 0xDF, 0x0F, 0xFE, 0xFD, 0xE0, 0x0F, + 0x04, 0xFE, 0xE0, 0x0F, 0x0B, 0xFE, 0xE1, 0x0F, 0x11, 0xFE, + 0xE2, 0x0F, 0x17, 0xFE, 0xE3, 0x0F, 0x1D, 0xFE, 0xE3, 0x0F, + 0x24, 0xFE, 0xE4, 0x0F, 0x2A, 0xFE, 0xE5, 0x0F, 0x30, 0xFE, + 0xE6, 0x0F, 0x36, 0xFE, 0xE6, 0x0F, 0x3D, 0xFE, 0xE7, 0x0F, + 0x43, 0xFE, 0xE8, 0x0F, 0x49, 0xFE, 0xE8, 0x0F, 0x4F, 0xFE, + 0xE9, 0x0F, 0x56, 0xFE, 0xEA, 0x0F, 0x5C, 0xFE, 0xEA, 0x0F, + 0x62, 0xFE, 0xEB, 0x0F, 0x68, 0xFE, 0xEC, 0x0F, 0x6F, 0xFE, + 0xEC, 0x0F, 0x75, 0xFE, 0xED, 0x0F, 0x7B, 0xFE, 0xED, 0x0F, + 0x81, 0xFE, 0xEE, 0x0F, 0x88, 0xFE, 0xEF, 0x0F, 0x8E, 0xFE, + 0xEF, 0x0F, 0x94, 0xFE, 0xF0, 0x0F, 0x9A, 0xFE, 0xF0, 0x0F, + 0xA1, 0xFE, 0xF1, 0x0F, 0xA7, 0xFE, 0xF1, 0x0F, 0xAD, 0xFE, + 0xF2, 0x0F, 0xB3, 0xFE, 0xF2, 0x0F, 0xBA, 0xFE, 0xF3, 0x0F, + 0xC0, 0xFE, 0xF3, 0x0F, 0xC6, 0xFE, 0xF4, 0x0F, 0xCC, 0xFE, + 0xF4, 0x0F, 0xD3, 0xFE, 0xF5, 0x0F, 0xD9, 0xFE, 0xF5, 0x0F, + 0xDF, 0xFE, 0xF6, 0x0F, 0xE5, 0xFE, 0xF6, 0x0F, 0xEC, 0xFE, + 0xF7, 0x0F, 0xF2, 0xFE, 0xF7, 0x0F, 0xF8, 0xFE, 0xF8, 0x0F, + 0xFF, 0xFE, 0xF8, 0x0F, 0x05, 0xFF, 0xF8, 0x0F, 0x0B, 0xFF, + 0xF9, 0x0F, 0x11, 0xFF, 0xF9, 0x0F, 0x18, 0xFF, 0xF9, 0x0F, + 0x1E, 0xFF, 0xFA, 0x0F, 0x24, 0xFF, 0xFA, 0x0F, 0x2A, 0xFF, + 0xFA, 0x0F, 0x31, 0xFF, 0xFB, 0x0F, 0x37, 0xFF, 0xFB, 0x0F, + 0x3D, 0xFF, 0xFB, 0x0F, 0x44, 0xFF, 0xFC, 0x0F, 0x4A, 0xFF, + 0xFC, 0x0F, 0x50, 0xFF, 0xFC, 0x0F, 0x56, 0xFF, 0xFC, 0x0F, + 0x5D, 0xFF, 0xFD, 0x0F, 0x63, 0xFF, 0xFD, 0x0F, 0x69, 0xFF, + 0xFD, 0x0F, 0x70, 0xFF, 0xFD, 0x0F, 0x76, 0xFF, 0xFE, 0x0F, + 0x7C, 0xFF, 0xFE, 0x0F, 0x82, 0xFF, 0xFE, 0x0F, 0x89, 0xFF, + 0xFE, 0x0F, 0x8F, 0xFF, 0xFE, 0x0F, 0x95, 0xFF, 0xFF, 0x0F, + 0x9B, 0xFF, 0xFF, 0x0F, 0xA2, 0xFF, 0xFF, 0x0F, 0xA8, 0xFF, + 0xFF, 0x0F, 0xAE, 0xFF, 0xFF, 0x0F, 0xB5, 0xFF, 0xFF, 0x0F, + 0xBB, 0xFF, 0xFF, 0x0F, 0xC1, 0xFF, 0x00, 0x10, 0xC7, 0xFF, + 0x00, 0x10, 0xCE, 0xFF, 0x00, 0x10, 0xD4, 0xFF, 0x00, 0x10, + 0xDA, 0xFF, 0x00, 0x10, 0xE1, 0xFF, 0x00, 0x10, 0xE7, 0xFF, + 0x00, 0x10, 0xED, 0xFF, 0x00, 0x10, 0xF3, 0xFF, 0x00, 0x10, + 0xFA, 0xFF, 0x00, 0x10 +}; + +unsigned int* gte_rcossin_tbl = (unsigned int*)&ida_chars[0];///@FIXME convert to uint[]; + +#ifndef max +# define max(a, b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef min +# define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + +void InitGeom() +{ + //_patch_gte(); //Extern +#if 0 + mfc0 $v0, SR + lui $v1, 0x4000 + or $v0, $v1 + mtc0 $v0, SR +#endif + ZSF3 = 341; + ZSF4 = 256; + H = 1000; + DQA = -98; + DQB = 340; + OFX = 0; + OFY = 0; +} + +void SetGeomOffset(int ofx, int ofy) +{ + OFX = ofx << 16; + OFY = ofy << 16; +} + +void SetGeomScreen(int h) +{ + H = h; +} + +static int m_sf; +static long long m_mac0; +static long long m_mac3; + +unsigned int gte_leadingzerocount(unsigned int lzcs) { + unsigned int lzcr = 0; + + if ((lzcs & 0x80000000) == 0) + lzcs = ~lzcs; + + while ((lzcs & 0x80000000) != 0) { + lzcr++; + lzcs <<= 1; + } + + return lzcr; +} + +int LIM(int value, int max, int min, unsigned int flag) { + if (value > max) { + FLAG |= flag; + return max; + } + else if (value < min) { + FLAG |= flag; + return min; + } + + return value; +} + +static unsigned int MFC2(int reg) { + switch (reg) { + case 1: + case 3: + case 5: + case 8: + case 9: + case 10: + case 11: + gteRegs.CP2D.p[reg].d = (int)gteRegs.CP2D.p[reg].sw.l; + break; + + case 7: + case 16: + case 17: + case 18: + case 19: + gteRegs.CP2D.p[reg].d = (unsigned int)gteRegs.CP2D.p[reg].w.l; + break; + + case 15: + gteRegs.CP2D.p[reg].d = SXY2; + break; + + case 28: + case 29: + gteRegs.CP2D.p[reg].d = LIM(IR1 >> 7, 0x1f, 0, 0) | (LIM(IR2 >> 7, 0x1f, 0, 0) << 5) | (LIM(IR3 >> 7, 0x1f, 0, 0) << 10); + break; + } + + return gteRegs.CP2D.p[reg].d; +} + +static void MTC2(unsigned int value, int reg) { + switch (reg) { + case 15: + SXY0 = SXY1; + SXY1 = SXY2; + SXY2 = value; + break; + + case 28: + IR1 = (value & 0x1f) << 7; + IR2 = (value & 0x3e0) << 2; + IR3 = (value & 0x7c00) >> 3; + break; + + case 30: + LZCR = gte_leadingzerocount(value); + break; + + case 31: + return; + } + + gteRegs.CP2D.p[reg].d = value; +} + +static void CTC2(unsigned int value, int reg) { + switch (reg) { + case 4: + case 12: + case 20: + case 26: + case 27: + case 29: + case 30: + value = (int)(short)value; + break; + + case 31: + value = value & 0x7ffff000; + if ((value & 0x7f87e000) != 0) + value |= 0x80000000; + break; + } + + gteRegs.CP2C.p[reg].d = value; +} + +#define _oB_ (gteRegs.GPR.r[_Rs_] + _Imm_) + +inline long long gte_shift(long long a, int sf) { + if (sf > 0) + return a >> 12; + else if (sf < 0) + return a << 12; + + return a; +} + +int BOUNDS(/*int44*/long long value, int max_flag, int min_flag) { + if (value/*.positive_overflow()*/ > (long long)0x7ffffffffff) + FLAG |= max_flag; + + if (value/*.negative_overflow()*/ < (long long)-0x8000000000) + FLAG |= min_flag; + + return gte_shift(value/*.value()*/, m_sf); +} + +unsigned int gte_divide(unsigned short numerator, unsigned short denominator) +{ + if (numerator < (denominator * 2)) + { + static unsigned char table[] = + { + 0xff, 0xfd, 0xfb, 0xf9, 0xf7, 0xf5, 0xf3, 0xf1, 0xef, 0xee, 0xec, 0xea, 0xe8, 0xe6, 0xe4, 0xe3, + 0xe1, 0xdf, 0xdd, 0xdc, 0xda, 0xd8, 0xd6, 0xd5, 0xd3, 0xd1, 0xd0, 0xce, 0xcd, 0xcb, 0xc9, 0xc8, + 0xc6, 0xc5, 0xc3, 0xc1, 0xc0, 0xbe, 0xbd, 0xbb, 0xba, 0xb8, 0xb7, 0xb5, 0xb4, 0xb2, 0xb1, 0xb0, + 0xae, 0xad, 0xab, 0xaa, 0xa9, 0xa7, 0xa6, 0xa4, 0xa3, 0xa2, 0xa0, 0x9f, 0x9e, 0x9c, 0x9b, 0x9a, + 0x99, 0x97, 0x96, 0x95, 0x94, 0x92, 0x91, 0x90, 0x8f, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x87, 0x86, + 0x85, 0x84, 0x83, 0x82, 0x81, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x75, 0x74, + 0x73, 0x72, 0x71, 0x70, 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, + 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, + 0x54, 0x53, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x48, + 0x47, 0x46, 0x45, 0x44, 0x43, 0x43, 0x42, 0x41, 0x40, 0x3f, 0x3f, 0x3e, 0x3d, 0x3c, 0x3c, 0x3b, + 0x3a, 0x39, 0x39, 0x38, 0x37, 0x36, 0x36, 0x35, 0x34, 0x33, 0x33, 0x32, 0x31, 0x31, 0x30, 0x2f, + 0x2e, 0x2e, 0x2d, 0x2c, 0x2c, 0x2b, 0x2a, 0x2a, 0x29, 0x28, 0x28, 0x27, 0x26, 0x26, 0x25, 0x24, + 0x24, 0x23, 0x22, 0x22, 0x21, 0x20, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, + 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, 0x12, 0x12, 0x11, 0x11, + 0x10, 0x0f, 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, + 0x07, 0x07, 0x06, 0x06, 0x05, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, + 0x00 + }; + + int shift = gte_leadingzerocount(denominator) - 16; + + int r1 = (denominator << shift) & 0x7fff; + int r2 = table[((r1 + 0x40) >> 7)] + 0x101; + int r3 = ((0x80 - (r2 * (r1 + 0x8000))) >> 8) & 0x1ffff; + unsigned int reciprocal = ((r2 * r3) + 0x80) >> 8; + + return (unsigned int)((((unsigned long long)reciprocal * (numerator << shift)) + 0x8000) >> 16); + } + + return 0xffffffff; +} + +/* Setting bits 12 & 19-22 in FLAG does not set bit 31 */ + +int A1(/*int44*/long long a) { return BOUNDS(a, (1 << 31) | (1 << 30), (1 << 31) | (1 << 27)); } +int A2(/*int44*/long long a) { return BOUNDS(a, (1 << 31) | (1 << 29), (1 << 31) | (1 << 26)); } +int A3(/*int44*/long long a) { m_mac3 = a; return BOUNDS(a, (1 << 31) | (1 << 28), (1 << 31) | (1 << 25)); } +int Lm_B1(int a, int lm) { return LIM(a, 0x7fff, -0x8000 * !lm, (1 << 31) | (1 << 24)); } +int Lm_B2(int a, int lm) { return LIM(a, 0x7fff, -0x8000 * !lm, (1 << 31) | (1 << 23)); } +int Lm_B3(int a, int lm) { return LIM(a, 0x7fff, -0x8000 * !lm, (1 << 22)); } + +int Lm_B3_sf(long long value, int sf, int lm) { + int value_sf = gte_shift(value, sf); + int value_12 = gte_shift(value, 1); + int max = 0x7fff; + int min = 0; + if (lm == 0) + min = -0x8000; + + if (value_12 < -0x8000 || value_12 > 0x7fff) + FLAG |= (1 << 22); + + if (value_sf > max) + return max; + else if (value_sf < min) + return min; + + return value_sf; +} + +int Lm_C1(int a) { return LIM(a, 0x00ff, 0x0000, (1 << 21)); } +int Lm_C2(int a) { return LIM(a, 0x00ff, 0x0000, (1 << 20)); } +int Lm_C3(int a) { return LIM(a, 0x00ff, 0x0000, (1 << 19)); } +int Lm_D(long long a, int sf) { return LIM(gte_shift(a, sf), 0xffff, 0x0000, (1 << 31) | (1 << 18)); } + +unsigned int Lm_E(unsigned int result) { + if (result == 0xffffffff) { + FLAG |= (1 << 31) | (1 << 17); + return 0x1ffff; + } + + if (result > 0x1ffff) + return 0x1ffff; + + return result; +} + +long long F(long long a) { + m_mac0 = a; + + if (a > (long long)0x7fffffff) + FLAG |= (1 << 31) | (1 << 16); + + if (a < (long long)-0x80000000) + FLAG |= (1 << 31) | (1 << 15); + + return a; +} + +int Lm_G1(long long a) { + if (a > 0x3ff) { + FLAG |= (1 << 31) | (1 << 14); + return 0x3ff; + } + if (a < -0x400) { + FLAG |= (1 << 31) | (1 << 14); + return -0x400; + } + + return a; +} + +int Lm_G2(long long a) { + if (a > 0x3ff) { + FLAG |= (1 << 31) | (1 << 13); + return 0x3ff; + } + + if (a < -0x400) { + FLAG |= (1 << 31) | (1 << 13); + return -0x400; + } + + return a; +} + +int Lm_G1_ia(long long a) { + if (a > 0x3ffffff) + return 0x3ffffff; + + if (a < -0x4000000) + return -0x4000000; + + return a; +} + +int Lm_G2_ia(long long a) { + if (a > 0x3ffffff) + return 0x3ffffff; + + if (a < -0x4000000) + return -0x4000000; + + return a; +} + +int Lm_H(long long value, int sf) { + long long value_sf = gte_shift(value, sf); + int value_12 = gte_shift(value, 1); + int max = 0x1000; + int min = 0x0000; + + if (value_sf < min || value_sf > max) + FLAG |= (1 << 12); + + if (value_12 > max) + return max; + + if (value_12 < min) + return min; + + return value_12; +} + +int docop2(int op) { + int v; + int lm; + int cv; + int mx; + int h_over_sz3 = 0; + + lm = GTE_LM(gteop(op)); + m_sf = GTE_SF(gteop(op)); + + FLAG = 0; + + switch (GTE_FUNCT(gteop(op))) { + case 0x00: + case 0x01: +#ifdef GTE_LOG + GTELOG("%08x RTPS", op); +#endif + + MAC1 = A1(/*int44*/(long long)((long long)TRX << 12) + (R11 * VX0) + (R12 * VY0) + (R13 * VZ0)); + MAC2 = A2(/*int44*/(long long)((long long)TRY << 12) + (R21 * VX0) + (R22 * VY0) + (R23 * VZ0)); + MAC3 = A3(/*int44*/(long long)((long long)TRZ << 12) + (R31 * VX0) + (R32 * VY0) + (R33 * VZ0)); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3_sf(m_mac3, m_sf, lm); + SZ0 = SZ1; + SZ1 = SZ2; + SZ2 = SZ3; + SZ3 = Lm_D(m_mac3, 1); + h_over_sz3 = Lm_E(gte_divide(H, SZ3)); + SXY0 = SXY1; + SXY1 = SXY2; + SX2 = Lm_G1(F((long long)OFX + ((long long)IR1 * h_over_sz3) * (WIDE_SCREEN ? 0.75 : 1)) >> 16); + SY2 = Lm_G2(F((long long)OFY + ((long long)IR2 * h_over_sz3)) >> 16); + +#if defined(PGXP) + if (pgxp_vertex_index == 871) + { + int test = 0; + test++; + } + pgxp_vertex_buffer[pgxp_vertex_index].originalSXY2 = SXY2; + pgxp_vertex_buffer[pgxp_vertex_index].x = (Lm_G1_ia((long long)OFX + (long long)(IR1 * h_over_sz3) * (false ? 0.75 : 1))) / (float)(1 << 16); + pgxp_vertex_buffer[pgxp_vertex_index].y = (Lm_G2_ia((long long)OFY + (long long)(IR2 * h_over_sz3))) / (float)(1 << 16); + pgxp_vertex_buffer[pgxp_vertex_index++].z = max(SZ3, H / 2) / (float)(1 << 16); +#endif + MAC0 = F((long long)DQB + ((long long)DQA * h_over_sz3)); + IR0 = Lm_H(m_mac0, 1); + return 1; + + case 0x06: +#ifdef GTE_LOG + GTELOG("%08x NCLIP", op); +#endif + + MAC0 = F((long long)(SX0 * SY1) + (SX1 * SY2) + (SX2 * SY0) - (SX0 * SY2) - (SX1 * SY0) - (SX2 * SY1)); + return 1; + + case 0x0c: +#ifdef GTE_LOG + GTELOG("%08x OP", op); +#endif + + MAC1 = A1((long long)(R22 * IR3) - (R33 * IR2)); + MAC2 = A2((long long)(R33 * IR1) - (R11 * IR3)); + MAC3 = A3((long long)(R11 * IR2) - (R22 * IR1)); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + return 1; + + case 0x10: +#ifdef GTE_LOG + GTELOG("%08x DPCS", op); +#endif + + MAC1 = A1((R << 16) + (IR0 * Lm_B1(A1(((long long)RFC << 12) - (R << 16)), 0))); + MAC2 = A2((G << 16) + (IR0 * Lm_B2(A2(((long long)GFC << 12) - (G << 16)), 0))); + MAC3 = A3((B << 16) + (IR0 * Lm_B3(A3(((long long)BFC << 12) - (B << 16)), 0))); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + RGB0 = RGB1; + RGB1 = RGB2; + CD2 = CODE; + R2 = Lm_C1(MAC1 >> 4); + G2 = Lm_C2(MAC2 >> 4); + B2 = Lm_C3(MAC3 >> 4); + return 1; + + case 0x11: +#ifdef GTE_LOG + GTELOG("%08x INTPL", op); +#endif + + MAC1 = A1((IR1 << 12) + (IR0 * Lm_B1(A1(((long long)RFC << 12) - (IR1 << 12)), 0))); + MAC2 = A2((IR2 << 12) + (IR0 * Lm_B2(A2(((long long)GFC << 12) - (IR2 << 12)), 0))); + MAC3 = A3((IR3 << 12) + (IR0 * Lm_B3(A3(((long long)BFC << 12) - (IR3 << 12)), 0))); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + RGB0 = RGB1; + RGB1 = RGB2; + CD2 = CODE; + R2 = Lm_C1(MAC1 >> 4); + G2 = Lm_C2(MAC2 >> 4); + B2 = Lm_C3(MAC3 >> 4); + return 1; + + case 0x12: +#ifdef GTE_LOG + GTELOG("%08x MVMVA", op); +#endif + + mx = GTE_MX(gteop(op)); + v = GTE_V(gteop(op)); + cv = GTE_CV(gteop(op)); + + switch (cv) { + case 2: + MAC1 = A1((long long)(MX12(mx) * VY(v)) + (MX13(mx) * VZ(v))); + MAC2 = A2((long long)(MX22(mx) * VY(v)) + (MX23(mx) * VZ(v))); + MAC3 = A3((long long)(MX32(mx) * VY(v)) + (MX33(mx) * VZ(v))); + Lm_B1(A1(((long long)CV1(cv) << 12) + (MX11(mx) * VX(v))), 0); + Lm_B2(A2(((long long)CV2(cv) << 12) + (MX21(mx) * VX(v))), 0); + Lm_B3(A3(((long long)CV3(cv) << 12) + (MX31(mx) * VX(v))), 0); + break; + + default: + MAC1 = A1(/*int44*/(long long)((long long)CV1(cv) << 12) + (MX11(mx) * VX(v)) + (MX12(mx) * VY(v)) + (MX13(mx) * VZ(v))); + MAC2 = A2(/*int44*/(long long)((long long)CV2(cv) << 12) + (MX21(mx) * VX(v)) + (MX22(mx) * VY(v)) + (MX23(mx) * VZ(v))); + MAC3 = A3(/*int44*/(long long)((long long)CV3(cv) << 12) + (MX31(mx) * VX(v)) + (MX32(mx) * VY(v)) + (MX33(mx) * VZ(v))); + break; + } + + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + return 1; + + case 0x13: +#ifdef GTE_LOG + GTELOG("%08x NCDS", op); +#endif + + MAC1 = A1((long long)(L11 * VX0) + (L12 * VY0) + (L13 * VZ0)); + MAC2 = A2((long long)(L21 * VX0) + (L22 * VY0) + (L23 * VZ0)); + MAC3 = A3((long long)(L31 * VX0) + (L32 * VY0) + (L33 * VZ0)); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + MAC1 = A1(/*int44*/(long long)((long long)RBK << 12) + (LR1 * IR1) + (LR2 * IR2) + (LR3 * IR3)); + MAC2 = A2(/*int44*/(long long)((long long)GBK << 12) + (LG1 * IR1) + (LG2 * IR2) + (LG3 * IR3)); + MAC3 = A3(/*int44*/(long long)((long long)BBK << 12) + (LB1 * IR1) + (LB2 * IR2) + (LB3 * IR3)); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + MAC1 = A1(((R << 4) * IR1) + (IR0 * Lm_B1(A1(((long long)RFC << 12) - ((R << 4) * IR1)), 0))); + MAC2 = A2(((G << 4) * IR2) + (IR0 * Lm_B2(A2(((long long)GFC << 12) - ((G << 4) * IR2)), 0))); + MAC3 = A3(((B << 4) * IR3) + (IR0 * Lm_B3(A3(((long long)BFC << 12) - ((B << 4) * IR3)), 0))); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + RGB0 = RGB1; + RGB1 = RGB2; + CD2 = CODE; + R2 = Lm_C1(MAC1 >> 4); + G2 = Lm_C2(MAC2 >> 4); + B2 = Lm_C3(MAC3 >> 4); + return 1; + + case 0x14: +#ifdef GTE_LOG + GTELOG("%08x CDP", op); +#endif + + MAC1 = A1(/*int44*/(long long)((long long)RBK << 12) + (LR1 * IR1) + (LR2 * IR2) + (LR3 * IR3)); + MAC2 = A2(/*int44*/(long long)((long long)GBK << 12) + (LG1 * IR1) + (LG2 * IR2) + (LG3 * IR3)); + MAC3 = A3(/*int44*/(long long)((long long)BBK << 12) + (LB1 * IR1) + (LB2 * IR2) + (LB3 * IR3)); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + MAC1 = A1(((R << 4) * IR1) + (IR0 * Lm_B1(A1(((long long)RFC << 12) - ((R << 4) * IR1)), 0))); + MAC2 = A2(((G << 4) * IR2) + (IR0 * Lm_B2(A2(((long long)GFC << 12) - ((G << 4) * IR2)), 0))); + MAC3 = A3(((B << 4) * IR3) + (IR0 * Lm_B3(A3(((long long)BFC << 12) - ((B << 4) * IR3)), 0))); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + RGB0 = RGB1; + RGB1 = RGB2; + CD2 = CODE; + R2 = Lm_C1(MAC1 >> 4); + G2 = Lm_C2(MAC2 >> 4); + B2 = Lm_C3(MAC3 >> 4); + return 1; + + case 0x16: +#ifdef GTE_LOG + GTELOG("%08x NCDT", op); +#endif + + for (v = 0; v < 3; v++) { + MAC1 = A1((long long)(L11 * VX(v)) + (L12 * VY(v)) + (L13 * VZ(v))); + MAC2 = A2((long long)(L21 * VX(v)) + (L22 * VY(v)) + (L23 * VZ(v))); + MAC3 = A3((long long)(L31 * VX(v)) + (L32 * VY(v)) + (L33 * VZ(v))); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + MAC1 = A1(/*int44*/(long long)((long long)RBK << 12) + (LR1 * IR1) + (LR2 * IR2) + (LR3 * IR3)); + MAC2 = A2(/*int44*/(long long)((long long)GBK << 12) + (LG1 * IR1) + (LG2 * IR2) + (LG3 * IR3)); + MAC3 = A3(/*int44*/(long long)((long long)BBK << 12) + (LB1 * IR1) + (LB2 * IR2) + (LB3 * IR3)); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + MAC1 = A1(((R << 4) * IR1) + (IR0 * Lm_B1(A1(((long long)RFC << 12) - ((R << 4) * IR1)), 0))); + MAC2 = A2(((G << 4) * IR2) + (IR0 * Lm_B2(A2(((long long)GFC << 12) - ((G << 4) * IR2)), 0))); + MAC3 = A3(((B << 4) * IR3) + (IR0 * Lm_B3(A3(((long long)BFC << 12) - ((B << 4) * IR3)), 0))); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + RGB0 = RGB1; + RGB1 = RGB2; + CD2 = CODE; + R2 = Lm_C1(MAC1 >> 4); + G2 = Lm_C2(MAC2 >> 4); + B2 = Lm_C3(MAC3 >> 4); + } + return 1; + + case 0x1b: +#ifdef GTE_LOG + GTELOG("%08x NCCS", op); +#endif + + MAC1 = A1((long long)(L11 * VX0) + (L12 * VY0) + (L13 * VZ0)); + MAC2 = A2((long long)(L21 * VX0) + (L22 * VY0) + (L23 * VZ0)); + MAC3 = A3((long long)(L31 * VX0) + (L32 * VY0) + (L33 * VZ0)); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + MAC1 = A1(/*int44*/(long long)((long long)RBK << 12) + (LR1 * IR1) + (LR2 * IR2) + (LR3 * IR3)); + MAC2 = A2(/*int44*/(long long)((long long)GBK << 12) + (LG1 * IR1) + (LG2 * IR2) + (LG3 * IR3)); + MAC3 = A3(/*int44*/(long long)((long long)BBK << 12) + (LB1 * IR1) + (LB2 * IR2) + (LB3 * IR3)); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + MAC1 = A1((R << 4) * IR1); + MAC2 = A2((G << 4) * IR2); + MAC3 = A3((B << 4) * IR3); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + RGB0 = RGB1; + RGB1 = RGB2; + CD2 = CODE; + R2 = Lm_C1(MAC1 >> 4); + G2 = Lm_C2(MAC2 >> 4); + B2 = Lm_C3(MAC3 >> 4); + return 1; + + case 0x1c: +#ifdef GTE_LOG + GTELOG("%08x CC", op); +#endif + + MAC1 = A1(/*int44*/(long long)(((long long)RBK) << 12) + (LR1 * IR1) + (LR2 * IR2) + (LR3 * IR3)); + MAC2 = A2(/*int44*/(long long)(((long long)GBK) << 12) + (LG1 * IR1) + (LG2 * IR2) + (LG3 * IR3)); + MAC3 = A3(/*int44*/(long long)(((long long)BBK) << 12) + (LB1 * IR1) + (LB2 * IR2) + (LB3 * IR3)); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + MAC1 = A1((R << 4) * IR1); + MAC2 = A2((G << 4) * IR2); + MAC3 = A3((B << 4) * IR3); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + RGB0 = RGB1; + RGB1 = RGB2; + CD2 = CODE; + R2 = Lm_C1(MAC1 >> 4); + G2 = Lm_C2(MAC2 >> 4); + B2 = Lm_C3(MAC3 >> 4); + return 1; + + case 0x1e: +#ifdef GTE_LOG + GTELOG("%08x NCS", op); +#endif + + MAC1 = A1((long long)(L11 * VX0) + (L12 * VY0) + (L13 * VZ0)); + MAC2 = A2((long long)(L21 * VX0) + (L22 * VY0) + (L23 * VZ0)); + MAC3 = A3((long long)(L31 * VX0) + (L32 * VY0) + (L33 * VZ0)); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + MAC1 = A1(/*int44*/(long long)((long long)RBK << 12) + (LR1 * IR1) + (LR2 * IR2) + (LR3 * IR3)); + MAC2 = A2(/*int44*/(long long)((long long)GBK << 12) + (LG1 * IR1) + (LG2 * IR2) + (LG3 * IR3)); + MAC3 = A3(/*int44*/(long long)((long long)BBK << 12) + (LB1 * IR1) + (LB2 * IR2) + (LB3 * IR3)); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + RGB0 = RGB1; + RGB1 = RGB2; + CD2 = CODE; + R2 = Lm_C1(MAC1 >> 4); + G2 = Lm_C2(MAC2 >> 4); + B2 = Lm_C3(MAC3 >> 4); + return 1; + + case 0x20: +#ifdef GTE_LOG + GTELOG("%08x NCT", op); +#endif + + for (v = 0; v < 3; v++) { + MAC1 = A1((long long)(L11 * VX(v)) + (L12 * VY(v)) + (L13 * VZ(v))); + MAC2 = A2((long long)(L21 * VX(v)) + (L22 * VY(v)) + (L23 * VZ(v))); + MAC3 = A3((long long)(L31 * VX(v)) + (L32 * VY(v)) + (L33 * VZ(v))); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + MAC1 = A1(/*int44*/(long long)((long long)RBK << 12) + (LR1 * IR1) + (LR2 * IR2) + (LR3 * IR3)); + MAC2 = A2(/*int44*/(long long)((long long)GBK << 12) + (LG1 * IR1) + (LG2 * IR2) + (LG3 * IR3)); + MAC3 = A3(/*int44*/(long long)((long long)BBK << 12) + (LB1 * IR1) + (LB2 * IR2) + (LB3 * IR3)); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + RGB0 = RGB1; + RGB1 = RGB2; + CD2 = CODE; + R2 = Lm_C1(MAC1 >> 4); + G2 = Lm_C2(MAC2 >> 4); + B2 = Lm_C3(MAC3 >> 4); + } + return 1; + + case 0x28: +#ifdef GTE_LOG + GTELOG("%08x SQR", op); +#endif + + MAC1 = A1(IR1 * IR1); + MAC2 = A2(IR2 * IR2); + MAC3 = A3(IR3 * IR3); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + return 1; + + case 0x29: +#ifdef GTE_LOG + GTELOG("%08x DPCL", op); +#endif + + MAC1 = A1(((R << 4) * IR1) + (IR0 * Lm_B1(A1(((long long)RFC << 12) - ((R << 4) * IR1)), 0))); + MAC2 = A2(((G << 4) * IR2) + (IR0 * Lm_B2(A2(((long long)GFC << 12) - ((G << 4) * IR2)), 0))); + MAC3 = A3(((B << 4) * IR3) + (IR0 * Lm_B3(A3(((long long)BFC << 12) - ((B << 4) * IR3)), 0))); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + RGB0 = RGB1; + RGB1 = RGB2; + CD2 = CODE; + R2 = Lm_C1(MAC1 >> 4); + G2 = Lm_C2(MAC2 >> 4); + B2 = Lm_C3(MAC3 >> 4); + return 1; + + case 0x2a: +#ifdef GTE_LOG + GTELOG("%08x DPCT", op); +#endif + + for (v = 0; v < 3; v++) { + MAC1 = A1((R0 << 16) + (IR0 * Lm_B1(A1(((long long)RFC << 12) - (R0 << 16)), 0))); + MAC2 = A2((G0 << 16) + (IR0 * Lm_B2(A2(((long long)GFC << 12) - (G0 << 16)), 0))); + MAC3 = A3((B0 << 16) + (IR0 * Lm_B3(A3(((long long)BFC << 12) - (B0 << 16)), 0))); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + RGB0 = RGB1; + RGB1 = RGB2; + CD2 = CODE; + R2 = Lm_C1(MAC1 >> 4); + G2 = Lm_C2(MAC2 >> 4); + B2 = Lm_C3(MAC3 >> 4); + } + return 1; + + case 0x2d: +#ifdef GTE_LOG + GTELOG("%08x AVSZ3", op); +#endif + + MAC0 = F((long long)(ZSF3 * SZ1) + (ZSF3 * SZ2) + (ZSF3 * SZ3)); + OTZ = Lm_D(m_mac0, 1); + return 1; + + case 0x2e: +#ifdef GTE_LOG + GTELOG("%08x AVSZ4", op); +#endif + + MAC0 = F((long long)(ZSF4 * SZ0) + (ZSF4 * SZ1) + (ZSF4 * SZ2) + (ZSF4 * SZ3)); + OTZ = Lm_D(m_mac0, 1); + return 1; + + case 0x30: +#ifdef GTE_LOG + GTELOG("%08x RTPT", op); +#endif + + for (v = 0; v < 3; v++) { + MAC1 = A1(/*int44*/(long long)((long long)TRX << 12) + (R11 * VX(v)) + (R12 * VY(v)) + (R13 * VZ(v))); + MAC2 = A2(/*int44*/(long long)((long long)TRY << 12) + (R21 * VX(v)) + (R22 * VY(v)) + (R23 * VZ(v))); + MAC3 = A3(/*int44*/(long long)((long long)TRZ << 12) + (R31 * VX(v)) + (R32 * VY(v)) + (R33 * VZ(v))); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3_sf(m_mac3, m_sf, lm); + SZ0 = SZ1; + SZ1 = SZ2; + SZ2 = SZ3; + SZ3 = Lm_D(m_mac3, 1); + h_over_sz3 = Lm_E(gte_divide(H, SZ3)); + SXY0 = SXY1; + SXY1 = SXY2; + SX2 = Lm_G1(F((long long)OFX + ((long long)IR1 * h_over_sz3) * (false ? 0.75 : 1)) >> 16); + SY2 = Lm_G2(F((long long)OFY + ((long long)IR2 * h_over_sz3)) >> 16); + +#if defined(PGXP) + pgxp_vertex_buffer[pgxp_vertex_index].originalSXY2 = SXY2; + pgxp_vertex_buffer[pgxp_vertex_index].x = Lm_G1_ia((long long)OFX + (long long)(IR1 * h_over_sz3) * (false ? 0.75 : 1)) / (float)(1 << 16); + pgxp_vertex_buffer[pgxp_vertex_index].y = Lm_G2_ia((long long)OFY + (long long)(IR2 * h_over_sz3)) / (float)(1 << 16); + pgxp_vertex_buffer[pgxp_vertex_index++].z = max(SZ3, H / 2) / (float)(1 << 16); +#endif + } + + MAC0 = F((long long)DQB + ((long long)DQA * h_over_sz3)); + IR0 = Lm_H(m_mac0, 1); + return 1; + + case 0x3d: +#ifdef GTE_LOG + GTELOG("%08x GPF", op); +#endif + + MAC1 = A1(IR0 * IR1); + MAC2 = A2(IR0 * IR2); + MAC3 = A3(IR0 * IR3); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + RGB0 = RGB1; + RGB1 = RGB2; + CD2 = CODE; + R2 = Lm_C1(MAC1 >> 4); + G2 = Lm_C2(MAC2 >> 4); + B2 = Lm_C3(MAC3 >> 4); + return 1; + + case 0x3e: +#ifdef GTE_LOG + GTELOG("%08x GPL", op); +#endif + + MAC1 = A1(gte_shift(MAC1, -m_sf) + (IR0 * IR1)); + MAC2 = A2(gte_shift(MAC2, -m_sf) + (IR0 * IR2)); + MAC3 = A3(gte_shift(MAC3, -m_sf) + (IR0 * IR3)); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + RGB0 = RGB1; + RGB1 = RGB2; + CD2 = CODE; + R2 = Lm_C1(MAC1 >> 4); + G2 = Lm_C2(MAC2 >> 4); + B2 = Lm_C3(MAC3 >> 4); + return 1; + + case 0x3f: +#ifdef GTE_LOG + GTELOG("%08x NCCT", op); +#endif + + for (v = 0; v < 3; v++) { + MAC1 = A1((long long)(L11 * VX(v)) + (L12 * VY(v)) + (L13 * VZ(v))); + MAC2 = A2((long long)(L21 * VX(v)) + (L22 * VY(v)) + (L23 * VZ(v))); + MAC3 = A3((long long)(L31 * VX(v)) + (L32 * VY(v)) + (L33 * VZ(v))); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + MAC1 = A1(/*int44*/(long long)((long long)RBK << 12) + (LR1 * IR1) + (LR2 * IR2) + (LR3 * IR3)); + MAC2 = A2(/*int44*/(long long)((long long)GBK << 12) + (LG1 * IR1) + (LG2 * IR2) + (LG3 * IR3)); + MAC3 = A3(/*int44*/(long long)((long long)BBK << 12) + (LB1 * IR1) + (LB2 * IR2) + (LB3 * IR3)); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + MAC1 = A1((R << 4) * IR1); + MAC2 = A2((G << 4) * IR2); + MAC3 = A3((B << 4) * IR3); + IR1 = Lm_B1(MAC1, lm); + IR2 = Lm_B2(MAC2, lm); + IR3 = Lm_B3(MAC3, lm); + RGB0 = RGB1; + RGB1 = RGB2; + CD2 = CODE; + R2 = Lm_C1(MAC1 >> 4); + G2 = Lm_C2(MAC2 >> 4); + B2 = Lm_C3(MAC3 >> 4); + } + return 1; + } + + return 0; +} + +void SetRotMatrix(MATRIX* m) +{ + R11 = m->m[0][0]; + R12 = m->m[0][1]; + R13 = m->m[0][2]; + R21 = m->m[1][0]; + R22 = m->m[1][1]; + R23 = m->m[1][2]; + R31 = m->m[2][0]; + R32 = m->m[2][1]; + R33 = m->m[2][2]; +} + +void SetLightMatrix(MATRIX* m) +{ + L11 = m->m[0][0]; + L12 = m->m[0][1]; + L13 = m->m[0][2]; + L21 = m->m[1][0]; + L22 = m->m[1][1]; + L23 = m->m[1][2]; + L31 = m->m[2][0]; + L32 = m->m[2][1]; + L33 = m->m[2][2]; +} + +void SetColorMatrix(MATRIX* m) +{ + LR1 = m->m[0][0]; + LR2 = m->m[0][1]; + LR3 = m->m[0][2]; + LG1 = m->m[1][0]; + LG2 = m->m[1][1]; + LG3 = m->m[1][2]; + LB1 = m->m[2][0]; + LB2 = m->m[2][1]; + LB3 = m->m[2][2]; +} + +void SetTransMatrix(MATRIX* m) +{ + TRX = m->t[0]; + TRY = m->t[1]; + TRZ = m->t[2]; +} + +#define MAX_NUM_MATRICES 20 +int matrixLevel = 0; +MATRIX stack[MAX_NUM_MATRICES];//unk_410 +MATRIX* currentMatrix = &stack[0];//unk_40C + +void PushMatrix() +{ + if (matrixLevel < 20) + { + MATRIX* m = &stack[matrixLevel];//$t7 + m->m[0][0] = R11; + m->m[0][1] = R12; + m->m[0][2] = R13; + m->m[1][0] = R21; + m->m[1][1] = R22; + m->m[1][2] = R23; + m->m[2][0] = R31; + m->m[2][1] = R32; + m->m[2][2] = R33; + m->t[0] = TRX; + m->t[1] = TRY; + m->t[2] = TRZ; + currentMatrix++; + matrixLevel++; + } + else + { + printf("Error: Can't push matrix,stack(max 20) is full!\n"); + } +} + +void PopMatrix() +{ + if (matrixLevel > 0) + { + currentMatrix--; + matrixLevel--; + MATRIX* m = &stack[matrixLevel];//$t7 + R11 = m->m[0][0]; + R12 = m->m[0][1]; + R13 = m->m[0][2]; + R21 = m->m[1][0]; + R22 = m->m[1][1]; + R23 = m->m[1][2]; + R31 = m->m[2][0]; + R32 = m->m[2][1]; + R33 = m->m[2][2]; + TRX = m->t[0]; + TRY = m->t[1]; + TRZ = m->t[2]; + } + else + { + printf("Error: Can't pop matrix,stack is empty!\n"); + } +} + +long RotTransPers(struct SVECTOR* v0, long* sxy, long* p, long* flag) +{ + VX0 = v0->vx; + VY0 = v0->vy; + VZ0 = v0->vz; + + docop2(0x180001); + + sxy[0] = SXY2; + p[0] = IR0; + flag[0] = FLAG; + + return SZ3 >> 2; +} + +void RotTrans(struct SVECTOR* v0, VECTOR* v1, long* flag) +{ + UNIMPLEMENTED(); +} + +void NormalColorDpq(struct SVECTOR* v0, struct CVECTOR* v1, long p, struct CVECTOR* v2) +{ + UNIMPLEMENTED(); +} + +void NormalColorCol(struct SVECTOR* v0, struct CVECTOR* v1, struct CVECTOR* v2) +{ + UNIMPLEMENTED(); +} + +long RotAverageNclip4(struct SVECTOR* v0, struct SVECTOR* v1, struct SVECTOR* v2, struct SVECTOR* v3, long* sxy0/*arg_10*/, long* sxy1/*arg_14*/, long* sxy2/*arg_18*/, long* sxy3/*arg_1C*/, long* p/*arg_20*/, long* otz/*arg_24*/, long* flag/*arg_28*/) +{ + VX0 = v0->vx; + VY0 = v0->vy; + VZ0 = v0->vz; + + VX1 = v1->vx; + VY1 = v1->vy; + VZ1 = v1->vz; + + VX2 = v2->vx; + VY2 = v2->vy; + VZ2 = v2->vz; + + docop2(0x280030); + + flag[0] = FLAG; + + docop2(0x1400006); + + if (MAC0 > 0) + { + SXY0 = sxy0[0]; + SXY1 = sxy1[0]; + SXY2 = sxy2[0]; + + VX0 = v3->vx; + VY0 = v3->vy; + VZ0 = v3->vz; + + docop2(0x180001); + + sxy3[0] = SXY2; + p[0] = IR0; + flag[0] |= FLAG; + + docop2(0x168002E); + + otz[0] = OTZ; + } + + return MAC0; +} + +MATRIX* MulMatrix0(MATRIX* m0, MATRIX* m1, MATRIX* m2) +{ + UNIMPLEMENTED(); + return NULL; +} + +MATRIX* MulMatrix(MATRIX* m0, MATRIX* m1) +{ + UNIMPLEMENTED(); + return NULL; +} + +MATRIX* MulMatrix2(MATRIX* m0, MATRIX* m1) +{ + UNIMPLEMENTED(); + return NULL; +} + +void SetBackColor(long rbk, long gbk, long bbk) +{ + UNIMPLEMENTED(); +} + +void SetFarColor(long rfc, long gfc, long bfc) +{ + UNIMPLEMENTED(); +} + +MATRIX* RotMatrix(struct SVECTOR* r, MATRIX* m) +{ + int t7 = r->vx; + int t9 = t7 & 0xFFF; + int t8 = 0; + int t3 = 0; + int t0 = 0; + int t6 = 0; + int t1 = 0; + int t4 = 0; + int t5 = 0; + int t2 = 0; + + if (t7 < 0) + { + t7 = -t7; + t7 &= 0xFFF; + t9 = gte_rcossin_tbl[t7]; + t8 = (t9 << 16) >> 16; + t3 = -t8; + t0 = t9 >> 16; + } + else + { + //loc_244 + t9 = gte_rcossin_tbl[t9]; + t3 = (t9 << 16) >> 16; + t0 = t9 >> 16; + } + + //loc_264 + t7 = r->vy; + t9 = t7 & 0xFFF; + + if (t7 < 0) + { + t7 = -t7; + t7 &= 0xFFF; + t9 = gte_rcossin_tbl[t7]; + t4 = (t9 << 16) >> 16; + t6 = -t4; + t1 = t9 >> 16; + } + else + { + //loc_2A8 + t9 = gte_rcossin_tbl[t9]; + t6 = (t9 << 16) >> 16; + t4 = -t6; + t1 = t9 >> 16; + } + + //loc_2CC + t8 = t1 * t3; + t7 = r->vz; + m->m[0][2] = t6; + t9 = -t8; + t6 = t9 >> 12; + t8 = t1 * t0; + m->m[1][2] = t6; + t9 = t7 & 0xFFF; + + if (t7 < 0) + { + t6 = t8 >> 12; + m->m[2][2] = t6; + t7 = -t7; + t7 &= 0xFFF; + t9 = gte_rcossin_tbl[t7]; + t8 = t9 & 0xFFFF; + t5 = -t8; + t2 = t9 >> 16; + } + else + { + //loc_334 + t7 = t8; + t6 = t7 >> 12; + m->m[2][2] = t6; + t9 = gte_rcossin_tbl[t9]; + t5 = t9 & 0xFFFF; + t2 = t9 >> 16; + } + + //loc_360 + t7 = t2 * t1; + t6 = t7 >> 12; + m->m[0][0] = t6; + + t7 = t5 * t1; + t6 = -t7; + t7 = t6 >> 12; + m->m[0][1] = t7; + + t7 = t2 * t4; + t8 = t7 >> 12; + t7 = t8 * t3; + t6 = t7 >> 12; + t7 = t5 * t0; + t9 = t7 >> 12; + t7 = t9 - t6; + m->m[1][0] = t7; + + t6 = t8 * t0; + t7 = t6 >> 12; + t6 = t5 * t3; + t9 = t6 >> 12; + t6 = t9 + t7; + m->m[2][0] = t6; + + t7 = t5 * t4; + t8 = t7 >> 12; + t7 = t8 * t3; + t6 = t7 >> 12; + t7 = t2 * t0; + t9 = t7 >> 12; + t7 = t9 + t6; + m->m[1][1] = t7; + + t6 = t8 * t0; + t7 = t6 >> 12; + t6 = t2 * t3; + t9 = t6 >> 12; + t6 = t9 - t7; + m->m[2][1] = t6; + + return m; +} + +MATRIX* TransMatrix(MATRIX* m, VECTOR* v) +{ + ((int*)m)[5] = v->vx; + ((int*)m)[6] = v->vy; + ((int*)m)[7] = v->vz; + return m; +} + +MATRIX* ScaleMatrix(MATRIX* m, VECTOR* v) +{ + UNIMPLEMENTED(); + return NULL; +} + +void SetDQA(int iDQA) +{ + DQA = iDQA; +} + +void SetDQB(int iDQB) +{ + DQB = iDQB; +} + +void SetFogNear(long a, long h) +{ + //Error division by 0 + assert(h != 0); + int depthQ = -(((a << 2) + a) << 6); + assert(h != -1 && depthQ != 0x8000); + SetDQA(depthQ / h); + SetDQB(20971520); +} + +int rsin(int a) +{ + UNIMPLEMENTED(); + return 0; +} diff --git a/src_rebuild/EMULATOR/LIBGTE.H b/src_rebuild/EMULATOR/LIBGTE.H new file mode 100644 index 00000000..75f74b00 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBGTE.H @@ -0,0 +1,169 @@ +#ifndef LIBGTE_H +#define LIBGTE_H + +#include "TYPES.H" + +typedef struct { + short m[3][3]; /* 3x3 rotation matrix */ + long t[3]; /* transfer vector */ +} MATRIX; + +typedef struct { /* long word type 3D vector */ + long vx, vy; + long vz, pad; +} VECTOR; + +struct SVECTOR { /* short word type 3D vector */ + short vx, vy; + short vz, pad; +}; + +struct CVECTOR { /* color type vector */ + unsigned char r, g, b, cd; +}; + +typedef struct { /* 2D short vector */ + short vx, vy; +} DVECTOR; + +extern void InitGeom(); +extern void SetGeomOffset(int ofx, int ofy); +extern void SetGeomScreen(int h); + +typedef union +{ + struct { unsigned char l, h, h2, h3; } b; + struct { unsigned short l, h; } w; + struct { char l, h, h2, h3; } sb; + struct { short l, h; } sw; + + unsigned int d; + int sd; +} PAIR; + +typedef struct { + unsigned char r, g, b, c; +} CBGR; + +typedef struct { + short x, y, z, pad; +} SVector3D; + +typedef struct { + short x, y; +} SVector2D; + +typedef struct { + short z, pad; +} SVector2Dz; + +typedef struct { + short m11, m12, m13, m21, m22, m23, m31, m32, m33, pad; +} SMatrix3D; + +typedef union +{ + struct + { + SVector3D v0, v1, v2; + CBGR rgb; + int otz; + int ir0, ir1, ir2, ir3; + SVector2D sxy0, sxy1, sxy2, sxyp; + SVector2Dz sz0, sz1, sz2, sz3; + CBGR rgb0, rgb1, rgb2; + int reserved; + int mac0, mac1, mac2, mac3; + unsigned int irgb, orgb; + int lzcs, lzcr; + } n; + + unsigned int r[32]; + PAIR p[32]; + +} psxCP2Data; + +typedef union +{ + struct { + SMatrix3D rMatrix; + int trX, trY, trZ; + SMatrix3D lMatrix; + int rbk, gbk, bbk; + SMatrix3D cMatrix; + int rfc, gfc, bfc; + int ofx, ofy; + int h; + int dqa, dqb; + int zsf3, zsf4; + int flag; + } n; + unsigned int r[32]; + PAIR p[32]; +} psxCP2Ctrl; + +typedef union { + struct { + unsigned int Index, Random, EntryLo0, BPC, + Context, BDA, PIDMask, DCIC, + BadVAddr, BDAM, EntryHi, BPCM, + Status, Cause, EPC, PRid, + Config, LLAddr, WatchLO, WatchHI, + XContext, Reserved1, Reserved2, Reserved3, + Reserved4, Reserved5, ECC, CacheErr, + TagLo, TagHi, ErrorEPC, Reserved6; + } n; + unsigned int r[32]; +} psxCP0Regs; + +typedef struct +{ + psxCP0Regs CP0; /* Coprocessor0 Registers */ + psxCP2Data CP2D; /* Cop2 data registers */ + psxCP2Ctrl CP2C; /* Cop2 control registers */ +} GTERegisters; + +extern GTERegisters gteRegs; +extern unsigned int gte_leadingzerocount(unsigned int lzcs); + +extern void SetRotMatrix(MATRIX* m); +extern void SetLightMatrix(MATRIX* m); +extern void SetColorMatrix(MATRIX* m); +extern void SetTransMatrix(MATRIX* m); +extern void PushMatrix(); +extern void PopMatrix(); +extern long RotTransPers(struct SVECTOR* v0, long* sxy, long* p, long* flag); +extern void RotTrans(struct SVECTOR* v0, VECTOR* v1, long* flag); +extern void NormalColorDpq(struct SVECTOR* v0, struct CVECTOR* v1, long p, struct CVECTOR* v2); +extern void NormalColorCol(struct SVECTOR* v0, struct CVECTOR* v1, struct CVECTOR* v2); +extern long RotAverageNclip4(struct SVECTOR* v0, struct SVECTOR* v1, struct SVECTOR* v2, struct SVECTOR* v3, long* sxy0/*arg_10*/, long* sxy1/*arg_14*/, long* sxy2/*arg_18*/, long* sxy3/*arg_1C*/, long* p/*arg_20*/, long* otz/*arg_24*/, long* flag/*arg_28*/); +extern MATRIX* MulMatrix0(MATRIX* m0, MATRIX* m1, MATRIX* m2); +extern MATRIX* MulMatrix(MATRIX* m0, MATRIX* m1); +extern MATRIX* MulMatrix2(MATRIX* m0, MATRIX* m1); +extern void SetBackColor(long rbk, long gbk, long bbk); +extern void SetFarColor(long rfc, long gfc, long bfc); +extern MATRIX* RotMatrix(struct SVECTOR* r, MATRIX* m); +extern MATRIX* TransMatrix(MATRIX* m, VECTOR* v); +extern MATRIX* ScaleMatrix(MATRIX* m, VECTOR* v); +extern void SetDQA(int iDQA); +extern void SetDQB(int iDQB); +extern void SetFogNear(long a, long h); +extern int rsin(int a); + +#if defined(PGXP) +#define MAX_NUM_VERTICES 32768 + +struct PGXPVertex +{ + unsigned int originalSXY2; + float x; + float y; + float z; +}; + +extern struct PGXPVertex pgxp_vertex_buffer[MAX_NUM_VERTICES]; +extern int pgxp_vertex_index; +extern int pgxp_vertex_count; +#endif + +#endif \ No newline at end of file diff --git a/src_rebuild/EMULATOR/LIBMATH.H b/src_rebuild/EMULATOR/LIBMATH.H new file mode 100644 index 00000000..c9cf98d7 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBMATH.H @@ -0,0 +1,6 @@ +#ifndef LIBMATH_H +#define LIBMATH_H + + + +#endif \ No newline at end of file diff --git a/src_rebuild/EMULATOR/LIBMCRD.C b/src_rebuild/EMULATOR/LIBMCRD.C new file mode 100644 index 00000000..a651fdd7 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBMCRD.C @@ -0,0 +1,309 @@ +#include "LIBMCRD.H" +#include +#include "EMULATOR.H" +#include + +#define MC_HEADER_FRAME_INDEX (0) + +#pragma pack(push,1) +typedef struct MemoryCardFrame +{ + unsigned int attr; + unsigned int size; + unsigned short unknown; + char name[20]; + char padding[98]; +} MemoryCardFrame_s, *MemoryCardFrame_p; +#pragma pack(pop) + +int bIsInitialised = 0; +int bCanUseMemoryCardFuncs = 0; +int memoryCardStatus = -1; + +FILE* memoryCards[2]; +int memoryCardsNew[2]; + +int memoryCardCmds = -1; +int memoryCardResult = -1; +int openFrameIndex = 0; +int currentlyOpenedMemoryCard = -1; + +void MemCardInit(long val) +{ + bIsInitialised = 1; + bCanUseMemoryCardFuncs = 0; + memoryCardStatus = -1; + memoryCardCmds = -1; + memoryCardResult = -1; + memoryCardsNew[0] = 1; + memoryCardsNew[1] = 1; +} + +void MemCardEnd() +{ + if (!bCanUseMemoryCardFuncs) + return; + +} + +void MemCardStart() +{ + bCanUseMemoryCardFuncs = 1; +} + +void MemCardStop() +{ + if (!bCanUseMemoryCardFuncs) + return; + + bCanUseMemoryCardFuncs = 0; + memoryCardStatus = -1; + memoryCardCmds = -1; + memoryCardResult = -1; + memoryCardsNew[0] = 1; + memoryCardsNew[1] = 1; + + if (memoryCards[0] != NULL) + { + fclose(memoryCards[0]); + } + + if (memoryCards[1] != NULL) + { + fclose(memoryCards[1]); + } +} + +long MemCardExist(long chan) +{ + if (!bCanUseMemoryCardFuncs) + return 0; + + char buf[16]; + sprintf(&buf[0], "%ld.MCD", chan); + memoryCards[chan] = fopen(&buf[0], "rb"); + + memoryCardCmds = McFuncExist; + + if (memoryCards[chan] == NULL) + { + memoryCardStatus = -1;//CHECKME + memoryCardResult = McErrCardNotExist;//CHECKME + return 0; + } + else + { + fclose(memoryCards[chan]); + + if (memoryCardResult == McErrNewCard) + { + memoryCardResult = McErrNone; + memoryCardStatus = 0; + } + else + { + memoryCardResult = McErrNewCard; + memoryCardStatus = 1; + } + } + + + return 1; +} + +long MemCardAccept(long chan) +{ + if (!bCanUseMemoryCardFuncs) + return 0; + + char buf[16]; + sprintf(&buf[0], "%ld.MCD", chan); + memoryCards[chan] = fopen(&buf[0], "rb"); + memoryCardCmds = McFuncAccept; + + unsigned int fileMagic = 0; + fread(&fileMagic, 4, 1, memoryCards[chan]); + fclose(memoryCards[chan]); + + //Is this card formatted? + if (fileMagic != 0x0000434D) + { + //If not, this is a new card! + memoryCardResult = McErrNewCard; + memoryCardsNew[chan] = 0; + return 0; + } + + memoryCardResult = 3; + memoryCardStatus = 1; + return 1; +} +long MemCardOpen(long chan, char* file, long flag) +{ + if (!bCanUseMemoryCardFuncs) + return 0; + + char buf[16]; + sprintf(&buf[0], "%ld.MCD", chan); + + switch (flag) + { + case 1: + memoryCards[chan] = fopen(&buf[0], "rb"); + break; + case 2://Unchecked + memoryCards[chan] = fopen(&buf[0], "wb"); + break; + } + + fseek(memoryCards[chan], 0, SEEK_SET); + currentlyOpenedMemoryCard = chan; + + for (int i = 0; i < 16; i++) + { + struct MemoryCardFrame frame; + fread(&frame, sizeof(struct MemoryCardFrame), 1, memoryCards[chan]); + + if (i > MC_HEADER_FRAME_INDEX && frame.name[0] != '\0') + { + if (strcmp(&frame.name[0], file) == 0) + { + break; + } + + openFrameIndex += frame.attr & 0x7; + } + } + + return 0; +} + +void MemCardClose() +{ + openFrameIndex = -1; + fclose(memoryCards[currentlyOpenedMemoryCard]); +} + +long MemCardReadData(unsigned long* adrs, long ofs, long bytes) +{ + memoryCardCmds = McFuncReadData; + if (bytes % 128) + { + return 0; + } + + fseek(memoryCards[currentlyOpenedMemoryCard], (64 * 128) + (openFrameIndex * 16384) + ofs, SEEK_SET); + fread(adrs, bytes, 1, memoryCards[currentlyOpenedMemoryCard]); + + return 1; +} + +long MemCardReadFile(long chan, char* file, unsigned long* adrs, long ofs, long bytes) +{ + memoryCardCmds = McFuncReadFile; + return 0; +} + +long MemCardWriteData(unsigned long* adrs, long ofs, long bytes) +{ + memoryCardCmds = McFuncWriteData; + return 0; +} + +long MemCardWriteFile(long chan, char* file, unsigned long* adrs, long ofs, long bytes) +{ + memoryCardCmds = McFuncWriteFile; + + return 0; +} + +long MemCardCreateFile(long chan, char* file, long blocks) +{ + UNIMPLEMENTED(); + return 0; +} + +long MemCardDeleteFile(long chan, char* file) +{ + UNIMPLEMENTED(); + return 0; +} + +long MemCardFormat(long chan) +{ + UNIMPLEMENTED(); + return 0; +} + +long MemCardUnformat(long chan) +{ + UNIMPLEMENTED(); + return 0; +} + +long MemCardSync(long mode, long* cmds, long* rslt) +{ + static int timesCalled = 0; + + //if (timesCalled++ >= 4) //Doesn't work o.o + { + timesCalled = 0; + + if (memoryCardCmds != -1) + { + *cmds = memoryCardCmds; + } + + if (memoryCardResult != -1) + { + *rslt = memoryCardResult; + } + + if (mode == 1) + { + return memoryCardStatus; + } + } + + return -1; +} + +MemCB MemCardCallback(MemCB func) +{ + UNIMPLEMENTED(); + return 0; +} + +long MemCardGetDirentry(long chan, char* name, struct DIRENTRY* dir, long* files, long ofs, long max) +{ + char buf[16]; + sprintf(&buf[0], "%ld.MCD", chan); + memoryCards[chan] = fopen(&buf[0], "rb");///@FIXME potential bug, if this is called twice then we can open a card twice. Maybe add a flag for whether memcard is open or not if original SDK did this. + fseek(memoryCards[chan], 0, SEEK_SET); + + if (strcmp(name, "*") == 0) + { + for (int i = 0, head = -64; i < 16; i++, head += 128) + { + struct MemoryCardFrame frame; + fread(&frame, sizeof(struct MemoryCardFrame), 1, memoryCards[chan]); + + if (i > MC_HEADER_FRAME_INDEX && frame.name[0] != '\0') + { + memcpy(dir->name, &frame.name[0], 20); + dir->attr = frame.attr & 0xF0; + dir->size = frame.size; + dir->next = (struct DIRENTRY*)9; + dir->head = head; + dir->system[0] = 9; + dir++; + files[0]++; + } + } + } + memoryCardCmds = McFuncExist; + memoryCardResult = 0; + memoryCardStatus = 1; + + return 0; +} diff --git a/src_rebuild/EMULATOR/LIBMCRD.H b/src_rebuild/EMULATOR/LIBMCRD.H new file mode 100644 index 00000000..3fba3c39 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBMCRD.H @@ -0,0 +1,45 @@ +#ifndef LIBMCRD_H +#define LIBMCRD_H + +#include "KERNEL.H" + +typedef void (*MemCB)( long cmds, long rslt ); + +#define McFuncExist (1) +#define McFuncAccept (2) +#define McFuncReadFile (3) +#define McFuncWriteFile (4) +#define McFuncReadData (5) +#define McFuncWriteData (6) + +#define McErrNone (0) +#define McErrCardNotExist (1) +#define McErrCardInvalid (2) +#define McErrNewCard (3) +#define McErrNotFormat (4) +#define McErrFileNotExist (5) +#define McErrAlreadyExist (6) +#define McErrBlockFull (7) +#define McErrExtend (0x8000) + +extern void MemCardInit( long val ); +extern void MemCardEnd( void ); +extern void MemCardStart(void); +extern void MemCardStop(void); +extern long MemCardExist( long chan ); +extern long MemCardAccept( long chan ); +extern long MemCardOpen( long chan, char* file, long flag ); +extern void MemCardClose(void); +extern long MemCardReadData( unsigned long* adrs, long ofs, long bytes ); +extern long MemCardReadFile( long chan, char* file, unsigned long* adrs, long ofs, long bytes ); +extern long MemCardWriteData( unsigned long* adrs, long ofs, long bytes ); +extern long MemCardWriteFile( long chan, char* file, unsigned long* adrs, long ofs ,long bytes ); +extern long MemCardCreateFile( long chan, char* file, long blocks ); +extern long MemCardDeleteFile( long chan, char* file ); +extern long MemCardFormat( long chan ); +extern long MemCardUnformat(long chan); +extern long MemCardSync( long mode, long* cmds, long* rslt ); +extern MemCB MemCardCallback( MemCB func ); +extern long MemCardGetDirentry( long chan, char* name, struct DIRENTRY* dir, long* files, long ofs, long max ); + +#endif diff --git a/src_rebuild/EMULATOR/LIBPAD.C b/src_rebuild/EMULATOR/LIBPAD.C new file mode 100644 index 00000000..61fda9e6 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBPAD.C @@ -0,0 +1,309 @@ +#include "LIBPAD.H" + +#include "EMULATOR.H" + +SDL_GameController* padHandle[MAX_CONTROLLERS]; +unsigned char* padData[MAX_CONTROLLERS]; +const unsigned char* keyboardState; + +void PadInitDirect(unsigned char* pad1, unsigned char* pad2) +{ + if (pad1 != NULL) + { + padData[0] = pad1; + padData[0][0] = 0xFF; + } + + if (pad2 != NULL) + { + padData[1] = pad2; + padData[1][0] = 0xFF; + } + + if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0) + { + eprinterr("Failed to initialise subsystem GAMECONTROLLER\n"); + } + + if (SDL_NumJoysticks() < 1) + { + eprinterr("Failed to locate a connected gamepad!\n"); + } + else + { + for (int i = 0; i < SDL_NumJoysticks(); i++) + { + if (SDL_IsGameController(i) && i < MAX_CONTROLLERS) + { + padHandle[i] = SDL_GameControllerOpen(i);///@TODO close joysticks + } + } + } + + keyboardState = SDL_GetKeyboardState(NULL); +} + +void PadInitMtap(unsigned char* unk00, unsigned char* unk01) +{ + UNIMPLEMENTED(); +} + +void PadInitGun(unsigned char* unk00, int unk01) +{ + UNIMPLEMENTED(); +} + +int PadChkVsync() +{ + UNIMPLEMENTED(); + return 0; +} + +void PadStartCom() +{ + UNIMPLEMENTED(); +} + +void PadStopCom() +{ + UNIMPLEMENTED(); +} + +unsigned int PadEnableCom(unsigned int unk00) +{ + UNIMPLEMENTED(); + return 0; +} + +void PadEnableGun(unsigned char unk00) +{ + UNIMPLEMENTED(); +} + +void PadRemoveGun() +{ + UNIMPLEMENTED(); +} + +int PadGetState(int port) +{ +#if _DEBUG || 1 + return PadStateStable;//FIXME should check if keyboard is connected +#endif + if (!(SDL_GameControllerGetAttached(padHandle[port]))) + { + return PadStateDiscon; + } + else + { + return PadStateStable; + } + + return 0; +} + +int PadInfoMode(int unk00, int unk01, int unk02) +{ + return 7;//? +} + +int PadInfoAct(int unk00, int unk01, int unk02) +{ + UNIMPLEMENTED(); + return 0; +} + +int PadInfoComb(int unk00, int unk01, int unk02) +{ + UNIMPLEMENTED(); + return 0; +} + +int PadSetActAlign(int unk00, unsigned char* unk01) +{ + UNIMPLEMENTED(); + return 0; +} + +int PadSetMainMode(int socket, int offs, int lock) +{ + UNIMPLEMENTED(); + return 0; +} + +void PadSetAct(int unk00, unsigned char* unk01, int unk02) +{ + UNIMPLEMENTED(); +} + +unsigned short UpdateGameControllerInput(SDL_GameController* pad) +{ + unsigned short ret = 0xFFFF; + + if (SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_X))//Square + { + ret &= ~0x8000; + } + + if (SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_B))//Circle + { + ret &= ~0x2000; + } + + if (SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_Y))//Triangle + { + ret &= ~0x1000; + } + + if (SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_A))//Cross + { + ret &= ~0x4000; + } + + if (SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_LEFTSHOULDER))//L1 + { + ret &= ~0x400; + } + + if (SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER))//R1 + { + ret &= ~0x800; + } + + if (SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_DPAD_UP))//UP + { + ret &= ~0x10; + } + + if (SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_DPAD_DOWN))//DOWN + { + ret &= ~0x40; + } + + if (SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_DPAD_LEFT))//LEFT + { + ret &= ~0x80; + } + + if (SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_DPAD_RIGHT))//RIGHT + { + ret &= ~0x20; + } + + if (SDL_GameControllerGetAxis(pad, SDL_CONTROLLER_AXIS_TRIGGERLEFT))//L2 + { + ret &= ~0x100; + } + + if (SDL_GameControllerGetAxis(pad, SDL_CONTROLLER_AXIS_TRIGGERRIGHT))//R2 + { + ret &= ~0x200; + } + + if (SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_LEFTSTICK))//L3 + { + ret &= ~0x2; + } + + if (SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_RIGHTSTICK))//R3 + { + ret &= ~0x4; + } + + if (SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_BACK))//SELECT + { + ret &= ~0x1; + } + + if (SDL_GameControllerGetButton(pad, SDL_CONTROLLER_BUTTON_START))//START + { + ret &= ~0x8; + } + + return ret; +} + +unsigned short UpdateKeyboardInput() +{ + unsigned short ret = 0xFFFF; + + //Not initialised yet + if (keyboardState == NULL) + { + return ret; + } + + SDL_PumpEvents(); + + if (keyboardState[SDL_SCANCODE_X])//Square + { + ret &= ~0x8000; + } + + if (keyboardState[SDL_SCANCODE_V])//Circle + { + ret &= ~0x2000; + } + + if (keyboardState[SDL_SCANCODE_Z])//Triangle + { + ret &= ~0x1000; + } + + if (keyboardState[SDL_SCANCODE_C])//Cross + { + ret &= ~0x4000; + } + + if (keyboardState[SDL_SCANCODE_LSHIFT])//L1 + { + ret &= ~0x400; + } + + if (keyboardState[SDL_SCANCODE_RSHIFT])//R1 + { + ret &= ~0x800; + } + + if (keyboardState[SDL_SCANCODE_UP])//UP + { + ret &= ~0x10; + } + + if (keyboardState[SDL_SCANCODE_DOWN])//DOWN + { + ret &= ~0x40; + } + + if (keyboardState[SDL_SCANCODE_LEFT])//LEFT + { + ret &= ~0x80; + } + + if (keyboardState[SDL_SCANCODE_RIGHT])//RIGHT + { + ret &= ~0x20; + } + + if (keyboardState[SDL_SCANCODE_LCTRL])//L2 + { + ret &= ~0x100; + } + + if (keyboardState[SDL_SCANCODE_RCTRL])//R2 + { + ret &= ~0x200; + } + + if (keyboardState[SDL_SCANCODE_SPACE])//SELECT + { + ret &= ~0x1; + } + + if (keyboardState[SDL_SCANCODE_RETURN])//START + { + ret &= ~0x8; + } + + return ret; +} diff --git a/src_rebuild/EMULATOR/LIBPAD.H b/src_rebuild/EMULATOR/LIBPAD.H new file mode 100644 index 00000000..85e39942 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBPAD.H @@ -0,0 +1,55 @@ +#ifndef LIBPAD_H +#define LIBPAD_H + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef NULL +#define NULL 0 +#endif + +#define PadStateDiscon 0 +#define PadStateFindPad 1 +#define PadStateFindCTP1 2 +#define PadStateFindCTP2 3 +#define PadStateReqInfo 4 +#define PadStateExecCmd 5 +#define PadStateStable 6 + +#define InfoModeCurID 1 +#define InfoModeCurExID 2 +#define InfoModeCurExOffs 3 +#define InfoModeIdTable 4 + +#define InfoActFunc 1 +#define InfoActSub 2 +#define InfoActSize 3 +#define InfoActCurr 4 +#define InfoActSign 5 + +#define PadMaxCurr 60 +#define PadCurrCTP1 10 + +#define MAX_CONTROLLERS 2 + +extern void PadInitDirect(unsigned char* pad1, unsigned char* pad2); +extern void PadInitMtap(unsigned char* unk00, unsigned char* unk01); +extern void PadInitGun(unsigned char* unk00, int unk01); +extern int PadChkVsync(); +extern void PadStartCom(); +extern void PadStopCom(); +extern unsigned int PadEnableCom(unsigned int unk00); +extern void PadEnableGun(unsigned char unk00); +extern void PadRemoveGun(); +extern int PadGetState(int port); +extern int PadInfoMode(int unk00, int, int unk01); +extern int PadInfoAct(int unk00, int, int unk01); +extern int PadInfoComb(int unk00, int, int unk01); +extern int PadSetActAlign(int unk00, unsigned char* unk01); +extern int PadSetMainMode(int socket, int offs, int lock); +extern void PadSetAct(int unk00, unsigned char* unk01, int unk02); + +#endif \ No newline at end of file diff --git a/src_rebuild/EMULATOR/LIBSN.C b/src_rebuild/EMULATOR/LIBSN.C new file mode 100644 index 00000000..203ef1ce --- /dev/null +++ b/src_rebuild/EMULATOR/LIBSN.C @@ -0,0 +1,72 @@ +#include "LIBSN.H" + +//#include "EMULATOR.H" + +#include + +uintptr_t fileHandle = 0; + +#define INVALID_FILE_HANDLE (-1) + +int PCinit() +{ + //UNIMPLEMENTED(); + return 0; +} + +uintptr_t PCopen(char* name, int flags, int perms) +{ + //TOMB5 hack for CUTSEQ.JIZ + if (name[0] == '\\') + { + ++name; + } + +#if defined(__ANDROID__) + char buff[64]; + sprintf(&buff[0], "/storage/emulated/0/TOMB5/%s", name); + name = &buff[0]; +#endif + + switch (flags) + { + case 0: + fileHandle = (uintptr_t)fopen(name, "rb"); + break; + case 1: + fileHandle = (uintptr_t)fopen(name, "wb"); + break; + case 2: + fileHandle = (uintptr_t)fopen(name, "rwb"); + break; + } + + return fileHandle == 0 ? INVALID_FILE_HANDLE : fileHandle; +} + +int PCcreat(char* name, int perms) +{ + //UNIMPLEMENTED(); + return 0; +} + +int PClseek(uintptr_t fd, int offset, int mode) +{ + fseek((FILE*)fd, offset, mode); + return ftell((FILE*)fd); +} + +int PCread(uintptr_t fd, char* buff, int len) +{ + return fread(buff, len, 1, (FILE*)fd); +} + +int PCwrite(uintptr_t fd, char* buff, int len) +{ + return fwrite(buff, len, 1, (FILE*)fd); +} + +int PCclose(uintptr_t fd) +{ + return fclose((FILE*)fd); +} \ No newline at end of file diff --git a/src_rebuild/EMULATOR/LIBSN.H b/src_rebuild/EMULATOR/LIBSN.H new file mode 100644 index 00000000..a848568c --- /dev/null +++ b/src_rebuild/EMULATOR/LIBSN.H @@ -0,0 +1,14 @@ +#ifndef LIBSN_H +#define LIBSN_H + +#include + +extern int PCinit(); +extern uintptr_t PCopen(char* name, int flags, int perms); +extern int PCcreat(char* name, int perms); +extern int PClseek(uintptr_t fd, int offset, int mode); +extern int PCread(uintptr_t fd, char* buff, int len); +extern int PCwrite(uintptr_t fd, char* buff, int len); +extern int PCclose(uintptr_t fd); + +#endif \ No newline at end of file diff --git a/src_rebuild/EMULATOR/LIBSPU.C b/src_rebuild/EMULATOR/LIBSPU.C new file mode 100644 index 00000000..8150b51d --- /dev/null +++ b/src_rebuild/EMULATOR/LIBSPU.C @@ -0,0 +1,286 @@ +#include "LIBSPU.H" +#include "LIBETC.H" +#include +#include "EMULATOR.H" +#include "LIBAPI.H" + +#include + +#define SPU_CENTERNOTE (49152) + +short _spu_voice_centerNote[24] = +{ + SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, + SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, + SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE +}; + +SpuCommonAttr dword_424;//Might be wrong struct, need to check +int _spu_isCalled = 0; +int _spu_FiDMA = 0;///@TODO decl as extern find initial value +int _spu_EVdma = 0; +int _spu_rev_flag = 0; +int _spu_rev_reserve_wa = 0; +int _spu_rev_offsetaddr = 0; +int _spu_rev_startaddr = 0; +int _spu_AllocBlockNum = 0; +int _spu_AllocLastNum = 0; +int _spu_memList = 0; +int _spu_trans_mode = 0; +int _spu_transMode = 0; +int _spu_keystat = 0; +int _spu_RQmask = 0; +int _spu_RQvoice = 0; +int _spu_env = 0; +char spu[440];//0x1F801C00 is base address +short* _spu_RXX = (short*)&spu[0]; +int _spu_mem_mode_plus = 3; +void* _spu_transferCallback = NULL;///@TODO initial value check +int _spu_inTransfer = 0;///@TODO initial value check +unsigned short _spu_tsa = 0; + +void SpuGetAllKeysStatus(char* status) +{ + UNIMPLEMENTED(); +} + +void SpuSetKeyOnWithAttr(SpuVoiceAttr* attr) +{ + UNIMPLEMENTED(); +} + +void _spu_t(int mode, int flag) +{ + UNIMPLEMENTED(); +} + +void _spu_Fw(unsigned char* addr, unsigned long size) +{ + //v0 = _spu_transMode + //s1 = addr + //s0 = size + + if (_spu_trans_mode == 0) + { + //v0 = _spu_tsa + //a1 = _spu_mem_mode_plus + //a0 = 2 + _spu_t(2, _spu_tsa << _spu_mem_mode_plus); + ///@TODO check if a1 is modified in spu_t + } + //loc_A84 +#if 0 +jal _spu_t +sllv $a1, $v0, $a1 + +jal _spu_t +li $a0, 1 + +li $a0, 3 +move $a1, $s1 +jal _spu_t +move $a2, $s0 +j loc_A94 +move $v0, $s0 + +loc_A84: +move $a0, $s1 +jal sub_480 +move $a1, $s0 +move $v0, $s0 + +loc_A94: +lw $ra, 0x20+var_8($sp) +lw $s1, 0x20+var_C($sp) +lw $s0, 0x20+var_10($sp) +jr $ra +addiu $sp, 0x20 + # End of function _spu_Fw +#endif +} + +unsigned long SpuWrite(unsigned char* addr, unsigned long size) +{ + if (0x7EFF0 < size) + { + size = 0x7EFF0; + } + + //loc_228 + _spu_Fw(addr, size); + + if (_spu_transferCallback == NULL) + { + _spu_inTransfer = 0; + } + + return size; +} + +long SpuSetTransferMode(long mode) +{ + long mode_fix = mode == 0 ? 0 : 1; + + //trans_mode = mode; + //transMode = mode_fix; + + return mode_fix; +} + +unsigned long SpuSetTransferStartAddr(unsigned long addr) +{ + UNIMPLEMENTED(); + return 0; +} + +long SpuIsTransferCompleted(long flag) +{ + UNIMPLEMENTED(); + return 0; +} + +void _SpuDataCallback(int a0) +{ + UNIMPLEMENTED(); +} + +void SpuStart()//(F) +{ + long event = 0; + + if (_spu_isCalled == 0) + { + _spu_isCalled = 1; + EnterCriticalSection(); + _SpuDataCallback(_spu_FiDMA); + event = OpenEvent(HwSPU, EvSpCOMP, EvMdNOINTR, NULL); + _spu_EVdma = event; + EnableEvent(event); + ExitCriticalSection(); + } + //loc_348 +} + +void _spu_init(int a0) +{ + UNIMPLEMENTED(); +} + +void _spu_FsetRXX(int a0, int a1, int a2)//(F) +{ + if (a2 == 0) + { + _spu_RXX[a0] = a1; + } + else + { + _spu_RXX[a0] = a1 >> _spu_mem_mode_plus; + } +} + +void _SpuInit(int a0) +{ + ResetCallback(); + _spu_init(a0); + + if (a0 == 0) + { + for (int i = 0; i < sizeof(_spu_voice_centerNote) / sizeof(short); i++) + { + _spu_voice_centerNote[i] = SPU_CENTERNOTE; + } + } + //loc_240 + SpuStart(); + + _spu_rev_flag = 0; + _spu_rev_reserve_wa = 0; + dword_424.mask = 0; + dword_424.mvol.left = 0; + dword_424.mvol.right = 0; + dword_424.mvolmode.left = 0; + dword_424.mvolmode.right = 0; + dword_424.mvolx.left = 0; + dword_424.mvolx.right = 0; + _spu_rev_offsetaddr = _spu_rev_startaddr; + _spu_FsetRXX(209, _spu_rev_startaddr, 0); + _spu_AllocBlockNum = 0; + _spu_AllocLastNum = 0; + _spu_memList = 0; + _spu_trans_mode = 0; + _spu_transMode = 0; + _spu_keystat = 0; + _spu_RQmask = 0; + _spu_RQvoice = 0; + _spu_env = 0; +} + +void SpuInit(void) +{ + _SpuInit(0); +} + +long SpuSetReverb(long on_off) +{ + UNIMPLEMENTED(); + return 0; +} + +unsigned long SpuSetReverbVoice(long on_off, unsigned long voice_bit) +{ + UNIMPLEMENTED(); + return 0; +} + +void SpuSetCommonAttr(SpuCommonAttr* attr) +{ + UNIMPLEMENTED(); +} + +long SpuInitMalloc(long num, char* top)//(F) +{ + if (num > 0) + { + //loc_214 + ((int*)top)[0] = 0x40001010; + _spu_memList = (uintptr_t)top; + _spu_AllocLastNum = 0; + _spu_AllocBlockNum = num; + ((int*)top)[1] = (0x10000000 << _spu_mem_mode_plus) - 0x1010; + } + + return num; +} + +long SpuMalloc(long size) +{ + return 0/*(long)(uintptr_t)malloc(size)*/; +} + +long SpuMallocWithStartAddr(unsigned long addr, long size) +{ + UNIMPLEMENTED(); + return 0; +} + +void SpuFree(unsigned long addr) +{ + /*free((void*)(uintptr_t)addr)*/; +} + +void SpuSetCommonMasterVolume(short mvol_left, short mvol_right)// (F) +{ + //MasterVolume.VolumeLeft.Raw = mvol_left; + //MasterVolume.VolumeRight.Raw = mvol_right; +} + +long SpuSetReverbModeType(long mode) +{ + UNIMPLEMENTED(); + return 0; +} + +void SpuSetReverbModeDepth(short depth_left, short depth_right) +{ + UNIMPLEMENTED(); +} diff --git a/src_rebuild/EMULATOR/LIBSPU.H b/src_rebuild/EMULATOR/LIBSPU.H new file mode 100644 index 00000000..ab8cbe33 --- /dev/null +++ b/src_rebuild/EMULATOR/LIBSPU.H @@ -0,0 +1,552 @@ +#ifndef LIBSPU_H +#define LIBSPU_H + +/***************************************************************** + * -*- c -*- + * $RCSfile: libspu.h,v $ + * + * Copyright (c) 1993, 1994, 1995, 1996 Sony Computer Entertainment Inc. + * All Rights Reserved. + * + * This file is part of ``PlayStation(R)'' Programmer Tool / + * Runtime Library. + * + * R & D Division, Sony Computer Entertainment Inc. + * + * $Id: libspu.h,v 1.80 1997/06/24 11:14:04 kaol Exp $ + * + *****************************************************************/ +/* + * $PSLibId: Run-time Library Release 4.6$ + */ + +/* ---------------------------------------------------------------- + * CONSTANT + * ---------------------------------------------------------------- */ + +#define SPU_SUCCESS 0 +#define SPU_INVALID_ARGS (-3) +#define SPU_DIAG (-2) +#define SPU_CHECK (-1) +#define SPU_OFF 0 +#define SPU_ON 1 +#define SPU_CLEAR 2 +#define SPU_RESET 3 +#define SPU_DONT_CARE 4 +#define SPU_ALL 0 +#define SPU_CDONLY 5 +#define SPU_VOICEONLY 6 +#define SPU_CONT 7 +#define SPU_BIT 8 +#define SPU_NULL 0 +/* Macros below will be obsoleted. */ +#define SpuDiag SPU_DIAG +#define SpuCheck SPU_CHECK +#define SpuOff SPU_OFF +#define SpuOn SPU_ON +#define SpuClear SPU_CLEAR +#define SpuReset SPU_RESET +#define SpuDontCare SPU_DONT_CARE +#define SpuALL SPU_ALL +#define SpuCDOnly SPU_CDONLY +#define SpuVoiceOnly SPU_VOICEONLY +#define SpuCont SPU_CONT +#define SpuNull SPU_NULL + +#define SPU_OFF_ENV_ON 2 +#define SPU_ON_ENV_OFF 3 +/* Macros below will be obsoleted. */ +#define SpuOffEnvOn SPU_OFF_ENV_ON +#define SpuOnEnvOff SPU_ON_ENV_OFF + +#define SPU_ERROR (-1) +/* Macros below will be obsoleted. */ +#define SpuError SPU_ERROR + +#define SPU_TRANSFER_BY_DMA 0L +#define SPU_TRANSFER_BY_IO 1L +/* Macros below will be obsoleted. */ +#define SpuTransferByDMA SPU_TRANSFER_BY_DMA +#define SpuTransferByIO SPU_TRANSFER_BY_IO +#define SpuTransByDMA SpuTransferByDMA +#define SpuTransByIO SpuTransferByIO + +#define SPU_TRANSFER_WAIT 1 +#define SPU_TRANSFER_PEEK 0 +#define SPU_TRANSFER_GLANCE SPU_TRANSFER_PEEK + +/* + * Voice designate + */ + +#ifndef __SPU_VOICE +#define __SPU_VOICE + +#define SPU_00CH (0x1L<< 0) +#define SPU_01CH (0x1L<< 1) +#define SPU_02CH (0x1L<< 2) +#define SPU_03CH (0x1L<< 3) +#define SPU_04CH (0x1L<< 4) +#define SPU_05CH (0x1L<< 5) +#define SPU_06CH (0x1L<< 6) +#define SPU_07CH (0x1L<< 7) +#define SPU_08CH (0x1L<< 8) +#define SPU_09CH (0x1L<< 9) +#define SPU_10CH (0x1L<<10) +#define SPU_11CH (0x1L<<11) +#define SPU_12CH (0x1L<<12) +#define SPU_13CH (0x1L<<13) +#define SPU_14CH (0x1L<<14) +#define SPU_15CH (0x1L<<15) +#define SPU_16CH (0x1L<<16) +#define SPU_17CH (0x1L<<17) +#define SPU_18CH (0x1L<<18) +#define SPU_19CH (0x1L<<19) + +#define SPU_20CH (0x1L<<20) +#define SPU_21CH (0x1L<<21) +#define SPU_22CH (0x1L<<22) +#define SPU_23CH (0x1L<<23) + +#define SPU_0CH SPU_00CH +#define SPU_1CH SPU_01CH +#define SPU_2CH SPU_02CH +#define SPU_3CH SPU_03CH +#define SPU_4CH SPU_04CH +#define SPU_5CH SPU_05CH +#define SPU_6CH SPU_06CH +#define SPU_7CH SPU_07CH +#define SPU_8CH SPU_08CH +#define SPU_9CH SPU_09CH + +#define SPU_ALLCH (SPU_00CH | SPU_01CH | SPU_02CH | SPU_03CH | SPU_04CH | \ + SPU_05CH | SPU_06CH | SPU_07CH | SPU_08CH | SPU_09CH | \ + SPU_10CH | SPU_11CH | SPU_12CH | SPU_13CH | SPU_14CH | \ + SPU_15CH | SPU_16CH | SPU_17CH | SPU_18CH | SPU_19CH | \ + SPU_20CH | SPU_21CH | SPU_22CH | SPU_23CH) + +#define SPU_KEYCH(x) (0x1L<<(x)) +#define SPU_VOICECH(x) SPU_KEYCH(x) + +#endif /* __SPU_VOICE */ + +/* for Voice setting */ + +#define SPU_VOICE_VOLL (0x01 << 0) /* volume (left) */ +#define SPU_VOICE_VOLR (0x01 << 1) /* volume (right) */ +#define SPU_VOICE_VOLMODEL (0x01 << 2) /* volume mode (left) */ +#define SPU_VOICE_VOLMODER (0x01 << 3) /* volume mode (right) */ +#define SPU_VOICE_PITCH (0x01 << 4) /* tone (pitch setting) */ +#define SPU_VOICE_NOTE (0x01 << 5) /* tone (note setting) */ +#define SPU_VOICE_SAMPLE_NOTE (0x01 << 6) /* waveform data sample note */ +#define SPU_VOICE_WDSA (0x01 << 7) /* waveform data start address */ +#define SPU_VOICE_ADSR_AMODE (0x01 << 8) /* ADSR Attack rate mode */ +#define SPU_VOICE_ADSR_SMODE (0x01 << 9) /* ADSR Sustain rate mode */ +#define SPU_VOICE_ADSR_RMODE (0x01 << 10) /* ADSR Release rate mode */ +#define SPU_VOICE_ADSR_AR (0x01 << 11) /* ADSR Attack rate */ +#define SPU_VOICE_ADSR_DR (0x01 << 12) /* ADSR Decay rate */ +#define SPU_VOICE_ADSR_SR (0x01 << 13) /* ADSR Sustain rate */ +#define SPU_VOICE_ADSR_RR (0x01 << 14) /* ADSR Release rate */ +#define SPU_VOICE_ADSR_SL (0x01 << 15) /* ADSR Sustain level */ +#define SPU_VOICE_LSAX (0x01 << 16) /* start address for loop */ +#define SPU_VOICE_ADSR_ADSR1 (0x01 << 17) /* ADSR adsr1 for `VagAtr' */ +#define SPU_VOICE_ADSR_ADSR2 (0x01 << 18) /* ADSR adsr2 for `VagAtr' */ + +#define SPU_VOICE_DIRECT16 0 +#define SPU_VOICE_LINEARIncN 1 +#define SPU_VOICE_LINEARIncR 2 +#define SPU_VOICE_LINEARDecN 3 +#define SPU_VOICE_LINEARDecR 4 +#define SPU_VOICE_EXPIncN 5 +#define SPU_VOICE_EXPIncR 6 +#define SPU_VOICE_EXPDec 7 +#define SPU_VOICE_EXPDecN SPU_VOICE_EXPDec +#define SPU_VOICE_EXPDecR SPU_VOICE_EXPDec + +#define SPU_DECODED_FIRSTHALF 0 +#define SPU_DECODED_SECONDHALF 1 +#define SPU_DECODE_FIRSTHALF SPU_DECODED_FIRSTHALF +#define SPU_DECODE_SECONDHALF SPU_DECODED_SECONDHALF + + +#define SPU_COMMON_MVOLL (0x01 << 0) /* master volume (left) */ +#define SPU_COMMON_MVOLR (0x01 << 1) /* master volume (right) */ +#define SPU_COMMON_MVOLMODEL (0x01 << 2) /* master volume mode (left) */ +#define SPU_COMMON_MVOLMODER (0x01 << 3) /* master volume mode (right) */ +#define SPU_COMMON_RVOLL (0x01 << 4) /* reverb volume (left) */ +#define SPU_COMMON_RVOLR (0x01 << 5) /* reverb volume (right) */ +#define SPU_COMMON_CDVOLL (0x01 << 6) /* CD input volume (left) */ +#define SPU_COMMON_CDVOLR (0x01 << 7) /* CD input volume (right) */ +#define SPU_COMMON_CDREV (0x01 << 8) /* CD input reverb on/off */ +#define SPU_COMMON_CDMIX (0x01 << 9) /* CD input on/off */ +#define SPU_COMMON_EXTVOLL (0x01 << 10) /* external digital input volume (left) */ +#define SPU_COMMON_EXTVOLR (0x01 << 11) /* external digital input volume (right) */ +#define SPU_COMMON_EXTREV (0x01 << 12) /* external digital input reverb on/off */ +#define SPU_COMMON_EXTMIX (0x01 << 13) /* external digital input on/off */ + +/* for Reverb setting */ + +#define SPU_REV_MODE (0x01 << 0) /* mode setting */ +#define SPU_REV_DEPTHL (0x01 << 1) /* reverb depth (left) */ +#define SPU_REV_DEPTHR (0x01 << 2) /* reverb depth (right) */ +#define SPU_REV_DELAYTIME (0x01 << 3) /* Delay Time (ECHO, DELAY only) */ +#define SPU_REV_FEEDBACK (0x01 << 4) /* Feedback (ECHO only) */ + +#define SPU_REV_MODE_CHECK (-1) +#define SPU_REV_MODE_OFF 0 +#define SPU_REV_MODE_ROOM 1 +#define SPU_REV_MODE_STUDIO_A 2 +#define SPU_REV_MODE_STUDIO_B 3 +#define SPU_REV_MODE_STUDIO_C 4 +#define SPU_REV_MODE_HALL 5 +#define SPU_REV_MODE_SPACE 6 +#define SPU_REV_MODE_ECHO 7 +#define SPU_REV_MODE_DELAY 8 +#define SPU_REV_MODE_PIPE 9 +#define SPU_REV_MODE_MAX 10 + +#define SPU_REV_MODE_CLEAR_WA 0x100 + +/* ---------------------------------------------------------------- + * Event flushing + * ---------------------------------------------------------------- */ + +#define SPU_EVENT_KEY (0x01 << 0) +#define SPU_EVENT_PITCHLFO (0x01 << 1) +#define SPU_EVENT_NOISE (0x01 << 2) +#define SPU_EVENT_REVERB (0x01 << 3) + +#define SPU_EVENT_ALL 0 + +/* ---------------------------------------------------------------- + * Structure + * ---------------------------------------------------------------- */ + +typedef struct { + short left; /* Lch */ + short right; /* Rch */ +} SpuVolume; + +typedef struct { + unsigned long voice; /* set voice: + SpuSetVoiceAttr: each voice is a bit array + SpuGetVoiceAttr: voice is a bit value */ + unsigned long mask; /* settings attribute bit (invalid with Get) */ + SpuVolume volume; /* volume */ + SpuVolume volmode; /* volume mode */ + SpuVolume volumex; /* current volume (invalid with Set) */ + unsigned short pitch; /* tone (pitch setting) */ + unsigned short note; /* tone (note setting) */ + unsigned short sample_note; /* tone (note setting) */ + short envx; /* current envelope value (invalid with Set) */ + unsigned long addr; /* waveform data start address */ + unsigned long loop_addr; /* loop start address */ + long a_mode; /* Attack rate mode */ + long s_mode; /* Sustain rate mode */ + long r_mode; /* Release rate mode */ + unsigned short ar; /* Attack rate */ + unsigned short dr; /* Decay rate */ + unsigned short sr; /* Sustain rate */ + unsigned short rr; /* Release rate */ + unsigned short sl; /* Sustain level */ + unsigned short adsr1; /* adsr1 for `VagAtr' */ + unsigned short adsr2; /* adsr2 for `VagAtr' */ +} SpuVoiceAttr; + +typedef struct { + short voiceNum; /* voice number */ + short pad; /* padding */ + SpuVoiceAttr attr; /* voice attribute */ +} SpuLVoiceAttr; + +typedef struct { + unsigned long mask; /* settings mask */ + + long mode; /* reverb mode */ + SpuVolume depth; /* reverb depth */ + long delay; /* Delay Time (ECHO, DELAY only) */ + long feedback; /* Feedback (ECHO only) */ +} SpuReverbAttr; + +#define SPU_DECODEDDATA_SIZE 0x200 +#define SPU_DECODEDATA_SIZE SPU_DECODEDDATA_SIZE +typedef struct { + short cd_left [SPU_DECODEDDATA_SIZE]; + short cd_right [SPU_DECODEDDATA_SIZE]; + short voice1 [SPU_DECODEDDATA_SIZE]; + short voice3 [SPU_DECODEDDATA_SIZE]; +} SpuDecodedData; +typedef SpuDecodedData SpuDecodeData; + +typedef struct { + SpuVolume volume; /* volume */ + long reverb; /* reverb on/off */ + long mix; /* mixing on/off */ +} SpuExtAttr; + +typedef struct { + unsigned long mask; /* settings mask */ + + SpuVolume mvol; /* master volume */ + SpuVolume mvolmode; /* master volume mode */ + SpuVolume mvolx; /* current master volume */ + SpuExtAttr cd; /* CD input attributes */ + SpuExtAttr ext; /* external digital input attributes */ +} SpuCommonAttr; + +#ifndef __SPU_IRQCALLBACK_PROC +#define __SPU_IRQCALLBACK_PROC +typedef void (*SpuIRQCallbackProc)(void); +#endif /* __SPU_IRQCALLBACK_PROC */ +#ifndef __SPU_TRANSFERCALLBACK_PROC +#define __SPU_TRANSFERCALLBACK_PROC +typedef void (*SpuTransferCallbackProc)(void); +#endif /* __SPU_TRANSFERCALLBACK_PROC */ + +/* ---------------------------------------------------------------- + * for SPU Malloc (used in SpuInitMalloc()) + * ---------------------------------------------------------------- */ + +#define SPU_MALLOC_RECSIZ 8 + +/* ---------------------------------------------------------------- + * User specifiable global environment + * ---------------------------------------------------------------- */ + +typedef struct { + unsigned long mask; + unsigned long queueing; +} SpuEnv; + +#define SPU_ENV_EVENT_QUEUEING (0x01 << 0) + +/* ---------------------------------------------------------------- + * prototype declaration + * ---------------------------------------------------------------- */ + +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif +extern void SpuInit (void); +extern void SpuInitHot (void); +extern void SpuStart (void); +extern void SpuQuit (void); +extern long SpuSetMute (long on_off); +extern long SpuGetMute (void); +extern void SpuSetEnv (SpuEnv *env); + +extern long SpuSetNoiseClock (long n_clock); +extern long SpuGetNoiseClock (void); +extern unsigned long SpuSetNoiseVoice (long on_off, unsigned long voice_bit); +extern unsigned long SpuGetNoiseVoice (void); + +extern long SpuSetReverb (long on_off); +extern long SpuGetReverb (void); +extern long SpuSetReverbModeParam (SpuReverbAttr *attr); +extern void SpuGetReverbModeParam (SpuReverbAttr *attr); +extern long SpuSetReverbDepth (SpuReverbAttr *attr); +extern long SpuReserveReverbWorkArea (long on_off); +extern long SpuIsReverbWorkAreaReserved (long on_off); +extern unsigned long SpuSetReverbVoice (long on_off, unsigned long voice_bit); +extern unsigned long SpuGetReverbVoice (void); +extern long SpuClearReverbWorkArea (long mode); + +extern unsigned long SpuWrite (unsigned char *addr, unsigned long size); +extern unsigned long SpuWrite0 (unsigned long size); +extern unsigned long SpuRead (unsigned char *addr, unsigned long size); +extern long SpuSetTransferMode (long mode); +#define SpuSetTransMode(mode) SpuSetTransferMode((mode)) +extern long SpuGetTransferMode (void); +#define SpuGetTransMode() SpuGetTransferMode() +extern unsigned long SpuSetTransferStartAddr (unsigned long addr); +#define SpuSetTransStartAddr(addr) SpuSetTransferStartAddr((addr)) +extern unsigned long SpuGetTransferStartAddr (void); +#define SpuGetTransStartAddr() SpuGetTransferStartAddr() +extern unsigned long SpuWritePartly (unsigned char *addr, unsigned long size); + +extern long SpuIsTransferCompleted (long flag); +extern SpuTransferCallbackProc SpuSetTransferCallback (SpuTransferCallbackProc func); +extern long SpuReadDecodedData (SpuDecodedData *d_data, long flag); +#define SpuReadDecodeData(d_data,flag) SpuReadDecodedData((d_data), (flag)) + +extern long SpuSetIRQ (long on_off); +extern long SpuGetIRQ (void); +extern unsigned long SpuSetIRQAddr (unsigned long); +extern unsigned long SpuGetIRQAddr (void); +extern SpuIRQCallbackProc SpuSetIRQCallback (SpuIRQCallbackProc); + +extern void SpuSetVoiceAttr (SpuVoiceAttr *arg); +extern void SpuGetVoiceAttr (SpuVoiceAttr *arg); +extern void SpuSetKey (long on_off, unsigned long voice_bit); +extern void SpuSetKeyOnWithAttr (SpuVoiceAttr *attr); +extern long SpuGetKeyStatus (unsigned long voice_bit); +extern void SpuGetAllKeysStatus (char *status); +extern unsigned long SpuFlush (unsigned long ev); + +extern unsigned long SpuSetPitchLFOVoice (long on_off, unsigned long voice_bit); +extern unsigned long SpuGetPitchLFOVoice (void); + +extern void SpuSetCommonAttr (SpuCommonAttr *attr); +extern void SpuGetCommonAttr (SpuCommonAttr *attr); + +extern long SpuInitMalloc (long num, char *top); +extern long SpuMalloc (long size); +extern long SpuMallocWithStartAddr (unsigned long addr, long size); +extern void SpuFree (unsigned long addr); + +extern long SpuRGetAllKeysStatus (long min_, long max_, char *status); +extern long SpuRSetVoiceAttr (long min_, long max_, SpuVoiceAttr *arg); + +extern void SpuNSetVoiceAttr (int vNum, SpuVoiceAttr *arg); +extern void SpuNGetVoiceAttr (int vNum, SpuVoiceAttr *arg); + +extern void SpuLSetVoiceAttr (int num, SpuLVoiceAttr *argList); + +extern void SpuSetVoiceVolume (int vNum, short volL, short volR); +extern void SpuSetVoiceVolumeAttr (int vNum, short volL, short volR, + short volModeL, short volModeR); +extern void SpuSetVoicePitch (int vNum, unsigned short pitch); +extern void SpuSetVoiceNote (int vNum, unsigned short note); +extern void SpuSetVoiceSampleNote (int vNum, unsigned short sampleNote); +extern void SpuSetVoiceStartAddr (int vNum, unsigned long startAddr); +extern void SpuSetVoiceLoopStartAddr (int vNum, unsigned long lsa); +extern void SpuSetVoiceAR (int vNum, unsigned short AR); +extern void SpuSetVoiceDR (int vNum, unsigned short DR); +extern void SpuSetVoiceSR (int vNum, unsigned short SR); +extern void SpuSetVoiceRR (int vNum, unsigned short RR); +extern void SpuSetVoiceSL (int vNum, unsigned short SL); +extern void SpuSetVoiceARAttr (int vNum, unsigned short AR, long ARmode); +extern void SpuSetVoiceSRAttr (int vNum, unsigned short SR, long SRmode); +extern void SpuSetVoiceRRAttr (int vNum, unsigned short RR, long RRmode); +extern void SpuSetVoiceADSR (int vNum, unsigned short AR, unsigned short DR, + unsigned short SR, unsigned short RR, + unsigned short SL); +extern void SpuSetVoiceADSRAttr (int vNum, + unsigned short AR, unsigned short DR, + unsigned short SR, unsigned short RR, + unsigned short SL, + long ARmode, long SRmode, long RRmode); + +extern void SpuGetVoiceVolume (int vNum, short *volL, short *volR); +extern void SpuGetVoiceVolumeAttr (int vNum, short *volL, short *volR, + short *volModeL, short *volModeR); +extern void SpuGetVoiceVolumeX (int vNum, short *volXL, short *volXR); +extern void SpuGetVoicePitch (int vNum, unsigned short *pitch); +extern void SpuGetVoiceNote (int vNum, unsigned short *note); +extern void SpuGetVoiceSampleNote (int vNum, unsigned short *sampleNote); +extern void SpuGetVoiceEnvelope (int vNum, short *envx); +extern void SpuGetVoiceStartAddr (int vNum, unsigned long *startAddr); +extern void SpuGetVoiceLoopStartAddr (int vNum, unsigned long *loopStartAddr); +extern void SpuGetVoiceAR (int vNum, unsigned short *AR); +extern void SpuGetVoiceDR (int vNum, unsigned short *DR); +extern void SpuGetVoiceSR (int vNum, unsigned short *SR); +extern void SpuGetVoiceRR (int vNum, unsigned short *RR); +extern void SpuGetVoiceSL (int vNum, unsigned short *SL); +extern void SpuGetVoiceARAttr (int vNum, unsigned short *AR, long *ARmode); +extern void SpuGetVoiceSRAttr (int vNum, unsigned short *SR, long *SRmode); +extern void SpuGetVoiceRRAttr (int vNum, unsigned short *RR, long *RRmode); +extern void SpuGetVoiceADSR (int vNum, + unsigned short *AR, unsigned short *DR, + unsigned short *SR, unsigned short *RR, + unsigned short *SL); +extern void SpuGetVoiceADSRAttr (int vNum, + unsigned short *AR, unsigned short *DR, + unsigned short *SR, unsigned short *RR, + unsigned short *SL, + long *ARmode, long *SRmode, long *RRmode); +extern void SpuGetVoiceEnvelopeAttr (int vNum, long *keyStat, short *envx ); + +extern void SpuSetCommonMasterVolume (short mvol_left, short mvol_right); +extern void SpuSetCommonMasterVolumeAttr (short mvol_left, short mvol_right, + short mvolmode_left, + short mvolmode_right); +extern void SpuSetCommonCDMix (long cd_mix); +extern void SpuSetCommonCDVolume (short cd_left, short cd_right); +extern void SpuSetCommonCDReverb (long cd_reverb); + +extern void SpuGetCommonMasterVolume (short *mvol_left, short *mvol_right); +extern void SpuGetCommonMasterVolumeX (short *mvolx_left, short *mvolx_right); +extern void SpuGetCommonMasterVolumeAttr (short *mvol_left, short *mvol_right, + short *mvolmode_left, + short *mvolmode_right); +extern void SpuGetCommonCDMix (long *cd_mix); +extern void SpuGetCommonCDVolume (short *cd_left, short *cd_right); +extern void SpuGetCommonCDReverb (long *cd_reverb); + +extern long SpuSetReverbModeType (long mode); +extern void SpuSetReverbModeDepth (short depth_left, short depth_right); +extern void SpuSetReverbModeDelayTime (long delay); +extern void SpuSetReverbModeFeedback (long feedback); +extern void SpuGetReverbModeType (long *mode); +extern void SpuGetReverbModeDepth (short *depth_left, short *depth_right); +extern void SpuGetReverbModeDelayTime (long *delay); +extern void SpuGetReverbModeFeedback (long *feedback); +extern void SpuSetESA( long revAddr ); +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) || defined(c_plusplus) +} +#endif + +/* ---------------------------------------------------------------- */ + +#define SPU_ST_NOT_AVAILABLE 0 +#define SPU_ST_ACCEPT 1 + +#define SPU_ST_ERROR (-1) +#define SPU_ST_INVALID_ARGUMENT (-2) +#define SPU_ST_WRONG_STATUS (-3) + +#define SPU_ST_STOP 2 +#define SPU_ST_IDLE 3 +#define SPU_ST_PREPARE 4 +#define SPU_ST_START 5 +#define SPU_ST_PLAY 6 +#define SPU_ST_TRANSFER 7 +#define SPU_ST_FINAL 8 + + +/* VAG's header size */ +#define SPU_ST_VAG_HEADER_SIZE 0x30 + +typedef struct { + char status; /* stream status */ + char pad1; /* padding */ + char pad2; /* padding */ + char pad3; /* padding */ + long last_size; /* the size of last transferring + (last_size <= (size / 2)) */ + unsigned long buf_addr; /* The start address of stream buffer */ + unsigned long data_addr; /* The start address of SPU streaming + data in main memory */ +} SpuStVoiceAttr; + +typedef struct { + long size; /* The size of stream buffer */ + long low_priority; /* transfer priority */ + SpuStVoiceAttr voice [24]; +} SpuStEnv; + +#ifndef __SPU_ST_TRANSFERCALLBACK_PROC +#define __SPU_ST_TRANSFERCALLBACK_PROC +typedef void (*SpuStCallbackProc)(unsigned long, long); +#endif /* __SPU_TRANSFERCALLBACK_PROC */ + +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif +extern SpuStEnv *SpuStInit (long); +extern long SpuStQuit (void); +extern long SpuStGetStatus (void); +extern unsigned long SpuStGetVoiceStatus (void); +extern long SpuStTransfer (long flag, unsigned long voice_bit); +extern SpuStCallbackProc SpuStSetPreparationFinishedCallback (SpuStCallbackProc func); +extern SpuStCallbackProc SpuStSetTransferFinishedCallback (SpuStCallbackProc func); +extern SpuStCallbackProc SpuStSetStreamFinishedCallback (SpuStCallbackProc func); +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) || defined(c_plusplus) +} +#endif + +/* ---------------------------------------------------------------- + * End on File + * ---------------------------------------------------------------- */ +#endif /* _LIBSPU_H_ */ +/* DON'T ADD STUFF AFTER THIS */ diff --git a/src_rebuild/EMULATOR/PLATFORM/Android.cmake b/src_rebuild/EMULATOR/PLATFORM/Android.cmake new file mode 100644 index 00000000..bb502632 --- /dev/null +++ b/src_rebuild/EMULATOR/PLATFORM/Android.cmake @@ -0,0 +1,14 @@ +if(ANDROID) + +Message("Compiling for Android!") + +include_directories(${ROOT_DIR}/EXTERNAL/SDL/include) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=format-security -Wno-narrowing -Wno-nonportable-include-path") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wno-error=format-security -Wno-narrowing -Wno-nonportable-include-path") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wno-error=format-security -Wno-narrowing -Wno-nonportable-include-path") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=format-security -Wno-narrowing -Wno-nonportable-include-path") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-error=format-security -Wno-narrowing -Wno-nonportable-include-path") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wno-error=format-security -Wno-narrowing -Wno-nonportable-include-path") + +endif() \ No newline at end of file diff --git a/src_rebuild/EMULATOR/PLATFORM/Emscripten.cmake b/src_rebuild/EMULATOR/PLATFORM/Emscripten.cmake new file mode 100644 index 00000000..76401a6f --- /dev/null +++ b/src_rebuild/EMULATOR/PLATFORM/Emscripten.cmake @@ -0,0 +1,16 @@ +if(EMSCRIPTEN) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +find_package(OpenGL REQUIRED) +include_directories(${OPENGL_INCLUDE_DIR}) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s USE_SDL=2 --emrun -s ASSERTIONS=1 --std=c++11 -s USE_WEBGL2=1 -s FULL_ES3=1 -s WASM=1 -s ALLOW_MEMORY_GROWTH=1") + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=format-security -Wno-narrowing -Wno-nonportable-include-path") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wno-error=format-security -Wno-narrowing -Wno-nonportable-include-path") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wno-error=format-security -Wno-narrowing -Wno-nonportable-include-path") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=format-security -Wno-narrowing -Wno-nonportable-include-path") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-error=format-security -Wno-narrowing -Wno-nonportable-include-path") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wno-error=format-security -Wno-narrowing -Wno-nonportable-include-path") + +endif() \ No newline at end of file diff --git a/src_rebuild/EMULATOR/PLATFORM/Linux.cmake b/src_rebuild/EMULATOR/PLATFORM/Linux.cmake new file mode 100644 index 00000000..3611dfdc --- /dev/null +++ b/src_rebuild/EMULATOR/PLATFORM/Linux.cmake @@ -0,0 +1,23 @@ +if(LINUX) + +#Find libs +find_package(SDL2 REQUIRED) +find_package(OpenGL REQUIRED) +#We want to link GLEW statically +set(GLEW_USE_STATIC_LIBS ON) +find_package(GLEW REQUIRED) + +#Setup project include directories +include_directories(${GLEW_INCLUDE_DIR}) +include_directories(${SDL2_INCLUDE_DIR}) + +set(PSX_LIB libPSX.a) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-narrowing") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wno-narrowing") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wno-narrowing") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-narrowing") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-narrowing") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wno-narrowing") + +endif() \ No newline at end of file diff --git a/src_rebuild/EMULATOR/PLATFORM/Mingw.cmake b/src_rebuild/EMULATOR/PLATFORM/Mingw.cmake new file mode 100644 index 00000000..95a29f7e --- /dev/null +++ b/src_rebuild/EMULATOR/PLATFORM/Mingw.cmake @@ -0,0 +1,26 @@ +if(MINGW) + +Message("Compiling for Windows!") + +#Find libs +find_package(SDL2 REQUIRED) +find_package(OpenGL REQUIRED) +#We want to link GLEW statically +set(GLEW_USE_STATIC_LIBS ON) +find_package(GLEW REQUIRED) + +#We want to link GLEW statically +set(GLEW_USE_STATIC_LIBS ON) + +#Setup project include directories +include_directories(${GLEW_INCLUDE_DIR}) +include_directories(${SDL2_INCLUDE_DIR}) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-narrowing -std=c++11") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wno-narrowing -std=c++11") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wno-narrowing -std=c++11") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-narrowing -std=c++11") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-narrowing -std=c++11") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wno-narrowing -std=c++11") + +endif() \ No newline at end of file diff --git a/src_rebuild/EMULATOR/PLATFORM/Windows.cmake b/src_rebuild/EMULATOR/PLATFORM/Windows.cmake new file mode 100644 index 00000000..6c6ef353 --- /dev/null +++ b/src_rebuild/EMULATOR/PLATFORM/Windows.cmake @@ -0,0 +1,32 @@ +if(MSVC) + +Message("Compiling for Windows!") + +#SET(USE_VULKAN TRUE) +#SET(USE_D3D9 TRUE) + +# +list(APPEND CMAKE_PREFIX_PATH ${EXTERN_LIB_PATH}/glew-2.1.0) +list(APPEND CMAKE_LIBRARY_PATH ${EXTERN_LIB_PATH}/glew-2.1.0/lib/Release/Win32) + +#Find libs +find_package(SDL2 REQUIRED) +if(USE_VULKAN) +find_package(Vulkan REQUIRED) +include_directories(${Vulkan_INCLUDE_DIR}) +elseif(USE_D3D9) +find_package(D3D9 REQUIRED) +include_directories(${DIRECTX_INCLUDE_DIRS}) +else() +find_package(OpenGL REQUIRED) +#We want to link GLEW statically +set(GLEW_USE_STATIC_LIBS ON) +find_package(GLEW REQUIRED) + +#Setup project include directories +include_directories(${GLEW_INCLUDE_DIR}) +endif() + +include_directories(${SDL2_INCLUDE_DIR}) + +endif() \ No newline at end of file diff --git a/src_rebuild/EMULATOR/R3000.H b/src_rebuild/EMULATOR/R3000.H new file mode 100644 index 00000000..38453a08 --- /dev/null +++ b/src_rebuild/EMULATOR/R3000.H @@ -0,0 +1,235 @@ +#ifndef R3000_H +#define R3000_H + +#define K0BASE 0x80000000 +#define K0SIZE 0x20000000 +#define K1BASE 0xA0000000 +#define K1SIZE 0x20000000 +#define K2BASE 0xC0000000 +#define K2SIZE 0x20000000 + + + +#define UT_VEC K0BASE /* utlbmiss vector */ +#define E_VEC (K0BASE+0x80) /* exception vector */ +#define R_VEC (K1BASE+0x1fc00000) /* reset vector */ + +/* + * Address conversion macros + */ +#define K0_TO_K1(x) ((unsigned)(x)|0xA0000000) /* kseg0 to kseg1 */ +#define K1_TO_K0(x) ((unsigned)(x)&0x9FFFFFFF) /* kseg1 to kseg0 */ +#define K0_TO_PHYS(x) ((unsigned)(x)&0x1FFFFFFF) /* kseg0 to physical */ +#define K1_TO_PHYS(x) ((unsigned)(x)&0x1FFFFFFF) /* kseg1 to physical */ +#define PHYS_TO_K0(x) ((unsigned)(x)|0x80000000) /* physical to kseg0 */ +#define PHYS_TO_K1(x) ((unsigned)(x)|0xA0000000) /* physical to kseg1 */ + +/* + * Address predicates + */ +#define IS_KSEG0(x) ((unsigned)(x) >= K0BASE && (unsigned)(x) < K1BASE) +#define IS_KSEG1(x) ((unsigned)(x) >= K1BASE && (unsigned)(x) < K2BASE) +#define IS_KSEG2(x) ((unsigned)(x) >= K2BASE && (unsigned)(x) < KPTEBASE) +#define IS_KPTESEG(x) ((unsigned)(x) >= KPTEBASE) +#define IS_KUSEG(x) ((unsigned)(x) < K0BASE) + +/* + * Cache size constants + */ +#define MINCACHE +(4*1024) /* leading plus for mas's benefit */ +#define MAXCACHE +(64*1024) /* leading plus for mas's benefit */ + + +/* + * Status register + */ +#define SR_CUMASK 0xf0000000 /* coproc usable bits */ + +#define SR_CU3 0x80000000 /* Coprocessor 3 usable */ +#define SR_CU2 0x40000000 /* Coprocessor 2 usable */ +#define SR_CU1 0x20000000 /* Coprocessor 1 usable */ +#define SR_CU0 0x10000000 /* Coprocessor 0 usable */ + +#define SR_BEV 0x00400000 /* use boot exception vectors */ + +/* Cache control bits */ +#define SR_TS 0x00200000 /* TLB shutdown */ +#define SR_PE 0x00100000 /* cache parity error */ +#define SR_CM 0x00080000 /* cache miss */ +#define SR_PZ 0x00040000 /* cache parity zero */ +#define SR_SWC 0x00020000 /* swap cache */ +#define SR_ISC 0x00010000 /* Isolate data cache */ + +#define SR_MM_MODE 0x00010000 /* lwl/swl/etc become scache/etc */ +#define lcache lwl +#define scache swl +#define flush lwr $0, +#define inval swr $0, + +/* + * Interrupt enable bits + * (NOTE: bits set to 1 enable the corresponding level interrupt) + */ +#define SR_IMASK 0x0000ff00 /* Interrupt mask */ +#define SR_IMASK8 0x00000000 /* mask level 8 */ +#define SR_IMASK7 0x00008000 /* mask level 7 */ +#define SR_IMASK6 0x0000c000 /* mask level 6 */ +#define SR_IMASK5 0x0000e000 /* mask level 5 */ +#define SR_IMASK4 0x0000f000 /* mask level 4 */ +#define SR_IMASK3 0x0000f800 /* mask level 3 */ +#define SR_IMASK2 0x0000fc00 /* mask level 2 */ +#define SR_IMASK1 0x0000fe00 /* mask level 1 */ +#define SR_IMASK0 0x0000ff00 /* mask level 0 */ + +#define SR_IBIT8 0x00008000 /* bit level 8 */ +#define SR_IBIT7 0x00004000 /* bit level 7 */ +#define SR_IBIT6 0x00002000 /* bit level 6 */ +#define SR_IBIT5 0x00001000 /* bit level 5 */ +#define SR_IBIT4 0x00000800 /* bit level 4 */ +#define SR_IBIT3 0x00000400 /* bit level 3 */ +#define SR_IBIT2 0x00000200 /* bit level 2 */ +#define SR_IBIT1 0x00000100 /* bit level 1 */ + +#define SR_KUO 0x00000020 /* old kernel/user, 0 => k, 1 => u */ +#define SR_IEO 0x00000010 /* old interrupt enable, 1 => enable */ +#define SR_KUP 0x00000008 /* prev kernel/user, 0 => k, 1 => u */ +#define SR_IEP 0x00000004 /* prev interrupt enable, 1 => enable */ +#define SR_KUC 0x00000002 /* cur kernel/user, 0 => k, 1 => u */ +#define SR_IEC 0x00000001 /* cur interrupt enable, 1 => enable */ + +#define SR_IMASKSHIFT 8 + +#define SR_FMT "\20\40BD\26TS\25PE\24CM\23PZ\22SwC\21IsC\20IM7\17IM6\16IM5\15IM4\14IM3\13IM2\12IM1\11IM0\6KUo\5IEo\4KUp\3IEp\2KUc\1IEc" + +/* + * Cause Register + */ +#define CAUSE_BD 0x80000000 /* Branch delay slot */ +#define CAUSE_CEMASK 0x30000000 /* coprocessor error */ +#define CAUSE_CESHIFT 28 + +/* Interrupt pending bits */ +#define CAUSE_IP8 0x00008000 /* External level 8 pending */ +#define CAUSE_IP7 0x00004000 /* External level 7 pending */ +#define CAUSE_IP6 0x00002000 /* External level 6 pending */ +#define CAUSE_IP5 0x00001000 /* External level 5 pending */ +#define CAUSE_IP4 0x00000800 /* External level 4 pending */ +#define CAUSE_IP3 0x00000400 /* External level 3 pending */ +#define CAUSE_SW2 0x00000200 /* Software level 2 pending */ +#define CAUSE_SW1 0x00000100 /* Software level 1 pending */ + +#define CAUSE_IPMASK 0x0000FF00 /* Pending interrupt mask */ +#define CAUSE_IPSHIFT 8 + +#define CAUSE_EXCMASK 0x0000003C /* Cause code bits */ +#define CAUSE_EXCSHIFT 2 + +#define CAUSE_FMT "\20\40BD\36CE1\35CE0\20IP8\17IP7\16IP6\15IP5\14IP4\13IP3\12SW2\11SW1\1INT" + +/* Cause register exception codes */ + +#define EXC_CODE(x) ((x)<<2) + +/* Hardware exception codes */ +#define EXC_INT EXC_CODE(0) /* interrupt */ +#define EXC_MOD EXC_CODE(1) /* TLB mod */ +#define EXC_RMISS EXC_CODE(2) /* Read TLB Miss */ +#define EXC_WMISS EXC_CODE(3) /* Write TLB Miss */ +#define EXC_RADE EXC_CODE(4) /* Read Address Error */ +#define EXC_WADE EXC_CODE(5) /* Write Address Error */ +#define EXC_IBE EXC_CODE(6) /* Instruction Bus Error */ +#define EXC_DBE EXC_CODE(7) /* Data Bus Error */ +#define EXC_SYSCALL EXC_CODE(8) /* SYSCALL */ +#define EXC_BREAK EXC_CODE(9) /* BREAKpoint */ +#define EXC_II EXC_CODE(10) /* Illegal Instruction */ +#define EXC_CPU EXC_CODE(11) /* CoProcessor Unusable */ +#define EXC_OV EXC_CODE(12) /* OVerflow */ + +/* software exception codes */ +#define SEXC_SEGV EXC_CODE(16) /* Software detected seg viol */ +#define SEXC_RESCHED EXC_CODE(17) /* resched request */ +#define SEXC_PAGEIN EXC_CODE(18) /* page-in request */ +#define SEXC_CPU EXC_CODE(19) /* coprocessor unusable */ + + +/* + * Coprocessor 0 registers + */ +#define C0_INX $0 /* tlb index */ +#define C0_RAND $1 /* tlb random */ +#define C0_TLBLO $2 /* tlb entry low */ + +#define C0_CTXT $4 /* tlb context */ + +#define C0_PIDMASK $6 /* Mips2 */ + +#define C0_BADVADDR $8 /* bad virtual address */ + +#define C0_TLBHI $10 /* tlb entry hi */ +#define C0_PID $10 /* Mips2 */ + +#define C0_SR $12 /* status register */ +#define C0_CAUSE $13 /* exception cause */ +#define C0_EPC $14 /* exception pc */ +#define C0_PRID $15 /* revision identifier */ +#define C0_ERREG $16 /* Mips2 */ + +/* + * Coprocessor 0 operations + */ +#define C0_READI 0x1 /* read ITLB entry addressed by C0_INDEX */ +#define C0_WRITEI 0x2 /* write ITLB entry addressed by C0_INDEX */ +#define C0_WRITER 0x6 /* write ITLB entry addressed by C0_RAND */ +#define C0_PROBE 0x8 /* probe for ITLB entry addressed by TLBHI */ +#define C0_RFE 0x10 /* restore for exception */ + +/* + * Flags for the nofault handler. 0 means no fault is expected. + */ +#define NF_BADADDR 1 /* badaddr, wbadaddr */ +#define NF_COPYIO 2 /* copyin, copyout */ +#define NF_ADDUPC 3 /* addupc */ +#define NF_FSUMEM 4 /* fubyte, subyte, fuword, suword */ +#define NF_USERACC 5 /* useracc */ +#define NF_SOFTFP 6 /* softfp */ +#define NF_REVID 7 /* revision ids */ +#define NF_NENTRIES 8 + +/* + * TLB size constants + */ +#define TLBWIREDBASE 0 /* WAG for now */ +#define NWIREDENTRIES 8 /* WAG for now */ +#define TLBRANDOMBASE NWIREDENTRIES +#define NRANDOMENTRIES (NTLBENTRIES-NWIREDENTRIES) +#define NTLBENTRIES 64 /* WAG for now */ + +#define TLBRAND_RANDMASK 0x00003f00 +#define TLBRAND_RANDSHIFT 8 + + +/* + * Chip interrupt vector + */ +#define NC0VECS 8 +#ifndef LOCORE +#ifdef KERNEL +#if defined(_LANGUAGE_C_PLUS_PLUS)||defined(__cplusplus)||defined(c_plusplus) +extern "C" { +#endif +extern int (*c0vec_tbl[])(); +#if defined(_LANGUAGE_C_PLUS_PLUS)||defined(__cplusplus)||defined(c_plusplus) +} +#endif +#endif +#endif /* !LOCORE */ + +#define BRK_KERNEL 0xf1 +#define EXCEPT_NORM 1 +#define EXCEPT_UTLB 2 +#define EXCEPT_BRKPT 3 +#define EXCEPT_DB 4 +#define EXCEPT_GDB 4 +#define EXCEPT_INT 9 +#define EXCEPT_ELSE 0xff +#endif /* _R3000_H */ diff --git a/src_rebuild/EMULATOR/STRINGS.H b/src_rebuild/EMULATOR/STRINGS.H new file mode 100644 index 00000000..f4f451e2 --- /dev/null +++ b/src_rebuild/EMULATOR/STRINGS.H @@ -0,0 +1,6 @@ +#ifndef STRINGS_H +#define STRINGS_H + +#include //temp + +#endif \ No newline at end of file diff --git a/src_rebuild/EMULATOR/TYPES.H b/src_rebuild/EMULATOR/TYPES.H new file mode 100644 index 00000000..2c9dd14d --- /dev/null +++ b/src_rebuild/EMULATOR/TYPES.H @@ -0,0 +1,79 @@ +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +#if !defined(__APPLE__) +/* major part of a device */ +#define major(x) ((int)(((unsigned)(x)>>8)&0377)) + +/* minor part of a device */ +#define minor(x) ((int)((x)&0377)) + +/* make a device number */ +#define makedev(x,y) ((dev_t)(((x)<<8) | (y))) + +#endif + +#ifndef _UCHAR_T +#define _UCHAR_T +typedef unsigned char u_char; +#endif +#ifndef _USHORT_T +#define _USHORT_T +typedef unsigned short u_short; +#endif +#ifndef _UINT_T +#define _UINT_T +typedef unsigned int u_int; +#endif +#ifndef _ULONG_T +#define _ULONG_T +typedef unsigned long u_long; +#endif +#ifndef _SYSIII_USHORT +#define _SYSIII_USHORT +typedef unsigned short ushort; /* sys III compat */ +#endif +#ifndef __psx__ +#ifndef _SYSV_UINT +#define _SYSV_UINT +typedef unsigned int uint; /* sys V compat */ +#endif +#ifndef _SYSV_ULONG +#define _SYSV_ULONG +typedef unsigned long ulong; /* sys V compat */ +#endif +#endif /* ! __psx__ */ + +#if !__APPLE__ +typedef struct _physadr { int r[1]; } *physadr; +typedef struct label_t { + int val[12]; +} label_t; + +#if !defined(__ANDROID__) +typedef struct _quad { long val[2]; } quad; +typedef long daddr_t; +typedef char * caddr_t; +typedef long * qaddr_t; +//typedef u_long ino_t; +typedef long swblk_t; +#endif + +#if !defined(__EMSCRIPTEN__) +#ifndef _SIZE_T +#define _SIZE_T +typedef unsigned int size_t; +#endif +#endif + +//typedef long time_t; +//typedef short dev_t; +//typedef long off_t; +//typedef u_short uid_t; +//typedef u_short gid_t; + +#endif + +#define NBBY 8 + +#endif